package grafanabackuper import ( "context" "encoding/json" "errors" "slices" "git.ar21.de/yolokube/grafana-backuper/internal/config" "git.ar21.de/yolokube/grafana-backuper/pkg/git" "git.ar21.de/yolokube/grafana-backuper/pkg/grafana" ) var ErrAlreadyCommited = errors.New("already committed") type BackupClient struct { client *Client } func (b *BackupClient) Start(ctx context.Context, cfg *config.Config) error { b.client.logger.Debug().Str("search-type", string(grafana.SearchTypeDashboard)).Msg("Searching dashboards by type") dashboards, _, err := b.client.grafana.File.Search(ctx, grafana.WithType(grafana.SearchTypeDashboard)) if err != nil { return err } b.client.logger.Debug(). Str("search-type", string(grafana.SearchTypeDashboard)). Int("counter", len(dashboards)). Msg("Found dashboards") for _, dashboardInfo := range dashboards { b.client.logger.Debug(). Str("dashboard-uid", dashboardInfo.UID). Str("dashboard", dashboardInfo.Title). Msg("Fetching dashboard data") var dashboard *grafana.Dashboard dashboard, _, err = b.client.grafana.Dashboard.Get(ctx, dashboardInfo.UID) if err != nil { return err } b.client.logger.Debug(). Str("dashboard-uid", dashboardInfo.UID). Str("dashboard", dashboardInfo.Title). Msg("Fetching dashboard versions") var versions []*grafana.DashboardVersion versions, _, err = b.client.grafana.DashboardVersion.List(ctx, dashboardInfo.UID) if err != nil { return err } b.client.logger.Debug(). Str("dashboard-uid", dashboardInfo.UID). Str("dashboard", dashboardInfo.Title). Int("counter", len(versions)). Msg("Found dashboard versions") slices.Reverse(versions) uncommitedVersion := cfg.ForceCommits for _, version := range versions { b.client.logger.Debug(). Str("dashboard-uid", dashboardInfo.UID). Uint("version", version.Version). Msg("Fetching version data") var dashboardVersion *grafana.DashboardVersion dashboardVersion, _, err = b.client.grafana.DashboardVersion.Get(ctx, dashboardInfo.UID, version.Version) if err != nil { return err } var commitmsg string commitmsg, err = b.commitDashboardVersion( dashboard, dashboardVersion, dashboardInfo, cfg, uncommitedVersion, ) if errors.Is(err, ErrAlreadyCommited) { b.client.logger.Info().Str("commit-msg", commitmsg).Msg("Already committed") continue } else if err != nil { return err } uncommitedVersion = true b.client.logger.Info().Str("commit-msg", commitmsg).Msg("Commit created") } } if !b.client.git.HasChanges() { return nil } return b.client.git.Push(ctx) } func (b *BackupClient) commitDashboardVersion( dashboard *grafana.Dashboard, dashboardVersion *grafana.DashboardVersion, dashboardInfo *grafana.SearchResult, cfg *config.Config, force bool, ) (string, error) { commitmsg := Message{ ID: dashboardVersion.ID, Path: dashboardInfo.Title, Title: dashboardVersion.Message, UID: dashboardInfo.UID, }.String() b.client.logger.Debug().Str("commit", commitmsg).Msg("Checking commit existence") if !force && b.client.git.CommitExists(commitmsg) { return commitmsg, ErrAlreadyCommited } b.updateDashboardInfo(dashboard, dashboardVersion) b.client.logger.Debug(). Str("folder", dashboard.FolderTitle). Str("dashboard-uid", dashboardVersion.DashboardUID). Msg("Marshalling the dashboard version data") data, err := json.MarshalIndent(grafana.SchemaFromDashboardMeta(dashboard), "", " ") if err != nil { return commitmsg, err } commitOpts := []git.CommitOption{ git.WithAuthor(dashboardVersion.CreatedBy, ""), git.WithFileContent(data, dashboardInfo.Title, dashboard.FolderTitle), } if b.client.signer != nil { commitOpts = append(commitOpts, git.WithSigner(*b.client.signer)) } if cfg.GitUser != "" { commitOpts = append(commitOpts, git.WithCommitter(cfg.GitUser, cfg.GitEmail)) } commit := b.client.git.NewCommit(commitOpts...) b.client.logger.Debug().Str("commit", commitmsg).Msg("Creating new commit") return commitmsg, commit.Create(commitmsg) } func (b *BackupClient) updateDashboardInfo(d *grafana.Dashboard, dv *grafana.DashboardVersion) { b.client.logger.Debug(). Str("dashboard-uid", dv.DashboardUID). Str("folder", d.FolderTitle). Msg("Updating dashboard information") d.Dashboard = dv.Data d.UpdatedBy = dv.CreatedBy d.Updated = dv.Created d.Version = dv.Version b.client.logger.Debug(). Str("dashboard-uid", dv.DashboardUID). Str("folder", d.FolderTitle). Msg("Updated dashboard information successfully") }