From b6d349da8c1a4912b729df3591103aaf30c973ab Mon Sep 17 00:00:00 2001 From: Hidde Beydals Date: Tue, 13 Apr 2021 17:12:36 +0200 Subject: [PATCH] Put potentially destructive reconcile behind flag The behavior introduced during the introduction of go-git-providers was more strict, and has proven pretty quickly to not be useful to all users. Therefore, the reconciliation behavior for repository configuration has been put behind an opt-in flag, so that it does not overwrite people their configs by accident. Signed-off-by: Hidde Beydals --- cmd/flux/bootstrap_github.go | 5 ++ cmd/flux/bootstrap_gitlab.go | 5 ++ docs/cmd/flux_bootstrap_github.md | 1 + docs/cmd/flux_bootstrap_gitlab.md | 1 + internal/bootstrap/bootstrap_provider.go | 66 ++++++++++++++---------- 5 files changed, 52 insertions(+), 26 deletions(-) diff --git a/cmd/flux/bootstrap_github.go b/cmd/flux/bootstrap_github.go index 1dabf2fb..065a9fb6 100644 --- a/cmd/flux/bootstrap_github.go +++ b/cmd/flux/bootstrap_github.go @@ -80,6 +80,7 @@ type githubFlags struct { path flags.SafeRelativePath teams []string readWriteKey bool + reconcile bool } const ( @@ -100,6 +101,7 @@ func init() { bootstrapGitHubCmd.Flags().StringVar(&githubArgs.hostname, "hostname", ghDefaultDomain, "GitHub hostname") bootstrapGitHubCmd.Flags().Var(&githubArgs.path, "path", "path relative to the repository root, when specified the cluster sync will be scoped to this path") bootstrapGitHubCmd.Flags().BoolVar(&githubArgs.readWriteKey, "read-write-key", false, "if true, the deploy key is configured with read/write permissions") + bootstrapGitHubCmd.Flags().BoolVar(&githubArgs.reconcile, "reconcile", false, "if true, the configured options are also reconciled if the repository already exists") bootstrapCmd.AddCommand(bootstrapGitHubCmd) } @@ -235,6 +237,9 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error { if !githubArgs.private { bootstrapOpts = append(bootstrapOpts, bootstrap.WithProviderRepositoryConfig("", "", "public")) } + if githubArgs.reconcile { + bootstrapOpts = append(bootstrapOpts, bootstrap.WithReconcile()) + } // Setup bootstrapper with constructed configs b, err := bootstrap.NewGitProviderBootstrapper(gitClient, providerClient, kubeClient, bootstrapOpts...) diff --git a/cmd/flux/bootstrap_gitlab.go b/cmd/flux/bootstrap_gitlab.go index ec241fa1..a00bbd66 100644 --- a/cmd/flux/bootstrap_gitlab.go +++ b/cmd/flux/bootstrap_gitlab.go @@ -86,6 +86,7 @@ type gitlabFlags struct { path flags.SafeRelativePath teams []string readWriteKey bool + reconcile bool } var gitlabArgs gitlabFlags @@ -100,6 +101,7 @@ func init() { bootstrapGitLabCmd.Flags().StringVar(&gitlabArgs.hostname, "hostname", glDefaultDomain, "GitLab hostname") bootstrapGitLabCmd.Flags().Var(&gitlabArgs.path, "path", "path relative to the repository root, when specified the cluster sync will be scoped to this path") bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.readWriteKey, "read-write-key", false, "if true, the deploy key is configured with read/write permissions") + bootstrapGitLabCmd.Flags().BoolVar(&gitlabArgs.reconcile, "reconcile", false, "if true, the configured options are also reconciled if the repository already exists") bootstrapCmd.AddCommand(bootstrapGitLabCmd) } @@ -251,6 +253,9 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error { if !gitlabArgs.private { bootstrapOpts = append(bootstrapOpts, bootstrap.WithProviderRepositoryConfig("", "", "public")) } + if gitlabArgs.reconcile { + bootstrapOpts = append(bootstrapOpts, bootstrap.WithReconcile()) + } // Setup bootstrapper with constructed configs b, err := bootstrap.NewGitProviderBootstrapper(gitClient, providerClient, kubeClient, bootstrapOpts...) diff --git a/docs/cmd/flux_bootstrap_github.md b/docs/cmd/flux_bootstrap_github.md index ba233cb7..45c39e27 100644 --- a/docs/cmd/flux_bootstrap_github.md +++ b/docs/cmd/flux_bootstrap_github.md @@ -56,6 +56,7 @@ flux bootstrap github [flags] --personal if true, the owner is assumed to be a GitHub user; otherwise an org --private if true, the repository is setup or configured as private (default true) --read-write-key if true, the deploy key is configured with read/write permissions + --reconcile if true, the configured options are also reconciled if the repository already exists --repository string GitHub repository name --team stringArray GitHub team to be given maintainer access ``` diff --git a/docs/cmd/flux_bootstrap_gitlab.md b/docs/cmd/flux_bootstrap_gitlab.md index cdd36545..f2c114df 100644 --- a/docs/cmd/flux_bootstrap_gitlab.md +++ b/docs/cmd/flux_bootstrap_gitlab.md @@ -53,6 +53,7 @@ flux bootstrap gitlab [flags] --personal if true, the owner is assumed to be a GitLab user; otherwise a group --private if true, the repository is setup or configured as private (default true) --read-write-key if true, the deploy key is configured with read/write permissions + --reconcile if true, the configured options are also reconciled if the repository already exists --repository string GitLab repository name --team stringArray GitLab teams to be given maintainer access ``` diff --git a/internal/bootstrap/bootstrap_provider.go b/internal/bootstrap/bootstrap_provider.go index 367b2c72..88c4f241 100644 --- a/internal/bootstrap/bootstrap_provider.go +++ b/internal/bootstrap/bootstrap_provider.go @@ -45,6 +45,8 @@ type GitProviderBootstrapper struct { defaultBranch string visibility string + reconcile bool + teams map[string]string readWriteKey bool @@ -168,6 +170,16 @@ func (o sshHostnameOption) applyGitProvider(b *GitProviderBootstrapper) { b.sshHostname = string(o) } +func WithReconcile() GitProviderOption { + return reconcileOption(true) +} + +type reconcileOption bool + +func (o reconcileOption) applyGitProvider(b *GitProviderBootstrapper) { + b.reconcile = true +} + func (b *GitProviderBootstrapper) ReconcileSyncConfig(ctx context.Context, options sync.Options) error { repo, err := b.getRepository(ctx) if err != nil { @@ -279,18 +291,20 @@ func (b *GitProviderBootstrapper) reconcileOrgRepository(ctx context.Context) (g b.logger.Successf("repository %q created", repoRef.String()) } - // Set default branch before calling Reconcile due to bug described - // above. - repoInfo.DefaultBranch = repo.Get().DefaultBranch var changed bool - if err = retry(1, 2*time.Second, func() (err error) { - repo, changed, err = b.provider.OrgRepositories().Reconcile(ctx, repoRef, repoInfo) - return - }); err != nil { - return nil, fmt.Errorf("failed to reconcile Git repository %q: %w", repoRef.String(), err) - } - if changed { - b.logger.Successf("repository %q reconciled", repoRef.String()) + if b.reconcile { + // Set default branch before calling Reconcile due to bug described + // above. + repoInfo.DefaultBranch = repo.Get().DefaultBranch + if err = retry(1, 2*time.Second, func() (err error) { + repo, changed, err = b.provider.OrgRepositories().Reconcile(ctx, repoRef, repoInfo) + return + }); err != nil { + return nil, fmt.Errorf("failed to reconcile Git repository %q: %w", repoRef.String(), err) + } + if changed { + b.logger.Successf("repository %q reconciled", repoRef.String()) + } } // Build the team access config @@ -343,27 +357,27 @@ func (b *GitProviderBootstrapper) reconcileUserRepository(ctx context.Context) ( // of the available Reconcile methods, and setting e.g. the default // branch correctly. Resort to Create with AutoInit until this has // been resolved. - repo, err = b.provider.UserRepositories().Create(ctx, repoRef, repoInfo, &gitprovider.RepositoryCreateOptions{ - AutoInit: gitprovider.BoolVar(true), - }) + repo, err = b.provider.UserRepositories().Create(ctx, repoRef, repoInfo, &gitprovider.RepositoryCreateOptions{}) if err != nil { return nil, fmt.Errorf("failed to create new Git repository %q: %w", repoRef.String(), err) } b.logger.Successf("repository %q created", repoRef.String()) } - // Set default branch before calling Reconcile due to bug described - // above. - repoInfo.DefaultBranch = repo.Get().DefaultBranch - var changed bool - if err = retry(1, 2*time.Second, func() (err error) { - repo, changed, err = b.provider.UserRepositories().Reconcile(ctx, repoRef, repoInfo) - return - }); err != nil { - return nil, fmt.Errorf("failed to reconcile Git repository %q: %w", repoRef.String(), err) - } - if changed { - b.logger.Successf("repository %q reconciled", repoRef.String()) + if b.reconcile { + // Set default branch before calling Reconcile due to bug described + // above. + repoInfo.DefaultBranch = repo.Get().DefaultBranch + var changed bool + if err = retry(1, 2*time.Second, func() (err error) { + repo, changed, err = b.provider.UserRepositories().Reconcile(ctx, repoRef, repoInfo) + return + }); err != nil { + return nil, fmt.Errorf("failed to reconcile Git repository %q: %w", repoRef.String(), err) + } + if changed { + b.logger.Successf("repository %q reconciled", repoRef.String()) + } } return repo, nil