diff --git a/internal/cmd/backup.go b/internal/cmd/backup.go index f7afcca..dbb545e 100644 --- a/internal/cmd/backup.go +++ b/internal/cmd/backup.go @@ -2,11 +2,12 @@ package cmd import ( "context" - "encoding/json" + "errors" "fmt" "slices" "git.ar21.de/yolokube/grafana-backuper/internal/config" + "git.ar21.de/yolokube/grafana-backuper/internal/helper" "git.ar21.de/yolokube/grafana-backuper/pkg/git" "git.ar21.de/yolokube/grafana-backuper/pkg/grafana" "github.com/spf13/cobra" @@ -38,29 +39,15 @@ func backup(ctx context.Context, c *config.Config) error { grafana.WithToken(c.GrafanaToken), ) - project := git.NewProject( - c.GitRepo, - git.WithBasicAuth(c.GitUser, c.GitPass), - git.WithBranch(c.GitBranch), - git.WithOutputWriter(c.Output), - ) - - if err := project.Clone(ctx); err != nil { - return err - } - - if err := project.Checkout(); err != nil { - return err - } - - if err := project.Pull(ctx); err != nil { + project, err := helper.PrepareProject(ctx, c) + if err != nil { return err } var signer git.SignKey if c.GPGKey != "" { signer = git.SignKey{KeyFile: c.GPGKey} - if err := signer.ReadKeyFile(); err != nil { + if err = signer.ReadKeyFile(); err != nil { return err } } @@ -85,7 +72,7 @@ func backup(ctx context.Context, c *config.Config) error { slices.Reverse(versions) - var uncommitedVersion bool + uncommitedVersion := c.ForceCommits for _, version := range versions { var dashboardVersion *grafana.DashboardVersion dashboardVersion, _, err = client.DashboardVersion.Get(ctx, dashboardInfo.UID, version.Version) @@ -93,57 +80,31 @@ func backup(ctx context.Context, c *config.Config) error { return err } - dashboard.Dashboard = dashboardVersion.Data - dashboard.UpdatedBy = dashboardVersion.CreatedBy - dashboard.Updated = dashboardVersion.Created - dashboard.Version = dashboardVersion.Version - - var data []byte - data, err = json.MarshalIndent(grafana.SchemaFromDashboardMeta(dashboard), "", " ") - if err != nil { - return err - } - - commitMsg := fmt.Sprintf( - "%s: Update %s to version %d", - dashboardInfo.Title, - dashboardInfo.UID, - dashboardVersion.ID, + var commitMsg string + commitMsg, err = helper.CommitVersion( + dashboard, + dashboardVersion, + dashboardInfo, + project, + c, + signer, + uncommitedVersion, ) - if dashboardVersion.Message != "" { - commitMsg += fmt.Sprintf(" => %s", dashboardVersion.Message) - } - - commitOpts := []git.CommitOption{ - git.WithAuthor(dashboardVersion.CreatedBy, ""), - git.WithFileContent(data, dashboardInfo.Title, dashboard.FolderTitle), - git.WithSigner(signer), - } - - if c.GitUser != "" { - commitOpts = append(commitOpts, git.WithCommitter(c.GitUser, c.GitEmail)) - } - - commit := project.NewCommit(commitOpts...) - - if commit.Exists(dashboardVersion.DashboardUID, dashboardVersion.ID) && !c.ForceCommits && !uncommitedVersion { - fmt.Fprintf(c.Output, "%s -> already committed\n", commitMsg) + if errors.Is(err, helper.ErrAlreadyCommited) { + fmt.Fprintf(c.Output, "%s -> %v\n", commitMsg, err) continue + } else if err != nil { + return err } uncommitedVersion = true - if err = commit.Create(commitMsg); err != nil { - return err - } fmt.Fprintln(c.Output, commitMsg) } } - if project.HasChanges() { - if err = project.Push(ctx); err != nil { - return err - } + if !project.HasChanges() { + return nil } - return nil + return project.Push(ctx) } diff --git a/internal/helper/helper.go b/internal/helper/helper.go new file mode 100644 index 0000000..37add25 --- /dev/null +++ b/internal/helper/helper.go @@ -0,0 +1,90 @@ +package helper + +import ( + "context" + "encoding/json" + "errors" + "fmt" + + "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") + +func CreateCommitMsg(d *grafana.DashboardVersion, title, uid string) string { + commitMsg := fmt.Sprintf("%s: Update %s to version %d", title, uid, d.ID) + + if d.Message != "" { + commitMsg += fmt.Sprintf(" => %s", d.Message) + } + + return commitMsg +} + +func CommitVersion( + dashboard *grafana.Dashboard, + dashboardVersion *grafana.DashboardVersion, + dashboardInfo *grafana.SearchResult, + project *git.Project, + cfg *config.Config, + signer git.SignKey, + force bool, +) (string, error) { + commitMsg := CreateCommitMsg(dashboardVersion, dashboardInfo.Title, dashboardInfo.UID) + + if !force && project.CommitExists(dashboardVersion.DashboardUID, dashboardVersion.ID) { + return commitMsg, ErrAlreadyCommited + } + + UpdateDashboardInfo(dashboard, dashboardVersion) + + 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), + git.WithSigner(signer), + } + + if cfg.GitUser != "" { + commitOpts = append(commitOpts, git.WithCommitter(cfg.GitUser, cfg.GitEmail)) + } + + commit := project.NewCommit(commitOpts...) + return commitMsg, commit.Create(commitMsg) +} + +func PrepareProject(ctx context.Context, c *config.Config) (*git.Project, error) { + project := git.NewProject( + c.GitRepo, + git.WithBasicAuth(c.GitUser, c.GitPass), + git.WithBranch(c.GitBranch), + git.WithOutputWriter(c.Output), + ) + + if err := project.Clone(ctx); err != nil { + return nil, err + } + + if err := project.Checkout(); err != nil { + return nil, err + } + + if err := project.Pull(ctx); err != nil { + return nil, err + } + + return project, nil +} + +func UpdateDashboardInfo(d *grafana.Dashboard, dv *grafana.DashboardVersion) { + d.Dashboard = dv.Data + d.UpdatedBy = dv.CreatedBy + d.Updated = dv.Created + d.Version = dv.Version +}