From b84aa02f1af99ae2f376466e33563d299d5d8f1e Mon Sep 17 00:00:00 2001 From: Somtochi Onyekwere Date: Fri, 27 Oct 2023 17:49:20 +0100 Subject: [PATCH] use error to check if flux is installed Signed-off-by: Somtochi Onyekwere --- cmd/flux/bootstrap_bitbucket_server.go | 19 +++++++++++++------ cmd/flux/bootstrap_git.go | 19 +++++++++++++------ cmd/flux/bootstrap_github.go | 20 ++++++++++++++------ cmd/flux/bootstrap_gitlab.go | 19 +++++++++++++------ cmd/flux/cluster_info.go | 13 +++++-------- cmd/flux/cluster_info_test.go | 19 ++++++++----------- cmd/flux/install.go | 11 ++++++++--- 7 files changed, 74 insertions(+), 46 deletions(-) diff --git a/cmd/flux/bootstrap_bitbucket_server.go b/cmd/flux/bootstrap_bitbucket_server.go index fe174bb99a..8bef858acf 100644 --- a/cmd/flux/bootstrap_bitbucket_server.go +++ b/cmd/flux/bootstrap_bitbucket_server.go @@ -26,6 +26,7 @@ import ( "github.com/fluxcd/pkg/git/gogit" "github.com/manifoldco/promptui" "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/api/errors" "github.com/fluxcd/flux2/v2/internal/flags" "github.com/fluxcd/flux2/v2/internal/utils" @@ -126,17 +127,23 @@ func bootstrapBServerCmdRun(cmd *cobra.Command, args []string) error { } if !bootstrapArgs.force { + installed := true info, err := getFluxClusterInfo(ctx, kubeClient) if err != nil { - return fmt.Errorf("cluster info unavailable: %w", err) + if !errors.IsNotFound(err) { + return fmt.Errorf("cluster info unavailable: %w", err) + } + installed = false } - err = confirmFluxInstallOverride(info) - if err != nil { - if err == promptui.ErrAbort { - return fmt.Errorf("bootstrap cancelled") + if installed { + err = confirmFluxInstallOverride(info) + if err != nil { + if err == promptui.ErrAbort { + return fmt.Errorf("bootstrap cancelled") + } + return err } - return err } } diff --git a/cmd/flux/bootstrap_git.go b/cmd/flux/bootstrap_git.go index db2c746dee..ed9e248db2 100644 --- a/cmd/flux/bootstrap_git.go +++ b/cmd/flux/bootstrap_git.go @@ -27,6 +27,7 @@ import ( "github.com/manifoldco/promptui" "github.com/spf13/cobra" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" "github.com/fluxcd/flux2/v2/internal/flags" "github.com/fluxcd/flux2/v2/internal/utils" @@ -147,17 +148,23 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error { } if !bootstrapArgs.force { + installed := true info, err := getFluxClusterInfo(ctx, kubeClient) if err != nil { - return fmt.Errorf("cluster info unavailable: %w", err) + if !errors.IsNotFound(err) { + return fmt.Errorf("cluster info unavailable: %w", err) + } + installed = false } - err = confirmFluxInstallOverride(info) - if err != nil { - if err == promptui.ErrAbort { - return fmt.Errorf("bootstrap cancelled") + if installed { + err = confirmFluxInstallOverride(info) + if err != nil { + if err == promptui.ErrAbort { + return fmt.Errorf("bootstrap cancelled") + } + return err } - return err } } diff --git a/cmd/flux/bootstrap_github.go b/cmd/flux/bootstrap_github.go index d468729854..ff6b3cb46f 100644 --- a/cmd/flux/bootstrap_github.go +++ b/cmd/flux/bootstrap_github.go @@ -26,6 +26,7 @@ import ( "github.com/fluxcd/pkg/git/gogit" "github.com/manifoldco/promptui" "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/api/errors" "github.com/fluxcd/flux2/v2/internal/flags" "github.com/fluxcd/flux2/v2/internal/utils" @@ -130,16 +131,23 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error { } if !bootstrapArgs.force { + installed := true info, err := getFluxClusterInfo(ctx, kubeClient) if err != nil { - return fmt.Errorf("cluster info unavailable: %w", err) + if !errors.IsNotFound(err) { + return fmt.Errorf("cluster info unavailable: %w", err) + } + installed = false } - err = confirmFluxInstallOverride(info) - if err != nil { - if err == promptui.ErrAbort { - return fmt.Errorf("bootstrap cancelled") + + if installed { + err = confirmFluxInstallOverride(info) + if err != nil { + if err == promptui.ErrAbort { + return fmt.Errorf("bootstrap cancelled") + } + return err } - return err } } diff --git a/cmd/flux/bootstrap_gitlab.go b/cmd/flux/bootstrap_gitlab.go index 0f860b61ec..78621965dd 100644 --- a/cmd/flux/bootstrap_gitlab.go +++ b/cmd/flux/bootstrap_gitlab.go @@ -28,6 +28,7 @@ import ( "github.com/fluxcd/pkg/git/gogit" "github.com/manifoldco/promptui" "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/api/errors" "github.com/fluxcd/flux2/v2/internal/flags" "github.com/fluxcd/flux2/v2/internal/utils" @@ -147,17 +148,23 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error { } if !bootstrapArgs.force { + installed := true info, err := getFluxClusterInfo(ctx, kubeClient) if err != nil { - return fmt.Errorf("cluster info unavailable: %w", err) + if !errors.IsNotFound(err) { + return fmt.Errorf("cluster info unavailable: %w", err) + } + installed = false } - err = confirmFluxInstallOverride(info) - if err != nil { - if err == promptui.ErrAbort { - return fmt.Errorf("bootstrap cancelled") + if installed { + err = confirmFluxInstallOverride(info) + if err != nil { + if err == promptui.ErrAbort { + return fmt.Errorf("bootstrap cancelled") + } + return err } - return err } } diff --git a/cmd/flux/cluster_info.go b/cmd/flux/cluster_info.go index 7cd91ef75d..6e76fa53f3 100644 --- a/cmd/flux/cluster_info.go +++ b/cmd/flux/cluster_info.go @@ -22,7 +22,6 @@ import ( "github.com/manifoldco/promptui" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -39,8 +38,6 @@ var bootstrapLabels = []string{ // fluxClusterInfo contains information about an existing flux installation on a cluster. type fluxClusterInfo struct { - // installed indicates that Flux is installed on the cluster. - installed bool // bootstrapped indicates that Flux was installed using the `flux bootstrap` command. bootstrapped bool // managedBy is the name of the tool being used to manage the installation of Flux. @@ -54,6 +51,8 @@ type fluxClusterInfo struct { // // This function retrieves the GitRepository CRD from the cluster and checks it // for a set of labels used to determine the Flux version and how Flux was installed. +// It returns the NotFound error from the underlying library if it was unable to find +// the GitRepository CRD and this can be used to check if Flux is installed. func getFluxClusterInfo(ctx context.Context, c client.Client) (fluxClusterInfo, error) { var info fluxClusterInfo crdMetadata := &metav1.PartialObjectMetadata{ @@ -66,13 +65,9 @@ func getFluxClusterInfo(ctx context.Context, c client.Client) (fluxClusterInfo, }, } if err := c.Get(ctx, client.ObjectKeyFromObject(crdMetadata), crdMetadata); err != nil { - if errors.IsNotFound(err) { - return info, nil - } return info, err } - info.installed = true info.version = crdMetadata.Labels["app.kubernetes.io/version"] var present bool @@ -83,6 +78,8 @@ func getFluxClusterInfo(ctx context.Context, c client.Client) (fluxClusterInfo, info.bootstrapped = true } + // the `app.kubernetes.io` label is not set by flux but might be set by other + // tools used to install Flux e.g Helm. if manager, ok := crdMetadata.Labels["app.kubernetes.io/managed-by"]; ok { info.managedBy = manager } @@ -95,7 +92,7 @@ func getFluxClusterInfo(ctx context.Context, c client.Client) (fluxClusterInfo, func confirmFluxInstallOverride(info fluxClusterInfo) error { // no need to display prompt if flux is not installed or installation is // managed by Flux - if !info.installed || info.managedBy == "" || info.managedBy == "flux" { + if info.managedBy == "" || info.managedBy == "flux" { return nil } diff --git a/cmd/flux/cluster_info_test.go b/cmd/flux/cluster_info_test.go index d4c7ab27ed..550ab16591 100644 --- a/cmd/flux/cluster_info_test.go +++ b/cmd/flux/cluster_info_test.go @@ -24,6 +24,7 @@ import ( . "github.com/onsi/gomega" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client/fake" @@ -47,7 +48,8 @@ func Test_getFluxClusterInfo(t *testing.T) { wantInfo fluxClusterInfo }{ { - name: "no git repository CRD present", + name: "no git repository CRD present", + wantErr: true, }, { name: "CRD with kustomize-controller labels", @@ -59,7 +61,6 @@ func Test_getFluxClusterInfo(t *testing.T) { wantInfo: fluxClusterInfo{ version: "v2.1.0", bootstrapped: true, - installed: true, }, }, { @@ -73,7 +74,6 @@ func Test_getFluxClusterInfo(t *testing.T) { wantInfo: fluxClusterInfo{ version: "v2.1.0", bootstrapped: true, - installed: true, managedBy: "flux", }, }, @@ -86,15 +86,12 @@ func Test_getFluxClusterInfo(t *testing.T) { wantInfo: fluxClusterInfo{ version: "v2.1.0", managedBy: "helm", - installed: true, }, }, { - name: "CRD with no labels", - labels: map[string]string{}, - wantInfo: fluxClusterInfo{ - installed: true, - }, + name: "CRD with no labels", + labels: map[string]string{}, + wantInfo: fluxClusterInfo{}, }, { name: "CRD with only version label", @@ -102,8 +99,7 @@ func Test_getFluxClusterInfo(t *testing.T) { "app.kubernetes.io/version": "v2.1.0", }, wantInfo: fluxClusterInfo{ - version: "v2.1.0", - installed: true, + version: "v2.1.0", }, }, } @@ -123,6 +119,7 @@ func Test_getFluxClusterInfo(t *testing.T) { info, err := getFluxClusterInfo(context.Background(), client) if tt.wantErr { g.Expect(err).To(HaveOccurred()) + g.Expect(errors.IsNotFound(err)).To(BeTrue()) } else { g.Expect(err).To(Not(HaveOccurred())) } diff --git a/cmd/flux/install.go b/cmd/flux/install.go index 8152a553c0..795cc1aad7 100644 --- a/cmd/flux/install.go +++ b/cmd/flux/install.go @@ -25,6 +25,7 @@ import ( "github.com/manifoldco/promptui" "github.com/spf13/cobra" + "k8s.io/apimachinery/pkg/api/errors" "github.com/fluxcd/flux2/v2/internal/flags" "github.com/fluxcd/flux2/v2/internal/utils" @@ -191,17 +192,21 @@ func installCmdRun(cmd *cobra.Command, args []string) error { return err } + installed := true info, err := getFluxClusterInfo(ctx, kubeClient) if err != nil { - return fmt.Errorf("cluster info unavailable: %w", err) + if !errors.IsNotFound(err) { + return fmt.Errorf("cluster info unavailable: %w", err) + } + installed = false } - if info.installed && info.bootstrapped { + if info.bootstrapped { return fmt.Errorf("this cluster has already been bootstrapped with Flux %s! Please use 'flux bootstrap' to upgrade", info.version) } - if !installArgs.force { + if installed && !installArgs.force { err := confirmFluxInstallOverride(info) if err != nil { if err == promptui.ErrAbort {