From 2409dc7bd42bc3b3c362f9384c1518b8a5b359f2 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Sun, 19 Nov 2023 14:48:49 +0200 Subject: [PATCH 01/32] add controllers configurations with acceptance and unit tests --- cmd/gitops/app/bootstrap/cmd.go | 11 + .../app/bootstrap/cmd_acceptance_test.go | 44 +++- pkg/bootstrap/bootstrap.go | 1 + pkg/bootstrap/steps/admin_password.go | 1 - pkg/bootstrap/steps/ask_bootstrap_flux.go | 9 +- .../steps/ask_bootstrap_flux_test.go | 2 +- pkg/bootstrap/steps/capi.go | 81 ++++++ pkg/bootstrap/steps/capi_test.go | 132 ++++++++++ pkg/bootstrap/steps/common_tests.go | 77 ++++++ pkg/bootstrap/steps/config.go | 13 + pkg/bootstrap/steps/extra_controllers.go | 101 ++++++++ pkg/bootstrap/steps/extra_controllers_test.go | 103 ++++++++ pkg/bootstrap/steps/install_oidc.go | 2 +- pkg/bootstrap/steps/oidc.go | 2 +- pkg/bootstrap/steps/policy_agent.go | 185 ++++++++++++++ pkg/bootstrap/steps/policy_agent_test.go | 235 ++++++++++++++++++ pkg/bootstrap/steps/step.go | 10 +- pkg/bootstrap/steps/terraform.go | 96 +++++++ pkg/bootstrap/steps/terraform_test.go | 188 ++++++++++++++ pkg/bootstrap/utils/flux.go | 33 ++- 20 files changed, 1298 insertions(+), 28 deletions(-) create mode 100644 pkg/bootstrap/steps/capi.go create mode 100644 pkg/bootstrap/steps/capi_test.go create mode 100644 pkg/bootstrap/steps/extra_controllers.go create mode 100644 pkg/bootstrap/steps/extra_controllers_test.go create mode 100644 pkg/bootstrap/steps/policy_agent.go create mode 100644 pkg/bootstrap/steps/policy_agent_test.go create mode 100644 pkg/bootstrap/steps/terraform.go create mode 100644 pkg/bootstrap/steps/terraform_test.go diff --git a/cmd/gitops/app/bootstrap/cmd.go b/cmd/gitops/app/bootstrap/cmd.go index 23d6ce40da..6a8dafad39 100644 --- a/cmd/gitops/app/bootstrap/cmd.go +++ b/cmd/gitops/app/bootstrap/cmd.go @@ -38,6 +38,12 @@ gitops bootstrap --version= --password= --discovery-url # Start WGE installation with OIDC and flux bootstrap with ssh gitops bootstrap --version= --password= --discovery-url= --client-id= --private-key-path= --private-key-password= --branch= --repo-path= --repo-url=ssh:// --client-secret= -s + +# Start WGE installation with extra controller like policy agent +gitops bootstrap --extra-controllers policy-agent + +# Start WGE installation with more than one extra controller +gitops bootstrap --extra-controllers policy-agent --extra-controllers capi --extra-controllers tf-controller ` ) @@ -69,6 +75,9 @@ type bootstrapFlags struct { // modes flags silent bool + + // extra controllers + extraControllers []string } var flags bootstrapFlags @@ -85,6 +94,7 @@ func Command(opts *config.Options) *cobra.Command { cmd.Flags().StringVarP(&flags.domainType, "domain-type", "t", "", "dashboard domain type: could be 'localhost' or 'externaldns'") cmd.Flags().StringVarP(&flags.domain, "domain", "d", "", "the domain to access the dashboard in case of using externaldns") cmd.Flags().StringVarP(&flags.version, "version", "v", "", "version of Weave GitOps Enterprise (should be from the latest 3 versions)") + cmd.Flags().StringArrayVarP(&flags.extraControllers, "extra-controllers", "", []string{}, "extra controllers to be installed from (none, policy-agent, tf-controller, capi)") cmd.PersistentFlags().BoolVarP(&flags.silent, "bootstrap-flux", "s", false, "always choose yes for interactive questions") cmd.PersistentFlags().StringVarP(&flags.gitUsername, "git-username", "", "", "git username used in https authentication type") cmd.PersistentFlags().StringVarP(&flags.gitPassword, "git-password", "", "", "git password/token used in https authentication type") @@ -123,6 +133,7 @@ func getBootstrapCmdRun(opts *config.Options) func(*cobra.Command, []string) err ). WithOIDCConfig(flags.discoveryURL, flags.clientID, flags.clientSecret, true). WithSilentFlag(flags.silent). + WithExtraControllers(flags.extraControllers). Build() if err != nil { diff --git a/cmd/gitops/app/bootstrap/cmd_acceptance_test.go b/cmd/gitops/app/bootstrap/cmd_acceptance_test.go index 45a48a13e3..ac2cda48bf 100644 --- a/cmd/gitops/app/bootstrap/cmd_acceptance_test.go +++ b/cmd/gitops/app/bootstrap/cmd_acceptance_test.go @@ -75,8 +75,6 @@ func TestBootstrapCmd(t *testing.T) { privateKeyFile := os.Getenv("GIT_PRIVATEKEY_PATH") g.Expect(privateKeyFile).NotTo(BeEmpty()) - privateKeyPassword := os.Getenv("GIT_PRIVATEKEY_PASSWORD") - repoURLSSH := os.Getenv("GIT_REPO_URL_SSH") g.Expect(repoURLSSH).NotTo(BeEmpty()) repoURLHTTPS := os.Getenv("GIT_REPO_URL_HTTPS") @@ -89,6 +87,10 @@ func TestBootstrapCmd(t *testing.T) { g.Expect(gitBranch).NotTo(BeEmpty()) gitRepoPath := os.Getenv("GIT_REPO_PATH") g.Expect(gitRepoPath).NotTo(BeEmpty()) + privateKeyPassword := os.Getenv("GIT_PRIVATEKEY_PASSWORD") + g.Expect(privateKeyPassword).NotTo(BeEmpty()) + oidcClientSecret := os.Getenv("OIDC_CLIENT_SECRET") + g.Expect(oidcClientSecret).NotTo(BeEmpty()) privateKeyFlag := fmt.Sprintf("--private-key=%s", privateKeyFile) privateKeyPasswordFlag := fmt.Sprintf("--private-key-password=%s", privateKeyPassword) @@ -103,8 +105,6 @@ func TestBootstrapCmd(t *testing.T) { gitBranchFlag := fmt.Sprintf("--branch=%s", gitBranch) gitRepoPathFlag := fmt.Sprintf("--repo-path=%s", gitRepoPath) - oidcClientSecret := os.Getenv("OIDC_CLIENT_SECRET") - g.Expect(oidcClientSecret).NotTo(BeEmpty()) oidcClientSecretFlag := fmt.Sprintf("--client-secret=%s", oidcClientSecret) _ = k8sClient.Create(context.Background(), &fluxSystemNamespace) @@ -119,13 +119,15 @@ func TestBootstrapCmd(t *testing.T) { { name: "journey flux exists: should bootstrap with valid arguments", flags: []string{kubeconfigFlag, - "--version=0.35.0", + "--version=0.36.0", privateKeyFlag, privateKeyPasswordFlag, "--password=admin123", "--domain-type=localhost", "--discovery-url=https://dex-01.wge.dev.weave.works/.well-known/openid-configuration", "--client-id=weave-gitops-enterprise", oidcClientSecretFlag, + "--extra-controllers=none", + "-s", }, setup: func(t *testing.T) { bootstrapFluxSsh(g, kubeconfigFlag) @@ -141,8 +143,7 @@ func TestBootstrapCmd(t *testing.T) { { name: "journey flux does not exist: should bootstrap with valid arguments", flags: []string{kubeconfigFlag, - "--version=0.35.0", - privateKeyFlag, privateKeyPasswordFlag, + "--version=0.36.0", "--password=admin123", "--domain-type=localhost", "--domain=localhost", "--discovery-url=https://dex-01.wge.dev.weave.works/.well-known/openid-configuration", @@ -150,6 +151,7 @@ func TestBootstrapCmd(t *testing.T) { gitUsernameFlag, gitPasswordFlag, gitBranchFlag, gitRepoPathFlag, repoHTTPSURLFlag, oidcClientSecretFlag, "-s", + "--extra-controllers=none", }, setup: func(t *testing.T) { createEntitlements(t, testLog) @@ -161,6 +163,31 @@ func TestBootstrapCmd(t *testing.T) { }, expectedErrorStr: "", }, + { + name: "journey bootstrap with extra controllers policy-agent capi and tf-controller", + flags: []string{kubeconfigFlag, + "--version=0.36.0", + privateKeyFlag, privateKeyPasswordFlag, + "--password=admin123", + "--domain-type=localhost", + "--discovery-url=https://dex-01.wge.dev.weave.works/.well-known/openid-configuration", + "--client-id=weave-gitops-enterprise", + oidcClientSecretFlag, "-s", + "--extra-controllers=policy-agent", + "--extra-controllers=capi", + "--extra-controllers=tf-controller", + }, + setup: func(t *testing.T) { + bootstrapFluxSsh(g, kubeconfigFlag) + createEntitlements(t, testLog) + }, + reset: func(t *testing.T) { + deleteEntitlements(t, testLog) + deleteClusterUser(t, testLog) + uninstallFlux(g, kubeconfigFlag) + }, + expectedErrorStr: "", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -202,8 +229,9 @@ func bootstrapFluxSsh(g *WithT, kubeconfigFlag string) { fmt.Println(privateKeyFile) privateKeyPassword := os.Getenv("GIT_PRIVATEKEY_PASSWORD") + g.Expect(privateKeyFile).NotTo(BeEmpty()) - args := []string{"bootstrap", "git", kubeconfigFlag, "-s", fmt.Sprintf("--url=%s", repoUrl), fmt.Sprintf("--password=%s", privateKeyPassword), fmt.Sprintf("--private-key-file=%s", privateKeyFile), "--path=clusters/management"} + args := []string{"bootstrap", "git", kubeconfigFlag, "-s", fmt.Sprintf("--url=%s", repoUrl), fmt.Sprintf("--private-key-file=%s", privateKeyFile), fmt.Sprintf("--password=%s", privateKeyPassword), "--path=clusters/management"} fmt.Println(args) s, err := runner.Run("flux", args...) diff --git a/pkg/bootstrap/bootstrap.go b/pkg/bootstrap/bootstrap.go index 10a8be05ec..bb736d95db 100644 --- a/pkg/bootstrap/bootstrap.go +++ b/pkg/bootstrap/bootstrap.go @@ -28,6 +28,7 @@ func Bootstrap(config steps.Config) error { steps.NewInstallOIDCStep(config), steps.NewOIDCConfigStep(config), steps.CheckUIDomainStep, + steps.NewInstallExtraControllers(config), } for _, step := range steps { diff --git a/pkg/bootstrap/steps/admin_password.go b/pkg/bootstrap/steps/admin_password.go index e734017b85..0ac2eaf129 100644 --- a/pkg/bootstrap/steps/admin_password.go +++ b/pkg/bootstrap/steps/admin_password.go @@ -19,7 +19,6 @@ const ( const ( adminSecretName = "cluster-user-auth" - confirmYes = "y" defaultAdminUsername = "wego-admin" ) diff --git a/pkg/bootstrap/steps/ask_bootstrap_flux.go b/pkg/bootstrap/steps/ask_bootstrap_flux.go index dc89598d07..fe05b50661 100644 --- a/pkg/bootstrap/steps/ask_bootstrap_flux.go +++ b/pkg/bootstrap/steps/ask_bootstrap_flux.go @@ -8,10 +8,11 @@ const ( var ( bootstrapFLuxQuestion = StepInput{ - Name: inBootstrapFlux, - Type: confirmInput, - Msg: bootstrapFluxMsg, - Enabled: canAskForFluxBootstrap, + Name: inBootstrapFlux, + Type: confirmInput, + Msg: bootstrapFluxMsg, + Enabled: canAskForFluxBootstrap, + DefaultValue: confirmYes, } ) diff --git a/pkg/bootstrap/steps/ask_bootstrap_flux_test.go b/pkg/bootstrap/steps/ask_bootstrap_flux_test.go index 0c1bd480e0..df6f52a982 100644 --- a/pkg/bootstrap/steps/ask_bootstrap_flux_test.go +++ b/pkg/bootstrap/steps/ask_bootstrap_flux_test.go @@ -28,7 +28,7 @@ func TestAskBootstrapFlux(t *testing.T) { input: []StepInput{ { Name: inBootstrapFlux, - Value: "n", + Value: confirmNo, }, }, config: &Config{ diff --git a/pkg/bootstrap/steps/capi.go b/pkg/bootstrap/steps/capi.go new file mode 100644 index 0000000000..685096ea96 --- /dev/null +++ b/pkg/bootstrap/steps/capi.go @@ -0,0 +1,81 @@ +package steps + +import ( + "encoding/json" + "fmt" + + "github.com/weaveworks/weave-gitops-enterprise/pkg/bootstrap/utils" +) + +const ( + capiInstallInfoMsg = "installing Capi Controller ..." + capiInstallConfirmMsg = "Capi Controller is installed successfully" +) + +const ( + capiCommitMsg = "Add Capi Controller" + defaultNamespace = "default" +) + +// NewInstallCapiControllerStep ask for continue installing OIDC +func NewInstallCapiControllerStep(config Config) BootstrapStep { + return BootstrapStep{ + Name: "install Capi Controller", + Step: installCapi, + } +} + +// installCapi start installing CAPI controller +func installCapi(input []StepInput, c *Config) ([]StepOutput, error) { + c.Logger.Actionf(capiInstallInfoMsg) + + capiValues := map[string]interface{}{ + "repositoryURL": c.RepoURL, + "repositoryPath": fmt.Sprintf("%s/clusters", c.RepoPath), + "repositoryClustersPath": c.RepoPath, + "baseBranch": c.Branch, + "templates": map[string]interface{}{ + "namespace": defaultNamespace, + }, + "clusters": map[string]interface{}{ + "namespace": defaultNamespace, + }, + } + + // enable capi in wge chart + valuesBytes, err := utils.GetHelmReleaseValues(c.KubernetesClient, WgeHelmReleaseName, WGEDefaultNamespace) + if err != nil { + return []StepOutput{}, err + } + var wgeValues valuesFile + + err = json.Unmarshal(valuesBytes, &wgeValues) + if err != nil { + return []StepOutput{}, err + } + + wgeValues.Global.CapiEnabled = true + wgeValues.Config.CAPI = capiValues + + wgeHelmRelease, err := constructWGEhelmRelease(wgeValues, c.WGEVersion) + if err != nil { + return []StepOutput{}, err + } + c.Logger.Actionf("rendered WGE HelmRelease file") + + c.Logger.Actionf("updating HelmRelease file") + helmreleaseFile := fileContent{ + Name: wgeHelmReleaseFileName, + Content: wgeHelmRelease, + CommitMsg: capiCommitMsg, + } + + c.Logger.Successf(capiInstallConfirmMsg) + return []StepOutput{ + { + Name: wgeHelmReleaseFileName, + Type: typeFile, + Value: helmreleaseFile, + }, + }, nil +} diff --git a/pkg/bootstrap/steps/capi_test.go b/pkg/bootstrap/steps/capi_test.go new file mode 100644 index 0000000000..6c5bfc6efa --- /dev/null +++ b/pkg/bootstrap/steps/capi_test.go @@ -0,0 +1,132 @@ +package steps + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +const ( + wgeHRFakeFileCapiController = `apiVersion: helm.toolkit.fluxcd.io/v2beta1 +kind: HelmRelease +metadata: + creationTimestamp: null + name: weave-gitops-enterprise + namespace: flux-system +spec: + chart: + spec: + chart: mccp + reconcileStrategy: ChartVersion + sourceRef: + kind: HelmRepository + name: weave-gitops-enterprise-charts + namespace: flux-system + version: 1.0.0 + install: + crds: CreateReplace + interval: 1h0m0s + upgrade: + crds: CreateReplace + values: + cluster-controller: + controllerManager: + manager: + image: + repository: docker.io/weaveworks/cluster-controller + tag: v1.5.2 + enabled: true + fullnameOverride: cluster + config: + capi: + baseBranch: "" + clusters: + namespace: default + repositoryClustersPath: "" + repositoryPath: /clusters + repositoryURL: "" + templates: + namespace: default + enablePipelines: true + gitopssets-controller: + controllerManager: + manager: + args: + - --health-probe-bind-address=:8081 + - --metrics-bind-address=127.0.0.1:8080 + - --leader-elect + - --enabled-generators=GitRepository,Cluster,PullRequests,List,APIClient,Matrix,Config + enabled: true + global: + capiEnabled: true + tls: + enabled: false +status: {} +` +) + +func TestInstallCapi(t *testing.T) { + tests := []struct { + name string + input []StepInput + output []StepOutput + err bool + }{ + { + name: "install capi controller", + output: []StepOutput{ + { + Name: wgeHelmReleaseFileName, + Type: typeFile, + Value: fileContent{ + Name: wgeHelmReleaseFileName, + Content: wgeHRFakeFileCapiController, + CommitMsg: capiCommitMsg, + }, + }, + }, + err: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + testConfig := Config{ + Silent: true, + WGEVersion: "1.0.0", + DomainType: domainTypeLocalhost, + } + wgeObject, err := createWGEHelmReleaseFakeObject("1.0.0") + if err != nil { + t.Fatalf("error create wge object: %v", err) + } + + config := makeTestConfig(t, testConfig, &wgeObject) + + out, err := installCapi(tt.input, &config) + if err != nil { + if tt.err { + return + } + t.Fatalf("error install capi controller: %v", err) + } + + for i, item := range out { + assert.Equal(t, item.Name, tt.output[i].Name, "wrong name") + assert.Equal(t, item.Type, tt.output[i].Type, "wrong type") + inFileContent, ok := tt.output[i].Value.(fileContent) + if !ok { + t.Fatalf("error install capi controller: %v", err) + } + outFileContent, ok := item.Value.(fileContent) + if !ok { + t.Fatalf("error install capi controller: %v", err) + } + assert.Equal(t, outFileContent.CommitMsg, inFileContent.CommitMsg, "wrong commit msg") + assert.Equal(t, outFileContent.Name, inFileContent.Name, "wrong filename") + assert.Equal(t, outFileContent.Content, inFileContent.Content, "wrong content") + } + }) + } + +} diff --git a/pkg/bootstrap/steps/common_tests.go b/pkg/bootstrap/steps/common_tests.go index d7a6ed18a0..0624aaaa63 100644 --- a/pkg/bootstrap/steps/common_tests.go +++ b/pkg/bootstrap/steps/common_tests.go @@ -1,9 +1,16 @@ package steps import ( + "encoding/json" + "fmt" "testing" + "time" + helmv2 "github.com/fluxcd/helm-controller/api/v2beta1" + sourcev1beta2 "github.com/fluxcd/source-controller/api/v1beta2" "github.com/weaveworks/weave-gitops-enterprise/test/utils" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -34,5 +41,75 @@ func makeTestConfig(t *testing.T, config Config, objects ...runtime.Object) Conf ClientSecret: config.ClientSecret, RedirectURL: config.RedirectURL, PromptedForDiscoveryURL: config.PromptedForDiscoveryURL, + Silent: config.Silent, + ExtraControllers: config.ExtraControllers, } } + +func createWGEHelmReleaseFakeObject(version string) (helmv2.HelmRelease, error) { + values := valuesFile{ + TLS: map[string]interface{}{ + "enabled": false, + }, + GitOpsSets: map[string]interface{}{ + "enabled": true, + "controllerManager": map[string]interface{}{ + "manager": map[string]interface{}{ + "args": []string{ + fmt.Sprintf("--health-probe-bind-address=%s", gitopssetsHealthBindAddress), + fmt.Sprintf("--metrics-bind-address=%s", gitopssetsBindAddress), + "--leader-elect", + fmt.Sprintf("--enabled-generators=%s", gitopssetsEnabledGenerators), + }, + }, + }, + }, + EnablePipelines: true, + ClusterController: clusterController{ + Enabled: true, + FullNameOverride: clusterControllerFullOverrideName, + ControllerManager: clusterControllerManager{ + Manager: clusterControllerManagerManager{ + Image: clusterControllerImage{ + Repository: clusterControllerImageName, + Tag: clusterControllerImageTag, + }, + }, + }}, + } + + valuesBytes, err := json.Marshal(values) + if err != nil { + return helmv2.HelmRelease{}, err + } + + wgeHRObject := helmv2.HelmRelease{ + ObjectMeta: v1.ObjectMeta{ + Name: WgeHelmReleaseName, + Namespace: WGEDefaultNamespace, + }, Spec: helmv2.HelmReleaseSpec{ + Chart: helmv2.HelmChartTemplate{ + Spec: helmv2.HelmChartTemplateSpec{ + Chart: wgeChartName, + ReconcileStrategy: sourcev1beta2.ReconcileStrategyChartVersion, + SourceRef: helmv2.CrossNamespaceObjectReference{ + Name: wgeHelmRepositoryName, + Namespace: WGEDefaultNamespace, + }, + Version: version, + }, + }, + Install: &helmv2.Install{ + CRDs: helmv2.CreateReplace, + }, + Upgrade: &helmv2.Upgrade{ + CRDs: helmv2.CreateReplace, + }, + Interval: v1.Duration{ + Duration: time.Hour, + }, + Values: &apiextensionsv1.JSON{Raw: valuesBytes}, + }, + } + return wgeHRObject, nil +} diff --git a/pkg/bootstrap/steps/config.go b/pkg/bootstrap/steps/config.go index 2dbce9219f..9c47f9429b 100644 --- a/pkg/bootstrap/steps/config.go +++ b/pkg/bootstrap/steps/config.go @@ -16,6 +16,8 @@ const ( const ( defaultAdminPassword = "password" + confirmYes = "y" + confirmNo = "n" ) // git schemes @@ -44,6 +46,8 @@ const ( inGitUserName = "username" inGitPassword = "gitPassowrd" inBootstrapFlux = "bootstrapFlux" + inExtraControllers = "extraControllers" + inEnableAdmission = "enableAdmission" ) // input/output types @@ -78,6 +82,7 @@ type ConfigBuilder struct { clientID string clientSecret string PromptedForDiscoveryURL bool + extraControllers []string } func NewConfigBuilder() *ConfigBuilder { @@ -150,6 +155,11 @@ func (c *ConfigBuilder) WithSilentFlag(silent bool) *ConfigBuilder { return c } +func (c *ConfigBuilder) WithExtraControllers(extraControllers []string) *ConfigBuilder { + c.extraControllers = extraControllers + return c +} + // Config is the configuration struct to user for WGE installation. It includes // configuration values as well as other required structs like clients type Config struct { @@ -186,6 +196,8 @@ type Config struct { ClientSecret string RedirectURL string PromptedForDiscoveryURL bool + + ExtraControllers []string } // Builds creates a valid config so boostrap could be executed. It uses values introduced @@ -244,6 +256,7 @@ func (cb *ConfigBuilder) Build() (Config, error) { ClientID: cb.clientID, ClientSecret: cb.clientSecret, PromptedForDiscoveryURL: cb.PromptedForDiscoveryURL, + ExtraControllers: cb.extraControllers, }, nil } diff --git a/pkg/bootstrap/steps/extra_controllers.go b/pkg/bootstrap/steps/extra_controllers.go new file mode 100644 index 0000000000..7ab3630505 --- /dev/null +++ b/pkg/bootstrap/steps/extra_controllers.go @@ -0,0 +1,101 @@ +package steps + +import ( + "fmt" +) + +const ( + extraControllersMsg = "do you want to install extra controllers from the following on your cluster" +) + +const ( + defaultController = "none" + policyAgentController = "policy-agent" + tfController = "tf-controller" + capiController = "capi" + allControllers = "all of above" +) + +// NewInstallExtraControllers start installing extra controllers +func NewInstallExtraControllers(config Config) BootstrapStep { + inputs := []StepInput{} + controllersValues := []string{ + defaultController, + policyAgentController, + tfController, + capiController, + allControllers, + } + + installExtraControllersStep := StepInput{ + Name: inExtraControllers, + Type: multiSelectionChoice, + Msg: extraControllersMsg, + Values: controllersValues, + DefaultValue: controllersValues[0], + } + + if len(config.ExtraControllers) < 1 { + inputs = append(inputs, installExtraControllersStep) + } + + return BootstrapStep{ + Name: "install extra controllers", + Input: inputs, + Step: installExtraControllers, + } +} + +func installExtraControllers(input []StepInput, c *Config) ([]StepOutput, error) { + for _, param := range input { + if param.Name == inExtraControllers { + extraControllers, ok := param.Value.(string) + if ok { + c.ExtraControllers = append(c.ExtraControllers, extraControllers) + } + } + } + for _, controller := range c.ExtraControllers { + switch controller { + case policyAgentController: + agentStep := NewInstallPolicyAgentStep(*c) + _, err := agentStep.Execute(c) + if err != nil { + return []StepOutput{}, fmt.Errorf("can't install policy agent: %v", err) + } + case tfController: + tfControllerStep := NewInstallTFControllerStep(*c) + _, err := tfControllerStep.Execute(c) + if err != nil { + return []StepOutput{}, fmt.Errorf("can't install tf controller: %v", err) + } + case capiController: + capiStep := NewInstallCapiControllerStep(*c) + _, err := capiStep.Execute(c) + if err != nil { + return []StepOutput{}, fmt.Errorf("can't install capi controller: %v", err) + } + case allControllers: + agentStep := NewInstallPolicyAgentStep(*c) + _, err := agentStep.Execute(c) + if err != nil { + return []StepOutput{}, fmt.Errorf("can't install policy agent: %v", err) + } + tfControllerStep := NewInstallTFControllerStep(*c) + _, err = tfControllerStep.Execute(c) + if err != nil { + return []StepOutput{}, fmt.Errorf("can't install tf controller: %v", err) + } + capiStep := NewInstallCapiControllerStep(*c) + _, err = capiStep.Execute(c) + if err != nil { + return []StepOutput{}, fmt.Errorf("can't install capi controller: %v", err) + } + default: + c.Logger.Successf("skipping installing controllers, selected: %s", controller) + return []StepOutput{}, nil + } + } + + return []StepOutput{}, nil +} diff --git a/pkg/bootstrap/steps/extra_controllers_test.go b/pkg/bootstrap/steps/extra_controllers_test.go new file mode 100644 index 0000000000..86f3909f4b --- /dev/null +++ b/pkg/bootstrap/steps/extra_controllers_test.go @@ -0,0 +1,103 @@ +package steps + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/assert" +) + +func TestNewInstallExtraControllers(t *testing.T) { + tests := []struct { + name string + config Config + want BootstrapStep + }{ + { + name: "return bootstrap step with inputs in case provided by user", + config: Config{}, + want: BootstrapStep{ + Name: "install extra controllers", + Input: []StepInput{ + { + Name: inExtraControllers, + Type: multiSelectionChoice, + Msg: extraControllersMsg, + Values: []string{ + defaultController, + policyAgentController, + tfController, + capiController, + allControllers, + }, + DefaultValue: defaultController, + }, + }, + Step: installExtraControllers, + }, + }, + { + name: "return bootstrap step with empty inputs in case not provided by user", + config: Config{ + ExtraControllers: []string{ + policyAgentController, + tfController, + capiController, + }, + }, + want: BootstrapStep{ + Name: "install extra controllers", + Input: []StepInput{}, + Step: installExtraControllers, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + config := makeTestConfig(t, tt.config) + step := NewInstallExtraControllers(config) + + assert.Equal(t, tt.want.Name, step.Name) + if diff := cmp.Diff(tt.want.Input, step.Input); diff != "" { + t.Fatalf("different step expected:\n%s", diff) + } + }) + } +} + +func TestInstallExtraControllers(t *testing.T) { + // note: can't test controllers as it requires pushing to git + // will test the functionality with the default controller only here + tests := []struct { + name string + stepInput []StepInput + err bool + }{ + { + name: "test skip installing controllers with defaults (none)", + stepInput: []StepInput{ + { + Name: inExtraControllers, + Type: multiSelectionChoice, + Msg: extraControllersMsg, + Value: defaultController, + }, + }, + err: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + config := makeTestConfig(t, Config{}) + _, err := installExtraControllers(tt.stepInput, &config) + assert.NoError(t, err, "unexpected error") + if err != nil { + if tt.err { + return + } + t.Fatalf("unexpected error: %v", err) + } + }) + } + +} diff --git a/pkg/bootstrap/steps/install_oidc.go b/pkg/bootstrap/steps/install_oidc.go index 8ab52f0fe9..57317cd0c6 100644 --- a/pkg/bootstrap/steps/install_oidc.go +++ b/pkg/bootstrap/steps/install_oidc.go @@ -6,7 +6,7 @@ func NewInstallOIDCStep(config Config) BootstrapStep { Name: inOidcInstalled, Type: confirmInput, Msg: oidcInstallMsg, - DefaultValue: "", + DefaultValue: confirmNo, Enabled: canAskOIDCPrompot, } diff --git a/pkg/bootstrap/steps/oidc.go b/pkg/bootstrap/steps/oidc.go index 766ed92501..a139ad92db 100644 --- a/pkg/bootstrap/steps/oidc.go +++ b/pkg/bootstrap/steps/oidc.go @@ -70,7 +70,7 @@ func NewOIDCConfigStep(config Config) BootstrapStep { Name: inExistingOIDC, Type: confirmInput, Msg: existingOIDCMsg, - DefaultValue: "", + DefaultValue: confirmYes, Enabled: isExistingOIDCConfig, StepInformation: fmt.Sprintf(oidcConfigExistWarningMsg, oidcSecretName, WGEDefaultNamespace), }, diff --git a/pkg/bootstrap/steps/policy_agent.go b/pkg/bootstrap/steps/policy_agent.go new file mode 100644 index 0000000000..a2072c4eed --- /dev/null +++ b/pkg/bootstrap/steps/policy_agent.go @@ -0,0 +1,185 @@ +package steps + +import ( + "encoding/json" + "fmt" + "time" + + helmv2 "github.com/fluxcd/helm-controller/api/v2beta1" + sourcev1beta2 "github.com/fluxcd/source-controller/api/v1beta2" + "github.com/weaveworks/weave-gitops-enterprise/pkg/bootstrap/utils" + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +const ( + admissionMsg = "do you want to enable the Agent's admission controller" + policyAgentInstallInfoMsg = "installing Policy Agent ..." + policyAgentInstallConfirmMsg = "Policy Agent is installed successfully" +) + +const ( + agentChartURL = "https://weaveworks.github.io/policy-agent/" + agentHelmRepoName = "policy-agent" + agentHelmReleaseName = "policy-agent" + agentNamespace = "policy-system" + agentHelmRepoFileName = "policy-agent-helmrepo.yaml" + agentHelmReleaseFileName = "policy-agent-helmrelease.yaml" + agentHelmRepoCommitMsg = "Add Policy Agent HelmRepository YAML file" + agentHelmReleaseCommitMsg = "Add Policy Agent HelmRelease YAML file" + agentVersion = "2.5.0" +) + +var enableAdmission = StepInput{ + Name: inEnableAdmission, + Type: confirmInput, + Msg: admissionMsg, + DefaultValue: confirmNo, +} + +// NewInstallPolicyAgentStep ask for continue installing OIDC +func NewInstallPolicyAgentStep(config Config) BootstrapStep { + config.Logger.Warningf("please note that the Policy Agent requires cert-manager to be installed!") + return BootstrapStep{ + Name: "install Policy Agent", + Input: []StepInput{enableAdmission}, + Step: installPolicyAgent, + } +} + +// installPolicyAgent start installing policy agent helm chart +func installPolicyAgent(input []StepInput, c *Config) ([]StepOutput, error) { + enableAdmission := false + + for _, param := range input { + if param.Name == inEnableAdmission { + enable, ok := param.Value.(string) + if ok && enable == confirmYes { + enableAdmission = true + } + } + } + c.Logger.Actionf(policyAgentInstallInfoMsg) + c.Logger.Actionf("rendering Policy Agent HelmRepository file") + agentHelmRepoObject := sourcev1beta2.HelmRepository{ + TypeMeta: v1.TypeMeta{ + APIVersion: sourcev1beta2.GroupVersion.Identifier(), + Kind: sourcev1beta2.HelmRepositoryKind, + }, + ObjectMeta: v1.ObjectMeta{ + Name: agentHelmRepoName, + Namespace: WGEDefaultNamespace, + CreationTimestamp: v1.Now(), + }, + Spec: sourcev1beta2.HelmRepositorySpec{ + URL: agentChartURL, + Interval: v1.Duration{ + Duration: time.Minute, + }, + }, + } + agentHelmRepoFile, err := utils.CreateHelmRepositoryYamlString(agentHelmRepoObject) + if err != nil { + return []StepOutput{}, fmt.Errorf("failed to render Policy Agent HelmRepository: %v", err) + } + c.Logger.Actionf("rendered Policy Agent HelmRepository file") + + c.Logger.Actionf("rendering Policy Agent HelmRelease file") + + values := map[string]interface{}{ + "config": map[string]interface{}{ + "admission": map[string]interface{}{ + "enabled": enableAdmission, + "sinks": map[string]interface{}{ + "k8sEventsSink": map[string]interface{}{ + "enabled": true, + }, + }, + }, + "audit": map[string]interface{}{ + "enabled": true, + "sinks": map[string]interface{}{ + "k8sEventsSink": map[string]interface{}{ + "enabled": true, + }, + }, + }, + }, + "excludeNamespaces": []string{ + "kube-system", + "flux-system", + }, + "failurePolicy": "Fail", + "useCertManager": true, + } + + valuesBytes, err := json.Marshal(values) + if err != nil { + return []StepOutput{}, fmt.Errorf("failed to render Policy Agent HelmRepository values: %v", err) + } + + agentHelmReleaseObject := helmv2.HelmRelease{ + TypeMeta: v1.TypeMeta{ + Kind: helmv2.HelmReleaseKind, + APIVersion: helmv2.GroupVersion.Identifier(), + }, + ObjectMeta: v1.ObjectMeta{ + Name: agentHelmReleaseName, + Namespace: WGEDefaultNamespace, + CreationTimestamp: v1.Now(), + }, Spec: helmv2.HelmReleaseSpec{ + Chart: helmv2.HelmChartTemplate{ + Spec: helmv2.HelmChartTemplateSpec{ + Chart: agentHelmRepoName, + SourceRef: helmv2.CrossNamespaceObjectReference{ + Kind: sourcev1beta2.HelmRepositoryKind, + Name: agentHelmRepoName, + Namespace: WGEDefaultNamespace, + APIVersion: sourcev1beta2.GroupVersion.Identifier(), + }, + Version: agentVersion, + }, + }, + Install: &helmv2.Install{ + CRDs: helmv2.CreateReplace, + CreateNamespace: true, + }, + Interval: v1.Duration{ + Duration: time.Minute * 10, + }, + TargetNamespace: agentNamespace, + Values: &apiextensionsv1.JSON{Raw: valuesBytes}, + }, + } + + agentHelmReleaseFile, err := utils.CreateHelmReleaseYamlString(agentHelmReleaseObject) + if err != nil { + return []StepOutput{}, fmt.Errorf("failed to render Policy Agent HelmRelease: %v", err) + } + c.Logger.Actionf("rendered Policy Agent HelmRelease file") + + helmrepoFile := fileContent{ + Name: agentHelmRepoFileName, + Content: agentHelmRepoFile, + CommitMsg: agentHelmRepoCommitMsg, + } + helmreleaseFile := fileContent{ + Name: agentHelmReleaseFileName, + Content: agentHelmReleaseFile, + CommitMsg: agentHelmReleaseCommitMsg, + } + + c.Logger.Successf(policyAgentInstallConfirmMsg) + return []StepOutput{ + { + Name: agentHelmRepoFileName, + Type: typeFile, + Value: helmrepoFile, + }, + { + Name: agentHelmReleaseFileName, + Type: typeFile, + Value: helmreleaseFile, + }, + }, nil +} diff --git a/pkg/bootstrap/steps/policy_agent_test.go b/pkg/bootstrap/steps/policy_agent_test.go new file mode 100644 index 0000000000..4ec1d03004 --- /dev/null +++ b/pkg/bootstrap/steps/policy_agent_test.go @@ -0,0 +1,235 @@ +package steps + +import ( + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/stretchr/testify/assert" +) + +const ( + testAgentHelmRepoFile = `apiVersion: source.toolkit.fluxcd.io/v1beta2 +kind: HelmRepository +metadata: + creationTimestamp: null + name: policy-agent + namespace: flux-system +spec: + interval: 1m0s + url: https://weaveworks.github.io/policy-agent/ +status: {} +` + testAgentHelmReleaseFileAdmissionDisabled = `apiVersion: helm.toolkit.fluxcd.io/v2beta1 +kind: HelmRelease +metadata: + creationTimestamp: null + name: policy-agent + namespace: flux-system +spec: + chart: + spec: + chart: policy-agent + reconcileStrategy: ChartVersion + sourceRef: + kind: HelmRepository + name: policy-agent + namespace: flux-system + version: 2.5.0 + install: + crds: CreateReplace + createNamespace: true + interval: 10m0s + values: + config: + admission: + enabled: false + sinks: + k8sEventsSink: + enabled: true + audit: + enabled: true + sinks: + k8sEventsSink: + enabled: true + excludeNamespaces: + - kube-system + - flux-system + failurePolicy: Fail + useCertManager: true +status: {} +` + testAgentHelmReleaseFileAdmissionEnabled = `apiVersion: helm.toolkit.fluxcd.io/v2beta1 +kind: HelmRelease +metadata: + creationTimestamp: null + name: policy-agent + namespace: flux-system +spec: + chart: + spec: + chart: policy-agent + reconcileStrategy: ChartVersion + sourceRef: + kind: HelmRepository + name: policy-agent + namespace: flux-system + version: 2.5.0 + install: + crds: CreateReplace + createNamespace: true + interval: 10m0s + values: + config: + admission: + enabled: true + sinks: + k8sEventsSink: + enabled: true + audit: + enabled: true + sinks: + k8sEventsSink: + enabled: true + excludeNamespaces: + - kube-system + - flux-system + failurePolicy: Fail + useCertManager: true +status: {} +` +) + +func TestInstallPolicyAgent(t *testing.T) { + tests := []struct { + name string + input []StepInput + output []StepOutput + err bool + }{ + { + name: "install policy agent controller with admission disabled", + input: []StepInput{ + { + Name: inEnableAdmission, + Type: confirmInput, + Msg: admissionMsg, + Value: confirmNo, + }, + }, + output: []StepOutput{ + { + Name: agentHelmRepoFileName, + Type: typeFile, + Value: fileContent{ + Name: agentHelmRepoFileName, + Content: testAgentHelmRepoFile, + CommitMsg: agentHelmRepoCommitMsg, + }, + }, + { + Name: agentHelmReleaseFileName, + Type: typeFile, + Value: fileContent{ + Name: agentHelmReleaseFileName, + Content: testAgentHelmReleaseFileAdmissionDisabled, + CommitMsg: agentHelmReleaseCommitMsg, + }, + }, + }, + err: false, + }, + { + name: "install policy agent controller with admission enabled", + input: []StepInput{ + { + Name: inEnableAdmission, + Type: confirmInput, + Msg: admissionMsg, + Value: confirmYes, + }, + }, + output: []StepOutput{ + { + Name: agentHelmRepoFileName, + Type: typeFile, + Value: fileContent{ + Name: agentHelmRepoFileName, + Content: testAgentHelmRepoFile, + CommitMsg: agentHelmRepoCommitMsg, + }, + }, + { + Name: agentHelmReleaseFileName, + Type: typeFile, + Value: fileContent{ + Name: agentHelmReleaseFileName, + Content: testAgentHelmReleaseFileAdmissionEnabled, + CommitMsg: agentHelmReleaseCommitMsg, + }, + }, + }, + err: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + testConfig := Config{} + + config := makeTestConfig(t, testConfig) + out, err := installPolicyAgent(tt.input, &config) + if err != nil { + if tt.err { + return + } + t.Fatalf("error install policy-agent: %v", err) + } + + for i, item := range out { + assert.Equal(t, item.Name, tt.output[i].Name, "wrong name") + assert.Equal(t, item.Type, tt.output[i].Type, "wrong type") + inFileContent, ok := tt.output[i].Value.(fileContent) + if !ok { + t.Fatalf("error install policy-agent: %v", err) + } + outFileContent, ok := item.Value.(fileContent) + if !ok { + t.Fatalf("error install policy-agent: %v", err) + } + assert.Equal(t, outFileContent.CommitMsg, inFileContent.CommitMsg, "wrong commit msg") + assert.Equal(t, outFileContent.Name, inFileContent.Name, "wrong filename") + assert.Equal(t, outFileContent.Content, inFileContent.Content, "wrong content") + } + }) + } + +} + +func TestNewInstallPolicyAgentStep(t *testing.T) { + tests := []struct { + name string + want BootstrapStep + }{ + + { + name: "return bootstrap step", + want: BootstrapStep{ + Name: "install Policy Agent", + Input: []StepInput{ + enableAdmission, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + config := makeTestConfig(t, Config{}) + step := NewInstallPolicyAgentStep(config) + + assert.Equal(t, tt.want.Name, step.Name) + if diff := cmp.Diff(tt.want.Input, step.Input); diff != "" { + t.Fatalf("different step expected:\n%s", diff) + } + }) + } +} diff --git a/pkg/bootstrap/steps/step.go b/pkg/bootstrap/steps/step.go index 29ff295135..a9573d5361 100644 --- a/pkg/bootstrap/steps/step.go +++ b/pkg/bootstrap/steps/step.go @@ -147,9 +147,15 @@ func defaultInputStep(inputs []StepInput, c *Config, stdin io.ReadCloser) ([]Ste if input.StepInformation != "" { c.Logger.Warningf(input.StepInformation) } - // if silent mode is enabled, select yes + // if silent mode is enabled, select the default value + // if no default value select yes by default if c.Silent { - input.Value = confirmYes + defaultVal, ok := input.DefaultValue.(string) + if ok { + input.Value = defaultVal + } else { + input.Value = confirmYes + } } // get the value from user otherwise diff --git a/pkg/bootstrap/steps/terraform.go b/pkg/bootstrap/steps/terraform.go new file mode 100644 index 0000000000..38ae649a0a --- /dev/null +++ b/pkg/bootstrap/steps/terraform.go @@ -0,0 +1,96 @@ +package steps + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/weaveworks/weave-gitops-enterprise/pkg/bootstrap/utils" +) + +const ( + tfInstallInfoMsg = "installing Terraform Controller ..." + tfInstallConfirmMsg = "Terraform Controller is installed successfully" +) + +const ( + tfCommitMsg = "Add Terraform Controller HelmRelease" + tfControllerUrl = "https://raw.githubusercontent.com/weaveworks/tf-controller/main/docs/release.yaml" + tfFileName = "tf-controller.yaml" +) + +// NewInstallTFControllerStep ask for continue installing OIDC +func NewInstallTFControllerStep(config Config) BootstrapStep { + return BootstrapStep{ + Name: "install Terraform Controller", + Step: installTerraform, + } +} + +// installTerraform start installing terraform controller helm release +func installTerraform(input []StepInput, c *Config) ([]StepOutput, error) { + c.Logger.Actionf(tfInstallInfoMsg) + resp, err := http.Get(tfControllerUrl) + if err != nil { + return []StepOutput{}, fmt.Errorf("error getting Terraform Controller HelmRelease: %v", err) + } + defer resp.Body.Close() + + var bodyBytes []byte + if resp.StatusCode != http.StatusOK { + return []StepOutput{}, fmt.Errorf("error getting Terraform Controller HelmRelease. status code: %d", resp.StatusCode) + } + + bodyBytes, err = io.ReadAll(resp.Body) + if err != nil { + return []StepOutput{}, fmt.Errorf("error getting Terraform Controller HelmRelease: %v", err) + } + + // enable tf ui + valuesBytes, err := utils.GetHelmReleaseValues(c.KubernetesClient, WgeHelmReleaseName, WGEDefaultNamespace) + if err != nil { + return []StepOutput{}, err + } + var wgeValues valuesFile + + err = json.Unmarshal(valuesBytes, &wgeValues) + if err != nil { + return []StepOutput{}, err + } + wgeValues.EnableTerraformUI = true + + wgeHelmRelease, err := constructWGEhelmRelease(wgeValues, c.WGEVersion) + if err != nil { + return []StepOutput{}, err + } + + c.Logger.Actionf("rendered WGE HelmRelease file") + + c.Logger.Actionf("updating HelmRelease file") + helmreleaseFile := fileContent{ + Name: wgeHelmReleaseFileName, + Content: wgeHelmRelease, + CommitMsg: tfCommitMsg, + } + + tfHelmFile := fileContent{ + Name: tfFileName, + Content: string(bodyBytes), + CommitMsg: tfCommitMsg, + } + + c.Logger.Successf(tfInstallConfirmMsg) + return []StepOutput{ + { + Name: tfFileName, + Type: typeFile, + Value: tfHelmFile, + }, + { + Name: wgeHelmReleaseFileName, + Type: typeFile, + Value: helmreleaseFile, + }, + }, nil +} diff --git a/pkg/bootstrap/steps/terraform_test.go b/pkg/bootstrap/steps/terraform_test.go new file mode 100644 index 0000000000..829051e540 --- /dev/null +++ b/pkg/bootstrap/steps/terraform_test.go @@ -0,0 +1,188 @@ +package steps + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +const ( + testTFControllerFile = `--- +apiVersion: source.toolkit.fluxcd.io/v1beta2 +kind: HelmRepository +metadata: + name: tf-controller + namespace: flux-system +spec: + interval: 1h0s + type: oci + url: oci://ghcr.io/weaveworks/charts +--- +apiVersion: helm.toolkit.fluxcd.io/v2beta1 +kind: HelmRelease +metadata: + name: tf-controller + namespace: flux-system +spec: + chart: + spec: + chart: tf-controller + sourceRef: + kind: HelmRepository + name: tf-controller + version: '>=0.16.0-rc.3' + interval: 1h0s + releaseName: tf-controller + targetNamespace: flux-system + install: + crds: Create + remediation: + retries: -1 + upgrade: + crds: CreateReplace + remediation: + retries: -1 + values: + replicaCount: 3 + concurrency: 24 + resources: + limits: + cpu: 1000m + memory: 2Gi + requests: + cpu: 400m + memory: 64Mi + caCertValidityDuration: 24h + certRotationCheckFrequency: 30m + image: + tag: v0.16.0-rc.3 + runner: + image: + tag: v0.16.0-rc.3 + grpc: + maxMessageSize: 30 +` + + wgeHRFakeFileTFController = `apiVersion: helm.toolkit.fluxcd.io/v2beta1 +kind: HelmRelease +metadata: + creationTimestamp: null + name: weave-gitops-enterprise + namespace: flux-system +spec: + chart: + spec: + chart: mccp + reconcileStrategy: ChartVersion + sourceRef: + kind: HelmRepository + name: weave-gitops-enterprise-charts + namespace: flux-system + version: 1.0.0 + install: + crds: CreateReplace + interval: 1h0m0s + upgrade: + crds: CreateReplace + values: + cluster-controller: + controllerManager: + manager: + image: + repository: docker.io/weaveworks/cluster-controller + tag: v1.5.2 + enabled: true + fullnameOverride: cluster + config: {} + enablePipelines: true + enableTerraformUI: true + gitopssets-controller: + controllerManager: + manager: + args: + - --health-probe-bind-address=:8081 + - --metrics-bind-address=127.0.0.1:8080 + - --leader-elect + - --enabled-generators=GitRepository,Cluster,PullRequests,List,APIClient,Matrix,Config + enabled: true + global: {} + tls: + enabled: false +status: {} +` +) + +func TestInstallTerraform(t *testing.T) { + tests := []struct { + name string + input []StepInput + output []StepOutput + err bool + }{ + { + name: "install tf controller", + output: []StepOutput{ + { + Name: tfFileName, + Type: typeFile, + Value: fileContent{ + Name: tfFileName, + Content: testTFControllerFile, + CommitMsg: tfCommitMsg, + }, + }, + { + Name: wgeHelmReleaseFileName, + Type: typeFile, + Value: fileContent{ + Name: wgeHelmReleaseFileName, + Content: wgeHRFakeFileTFController, + CommitMsg: tfCommitMsg, + }, + }, + }, + err: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + testConfig := Config{ + Silent: true, + WGEVersion: "1.0.0", + DomainType: domainTypeLocalhost, + } + wgeObject, err := createWGEHelmReleaseFakeObject("1.0.0") + if err != nil { + t.Fatalf("error create wge object: %v", err) + } + + config := makeTestConfig(t, testConfig, &wgeObject) + + out, err := installTerraform(tt.input, &config) + if err != nil { + if tt.err { + return + } + t.Fatalf("error install tf controller: %v", err) + } + + for i, item := range out { + assert.Equal(t, item.Name, tt.output[i].Name, "wrong name") + assert.Equal(t, item.Type, tt.output[i].Type, "wrong type") + inFileContent, ok := tt.output[i].Value.(fileContent) + if !ok { + t.Fatalf("error install tf controller: %v", err) + } + outFileContent, ok := item.Value.(fileContent) + if !ok { + t.Fatalf("error install tf controller: %v", err) + } + assert.Equal(t, outFileContent.CommitMsg, inFileContent.CommitMsg, "wrong commit msg") + assert.Equal(t, outFileContent.Name, inFileContent.Name, "wrong filename") + assert.Equal(t, outFileContent.Content, inFileContent.Content, "wrong content") + } + }) + } + +} diff --git a/pkg/bootstrap/utils/flux.go b/pkg/bootstrap/utils/flux.go index ea03c4e84f..57085695d0 100644 --- a/pkg/bootstrap/utils/flux.go +++ b/pkg/bootstrap/utils/flux.go @@ -42,13 +42,6 @@ func CreateHelmReleaseYamlString(hr helmv2.HelmRelease) (string, error) { Version: hr.Spec.Chart.Spec.Version, }, }, - Install: &helmv2.Install{ - CRDs: hr.Spec.Install.CRDs, - CreateNamespace: hr.Spec.Install.CreateNamespace, - }, - Upgrade: &helmv2.Upgrade{ - CRDs: hr.Spec.Upgrade.CRDs, - }, Interval: v1.Duration{ Duration: hr.Spec.Interval.Duration, }, @@ -56,6 +49,23 @@ func CreateHelmReleaseYamlString(hr helmv2.HelmRelease) (string, error) { }, } + if hr.Spec.Upgrade != nil { + helmRelease.Spec.Upgrade = &helmv2.Upgrade{ + CRDs: hr.Spec.Upgrade.CRDs, + } + } + + if hr.Spec.Install != nil { + helmRelease.Spec.Install = &helmv2.Install{ + CRDs: hr.Spec.Install.CRDs, + CreateNamespace: hr.Spec.Install.CreateNamespace, + } + } + + if hr.Spec.TargetNamespace != "" { + hr.Spec.TargetNamespace = helmRelease.Spec.TargetNamespace + } + helmReleaseBytes, err := k8syaml.Marshal(helmRelease) if err != nil { return "", err @@ -80,12 +90,15 @@ func CreateHelmRepositoryYamlString(helmRepo sourcev1.HelmRepository) (string, e Interval: v1.Duration{ Duration: helmRepo.Spec.Interval.Duration, }, - SecretRef: &meta.LocalObjectReference{ - Name: helmRepo.Spec.SecretRef.Name, - }, }, } + if helmRepo.Spec.SecretRef != nil { + repo.Spec.SecretRef = &meta.LocalObjectReference{ + Name: helmRepo.Spec.SecretRef.Name, + } + } + repoBytes, err := k8syaml.Marshal(repo) if err != nil { return "", err From 8da012a5d7e5a9e59ab461da80e7b6241ce0e5d8 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Tue, 28 Nov 2023 16:21:00 +0200 Subject: [PATCH 02/32] silent mode doesn't ask for extra controllers --- cmd/gitops/app/bootstrap/cmd.go | 4 ++-- .../app/bootstrap/cmd_acceptance_test.go | 24 ------------------- pkg/bootstrap/steps/extra_controllers.go | 2 +- 3 files changed, 3 insertions(+), 27 deletions(-) diff --git a/cmd/gitops/app/bootstrap/cmd.go b/cmd/gitops/app/bootstrap/cmd.go index 6a8dafad39..5b2ded5537 100644 --- a/cmd/gitops/app/bootstrap/cmd.go +++ b/cmd/gitops/app/bootstrap/cmd.go @@ -94,8 +94,8 @@ func Command(opts *config.Options) *cobra.Command { cmd.Flags().StringVarP(&flags.domainType, "domain-type", "t", "", "dashboard domain type: could be 'localhost' or 'externaldns'") cmd.Flags().StringVarP(&flags.domain, "domain", "d", "", "the domain to access the dashboard in case of using externaldns") cmd.Flags().StringVarP(&flags.version, "version", "v", "", "version of Weave GitOps Enterprise (should be from the latest 3 versions)") - cmd.Flags().StringArrayVarP(&flags.extraControllers, "extra-controllers", "", []string{}, "extra controllers to be installed from (none, policy-agent, tf-controller, capi)") - cmd.PersistentFlags().BoolVarP(&flags.silent, "bootstrap-flux", "s", false, "always choose yes for interactive questions") + cmd.Flags().StringArrayVarP(&flags.extraControllers, "extra-controllers", "", []string{}, "extra controllers to be installed from (policy-agent, tf-controller, capi)") + cmd.PersistentFlags().BoolVarP(&flags.silent, "silent", "s", false, "chose the defaults with current provided information without asking any questions") cmd.PersistentFlags().StringVarP(&flags.gitUsername, "git-username", "", "", "git username used in https authentication type") cmd.PersistentFlags().StringVarP(&flags.gitPassword, "git-password", "", "", "git password/token used in https authentication type") cmd.PersistentFlags().StringVarP(&flags.branch, "branch", "b", "", "git branch for your flux repository (example: main)") diff --git a/cmd/gitops/app/bootstrap/cmd_acceptance_test.go b/cmd/gitops/app/bootstrap/cmd_acceptance_test.go index ac2cda48bf..d2d2a97c66 100644 --- a/cmd/gitops/app/bootstrap/cmd_acceptance_test.go +++ b/cmd/gitops/app/bootstrap/cmd_acceptance_test.go @@ -126,7 +126,6 @@ func TestBootstrapCmd(t *testing.T) { "--discovery-url=https://dex-01.wge.dev.weave.works/.well-known/openid-configuration", "--client-id=weave-gitops-enterprise", oidcClientSecretFlag, - "--extra-controllers=none", "-s", }, setup: func(t *testing.T) { @@ -151,34 +150,11 @@ func TestBootstrapCmd(t *testing.T) { gitUsernameFlag, gitPasswordFlag, gitBranchFlag, gitRepoPathFlag, repoHTTPSURLFlag, oidcClientSecretFlag, "-s", - "--extra-controllers=none", - }, - setup: func(t *testing.T) { - createEntitlements(t, testLog) - }, - reset: func(t *testing.T) { - deleteEntitlements(t, testLog) - deleteClusterUser(t, testLog) - uninstallFlux(g, kubeconfigFlag) - }, - expectedErrorStr: "", - }, - { - name: "journey bootstrap with extra controllers policy-agent capi and tf-controller", - flags: []string{kubeconfigFlag, - "--version=0.36.0", - privateKeyFlag, privateKeyPasswordFlag, - "--password=admin123", - "--domain-type=localhost", - "--discovery-url=https://dex-01.wge.dev.weave.works/.well-known/openid-configuration", - "--client-id=weave-gitops-enterprise", - oidcClientSecretFlag, "-s", "--extra-controllers=policy-agent", "--extra-controllers=capi", "--extra-controllers=tf-controller", }, setup: func(t *testing.T) { - bootstrapFluxSsh(g, kubeconfigFlag) createEntitlements(t, testLog) }, reset: func(t *testing.T) { diff --git a/pkg/bootstrap/steps/extra_controllers.go b/pkg/bootstrap/steps/extra_controllers.go index 7ab3630505..011570ceca 100644 --- a/pkg/bootstrap/steps/extra_controllers.go +++ b/pkg/bootstrap/steps/extra_controllers.go @@ -35,7 +35,7 @@ func NewInstallExtraControllers(config Config) BootstrapStep { DefaultValue: controllersValues[0], } - if len(config.ExtraControllers) < 1 { + if len(config.ExtraControllers) < 1 && !config.Silent { inputs = append(inputs, installExtraControllersStep) } From b8606fb86813bc7401046eabbcb54b0918b83a19 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Tue, 28 Nov 2023 16:33:58 +0200 Subject: [PATCH 03/32] use components-extra instead of extra-controllers --- cmd/gitops/app/bootstrap/cmd.go | 10 +++---- .../app/bootstrap/cmd_acceptance_test.go | 4 +-- pkg/bootstrap/bootstrap.go | 2 +- pkg/bootstrap/steps/common_tests.go | 2 +- pkg/bootstrap/steps/config.go | 12 ++++---- pkg/bootstrap/steps/extra_controllers.go | 30 +++++++++---------- pkg/bootstrap/steps/extra_controllers_test.go | 24 +++++++-------- 7 files changed, 41 insertions(+), 43 deletions(-) diff --git a/cmd/gitops/app/bootstrap/cmd.go b/cmd/gitops/app/bootstrap/cmd.go index 5b2ded5537..77fed24c22 100644 --- a/cmd/gitops/app/bootstrap/cmd.go +++ b/cmd/gitops/app/bootstrap/cmd.go @@ -40,10 +40,10 @@ gitops bootstrap --version= --password= --discovery-url gitops bootstrap --version= --password= --discovery-url= --client-id= --private-key-path= --private-key-password= --branch= --repo-path= --repo-url=ssh:// --client-secret= -s # Start WGE installation with extra controller like policy agent -gitops bootstrap --extra-controllers policy-agent +gitops bootstrap --components-extra="policy-agent" # Start WGE installation with more than one extra controller -gitops bootstrap --extra-controllers policy-agent --extra-controllers capi --extra-controllers tf-controller +gitops bootstrap --components-extra="policy-agent,capi,tf-controller" ` ) @@ -77,7 +77,7 @@ type bootstrapFlags struct { silent bool // extra controllers - extraControllers []string + extraComponents []string } var flags bootstrapFlags @@ -94,7 +94,7 @@ func Command(opts *config.Options) *cobra.Command { cmd.Flags().StringVarP(&flags.domainType, "domain-type", "t", "", "dashboard domain type: could be 'localhost' or 'externaldns'") cmd.Flags().StringVarP(&flags.domain, "domain", "d", "", "the domain to access the dashboard in case of using externaldns") cmd.Flags().StringVarP(&flags.version, "version", "v", "", "version of Weave GitOps Enterprise (should be from the latest 3 versions)") - cmd.Flags().StringArrayVarP(&flags.extraControllers, "extra-controllers", "", []string{}, "extra controllers to be installed from (policy-agent, tf-controller, capi)") + cmd.Flags().StringSliceVar(&flags.extraComponents, "components-extra", nil, "extra components to be installed from (policy-agent, tf-controller, capi)") cmd.PersistentFlags().BoolVarP(&flags.silent, "silent", "s", false, "chose the defaults with current provided information without asking any questions") cmd.PersistentFlags().StringVarP(&flags.gitUsername, "git-username", "", "", "git username used in https authentication type") cmd.PersistentFlags().StringVarP(&flags.gitPassword, "git-password", "", "", "git password/token used in https authentication type") @@ -133,7 +133,7 @@ func getBootstrapCmdRun(opts *config.Options) func(*cobra.Command, []string) err ). WithOIDCConfig(flags.discoveryURL, flags.clientID, flags.clientSecret, true). WithSilentFlag(flags.silent). - WithExtraControllers(flags.extraControllers). + WithExtraComponents(flags.extraComponents). Build() if err != nil { diff --git a/cmd/gitops/app/bootstrap/cmd_acceptance_test.go b/cmd/gitops/app/bootstrap/cmd_acceptance_test.go index d2d2a97c66..6ee348f6f2 100644 --- a/cmd/gitops/app/bootstrap/cmd_acceptance_test.go +++ b/cmd/gitops/app/bootstrap/cmd_acceptance_test.go @@ -150,9 +150,7 @@ func TestBootstrapCmd(t *testing.T) { gitUsernameFlag, gitPasswordFlag, gitBranchFlag, gitRepoPathFlag, repoHTTPSURLFlag, oidcClientSecretFlag, "-s", - "--extra-controllers=policy-agent", - "--extra-controllers=capi", - "--extra-controllers=tf-controller", + "--components-extra=\"policy-agent,capi,tf-controller\"", }, setup: func(t *testing.T) { createEntitlements(t, testLog) diff --git a/pkg/bootstrap/bootstrap.go b/pkg/bootstrap/bootstrap.go index bb736d95db..8a8d80464f 100644 --- a/pkg/bootstrap/bootstrap.go +++ b/pkg/bootstrap/bootstrap.go @@ -28,7 +28,7 @@ func Bootstrap(config steps.Config) error { steps.NewInstallOIDCStep(config), steps.NewOIDCConfigStep(config), steps.CheckUIDomainStep, - steps.NewInstallExtraControllers(config), + steps.NewInstallExtraComponents(config), } for _, step := range steps { diff --git a/pkg/bootstrap/steps/common_tests.go b/pkg/bootstrap/steps/common_tests.go index 0624aaaa63..3b15cda7f2 100644 --- a/pkg/bootstrap/steps/common_tests.go +++ b/pkg/bootstrap/steps/common_tests.go @@ -42,7 +42,7 @@ func makeTestConfig(t *testing.T, config Config, objects ...runtime.Object) Conf RedirectURL: config.RedirectURL, PromptedForDiscoveryURL: config.PromptedForDiscoveryURL, Silent: config.Silent, - ExtraControllers: config.ExtraControllers, + ExtraComponents: config.ExtraComponents, } } diff --git a/pkg/bootstrap/steps/config.go b/pkg/bootstrap/steps/config.go index 9c47f9429b..e01939001e 100644 --- a/pkg/bootstrap/steps/config.go +++ b/pkg/bootstrap/steps/config.go @@ -46,7 +46,7 @@ const ( inGitUserName = "username" inGitPassword = "gitPassowrd" inBootstrapFlux = "bootstrapFlux" - inExtraControllers = "extraControllers" + inExtraComponents = "extraComponents" inEnableAdmission = "enableAdmission" ) @@ -82,7 +82,7 @@ type ConfigBuilder struct { clientID string clientSecret string PromptedForDiscoveryURL bool - extraControllers []string + extraComponents []string } func NewConfigBuilder() *ConfigBuilder { @@ -155,8 +155,8 @@ func (c *ConfigBuilder) WithSilentFlag(silent bool) *ConfigBuilder { return c } -func (c *ConfigBuilder) WithExtraControllers(extraControllers []string) *ConfigBuilder { - c.extraControllers = extraControllers +func (c *ConfigBuilder) WithExtraComponents(extraComponents []string) *ConfigBuilder { + c.extraComponents = extraComponents return c } @@ -197,7 +197,7 @@ type Config struct { RedirectURL string PromptedForDiscoveryURL bool - ExtraControllers []string + ExtraComponents []string } // Builds creates a valid config so boostrap could be executed. It uses values introduced @@ -256,7 +256,7 @@ func (cb *ConfigBuilder) Build() (Config, error) { ClientID: cb.clientID, ClientSecret: cb.clientSecret, PromptedForDiscoveryURL: cb.PromptedForDiscoveryURL, - ExtraControllers: cb.extraControllers, + ExtraComponents: cb.extraComponents, }, nil } diff --git a/pkg/bootstrap/steps/extra_controllers.go b/pkg/bootstrap/steps/extra_controllers.go index 011570ceca..fe8ee6edfe 100644 --- a/pkg/bootstrap/steps/extra_controllers.go +++ b/pkg/bootstrap/steps/extra_controllers.go @@ -5,7 +5,7 @@ import ( ) const ( - extraControllersMsg = "do you want to install extra controllers from the following on your cluster" + extraComponentsMsg = "do you want to install extra Components from the following on your cluster" ) const ( @@ -16,8 +16,8 @@ const ( allControllers = "all of above" ) -// NewInstallExtraControllers start installing extra controllers -func NewInstallExtraControllers(config Config) BootstrapStep { +// NewInstallExtraComponents start installing extra Components +func NewInstallExtraComponents(config Config) BootstrapStep { inputs := []StepInput{} controllersValues := []string{ defaultController, @@ -27,35 +27,35 @@ func NewInstallExtraControllers(config Config) BootstrapStep { allControllers, } - installExtraControllersStep := StepInput{ - Name: inExtraControllers, + installExtraComponentsStep := StepInput{ + Name: inExtraComponents, Type: multiSelectionChoice, - Msg: extraControllersMsg, + Msg: extraComponentsMsg, Values: controllersValues, DefaultValue: controllersValues[0], } - if len(config.ExtraControllers) < 1 && !config.Silent { - inputs = append(inputs, installExtraControllersStep) + if len(config.ExtraComponents) < 1 && !config.Silent { + inputs = append(inputs, installExtraComponentsStep) } return BootstrapStep{ - Name: "install extra controllers", + Name: "install extra components", Input: inputs, - Step: installExtraControllers, + Step: installExtraComponents, } } -func installExtraControllers(input []StepInput, c *Config) ([]StepOutput, error) { +func installExtraComponents(input []StepInput, c *Config) ([]StepOutput, error) { for _, param := range input { - if param.Name == inExtraControllers { - extraControllers, ok := param.Value.(string) + if param.Name == inExtraComponents { + extraComponents, ok := param.Value.(string) if ok { - c.ExtraControllers = append(c.ExtraControllers, extraControllers) + c.ExtraComponents = append(c.ExtraComponents, extraComponents) } } } - for _, controller := range c.ExtraControllers { + for _, controller := range c.ExtraComponents { switch controller { case policyAgentController: agentStep := NewInstallPolicyAgentStep(*c) diff --git a/pkg/bootstrap/steps/extra_controllers_test.go b/pkg/bootstrap/steps/extra_controllers_test.go index 86f3909f4b..ee81be8caa 100644 --- a/pkg/bootstrap/steps/extra_controllers_test.go +++ b/pkg/bootstrap/steps/extra_controllers_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" ) -func TestNewInstallExtraControllers(t *testing.T) { +func TestNewInstallExtraComponents(t *testing.T) { tests := []struct { name string config Config @@ -17,12 +17,12 @@ func TestNewInstallExtraControllers(t *testing.T) { name: "return bootstrap step with inputs in case provided by user", config: Config{}, want: BootstrapStep{ - Name: "install extra controllers", + Name: "install extra components", Input: []StepInput{ { - Name: inExtraControllers, + Name: inExtraComponents, Type: multiSelectionChoice, - Msg: extraControllersMsg, + Msg: extraComponentsMsg, Values: []string{ defaultController, policyAgentController, @@ -33,29 +33,29 @@ func TestNewInstallExtraControllers(t *testing.T) { DefaultValue: defaultController, }, }, - Step: installExtraControllers, + Step: installExtraComponents, }, }, { name: "return bootstrap step with empty inputs in case not provided by user", config: Config{ - ExtraControllers: []string{ + ExtraComponents: []string{ policyAgentController, tfController, capiController, }, }, want: BootstrapStep{ - Name: "install extra controllers", + Name: "install extra components", Input: []StepInput{}, - Step: installExtraControllers, + Step: installExtraComponents, }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { config := makeTestConfig(t, tt.config) - step := NewInstallExtraControllers(config) + step := NewInstallExtraComponents(config) assert.Equal(t, tt.want.Name, step.Name) if diff := cmp.Diff(tt.want.Input, step.Input); diff != "" { @@ -77,9 +77,9 @@ func TestInstallExtraControllers(t *testing.T) { name: "test skip installing controllers with defaults (none)", stepInput: []StepInput{ { - Name: inExtraControllers, + Name: inExtraComponents, Type: multiSelectionChoice, - Msg: extraControllersMsg, + Msg: extraComponentsMsg, Value: defaultController, }, }, @@ -89,7 +89,7 @@ func TestInstallExtraControllers(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { config := makeTestConfig(t, Config{}) - _, err := installExtraControllers(tt.stepInput, &config) + _, err := installExtraComponents(tt.stepInput, &config) assert.NoError(t, err, "unexpected error") if err != nil { if tt.err { From 2c5af0142bc7135cb20885905e34f948a931e35a Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Tue, 28 Nov 2023 16:35:39 +0200 Subject: [PATCH 04/32] install components before check ui domain --- pkg/bootstrap/bootstrap.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/bootstrap/bootstrap.go b/pkg/bootstrap/bootstrap.go index 8a8d80464f..006a4de803 100644 --- a/pkg/bootstrap/bootstrap.go +++ b/pkg/bootstrap/bootstrap.go @@ -27,8 +27,8 @@ func Bootstrap(config steps.Config) error { steps.NewInstallWGEStep(config), steps.NewInstallOIDCStep(config), steps.NewOIDCConfigStep(config), - steps.CheckUIDomainStep, steps.NewInstallExtraComponents(config), + steps.CheckUIDomainStep, } for _, step := range steps { From 33aae21243a5d24c79a619ef51777afade87f1b4 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Tue, 28 Nov 2023 16:36:20 +0200 Subject: [PATCH 05/32] remove example --- cmd/gitops/app/bootstrap/cmd.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmd/gitops/app/bootstrap/cmd.go b/cmd/gitops/app/bootstrap/cmd.go index 77fed24c22..d657e740b0 100644 --- a/cmd/gitops/app/bootstrap/cmd.go +++ b/cmd/gitops/app/bootstrap/cmd.go @@ -39,9 +39,6 @@ gitops bootstrap --version= --password= --discovery-url # Start WGE installation with OIDC and flux bootstrap with ssh gitops bootstrap --version= --password= --discovery-url= --client-id= --private-key-path= --private-key-password= --branch= --repo-path= --repo-url=ssh:// --client-secret= -s -# Start WGE installation with extra controller like policy agent -gitops bootstrap --components-extra="policy-agent" - # Start WGE installation with more than one extra controller gitops bootstrap --components-extra="policy-agent,capi,tf-controller" ` From c2d46dc21e4d99e4e224b75e56b0222373b6abc7 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Sun, 3 Dec 2023 20:43:15 +0200 Subject: [PATCH 06/32] use empty quotes instead of none value --- pkg/bootstrap/steps/extra_controllers.go | 4 +--- pkg/bootstrap/steps/extra_controllers_test.go | 7 +++---- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/pkg/bootstrap/steps/extra_controllers.go b/pkg/bootstrap/steps/extra_controllers.go index fe8ee6edfe..2631d07e8f 100644 --- a/pkg/bootstrap/steps/extra_controllers.go +++ b/pkg/bootstrap/steps/extra_controllers.go @@ -9,7 +9,6 @@ const ( ) const ( - defaultController = "none" policyAgentController = "policy-agent" tfController = "tf-controller" capiController = "capi" @@ -20,7 +19,6 @@ const ( func NewInstallExtraComponents(config Config) BootstrapStep { inputs := []StepInput{} controllersValues := []string{ - defaultController, policyAgentController, tfController, capiController, @@ -32,7 +30,7 @@ func NewInstallExtraComponents(config Config) BootstrapStep { Type: multiSelectionChoice, Msg: extraComponentsMsg, Values: controllersValues, - DefaultValue: controllersValues[0], + DefaultValue: "", } if len(config.ExtraComponents) < 1 && !config.Silent { diff --git a/pkg/bootstrap/steps/extra_controllers_test.go b/pkg/bootstrap/steps/extra_controllers_test.go index ee81be8caa..7db63a5bc4 100644 --- a/pkg/bootstrap/steps/extra_controllers_test.go +++ b/pkg/bootstrap/steps/extra_controllers_test.go @@ -24,13 +24,12 @@ func TestNewInstallExtraComponents(t *testing.T) { Type: multiSelectionChoice, Msg: extraComponentsMsg, Values: []string{ - defaultController, policyAgentController, tfController, capiController, allControllers, }, - DefaultValue: defaultController, + DefaultValue: "", }, }, Step: installExtraComponents, @@ -74,13 +73,13 @@ func TestInstallExtraControllers(t *testing.T) { err bool }{ { - name: "test skip installing controllers with defaults (none)", + name: "test skip installing controllers with defaults (\"\")", stepInput: []StepInput{ { Name: inExtraComponents, Type: multiSelectionChoice, Msg: extraComponentsMsg, - Value: defaultController, + Value: "", }, }, err: false, From dff196e51e223feec822aef4f98d2e071b7ba667 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Sun, 3 Dec 2023 20:49:05 +0200 Subject: [PATCH 07/32] remove creation timestamp --- pkg/bootstrap/steps/policy_agent.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/pkg/bootstrap/steps/policy_agent.go b/pkg/bootstrap/steps/policy_agent.go index a2072c4eed..b216024758 100644 --- a/pkg/bootstrap/steps/policy_agent.go +++ b/pkg/bootstrap/steps/policy_agent.go @@ -67,9 +67,8 @@ func installPolicyAgent(input []StepInput, c *Config) ([]StepOutput, error) { Kind: sourcev1beta2.HelmRepositoryKind, }, ObjectMeta: v1.ObjectMeta{ - Name: agentHelmRepoName, - Namespace: WGEDefaultNamespace, - CreationTimestamp: v1.Now(), + Name: agentHelmRepoName, + Namespace: WGEDefaultNamespace, }, Spec: sourcev1beta2.HelmRepositorySpec{ URL: agentChartURL, @@ -124,9 +123,8 @@ func installPolicyAgent(input []StepInput, c *Config) ([]StepOutput, error) { APIVersion: helmv2.GroupVersion.Identifier(), }, ObjectMeta: v1.ObjectMeta{ - Name: agentHelmReleaseName, - Namespace: WGEDefaultNamespace, - CreationTimestamp: v1.Now(), + Name: agentHelmReleaseName, + Namespace: WGEDefaultNamespace, }, Spec: helmv2.HelmReleaseSpec{ Chart: helmv2.HelmChartTemplate{ Spec: helmv2.HelmChartTemplateSpec{ From 1716b626e795ffd152485ad028c6ebcabf387cb6 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Mon, 4 Dec 2023 20:34:38 +0200 Subject: [PATCH 08/32] add flag to bootstrap flux to ensure the default behaviour --- cmd/gitops/app/bootstrap/cmd.go | 7 ++++++- cmd/gitops/app/bootstrap/cmd_acceptance_test.go | 1 + docs/cli/bootstrap.md | 7 +++++++ pkg/bootstrap/steps/admin_password.go | 4 ++-- pkg/bootstrap/steps/ask_bootstrap_flux.go | 8 ++++++-- pkg/bootstrap/steps/capi_test.go | 1 - pkg/bootstrap/steps/config.go | 8 ++++++++ pkg/bootstrap/steps/terraform_test.go | 1 - 8 files changed, 30 insertions(+), 7 deletions(-) diff --git a/cmd/gitops/app/bootstrap/cmd.go b/cmd/gitops/app/bootstrap/cmd.go index 774f97c990..302ff3a445 100644 --- a/cmd/gitops/app/bootstrap/cmd.go +++ b/cmd/gitops/app/bootstrap/cmd.go @@ -34,7 +34,7 @@ gitops bootstrap --password=hell0! gitops bootstrap --client-id --client-secret --discovery-url # Start WGE installation with OIDC and flux bootstrap with https -gitops bootstrap --version= --password= --discovery-url= --client-id= --git-username= -gitPassword=--branch= --repo-path= --repo-url=https:// --client-secret= -s +gitops bootstrap --version= --password= --discovery-url= --client-id= --git-username= --gitPassword= --bootstrap-flux --branch= --repo-path= --repo-url=https:// --client-secret= -s # Start WGE installation with OIDC and flux bootstrap with ssh gitops bootstrap --version= --password= --discovery-url= --client-id= --private-key-path= --private-key-password= --branch= --repo-path= --repo-url=ssh:// --client-secret= -s @@ -69,6 +69,9 @@ type bootstrapFlags struct { // modes flags silent bool + // flux flag + bootstrapFlux bool + // extra controllers extraComponents []string } @@ -87,6 +90,7 @@ func Command(opts *config.Options) *cobra.Command { cmd.Flags().StringVarP(&flags.version, "version", "v", "", "version of Weave GitOps Enterprise (should be from the latest 3 versions)") cmd.Flags().StringSliceVar(&flags.extraComponents, "components-extra", nil, "extra components to be installed from (policy-agent, tf-controller, capi)") cmd.PersistentFlags().BoolVarP(&flags.silent, "silent", "s", false, "chose the defaults with current provided information without asking any questions") + cmd.PersistentFlags().BoolVarP(&flags.bootstrapFlux, "bootstrap-flux", "", false, "chose whether you want to install flux in the generic way in case no flux installation detected") cmd.PersistentFlags().StringVarP(&flags.gitUsername, "git-username", "", "", "git username used in https authentication type") cmd.PersistentFlags().StringVarP(&flags.gitPassword, "git-password", "", "", "git password/token used in https authentication type") cmd.PersistentFlags().StringVarP(&flags.branch, "branch", "b", "", "git branch for your flux repository (example: main)") @@ -122,6 +126,7 @@ func getBootstrapCmdRun(opts *config.Options) func(*cobra.Command, []string) err ). WithOIDCConfig(flags.discoveryURL, flags.clientID, flags.clientSecret, true). WithSilentFlag(flags.silent). + WithBootstrapFluxFlag(flags.bootstrapFlux). WithExtraComponents(flags.extraComponents). Build() diff --git a/cmd/gitops/app/bootstrap/cmd_acceptance_test.go b/cmd/gitops/app/bootstrap/cmd_acceptance_test.go index f4db3b0232..f653025211 100644 --- a/cmd/gitops/app/bootstrap/cmd_acceptance_test.go +++ b/cmd/gitops/app/bootstrap/cmd_acceptance_test.go @@ -149,6 +149,7 @@ func TestBootstrapCmd(t *testing.T) { repoHTTPSURLFlag, oidcClientSecretFlag, "-s", "--components-extra=\"policy-agent,capi,tf-controller\"", + "--bootstrap-flux", }, setup: func(t *testing.T) { createEntitlements(t, testLog) diff --git a/docs/cli/bootstrap.md b/docs/cli/bootstrap.md index 564eae2764..272bec9e62 100644 --- a/docs/cli/bootstrap.md +++ b/docs/cli/bootstrap.md @@ -274,9 +274,16 @@ func selectWgeVersion(input []StepInput, c *Config) ([]StepOutput, error) { ``` +## Default Behaviours (default value in inputs) +CLI take the decisions that considered safe to user by using the information provided by user in which no mutation could happen on the user's cluster. +The default values in the step input will be used while silent mode is on by providing `-s`, `--silent` +Examples: +- Using existing credentials this will not replace the user's data and it's safe +- Not to install extra controllers unless provided otherwise +- Not to install OIDC unless provided otherwise ## Error management diff --git a/pkg/bootstrap/steps/admin_password.go b/pkg/bootstrap/steps/admin_password.go index 760233460f..19fae4baca 100644 --- a/pkg/bootstrap/steps/admin_password.go +++ b/pkg/bootstrap/steps/admin_password.go @@ -13,8 +13,8 @@ import ( const ( adminPasswordMsg = "dashboard admin password (minimum characters: 6)" secretConfirmationMsg = "admin login credentials has been created successfully!" - adminSecretExistsErrorMsgFormat = "admin login credentials already exist on the cluster. To reset admin credentials please remove secret '%s' in namespace '%s'." - useExistingMessageFormat = "using existing admin login credentials from secret '%s' in namespace '%s'. To reset admin credentials please remove the secret." + adminSecretExistsErrorMsgFormat = "admin login credentials already exist on the cluster. To reset admin credentials please remove secret '%s' in namespace '%s'" + useExistingMessageFormat = "using existing admin login credentials from secret '%s' in namespace '%s'. To reset admin credentials please remove the secret" ) const ( diff --git a/pkg/bootstrap/steps/ask_bootstrap_flux.go b/pkg/bootstrap/steps/ask_bootstrap_flux.go index fe05b50661..180959397d 100644 --- a/pkg/bootstrap/steps/ask_bootstrap_flux.go +++ b/pkg/bootstrap/steps/ask_bootstrap_flux.go @@ -12,7 +12,7 @@ var ( Type: confirmInput, Msg: bootstrapFluxMsg, Enabled: canAskForFluxBootstrap, - DefaultValue: confirmYes, + DefaultValue: confirmNo, } ) @@ -31,12 +31,16 @@ func askBootstrapFlux(input []StepInput, c *Config) ([]StepOutput, error) { if !canAskForFluxBootstrap(input, c) { return []StepOutput{}, nil } + if c.BootstrapFlux && c.Silent { + c.Logger.Generatef("bootstrapping flux in the generic way") + return []StepOutput{}, nil + } for _, param := range input { if param.Name == inBootstrapFlux { fluxBootstrapRes, ok := param.Value.(string) if ok { if fluxBootstrapRes != "y" { - return []StepOutput{}, fmt.Errorf("flux bootstrapped error: %s", fluxFatalErrorMsg) + return []StepOutput{}, fmt.Errorf("flux error: %s", fluxFatalErrorMsg) } } diff --git a/pkg/bootstrap/steps/capi_test.go b/pkg/bootstrap/steps/capi_test.go index 6c5bfc6efa..8123c651b2 100644 --- a/pkg/bootstrap/steps/capi_test.go +++ b/pkg/bootstrap/steps/capi_test.go @@ -94,7 +94,6 @@ func TestInstallCapi(t *testing.T) { testConfig := Config{ Silent: true, WGEVersion: "1.0.0", - DomainType: domainTypeLocalhost, } wgeObject, err := createWGEHelmReleaseFakeObject("1.0.0") if err != nil { diff --git a/pkg/bootstrap/steps/config.go b/pkg/bootstrap/steps/config.go index 68f0569f8a..406ca5da32 100644 --- a/pkg/bootstrap/steps/config.go +++ b/pkg/bootstrap/steps/config.go @@ -77,6 +77,7 @@ type ConfigBuilder struct { clientID string clientSecret string PromptedForDiscoveryURL bool + bootstrapFlux bool extraComponents []string } @@ -138,6 +139,11 @@ func (c *ConfigBuilder) WithSilentFlag(silent bool) *ConfigBuilder { return c } +func (c *ConfigBuilder) WithBootstrapFluxFlag(bootstrapFlux bool) *ConfigBuilder { + c.bootstrapFlux = bootstrapFlux + return c +} + func (c *ConfigBuilder) WithExtraComponents(extraComponents []string) *ConfigBuilder { c.extraComponents = extraComponents return c @@ -184,6 +190,7 @@ type Config struct { RedirectURL string PromptedForDiscoveryURL bool + BootstrapFlux bool ExtraComponents []string } @@ -240,6 +247,7 @@ func (cb *ConfigBuilder) Build() (Config, error) { ClientSecret: cb.clientSecret, PromptedForDiscoveryURL: cb.PromptedForDiscoveryURL, ExtraComponents: cb.extraComponents, + BootstrapFlux: cb.bootstrapFlux, }, nil } diff --git a/pkg/bootstrap/steps/terraform_test.go b/pkg/bootstrap/steps/terraform_test.go index 829051e540..df1641381b 100644 --- a/pkg/bootstrap/steps/terraform_test.go +++ b/pkg/bootstrap/steps/terraform_test.go @@ -150,7 +150,6 @@ func TestInstallTerraform(t *testing.T) { testConfig := Config{ Silent: true, WGEVersion: "1.0.0", - DomainType: domainTypeLocalhost, } wgeObject, err := createWGEHelmReleaseFakeObject("1.0.0") if err != nil { From 7ac0f28ad94328f79e50c1a198f1b69f63b9ca3e Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Mon, 4 Dec 2023 20:54:32 +0200 Subject: [PATCH 09/32] remove all of above option --- pkg/bootstrap/steps/extra_controllers.go | 21 ++----------------- pkg/bootstrap/steps/extra_controllers_test.go | 2 +- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/pkg/bootstrap/steps/extra_controllers.go b/pkg/bootstrap/steps/extra_controllers.go index 2631d07e8f..ce0eea26f0 100644 --- a/pkg/bootstrap/steps/extra_controllers.go +++ b/pkg/bootstrap/steps/extra_controllers.go @@ -12,17 +12,16 @@ const ( policyAgentController = "policy-agent" tfController = "tf-controller" capiController = "capi" - allControllers = "all of above" ) // NewInstallExtraComponents start installing extra Components func NewInstallExtraComponents(config Config) BootstrapStep { inputs := []StepInput{} controllersValues := []string{ + "", policyAgentController, tfController, capiController, - allControllers, } installExtraComponentsStep := StepInput{ @@ -73,24 +72,8 @@ func installExtraComponents(input []StepInput, c *Config) ([]StepOutput, error) if err != nil { return []StepOutput{}, fmt.Errorf("can't install capi controller: %v", err) } - case allControllers: - agentStep := NewInstallPolicyAgentStep(*c) - _, err := agentStep.Execute(c) - if err != nil { - return []StepOutput{}, fmt.Errorf("can't install policy agent: %v", err) - } - tfControllerStep := NewInstallTFControllerStep(*c) - _, err = tfControllerStep.Execute(c) - if err != nil { - return []StepOutput{}, fmt.Errorf("can't install tf controller: %v", err) - } - capiStep := NewInstallCapiControllerStep(*c) - _, err = capiStep.Execute(c) - if err != nil { - return []StepOutput{}, fmt.Errorf("can't install capi controller: %v", err) - } default: - c.Logger.Successf("skipping installing controllers, selected: %s", controller) + c.Logger.Warningf("unsupported or empty controller, selected: %s", controller) return []StepOutput{}, nil } } diff --git a/pkg/bootstrap/steps/extra_controllers_test.go b/pkg/bootstrap/steps/extra_controllers_test.go index 7db63a5bc4..03a9858b9a 100644 --- a/pkg/bootstrap/steps/extra_controllers_test.go +++ b/pkg/bootstrap/steps/extra_controllers_test.go @@ -24,10 +24,10 @@ func TestNewInstallExtraComponents(t *testing.T) { Type: multiSelectionChoice, Msg: extraComponentsMsg, Values: []string{ + "", policyAgentController, tfController, capiController, - allControllers, }, DefaultValue: "", }, From 19ef3b0a5a4cf6a7ce0414e8a655b425bb68b466 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Mon, 4 Dec 2023 21:29:40 +0200 Subject: [PATCH 10/32] add case for one or more controllers --- pkg/bootstrap/steps/admin_password_test.go | 2 +- pkg/bootstrap/steps/extra_controllers_test.go | 37 ++++++++++++++----- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/pkg/bootstrap/steps/admin_password_test.go b/pkg/bootstrap/steps/admin_password_test.go index 6f8ae2cd3d..10dad74df6 100644 --- a/pkg/bootstrap/steps/admin_password_test.go +++ b/pkg/bootstrap/steps/admin_password_test.go @@ -78,7 +78,7 @@ func TestNewAskAdminCredsSecretStep(t *testing.T) { Password: "password123", }, want: BootstrapStep{}, - wantErr: "admin login credentials already exist on the cluster. To reset admin credentials please remove secret 'cluster-user-auth' in namespace 'flux-system'.", + wantErr: "admin login credentials already exist on the cluster. To reset admin credentials please remove secret 'cluster-user-auth' in namespace 'flux-system'", }, } for _, tt := range tests { diff --git a/pkg/bootstrap/steps/extra_controllers_test.go b/pkg/bootstrap/steps/extra_controllers_test.go index 03a9858b9a..9266946cba 100644 --- a/pkg/bootstrap/steps/extra_controllers_test.go +++ b/pkg/bootstrap/steps/extra_controllers_test.go @@ -65,12 +65,9 @@ func TestNewInstallExtraComponents(t *testing.T) { } func TestInstallExtraControllers(t *testing.T) { - // note: can't test controllers as it requires pushing to git - // will test the functionality with the default controller only here tests := []struct { name string stepInput []StepInput - err bool }{ { name: "test skip installing controllers with defaults (\"\")", @@ -82,18 +79,40 @@ func TestInstallExtraControllers(t *testing.T) { Value: "", }, }, - err: false, + }, + { + name: "test install controllers with policy agent ", + stepInput: []StepInput{ + { + Name: inExtraComponents, + Value: "policy-agent", + }, + }, + }, + { + name: "test install controllers with policy agent and capi", + stepInput: []StepInput{ + { + Name: inExtraComponents, + Value: policyAgentController, + }, + { + Name: inExtraComponents, + Value: capiController, + }, + }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - config := makeTestConfig(t, Config{}) - _, err := installExtraComponents(tt.stepInput, &config) + wgeObject, err := createWGEHelmReleaseFakeObject("1.0.0") + if err != nil { + t.Fatalf("error create wge object: %v", err) + } + config := makeTestConfig(t, Config{}, &wgeObject) + _, err = installExtraComponents(tt.stepInput, &config) assert.NoError(t, err, "unexpected error") if err != nil { - if tt.err { - return - } t.Fatalf("unexpected error: %v", err) } }) From 427d346a8315c30e00c9c204dd56999f376cfe34 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Mon, 4 Dec 2023 21:32:14 +0200 Subject: [PATCH 11/32] add case for silent mode --- pkg/bootstrap/steps/extra_controllers_test.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/pkg/bootstrap/steps/extra_controllers_test.go b/pkg/bootstrap/steps/extra_controllers_test.go index 9266946cba..2f141abfba 100644 --- a/pkg/bootstrap/steps/extra_controllers_test.go +++ b/pkg/bootstrap/steps/extra_controllers_test.go @@ -67,6 +67,7 @@ func TestNewInstallExtraComponents(t *testing.T) { func TestInstallExtraControllers(t *testing.T) { tests := []struct { name string + config Config stepInput []StepInput }{ { @@ -81,7 +82,14 @@ func TestInstallExtraControllers(t *testing.T) { }, }, { - name: "test install controllers with policy agent ", + name: "test skip installing controllers as default from silent mode", + config: Config{ + Silent: true, + }, + }, + { + name: "test install controllers with policy agent ", + config: Config{}, stepInput: []StepInput{ { Name: inExtraComponents, @@ -90,7 +98,8 @@ func TestInstallExtraControllers(t *testing.T) { }, }, { - name: "test install controllers with policy agent and capi", + name: "test install controllers with policy agent and capi", + config: Config{}, stepInput: []StepInput{ { Name: inExtraComponents, @@ -109,7 +118,7 @@ func TestInstallExtraControllers(t *testing.T) { if err != nil { t.Fatalf("error create wge object: %v", err) } - config := makeTestConfig(t, Config{}, &wgeObject) + config := makeTestConfig(t, tt.config, &wgeObject) _, err = installExtraComponents(tt.stepInput, &config) assert.NoError(t, err, "unexpected error") if err != nil { From 78c2bb9fcf3efa81054a0058cc6822f27302de87 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Mon, 4 Dec 2023 21:55:41 +0200 Subject: [PATCH 12/32] fix terraform controller test --- pkg/bootstrap/steps/extra_controllers.go | 2 +- pkg/bootstrap/steps/terraform.go | 14 +---- pkg/bootstrap/steps/terraform_test.go | 72 +++++------------------- 3 files changed, 15 insertions(+), 73 deletions(-) diff --git a/pkg/bootstrap/steps/extra_controllers.go b/pkg/bootstrap/steps/extra_controllers.go index ce0eea26f0..8f4e38ca98 100644 --- a/pkg/bootstrap/steps/extra_controllers.go +++ b/pkg/bootstrap/steps/extra_controllers.go @@ -73,7 +73,7 @@ func installExtraComponents(input []StepInput, c *Config) ([]StepOutput, error) return []StepOutput{}, fmt.Errorf("can't install capi controller: %v", err) } default: - c.Logger.Warningf("unsupported or empty controller, selected: %s", controller) + c.Logger.Warningf("unsupported or empty controller selected: %s", controller) return []StepOutput{}, nil } } diff --git a/pkg/bootstrap/steps/terraform.go b/pkg/bootstrap/steps/terraform.go index 38ae649a0a..df6621489c 100644 --- a/pkg/bootstrap/steps/terraform.go +++ b/pkg/bootstrap/steps/terraform.go @@ -3,8 +3,6 @@ package steps import ( "encoding/json" "fmt" - "io" - "net/http" "github.com/weaveworks/weave-gitops-enterprise/pkg/bootstrap/utils" ) @@ -31,18 +29,8 @@ func NewInstallTFControllerStep(config Config) BootstrapStep { // installTerraform start installing terraform controller helm release func installTerraform(input []StepInput, c *Config) ([]StepOutput, error) { c.Logger.Actionf(tfInstallInfoMsg) - resp, err := http.Get(tfControllerUrl) - if err != nil { - return []StepOutput{}, fmt.Errorf("error getting Terraform Controller HelmRelease: %v", err) - } - defer resp.Body.Close() - - var bodyBytes []byte - if resp.StatusCode != http.StatusOK { - return []StepOutput{}, fmt.Errorf("error getting Terraform Controller HelmRelease. status code: %d", resp.StatusCode) - } - bodyBytes, err = io.ReadAll(resp.Body) + bodyBytes, err := doBasicAuthGetRequest(tfControllerUrl, "", "") if err != nil { return []StepOutput{}, fmt.Errorf("error getting Terraform Controller HelmRelease: %v", err) } diff --git a/pkg/bootstrap/steps/terraform_test.go b/pkg/bootstrap/steps/terraform_test.go index df1641381b..42b75274c8 100644 --- a/pkg/bootstrap/steps/terraform_test.go +++ b/pkg/bootstrap/steps/terraform_test.go @@ -1,68 +1,13 @@ package steps import ( + "fmt" "testing" "github.com/stretchr/testify/assert" ) const ( - testTFControllerFile = `--- -apiVersion: source.toolkit.fluxcd.io/v1beta2 -kind: HelmRepository -metadata: - name: tf-controller - namespace: flux-system -spec: - interval: 1h0s - type: oci - url: oci://ghcr.io/weaveworks/charts ---- -apiVersion: helm.toolkit.fluxcd.io/v2beta1 -kind: HelmRelease -metadata: - name: tf-controller - namespace: flux-system -spec: - chart: - spec: - chart: tf-controller - sourceRef: - kind: HelmRepository - name: tf-controller - version: '>=0.16.0-rc.3' - interval: 1h0s - releaseName: tf-controller - targetNamespace: flux-system - install: - crds: Create - remediation: - retries: -1 - upgrade: - crds: CreateReplace - remediation: - retries: -1 - values: - replicaCount: 3 - concurrency: 24 - resources: - limits: - cpu: 1000m - memory: 2Gi - requests: - cpu: 400m - memory: 64Mi - caCertValidityDuration: 24h - certRotationCheckFrequency: 30m - image: - tag: v0.16.0-rc.3 - runner: - image: - tag: v0.16.0-rc.3 - grpc: - maxMessageSize: 30 -` - wgeHRFakeFileTFController = `apiVersion: helm.toolkit.fluxcd.io/v2beta1 kind: HelmRelease metadata: @@ -127,7 +72,7 @@ func TestInstallTerraform(t *testing.T) { Type: typeFile, Value: fileContent{ Name: tfFileName, - Content: testTFControllerFile, + Content: getTerrafromControllerTestFile(), CommitMsg: tfCommitMsg, }, }, @@ -171,11 +116,11 @@ func TestInstallTerraform(t *testing.T) { assert.Equal(t, item.Type, tt.output[i].Type, "wrong type") inFileContent, ok := tt.output[i].Value.(fileContent) if !ok { - t.Fatalf("error install tf controller: %v", err) + t.Fatalf("error test tf controller: %v", err) } outFileContent, ok := item.Value.(fileContent) if !ok { - t.Fatalf("error install tf controller: %v", err) + t.Fatalf("error test tf controller: %v", err) } assert.Equal(t, outFileContent.CommitMsg, inFileContent.CommitMsg, "wrong commit msg") assert.Equal(t, outFileContent.Name, inFileContent.Name, "wrong filename") @@ -185,3 +130,12 @@ func TestInstallTerraform(t *testing.T) { } } + +func getTerrafromControllerTestFile() string { + tfHelmFile, err := doBasicAuthGetRequest(tfControllerUrl, "", "") + if err != nil { + fmt.Printf("error getting Terraform Controller HelmRelease: %v", err) + return "" + } + return string(tfHelmFile) +} From 1c0ffab55359c57a977b4640e29866d541ac106a Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Mon, 4 Dec 2023 23:05:58 +0200 Subject: [PATCH 13/32] fix target namespace --- pkg/bootstrap/steps/policy_agent_test.go | 2 ++ pkg/bootstrap/utils/flux.go | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/bootstrap/steps/policy_agent_test.go b/pkg/bootstrap/steps/policy_agent_test.go index 4ec1d03004..b3128fcac5 100644 --- a/pkg/bootstrap/steps/policy_agent_test.go +++ b/pkg/bootstrap/steps/policy_agent_test.go @@ -39,6 +39,7 @@ spec: crds: CreateReplace createNamespace: true interval: 10m0s + targetNamespace: policy-system values: config: admission: @@ -78,6 +79,7 @@ spec: crds: CreateReplace createNamespace: true interval: 10m0s + targetNamespace: policy-system values: config: admission: diff --git a/pkg/bootstrap/utils/flux.go b/pkg/bootstrap/utils/flux.go index fb127e5969..96abec9ee5 100644 --- a/pkg/bootstrap/utils/flux.go +++ b/pkg/bootstrap/utils/flux.go @@ -70,7 +70,7 @@ func CreateHelmReleaseYamlString(hr helmv2.HelmRelease) (string, error) { } if hr.Spec.TargetNamespace != "" { - hr.Spec.TargetNamespace = helmRelease.Spec.TargetNamespace + helmRelease.Spec.TargetNamespace = hr.Spec.TargetNamespace } helmReleaseBytes, err := k8syaml.Marshal(helmRelease) From 6b5c565f461cb382a8bf908ea5daf254d0333332 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Wed, 6 Dec 2023 10:06:40 +0200 Subject: [PATCH 14/32] handle update scenario --- pkg/bootstrap/bootstrap.go | 8 ++++ pkg/bootstrap/steps/common_tests.go | 1 + pkg/bootstrap/steps/config.go | 5 ++- ...tra_controllers.go => extra_components.go} | 15 ++++--- ...llers_test.go => extra_components_test.go} | 13 ++---- pkg/bootstrap/steps/policy_agent.go | 15 +++++-- pkg/bootstrap/steps/policy_agent_test.go | 44 +++++++++++++++---- pkg/bootstrap/steps/terraform.go | 5 +++ pkg/bootstrap/steps/terraform_test.go | 21 ++++++--- 9 files changed, 93 insertions(+), 34 deletions(-) rename pkg/bootstrap/steps/{extra_controllers.go => extra_components.go} (93%) rename pkg/bootstrap/steps/{extra_controllers_test.go => extra_components_test.go} (92%) diff --git a/pkg/bootstrap/bootstrap.go b/pkg/bootstrap/bootstrap.go index 80b812f98d..c2adf7a8a0 100644 --- a/pkg/bootstrap/bootstrap.go +++ b/pkg/bootstrap/bootstrap.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/weaveworks/weave-gitops-enterprise/pkg/bootstrap/steps" + "github.com/weaveworks/weave-gitops-enterprise/pkg/bootstrap/utils" ) // Bootstrap initiated by the command runs the WGE bootstrap workflow @@ -16,6 +17,13 @@ func Bootstrap(config steps.Config) error { repositoryConfig := steps.NewGitRepositoryConfigStep(config.GitRepository) + // add existing controllers to skip installing them + for _, component := range steps.ExtraComponents { + version, err := utils.GetHelmReleaseProperty(config.KubernetesClient, component, steps.WGEDefaultNamespace, utils.HelmVersionProperty) + if err == nil && version != "" { + config.ExistingComponents = append(config.ExistingComponents, component) + } + } // TODO have a single workflow source of truth and documented in https://docs.gitops.weave.works/docs/0.33.0/enterprise/getting-started/install-enterprise/ var steps = []steps.BootstrapStep{ steps.VerifyFluxInstallation, diff --git a/pkg/bootstrap/steps/common_tests.go b/pkg/bootstrap/steps/common_tests.go index d95fd30970..6b31eec5da 100644 --- a/pkg/bootstrap/steps/common_tests.go +++ b/pkg/bootstrap/steps/common_tests.go @@ -65,6 +65,7 @@ func makeTestConfig(t *testing.T, config Config, objects ...runtime.Object) Conf PromptedForDiscoveryURL: config.PromptedForDiscoveryURL, Silent: config.Silent, ExtraComponents: config.ExtraComponents, + ExistingComponents: config.ExistingComponents, } } diff --git a/pkg/bootstrap/steps/config.go b/pkg/bootstrap/steps/config.go index 406ca5da32..e1a63a4981 100644 --- a/pkg/bootstrap/steps/config.go +++ b/pkg/bootstrap/steps/config.go @@ -190,8 +190,9 @@ type Config struct { RedirectURL string PromptedForDiscoveryURL bool - BootstrapFlux bool - ExtraComponents []string + BootstrapFlux bool + ExtraComponents []string + ExistingComponents []string } // Builds creates a valid config so boostrap could be executed. It uses values introduced diff --git a/pkg/bootstrap/steps/extra_controllers.go b/pkg/bootstrap/steps/extra_components.go similarity index 93% rename from pkg/bootstrap/steps/extra_controllers.go rename to pkg/bootstrap/steps/extra_components.go index 8f4e38ca98..30127db9da 100644 --- a/pkg/bootstrap/steps/extra_controllers.go +++ b/pkg/bootstrap/steps/extra_components.go @@ -14,21 +14,22 @@ const ( capiController = "capi" ) +var ExtraComponents = []string{ + "", + policyAgentController, + tfController, + capiController, +} + // NewInstallExtraComponents start installing extra Components func NewInstallExtraComponents(config Config) BootstrapStep { inputs := []StepInput{} - controllersValues := []string{ - "", - policyAgentController, - tfController, - capiController, - } installExtraComponentsStep := StepInput{ Name: inExtraComponents, Type: multiSelectionChoice, Msg: extraComponentsMsg, - Values: controllersValues, + Values: ExtraComponents, DefaultValue: "", } diff --git a/pkg/bootstrap/steps/extra_controllers_test.go b/pkg/bootstrap/steps/extra_components_test.go similarity index 92% rename from pkg/bootstrap/steps/extra_controllers_test.go rename to pkg/bootstrap/steps/extra_components_test.go index 2f141abfba..ae3461c154 100644 --- a/pkg/bootstrap/steps/extra_controllers_test.go +++ b/pkg/bootstrap/steps/extra_components_test.go @@ -20,15 +20,10 @@ func TestNewInstallExtraComponents(t *testing.T) { Name: "install extra components", Input: []StepInput{ { - Name: inExtraComponents, - Type: multiSelectionChoice, - Msg: extraComponentsMsg, - Values: []string{ - "", - policyAgentController, - tfController, - capiController, - }, + Name: inExtraComponents, + Type: multiSelectionChoice, + Msg: extraComponentsMsg, + Values: ExtraComponents, DefaultValue: "", }, }, diff --git a/pkg/bootstrap/steps/policy_agent.go b/pkg/bootstrap/steps/policy_agent.go index b216024758..0303288555 100644 --- a/pkg/bootstrap/steps/policy_agent.go +++ b/pkg/bootstrap/steps/policy_agent.go @@ -8,6 +8,7 @@ import ( helmv2 "github.com/fluxcd/helm-controller/api/v2beta1" sourcev1beta2 "github.com/fluxcd/source-controller/api/v1beta2" "github.com/weaveworks/weave-gitops-enterprise/pkg/bootstrap/utils" + "golang.org/x/exp/slices" apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -21,7 +22,6 @@ const ( const ( agentChartURL = "https://weaveworks.github.io/policy-agent/" agentHelmRepoName = "policy-agent" - agentHelmReleaseName = "policy-agent" agentNamespace = "policy-system" agentHelmRepoFileName = "policy-agent-helmrepo.yaml" agentHelmReleaseFileName = "policy-agent-helmrelease.yaml" @@ -40,9 +40,14 @@ var enableAdmission = StepInput{ // NewInstallPolicyAgentStep ask for continue installing OIDC func NewInstallPolicyAgentStep(config Config) BootstrapStep { config.Logger.Warningf("please note that the Policy Agent requires cert-manager to be installed!") + inputs := []StepInput{} + if !slices.Contains(config.ExistingComponents, policyAgentController) { + inputs = append(inputs, enableAdmission) + } + return BootstrapStep{ Name: "install Policy Agent", - Input: []StepInput{enableAdmission}, + Input: inputs, Step: installPolicyAgent, } } @@ -50,6 +55,10 @@ func NewInstallPolicyAgentStep(config Config) BootstrapStep { // installPolicyAgent start installing policy agent helm chart func installPolicyAgent(input []StepInput, c *Config) ([]StepOutput, error) { enableAdmission := false + if slices.Contains(c.ExistingComponents, policyAgentController) { + c.Logger.Warningf("policy agent is already installed!") + return []StepOutput{}, nil + } for _, param := range input { if param.Name == inEnableAdmission { @@ -123,7 +132,7 @@ func installPolicyAgent(input []StepInput, c *Config) ([]StepOutput, error) { APIVersion: helmv2.GroupVersion.Identifier(), }, ObjectMeta: v1.ObjectMeta{ - Name: agentHelmReleaseName, + Name: policyAgentController, Namespace: WGEDefaultNamespace, }, Spec: helmv2.HelmReleaseSpec{ Chart: helmv2.HelmChartTemplate{ diff --git a/pkg/bootstrap/steps/policy_agent_test.go b/pkg/bootstrap/steps/policy_agent_test.go index b3128fcac5..1fb9a60db3 100644 --- a/pkg/bootstrap/steps/policy_agent_test.go +++ b/pkg/bootstrap/steps/policy_agent_test.go @@ -106,6 +106,7 @@ func TestInstallPolicyAgent(t *testing.T) { name string input []StepInput output []StepOutput + config Config err bool }{ { @@ -138,7 +139,8 @@ func TestInstallPolicyAgent(t *testing.T) { }, }, }, - err: false, + config: Config{}, + err: false, }, { name: "install policy agent controller with admission enabled", @@ -170,15 +172,30 @@ func TestInstallPolicyAgent(t *testing.T) { }, }, }, + config: Config{}, + err: false, + }, + { + name: "do not install policy agent controller if it's already installed", + input: []StepInput{ + { + Name: inEnableAdmission, + Type: confirmInput, + Msg: admissionMsg, + Value: confirmYes, + }, + }, + output: []StepOutput{}, + config: Config{ + ExistingComponents: []string{policyAgentController}, + }, err: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - testConfig := Config{} - - config := makeTestConfig(t, testConfig) + config := makeTestConfig(t, tt.config) out, err := installPolicyAgent(tt.input, &config) if err != nil { if tt.err { @@ -186,7 +203,6 @@ func TestInstallPolicyAgent(t *testing.T) { } t.Fatalf("error install policy-agent: %v", err) } - for i, item := range out { assert.Equal(t, item.Name, tt.output[i].Name, "wrong name") assert.Equal(t, item.Type, tt.output[i].Type, "wrong type") @@ -209,8 +225,9 @@ func TestInstallPolicyAgent(t *testing.T) { func TestNewInstallPolicyAgentStep(t *testing.T) { tests := []struct { - name string - want BootstrapStep + name string + config Config + want BootstrapStep }{ { @@ -221,11 +238,22 @@ func TestNewInstallPolicyAgentStep(t *testing.T) { enableAdmission, }, }, + config: Config{}, + }, + { + name: "return bootstrap with no input in case existing installation", + want: BootstrapStep{ + Name: "install Policy Agent", + Input: []StepInput{}, + }, + config: Config{ + ExistingComponents: []string{policyAgentController}, + }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - config := makeTestConfig(t, Config{}) + config := makeTestConfig(t, tt.config) step := NewInstallPolicyAgentStep(config) assert.Equal(t, tt.want.Name, step.Name) diff --git a/pkg/bootstrap/steps/terraform.go b/pkg/bootstrap/steps/terraform.go index df6621489c..8e72de6a4e 100644 --- a/pkg/bootstrap/steps/terraform.go +++ b/pkg/bootstrap/steps/terraform.go @@ -5,6 +5,7 @@ import ( "fmt" "github.com/weaveworks/weave-gitops-enterprise/pkg/bootstrap/utils" + "golang.org/x/exp/slices" ) const ( @@ -28,6 +29,10 @@ func NewInstallTFControllerStep(config Config) BootstrapStep { // installTerraform start installing terraform controller helm release func installTerraform(input []StepInput, c *Config) ([]StepOutput, error) { + if slices.Contains(c.ExistingComponents, tfController) { + c.Logger.Warningf("terraform controller is already installed!") + return []StepOutput{}, nil + } c.Logger.Actionf(tfInstallInfoMsg) bodyBytes, err := doBasicAuthGetRequest(tfControllerUrl, "", "") diff --git a/pkg/bootstrap/steps/terraform_test.go b/pkg/bootstrap/steps/terraform_test.go index 42b75274c8..d9b4e09cdb 100644 --- a/pkg/bootstrap/steps/terraform_test.go +++ b/pkg/bootstrap/steps/terraform_test.go @@ -62,6 +62,7 @@ func TestInstallTerraform(t *testing.T) { name string input []StepInput output []StepOutput + config Config err bool }{ { @@ -86,22 +87,32 @@ func TestInstallTerraform(t *testing.T) { }, }, }, + config: Config{ + Silent: true, + WGEVersion: "1.0.0", + }, + err: false, + }, + { + name: "do not install if tf controller exists", + output: []StepOutput{}, + config: Config{ + ExistingComponents: []string{tfController}, + Silent: true, + WGEVersion: "1.0.0", + }, err: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - testConfig := Config{ - Silent: true, - WGEVersion: "1.0.0", - } wgeObject, err := createWGEHelmReleaseFakeObject("1.0.0") if err != nil { t.Fatalf("error create wge object: %v", err) } - config := makeTestConfig(t, testConfig, &wgeObject) + config := makeTestConfig(t, tt.config, &wgeObject) out, err := installTerraform(tt.input, &config) if err != nil { From ace8486522ca8030b38cedbf9dea28b1f09f75ca Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Wed, 6 Dec 2023 13:37:56 +0200 Subject: [PATCH 15/32] rename extra components to componetes extra to align with flag --- pkg/bootstrap/bootstrap.go | 2 +- pkg/bootstrap/steps/common_tests.go | 2 +- ...xtra_components.go => components_extra.go} | 20 +++++++++---------- ...nents_test.go => components_extra_test.go} | 18 ++++++++--------- pkg/bootstrap/steps/config.go | 12 +++++------ 5 files changed, 27 insertions(+), 27 deletions(-) rename pkg/bootstrap/steps/{extra_components.go => components_extra.go} (78%) rename pkg/bootstrap/steps/{extra_components_test.go => components_extra_test.go} (89%) diff --git a/pkg/bootstrap/bootstrap.go b/pkg/bootstrap/bootstrap.go index c2adf7a8a0..338a77a9cc 100644 --- a/pkg/bootstrap/bootstrap.go +++ b/pkg/bootstrap/bootstrap.go @@ -18,7 +18,7 @@ func Bootstrap(config steps.Config) error { repositoryConfig := steps.NewGitRepositoryConfigStep(config.GitRepository) // add existing controllers to skip installing them - for _, component := range steps.ExtraComponents { + for _, component := range steps.ComponentsExtra { version, err := utils.GetHelmReleaseProperty(config.KubernetesClient, component, steps.WGEDefaultNamespace, utils.HelmVersionProperty) if err == nil && version != "" { config.ExistingComponents = append(config.ExistingComponents, component) diff --git a/pkg/bootstrap/steps/common_tests.go b/pkg/bootstrap/steps/common_tests.go index 6b31eec5da..4226c8db19 100644 --- a/pkg/bootstrap/steps/common_tests.go +++ b/pkg/bootstrap/steps/common_tests.go @@ -64,7 +64,7 @@ func makeTestConfig(t *testing.T, config Config, objects ...runtime.Object) Conf RedirectURL: config.RedirectURL, PromptedForDiscoveryURL: config.PromptedForDiscoveryURL, Silent: config.Silent, - ExtraComponents: config.ExtraComponents, + ComponentsExtra: config.ComponentsExtra, ExistingComponents: config.ExistingComponents, } } diff --git a/pkg/bootstrap/steps/extra_components.go b/pkg/bootstrap/steps/components_extra.go similarity index 78% rename from pkg/bootstrap/steps/extra_components.go rename to pkg/bootstrap/steps/components_extra.go index 30127db9da..8010289d96 100644 --- a/pkg/bootstrap/steps/extra_components.go +++ b/pkg/bootstrap/steps/components_extra.go @@ -5,7 +5,7 @@ import ( ) const ( - extraComponentsMsg = "do you want to install extra Components from the following on your cluster" + componentsExtraMsg = "do you want to install extra Components from the following on your cluster" ) const ( @@ -14,7 +14,7 @@ const ( capiController = "capi" ) -var ExtraComponents = []string{ +var ComponentsExtra = []string{ "", policyAgentController, tfController, @@ -26,14 +26,14 @@ func NewInstallExtraComponents(config Config) BootstrapStep { inputs := []StepInput{} installExtraComponentsStep := StepInput{ - Name: inExtraComponents, + Name: inComponentsExtra, Type: multiSelectionChoice, - Msg: extraComponentsMsg, - Values: ExtraComponents, + Msg: componentsExtraMsg, + Values: ComponentsExtra, DefaultValue: "", } - if len(config.ExtraComponents) < 1 && !config.Silent { + if len(config.ComponentsExtra) < 1 && !config.Silent { inputs = append(inputs, installExtraComponentsStep) } @@ -46,14 +46,14 @@ func NewInstallExtraComponents(config Config) BootstrapStep { func installExtraComponents(input []StepInput, c *Config) ([]StepOutput, error) { for _, param := range input { - if param.Name == inExtraComponents { - extraComponents, ok := param.Value.(string) + if param.Name == inComponentsExtra { + componentsExtra, ok := param.Value.(string) if ok { - c.ExtraComponents = append(c.ExtraComponents, extraComponents) + c.ComponentsExtra = append(c.ComponentsExtra, componentsExtra) } } } - for _, controller := range c.ExtraComponents { + for _, controller := range c.ComponentsExtra { switch controller { case policyAgentController: agentStep := NewInstallPolicyAgentStep(*c) diff --git a/pkg/bootstrap/steps/extra_components_test.go b/pkg/bootstrap/steps/components_extra_test.go similarity index 89% rename from pkg/bootstrap/steps/extra_components_test.go rename to pkg/bootstrap/steps/components_extra_test.go index ae3461c154..e086ca66a6 100644 --- a/pkg/bootstrap/steps/extra_components_test.go +++ b/pkg/bootstrap/steps/components_extra_test.go @@ -20,10 +20,10 @@ func TestNewInstallExtraComponents(t *testing.T) { Name: "install extra components", Input: []StepInput{ { - Name: inExtraComponents, + Name: inComponentsExtra, Type: multiSelectionChoice, - Msg: extraComponentsMsg, - Values: ExtraComponents, + Msg: componentsExtraMsg, + Values: ComponentsExtra, DefaultValue: "", }, }, @@ -33,7 +33,7 @@ func TestNewInstallExtraComponents(t *testing.T) { { name: "return bootstrap step with empty inputs in case not provided by user", config: Config{ - ExtraComponents: []string{ + ComponentsExtra: []string{ policyAgentController, tfController, capiController, @@ -69,9 +69,9 @@ func TestInstallExtraControllers(t *testing.T) { name: "test skip installing controllers with defaults (\"\")", stepInput: []StepInput{ { - Name: inExtraComponents, + Name: inComponentsExtra, Type: multiSelectionChoice, - Msg: extraComponentsMsg, + Msg: componentsExtraMsg, Value: "", }, }, @@ -87,7 +87,7 @@ func TestInstallExtraControllers(t *testing.T) { config: Config{}, stepInput: []StepInput{ { - Name: inExtraComponents, + Name: inComponentsExtra, Value: "policy-agent", }, }, @@ -97,11 +97,11 @@ func TestInstallExtraControllers(t *testing.T) { config: Config{}, stepInput: []StepInput{ { - Name: inExtraComponents, + Name: inComponentsExtra, Value: policyAgentController, }, { - Name: inExtraComponents, + Name: inComponentsExtra, Value: capiController, }, }, diff --git a/pkg/bootstrap/steps/config.go b/pkg/bootstrap/steps/config.go index e1a63a4981..14efa147de 100644 --- a/pkg/bootstrap/steps/config.go +++ b/pkg/bootstrap/steps/config.go @@ -43,7 +43,7 @@ const ( inGitUserName = "username" inGitPassword = "gitPassowrd" inBootstrapFlux = "bootstrapFlux" - inExtraComponents = "extraComponents" + inComponentsExtra = "componentsExtra" inEnableAdmission = "enableAdmission" ) @@ -78,7 +78,7 @@ type ConfigBuilder struct { clientSecret string PromptedForDiscoveryURL bool bootstrapFlux bool - extraComponents []string + componentsExtra []string } func NewConfigBuilder() *ConfigBuilder { @@ -144,8 +144,8 @@ func (c *ConfigBuilder) WithBootstrapFluxFlag(bootstrapFlux bool) *ConfigBuilder return c } -func (c *ConfigBuilder) WithExtraComponents(extraComponents []string) *ConfigBuilder { - c.extraComponents = extraComponents +func (c *ConfigBuilder) WithComponentsExtra(componentsExtra []string) *ConfigBuilder { + c.componentsExtra = componentsExtra return c } @@ -191,7 +191,7 @@ type Config struct { PromptedForDiscoveryURL bool BootstrapFlux bool - ExtraComponents []string + ComponentsExtra []string ExistingComponents []string } @@ -247,7 +247,7 @@ func (cb *ConfigBuilder) Build() (Config, error) { ClientID: cb.clientID, ClientSecret: cb.clientSecret, PromptedForDiscoveryURL: cb.PromptedForDiscoveryURL, - ExtraComponents: cb.extraComponents, + ComponentsExtra: cb.componentsExtra, BootstrapFlux: cb.bootstrapFlux, }, nil From 68ef627e6e6554f35f26001373874ac56a141fad Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Wed, 6 Dec 2023 13:44:25 +0200 Subject: [PATCH 16/32] fix flags --- cmd/gitops/app/bootstrap/cmd.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/gitops/app/bootstrap/cmd.go b/cmd/gitops/app/bootstrap/cmd.go index 302ff3a445..c82909aed2 100644 --- a/cmd/gitops/app/bootstrap/cmd.go +++ b/cmd/gitops/app/bootstrap/cmd.go @@ -73,7 +73,7 @@ type bootstrapFlags struct { bootstrapFlux bool // extra controllers - extraComponents []string + componentsExtra []string } var flags bootstrapFlags @@ -88,7 +88,7 @@ func Command(opts *config.Options) *cobra.Command { } cmd.Flags().StringVarP(&flags.version, "version", "v", "", "version of Weave GitOps Enterprise (should be from the latest 3 versions)") - cmd.Flags().StringSliceVar(&flags.extraComponents, "components-extra", nil, "extra components to be installed from (policy-agent, tf-controller, capi)") + cmd.Flags().StringSliceVar(&flags.componentsExtra, "components-extra", nil, "extra components to be installed from (policy-agent, tf-controller, capi)") cmd.PersistentFlags().BoolVarP(&flags.silent, "silent", "s", false, "chose the defaults with current provided information without asking any questions") cmd.PersistentFlags().BoolVarP(&flags.bootstrapFlux, "bootstrap-flux", "", false, "chose whether you want to install flux in the generic way in case no flux installation detected") cmd.PersistentFlags().StringVarP(&flags.gitUsername, "git-username", "", "", "git username used in https authentication type") @@ -127,7 +127,7 @@ func getBootstrapCmdRun(opts *config.Options) func(*cobra.Command, []string) err WithOIDCConfig(flags.discoveryURL, flags.clientID, flags.clientSecret, true). WithSilentFlag(flags.silent). WithBootstrapFluxFlag(flags.bootstrapFlux). - WithExtraComponents(flags.extraComponents). + WithComponentsExtra(flags.componentsExtra). Build() if err != nil { From 0fbf5e6e7fcf37525607edfd8262f071c2ff9307 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Wed, 6 Dec 2023 13:50:12 +0200 Subject: [PATCH 17/32] add test case for bootstrap flux in silent mode --- pkg/bootstrap/steps/ask_bootstrap_flux.go | 2 +- pkg/bootstrap/steps/ask_bootstrap_flux_test.go | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/pkg/bootstrap/steps/ask_bootstrap_flux.go b/pkg/bootstrap/steps/ask_bootstrap_flux.go index 180959397d..074bdd20ef 100644 --- a/pkg/bootstrap/steps/ask_bootstrap_flux.go +++ b/pkg/bootstrap/steps/ask_bootstrap_flux.go @@ -51,5 +51,5 @@ func askBootstrapFlux(input []StepInput, c *Config) ([]StepOutput, error) { // canAskForGitConfig if fluxInstallation is false, then can ask for git config func canAskForFluxBootstrap(input []StepInput, c *Config) bool { - return !c.FluxInstallated + return !c.FluxInstallated && !c.Silent } diff --git a/pkg/bootstrap/steps/ask_bootstrap_flux_test.go b/pkg/bootstrap/steps/ask_bootstrap_flux_test.go index df6f52a982..e823784867 100644 --- a/pkg/bootstrap/steps/ask_bootstrap_flux_test.go +++ b/pkg/bootstrap/steps/ask_bootstrap_flux_test.go @@ -51,6 +51,17 @@ func TestAskBootstrapFlux(t *testing.T) { err: false, canAsk: true, }, + { + name: "check with silent mode and bootstrap flux flag available", + input: []StepInput{}, + config: &Config{ + FluxInstallated: false, + BootstrapFlux: true, + Silent: true, + }, + err: false, + canAsk: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { From c3b9291d276d2cc95e7fa88ec9706a8a5cee5f59 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Wed, 6 Dec 2023 13:55:43 +0200 Subject: [PATCH 18/32] don't use yes as default and fail if no defaults set --- pkg/bootstrap/steps/install_wge.go | 7 ++----- pkg/bootstrap/steps/step.go | 2 +- pkg/bootstrap/steps/wge_version.go | 9 +++++---- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/pkg/bootstrap/steps/install_wge.go b/pkg/bootstrap/steps/install_wge.go index e90e43c1f1..0ae6ce6d88 100644 --- a/pkg/bootstrap/steps/install_wge.go +++ b/pkg/bootstrap/steps/install_wge.go @@ -38,12 +38,9 @@ const ( // NewInstallWGEStep step to install Weave GitOps Enterprise func NewInstallWGEStep() BootstrapStep { - inputs := []StepInput{} - return BootstrapStep{ - Name: "Install Weave GitOps Enterprise", - Input: inputs, - Step: installWge, + Name: "Install Weave GitOps Enterprise", + Step: installWge, } } diff --git a/pkg/bootstrap/steps/step.go b/pkg/bootstrap/steps/step.go index 47f64fb410..31dd089a6d 100644 --- a/pkg/bootstrap/steps/step.go +++ b/pkg/bootstrap/steps/step.go @@ -154,7 +154,7 @@ func defaultInputStep(inputs []StepInput, c *Config, stdin io.ReadCloser) ([]Ste if ok { input.Value = defaultVal } else { - input.Value = confirmYes + return []StepInput{}, fmt.Errorf("invalid default value: %v", input.DefaultValue) } } diff --git a/pkg/bootstrap/steps/wge_version.go b/pkg/bootstrap/steps/wge_version.go index 81731d12f6..5bca5b2a18 100644 --- a/pkg/bootstrap/steps/wge_version.go +++ b/pkg/bootstrap/steps/wge_version.go @@ -19,10 +19,11 @@ const ( ) var getVersionInput = StepInput{ - Name: inWGEVersion, - Type: multiSelectionChoice, - Msg: versionMsg, - Valuesfn: getWgeVersions, + Name: inWGEVersion, + Type: multiSelectionChoice, + Msg: versionMsg, + Valuesfn: getWgeVersions, + DefaultValue: "", } func NewSelectWgeVersionStep(config Config) BootstrapStep { From 7853602135838efef37a91ba9f0e30f5a0c63f8c Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Wed, 6 Dec 2023 14:58:56 +0200 Subject: [PATCH 19/32] remove capi controller and refactor configuration --- pkg/bootstrap/bootstrap.go | 12 +- pkg/bootstrap/steps/capi.go | 81 ------------ pkg/bootstrap/steps/capi_test.go | 131 ------------------- pkg/bootstrap/steps/common_tests.go | 1 - pkg/bootstrap/steps/components_extra.go | 55 +++++--- pkg/bootstrap/steps/components_extra_test.go | 19 ++- pkg/bootstrap/steps/config.go | 12 +- pkg/bootstrap/steps/policy_agent.go | 4 +- pkg/bootstrap/steps/policy_agent_test.go | 10 +- pkg/bootstrap/steps/terraform.go | 2 +- pkg/bootstrap/steps/terraform_test.go | 8 +- 11 files changed, 79 insertions(+), 256 deletions(-) delete mode 100644 pkg/bootstrap/steps/capi.go delete mode 100644 pkg/bootstrap/steps/capi_test.go diff --git a/pkg/bootstrap/bootstrap.go b/pkg/bootstrap/bootstrap.go index 338a77a9cc..00b1e85ef3 100644 --- a/pkg/bootstrap/bootstrap.go +++ b/pkg/bootstrap/bootstrap.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/weaveworks/weave-gitops-enterprise/pkg/bootstrap/steps" - "github.com/weaveworks/weave-gitops-enterprise/pkg/bootstrap/utils" ) // Bootstrap initiated by the command runs the WGE bootstrap workflow @@ -17,13 +16,8 @@ func Bootstrap(config steps.Config) error { repositoryConfig := steps.NewGitRepositoryConfigStep(config.GitRepository) - // add existing controllers to skip installing them - for _, component := range steps.ComponentsExtra { - version, err := utils.GetHelmReleaseProperty(config.KubernetesClient, component, steps.WGEDefaultNamespace, utils.HelmVersionProperty) - if err == nil && version != "" { - config.ExistingComponents = append(config.ExistingComponents, component) - } - } + componentesExtra := steps.NewInstallExtraComponentsStep(config.ComponentsExtra, config.Silent) + // TODO have a single workflow source of truth and documented in https://docs.gitops.weave.works/docs/0.33.0/enterprise/getting-started/install-enterprise/ var steps = []steps.BootstrapStep{ steps.VerifyFluxInstallation, @@ -36,7 +30,7 @@ func Bootstrap(config steps.Config) error { steps.NewInstallWGEStep(), steps.NewInstallOIDCStep(config), steps.NewOIDCConfigStep(config), - steps.NewInstallExtraComponents(config), + componentesExtra, steps.CheckUIDomainStep, } diff --git a/pkg/bootstrap/steps/capi.go b/pkg/bootstrap/steps/capi.go deleted file mode 100644 index 685096ea96..0000000000 --- a/pkg/bootstrap/steps/capi.go +++ /dev/null @@ -1,81 +0,0 @@ -package steps - -import ( - "encoding/json" - "fmt" - - "github.com/weaveworks/weave-gitops-enterprise/pkg/bootstrap/utils" -) - -const ( - capiInstallInfoMsg = "installing Capi Controller ..." - capiInstallConfirmMsg = "Capi Controller is installed successfully" -) - -const ( - capiCommitMsg = "Add Capi Controller" - defaultNamespace = "default" -) - -// NewInstallCapiControllerStep ask for continue installing OIDC -func NewInstallCapiControllerStep(config Config) BootstrapStep { - return BootstrapStep{ - Name: "install Capi Controller", - Step: installCapi, - } -} - -// installCapi start installing CAPI controller -func installCapi(input []StepInput, c *Config) ([]StepOutput, error) { - c.Logger.Actionf(capiInstallInfoMsg) - - capiValues := map[string]interface{}{ - "repositoryURL": c.RepoURL, - "repositoryPath": fmt.Sprintf("%s/clusters", c.RepoPath), - "repositoryClustersPath": c.RepoPath, - "baseBranch": c.Branch, - "templates": map[string]interface{}{ - "namespace": defaultNamespace, - }, - "clusters": map[string]interface{}{ - "namespace": defaultNamespace, - }, - } - - // enable capi in wge chart - valuesBytes, err := utils.GetHelmReleaseValues(c.KubernetesClient, WgeHelmReleaseName, WGEDefaultNamespace) - if err != nil { - return []StepOutput{}, err - } - var wgeValues valuesFile - - err = json.Unmarshal(valuesBytes, &wgeValues) - if err != nil { - return []StepOutput{}, err - } - - wgeValues.Global.CapiEnabled = true - wgeValues.Config.CAPI = capiValues - - wgeHelmRelease, err := constructWGEhelmRelease(wgeValues, c.WGEVersion) - if err != nil { - return []StepOutput{}, err - } - c.Logger.Actionf("rendered WGE HelmRelease file") - - c.Logger.Actionf("updating HelmRelease file") - helmreleaseFile := fileContent{ - Name: wgeHelmReleaseFileName, - Content: wgeHelmRelease, - CommitMsg: capiCommitMsg, - } - - c.Logger.Successf(capiInstallConfirmMsg) - return []StepOutput{ - { - Name: wgeHelmReleaseFileName, - Type: typeFile, - Value: helmreleaseFile, - }, - }, nil -} diff --git a/pkg/bootstrap/steps/capi_test.go b/pkg/bootstrap/steps/capi_test.go deleted file mode 100644 index 8123c651b2..0000000000 --- a/pkg/bootstrap/steps/capi_test.go +++ /dev/null @@ -1,131 +0,0 @@ -package steps - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -const ( - wgeHRFakeFileCapiController = `apiVersion: helm.toolkit.fluxcd.io/v2beta1 -kind: HelmRelease -metadata: - creationTimestamp: null - name: weave-gitops-enterprise - namespace: flux-system -spec: - chart: - spec: - chart: mccp - reconcileStrategy: ChartVersion - sourceRef: - kind: HelmRepository - name: weave-gitops-enterprise-charts - namespace: flux-system - version: 1.0.0 - install: - crds: CreateReplace - interval: 1h0m0s - upgrade: - crds: CreateReplace - values: - cluster-controller: - controllerManager: - manager: - image: - repository: docker.io/weaveworks/cluster-controller - tag: v1.5.2 - enabled: true - fullnameOverride: cluster - config: - capi: - baseBranch: "" - clusters: - namespace: default - repositoryClustersPath: "" - repositoryPath: /clusters - repositoryURL: "" - templates: - namespace: default - enablePipelines: true - gitopssets-controller: - controllerManager: - manager: - args: - - --health-probe-bind-address=:8081 - - --metrics-bind-address=127.0.0.1:8080 - - --leader-elect - - --enabled-generators=GitRepository,Cluster,PullRequests,List,APIClient,Matrix,Config - enabled: true - global: - capiEnabled: true - tls: - enabled: false -status: {} -` -) - -func TestInstallCapi(t *testing.T) { - tests := []struct { - name string - input []StepInput - output []StepOutput - err bool - }{ - { - name: "install capi controller", - output: []StepOutput{ - { - Name: wgeHelmReleaseFileName, - Type: typeFile, - Value: fileContent{ - Name: wgeHelmReleaseFileName, - Content: wgeHRFakeFileCapiController, - CommitMsg: capiCommitMsg, - }, - }, - }, - err: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - testConfig := Config{ - Silent: true, - WGEVersion: "1.0.0", - } - wgeObject, err := createWGEHelmReleaseFakeObject("1.0.0") - if err != nil { - t.Fatalf("error create wge object: %v", err) - } - - config := makeTestConfig(t, testConfig, &wgeObject) - - out, err := installCapi(tt.input, &config) - if err != nil { - if tt.err { - return - } - t.Fatalf("error install capi controller: %v", err) - } - - for i, item := range out { - assert.Equal(t, item.Name, tt.output[i].Name, "wrong name") - assert.Equal(t, item.Type, tt.output[i].Type, "wrong type") - inFileContent, ok := tt.output[i].Value.(fileContent) - if !ok { - t.Fatalf("error install capi controller: %v", err) - } - outFileContent, ok := item.Value.(fileContent) - if !ok { - t.Fatalf("error install capi controller: %v", err) - } - assert.Equal(t, outFileContent.CommitMsg, inFileContent.CommitMsg, "wrong commit msg") - assert.Equal(t, outFileContent.Name, inFileContent.Name, "wrong filename") - assert.Equal(t, outFileContent.Content, inFileContent.Content, "wrong content") - } - }) - } - -} diff --git a/pkg/bootstrap/steps/common_tests.go b/pkg/bootstrap/steps/common_tests.go index 4226c8db19..9a92817bc2 100644 --- a/pkg/bootstrap/steps/common_tests.go +++ b/pkg/bootstrap/steps/common_tests.go @@ -65,7 +65,6 @@ func makeTestConfig(t *testing.T, config Config, objects ...runtime.Object) Conf PromptedForDiscoveryURL: config.PromptedForDiscoveryURL, Silent: config.Silent, ComponentsExtra: config.ComponentsExtra, - ExistingComponents: config.ExistingComponents, } } diff --git a/pkg/bootstrap/steps/components_extra.go b/pkg/bootstrap/steps/components_extra.go index 8010289d96..937578ba15 100644 --- a/pkg/bootstrap/steps/components_extra.go +++ b/pkg/bootstrap/steps/components_extra.go @@ -2,6 +2,10 @@ package steps import ( "fmt" + + "github.com/weaveworks/weave-gitops-enterprise/pkg/bootstrap/utils" + "golang.org/x/exp/slices" + "sigs.k8s.io/controller-runtime/pkg/client" ) const ( @@ -11,18 +15,43 @@ const ( const ( policyAgentController = "policy-agent" tfController = "tf-controller" - capiController = "capi" ) var ComponentsExtra = []string{ "", policyAgentController, tfController, - capiController, } -// NewInstallExtraComponents start installing extra Components -func NewInstallExtraComponents(config Config) BootstrapStep { +// ComponentsExtraConfig contains the configuration for the extra components +type ComponentsExtraConfig struct { + Requested []string + Existing []string +} + +// NewInstallExtraComponentsConfig handles the extra components configurations +func NewInstallExtraComponentsConfig(components []string, client client.Client) (ComponentsExtraConfig, error) { + // validate requested components against pre-defined ComponentsExtra + config := ComponentsExtraConfig{ + Requested: components, + } + for _, component := range config.Requested { + if !slices.Contains(ComponentsExtra, component) { + return ComponentsExtraConfig{}, fmt.Errorf("unsupported component selected: %s", component) + } + } + // check existing components + for _, component := range ComponentsExtra { + version, err := utils.GetHelmReleaseProperty(client, component, WGEDefaultNamespace, utils.HelmVersionProperty) + if err == nil && version != "" { + config.Existing = append(config.Existing, component) + } + } + return config, nil +} + +// NewInstallExtraComponents contains the extra components installation step +func NewInstallExtraComponentsStep(config ComponentsExtraConfig, silent bool) BootstrapStep { inputs := []StepInput{} installExtraComponentsStep := StepInput{ @@ -33,7 +62,7 @@ func NewInstallExtraComponents(config Config) BootstrapStep { DefaultValue: "", } - if len(config.ComponentsExtra) < 1 && !config.Silent { + if len(config.Requested) < 1 && !silent { inputs = append(inputs, installExtraComponentsStep) } @@ -49,11 +78,11 @@ func installExtraComponents(input []StepInput, c *Config) ([]StepOutput, error) if param.Name == inComponentsExtra { componentsExtra, ok := param.Value.(string) if ok { - c.ComponentsExtra = append(c.ComponentsExtra, componentsExtra) + c.ComponentsExtra.Requested = append(c.ComponentsExtra.Requested, componentsExtra) } } } - for _, controller := range c.ComponentsExtra { + for _, controller := range c.ComponentsExtra.Requested { switch controller { case policyAgentController: agentStep := NewInstallPolicyAgentStep(*c) @@ -67,15 +96,11 @@ func installExtraComponents(input []StepInput, c *Config) ([]StepOutput, error) if err != nil { return []StepOutput{}, fmt.Errorf("can't install tf controller: %v", err) } - case capiController: - capiStep := NewInstallCapiControllerStep(*c) - _, err := capiStep.Execute(c) - if err != nil { - return []StepOutput{}, fmt.Errorf("can't install capi controller: %v", err) - } - default: - c.Logger.Warningf("unsupported or empty controller selected: %s", controller) + case "": + c.Logger.Successf("selected none extra components") return []StepOutput{}, nil + default: + return []StepOutput{}, fmt.Errorf("unsupported component selected: %s", controller) } } diff --git a/pkg/bootstrap/steps/components_extra_test.go b/pkg/bootstrap/steps/components_extra_test.go index e086ca66a6..48436b316b 100644 --- a/pkg/bootstrap/steps/components_extra_test.go +++ b/pkg/bootstrap/steps/components_extra_test.go @@ -33,10 +33,11 @@ func TestNewInstallExtraComponents(t *testing.T) { { name: "return bootstrap step with empty inputs in case not provided by user", config: Config{ - ComponentsExtra: []string{ - policyAgentController, - tfController, - capiController, + ComponentsExtra: ComponentsExtraConfig{ + Requested: []string{ + policyAgentController, + tfController, + }, }, }, want: BootstrapStep{ @@ -49,7 +50,11 @@ func TestNewInstallExtraComponents(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { config := makeTestConfig(t, tt.config) - step := NewInstallExtraComponents(config) + stepConfig, err := NewInstallExtraComponentsConfig(tt.config.ComponentsExtra.Requested, config.KubernetesClient) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + step := NewInstallExtraComponentsStep(stepConfig, config.Silent) assert.Equal(t, tt.want.Name, step.Name) if diff := cmp.Diff(tt.want.Input, step.Input); diff != "" { @@ -93,7 +98,7 @@ func TestInstallExtraControllers(t *testing.T) { }, }, { - name: "test install controllers with policy agent and capi", + name: "test install controllers with policy agent and terraform", config: Config{}, stepInput: []StepInput{ { @@ -102,7 +107,7 @@ func TestInstallExtraControllers(t *testing.T) { }, { Name: inComponentsExtra, - Value: capiController, + Value: tfController, }, }, }, diff --git a/pkg/bootstrap/steps/config.go b/pkg/bootstrap/steps/config.go index 14efa147de..c77a6422a3 100644 --- a/pkg/bootstrap/steps/config.go +++ b/pkg/bootstrap/steps/config.go @@ -190,9 +190,8 @@ type Config struct { RedirectURL string PromptedForDiscoveryURL bool - BootstrapFlux bool - ComponentsExtra []string - ExistingComponents []string + BootstrapFlux bool + ComponentsExtra ComponentsExtraConfig } // Builds creates a valid config so boostrap could be executed. It uses values introduced @@ -224,6 +223,11 @@ func (cb *ConfigBuilder) Build() (Config, error) { return Config{}, fmt.Errorf("error creating git repository configuration: %v", err) } + componentsExtraConfig, err := NewInstallExtraComponentsConfig(cb.componentsExtra, kubeHttp.Client) + if err != nil { + return Config{}, fmt.Errorf("cannot create components extra configuration: %v", err) + } + //TODO we should do validations in case invalid values and throw an error early return Config{ KubernetesClient: kubeHttp.Client, @@ -247,7 +251,7 @@ func (cb *ConfigBuilder) Build() (Config, error) { ClientID: cb.clientID, ClientSecret: cb.clientSecret, PromptedForDiscoveryURL: cb.PromptedForDiscoveryURL, - ComponentsExtra: cb.componentsExtra, + ComponentsExtra: componentsExtraConfig, BootstrapFlux: cb.bootstrapFlux, }, nil diff --git a/pkg/bootstrap/steps/policy_agent.go b/pkg/bootstrap/steps/policy_agent.go index 0303288555..2b6519f39f 100644 --- a/pkg/bootstrap/steps/policy_agent.go +++ b/pkg/bootstrap/steps/policy_agent.go @@ -41,7 +41,7 @@ var enableAdmission = StepInput{ func NewInstallPolicyAgentStep(config Config) BootstrapStep { config.Logger.Warningf("please note that the Policy Agent requires cert-manager to be installed!") inputs := []StepInput{} - if !slices.Contains(config.ExistingComponents, policyAgentController) { + if !slices.Contains(config.ComponentsExtra.Existing, policyAgentController) { inputs = append(inputs, enableAdmission) } @@ -55,7 +55,7 @@ func NewInstallPolicyAgentStep(config Config) BootstrapStep { // installPolicyAgent start installing policy agent helm chart func installPolicyAgent(input []StepInput, c *Config) ([]StepOutput, error) { enableAdmission := false - if slices.Contains(c.ExistingComponents, policyAgentController) { + if slices.Contains(c.ComponentsExtra.Existing, policyAgentController) { c.Logger.Warningf("policy agent is already installed!") return []StepOutput{}, nil } diff --git a/pkg/bootstrap/steps/policy_agent_test.go b/pkg/bootstrap/steps/policy_agent_test.go index 1fb9a60db3..55c5062eff 100644 --- a/pkg/bootstrap/steps/policy_agent_test.go +++ b/pkg/bootstrap/steps/policy_agent_test.go @@ -187,7 +187,10 @@ func TestInstallPolicyAgent(t *testing.T) { }, output: []StepOutput{}, config: Config{ - ExistingComponents: []string{policyAgentController}, + ComponentsExtra: ComponentsExtraConfig{ + Requested: []string{policyAgentController}, + Existing: []string{policyAgentController}, + }, }, err: false, }, @@ -247,7 +250,10 @@ func TestNewInstallPolicyAgentStep(t *testing.T) { Input: []StepInput{}, }, config: Config{ - ExistingComponents: []string{policyAgentController}, + ComponentsExtra: ComponentsExtraConfig{ + Existing: []string{policyAgentController}, + Requested: []string{policyAgentController}, + }, }, }, } diff --git a/pkg/bootstrap/steps/terraform.go b/pkg/bootstrap/steps/terraform.go index 8e72de6a4e..e04d917056 100644 --- a/pkg/bootstrap/steps/terraform.go +++ b/pkg/bootstrap/steps/terraform.go @@ -29,7 +29,7 @@ func NewInstallTFControllerStep(config Config) BootstrapStep { // installTerraform start installing terraform controller helm release func installTerraform(input []StepInput, c *Config) ([]StepOutput, error) { - if slices.Contains(c.ExistingComponents, tfController) { + if slices.Contains(c.ComponentsExtra.Existing, tfController) { c.Logger.Warningf("terraform controller is already installed!") return []StepOutput{}, nil } diff --git a/pkg/bootstrap/steps/terraform_test.go b/pkg/bootstrap/steps/terraform_test.go index d9b4e09cdb..6f4c36c937 100644 --- a/pkg/bootstrap/steps/terraform_test.go +++ b/pkg/bootstrap/steps/terraform_test.go @@ -97,9 +97,11 @@ func TestInstallTerraform(t *testing.T) { name: "do not install if tf controller exists", output: []StepOutput{}, config: Config{ - ExistingComponents: []string{tfController}, - Silent: true, - WGEVersion: "1.0.0", + ComponentsExtra: ComponentsExtraConfig{ + Existing: []string{tfController}, + }, + Silent: true, + WGEVersion: "1.0.0", }, err: false, }, From 0bfedbafa41c0dc69ea264dcf79a6fd2894034e0 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Wed, 6 Dec 2023 15:04:34 +0200 Subject: [PATCH 20/32] add case for silent mode --- pkg/bootstrap/steps/components_extra_test.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pkg/bootstrap/steps/components_extra_test.go b/pkg/bootstrap/steps/components_extra_test.go index 48436b316b..2ee0adb21f 100644 --- a/pkg/bootstrap/steps/components_extra_test.go +++ b/pkg/bootstrap/steps/components_extra_test.go @@ -46,6 +46,17 @@ func TestNewInstallExtraComponents(t *testing.T) { Step: installExtraComponents, }, }, + { + name: "return empty step in case of silent mode", + config: Config{ + Silent: true, + }, + want: BootstrapStep{ + Name: "install extra components", + Input: []StepInput{}, + Step: installExtraComponents, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { From c56804f9c89404c9ef402a00a7e67a21b5d5afa5 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Wed, 6 Dec 2023 15:05:01 +0200 Subject: [PATCH 21/32] add test case for silent mode --- pkg/bootstrap/steps/components_extra_test.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/pkg/bootstrap/steps/components_extra_test.go b/pkg/bootstrap/steps/components_extra_test.go index 2ee0adb21f..b1b8b06b64 100644 --- a/pkg/bootstrap/steps/components_extra_test.go +++ b/pkg/bootstrap/steps/components_extra_test.go @@ -75,12 +75,18 @@ func TestNewInstallExtraComponents(t *testing.T) { } } -func TestInstallExtraControllers(t *testing.T) { +func TestInstallExtraComponents(t *testing.T) { tests := []struct { name string config Config stepInput []StepInput }{ + { + name: "test skip installing nothing in silent mode", + config: Config{ + Silent: true, + }, + }, { name: "test skip installing controllers with defaults (\"\")", stepInput: []StepInput{ From 9e91b8c89833845031b0bdf0c3deaa42c9f153d5 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Wed, 6 Dec 2023 15:05:47 +0200 Subject: [PATCH 22/32] rename comment --- pkg/bootstrap/steps/policy_agent.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/bootstrap/steps/policy_agent.go b/pkg/bootstrap/steps/policy_agent.go index 2b6519f39f..f64284c5ea 100644 --- a/pkg/bootstrap/steps/policy_agent.go +++ b/pkg/bootstrap/steps/policy_agent.go @@ -37,7 +37,7 @@ var enableAdmission = StepInput{ DefaultValue: confirmNo, } -// NewInstallPolicyAgentStep ask for continue installing OIDC +// NewInstallPolicyAgentStep creates the policy agent installation step func NewInstallPolicyAgentStep(config Config) BootstrapStep { config.Logger.Warningf("please note that the Policy Agent requires cert-manager to be installed!") inputs := []StepInput{} From 8306cc0f038ac86d6530a7162019e02d1ae562fe Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Wed, 6 Dec 2023 15:22:23 +0200 Subject: [PATCH 23/32] remove capi leftovers --- cmd/gitops/app/bootstrap/cmd.go | 4 ++-- cmd/gitops/app/bootstrap/cmd_acceptance_test.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/gitops/app/bootstrap/cmd.go b/cmd/gitops/app/bootstrap/cmd.go index c82909aed2..035ae9a6c1 100644 --- a/cmd/gitops/app/bootstrap/cmd.go +++ b/cmd/gitops/app/bootstrap/cmd.go @@ -40,7 +40,7 @@ gitops bootstrap --version= --password= --discovery-url gitops bootstrap --version= --password= --discovery-url= --client-id= --private-key-path= --private-key-password= --branch= --repo-path= --repo-url=ssh:// --client-secret= -s # Start WGE installation with more than one extra controller -gitops bootstrap --components-extra="policy-agent,capi,tf-controller" +gitops bootstrap --components-extra="policy-agent,tf-controller" ` ) @@ -88,7 +88,7 @@ func Command(opts *config.Options) *cobra.Command { } cmd.Flags().StringVarP(&flags.version, "version", "v", "", "version of Weave GitOps Enterprise (should be from the latest 3 versions)") - cmd.Flags().StringSliceVar(&flags.componentsExtra, "components-extra", nil, "extra components to be installed from (policy-agent, tf-controller, capi)") + cmd.Flags().StringSliceVar(&flags.componentsExtra, "components-extra", nil, "extra components to be installed from (policy-agent, tf-controller)") cmd.PersistentFlags().BoolVarP(&flags.silent, "silent", "s", false, "chose the defaults with current provided information without asking any questions") cmd.PersistentFlags().BoolVarP(&flags.bootstrapFlux, "bootstrap-flux", "", false, "chose whether you want to install flux in the generic way in case no flux installation detected") cmd.PersistentFlags().StringVarP(&flags.gitUsername, "git-username", "", "", "git username used in https authentication type") diff --git a/cmd/gitops/app/bootstrap/cmd_acceptance_test.go b/cmd/gitops/app/bootstrap/cmd_acceptance_test.go index f653025211..458438b4ad 100644 --- a/cmd/gitops/app/bootstrap/cmd_acceptance_test.go +++ b/cmd/gitops/app/bootstrap/cmd_acceptance_test.go @@ -148,7 +148,7 @@ func TestBootstrapCmd(t *testing.T) { gitUsernameFlag, gitPasswordFlag, gitBranchFlag, gitRepoPathFlag, repoHTTPSURLFlag, oidcClientSecretFlag, "-s", - "--components-extra=\"policy-agent,capi,tf-controller\"", + "--components-extra=\"policy-agent,tf-controller\"", "--bootstrap-flux", }, setup: func(t *testing.T) { From 2c21cf387898348eb531b804c0d14dd485fb0ad1 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Wed, 6 Dec 2023 16:59:58 +0200 Subject: [PATCH 24/32] use policy agent from url in the repository --- pkg/bootstrap/steps/common_tests.go | 9 ++ pkg/bootstrap/steps/config.go | 1 - pkg/bootstrap/steps/policy_agent.go | 145 +----------------- pkg/bootstrap/steps/policy_agent_test.go | 178 +---------------------- pkg/bootstrap/steps/terraform_test.go | 12 +- 5 files changed, 22 insertions(+), 323 deletions(-) diff --git a/pkg/bootstrap/steps/common_tests.go b/pkg/bootstrap/steps/common_tests.go index 9a92817bc2..2883b1b952 100644 --- a/pkg/bootstrap/steps/common_tests.go +++ b/pkg/bootstrap/steps/common_tests.go @@ -135,3 +135,12 @@ func createWGEHelmReleaseFakeObject(version string) (helmv2.HelmRelease, error) } return wgeHRObject, nil } + +func getControllerHelmReleaseTestFile(url string) string { + tfHelmFile, err := doBasicAuthGetRequest(url, "", "") + if err != nil { + fmt.Printf("error getting: %s HelmRelease: %v", url, err) + return "" + } + return string(tfHelmFile) +} diff --git a/pkg/bootstrap/steps/config.go b/pkg/bootstrap/steps/config.go index c77a6422a3..073c921fd9 100644 --- a/pkg/bootstrap/steps/config.go +++ b/pkg/bootstrap/steps/config.go @@ -44,7 +44,6 @@ const ( inGitPassword = "gitPassowrd" inBootstrapFlux = "bootstrapFlux" inComponentsExtra = "componentsExtra" - inEnableAdmission = "enableAdmission" ) // input/output types diff --git a/pkg/bootstrap/steps/policy_agent.go b/pkg/bootstrap/steps/policy_agent.go index f64284c5ea..bec34d8419 100644 --- a/pkg/bootstrap/steps/policy_agent.go +++ b/pkg/bootstrap/steps/policy_agent.go @@ -1,188 +1,55 @@ package steps import ( - "encoding/json" "fmt" - "time" - helmv2 "github.com/fluxcd/helm-controller/api/v2beta1" - sourcev1beta2 "github.com/fluxcd/source-controller/api/v1beta2" - "github.com/weaveworks/weave-gitops-enterprise/pkg/bootstrap/utils" "golang.org/x/exp/slices" - apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) const ( - admissionMsg = "do you want to enable the Agent's admission controller" policyAgentInstallInfoMsg = "installing Policy Agent ..." policyAgentInstallConfirmMsg = "Policy Agent is installed successfully" ) const ( - agentChartURL = "https://weaveworks.github.io/policy-agent/" - agentHelmRepoName = "policy-agent" - agentNamespace = "policy-system" - agentHelmRepoFileName = "policy-agent-helmrepo.yaml" + agentControllerURL = "https://raw.githubusercontent.com/weaveworks/policy-agent/dev/docs/examples/policy-agent-helmrelease.yaml" agentHelmReleaseFileName = "policy-agent-helmrelease.yaml" - agentHelmRepoCommitMsg = "Add Policy Agent HelmRepository YAML file" agentHelmReleaseCommitMsg = "Add Policy Agent HelmRelease YAML file" - agentVersion = "2.5.0" ) -var enableAdmission = StepInput{ - Name: inEnableAdmission, - Type: confirmInput, - Msg: admissionMsg, - DefaultValue: confirmNo, -} - // NewInstallPolicyAgentStep creates the policy agent installation step func NewInstallPolicyAgentStep(config Config) BootstrapStep { config.Logger.Warningf("please note that the Policy Agent requires cert-manager to be installed!") - inputs := []StepInput{} - if !slices.Contains(config.ComponentsExtra.Existing, policyAgentController) { - inputs = append(inputs, enableAdmission) - } - return BootstrapStep{ Name: "install Policy Agent", - Input: inputs, + Input: []StepInput{}, Step: installPolicyAgent, } } // installPolicyAgent start installing policy agent helm chart func installPolicyAgent(input []StepInput, c *Config) ([]StepOutput, error) { - enableAdmission := false if slices.Contains(c.ComponentsExtra.Existing, policyAgentController) { c.Logger.Warningf("policy agent is already installed!") return []StepOutput{}, nil } - for _, param := range input { - if param.Name == inEnableAdmission { - enable, ok := param.Value.(string) - if ok && enable == confirmYes { - enableAdmission = true - } - } - } c.Logger.Actionf(policyAgentInstallInfoMsg) - c.Logger.Actionf("rendering Policy Agent HelmRepository file") - agentHelmRepoObject := sourcev1beta2.HelmRepository{ - TypeMeta: v1.TypeMeta{ - APIVersion: sourcev1beta2.GroupVersion.Identifier(), - Kind: sourcev1beta2.HelmRepositoryKind, - }, - ObjectMeta: v1.ObjectMeta{ - Name: agentHelmRepoName, - Namespace: WGEDefaultNamespace, - }, - Spec: sourcev1beta2.HelmRepositorySpec{ - URL: agentChartURL, - Interval: v1.Duration{ - Duration: time.Minute, - }, - }, - } - agentHelmRepoFile, err := utils.CreateHelmRepositoryYamlString(agentHelmRepoObject) - if err != nil { - return []StepOutput{}, fmt.Errorf("failed to render Policy Agent HelmRepository: %v", err) - } - c.Logger.Actionf("rendered Policy Agent HelmRepository file") - c.Logger.Actionf("rendering Policy Agent HelmRelease file") - - values := map[string]interface{}{ - "config": map[string]interface{}{ - "admission": map[string]interface{}{ - "enabled": enableAdmission, - "sinks": map[string]interface{}{ - "k8sEventsSink": map[string]interface{}{ - "enabled": true, - }, - }, - }, - "audit": map[string]interface{}{ - "enabled": true, - "sinks": map[string]interface{}{ - "k8sEventsSink": map[string]interface{}{ - "enabled": true, - }, - }, - }, - }, - "excludeNamespaces": []string{ - "kube-system", - "flux-system", - }, - "failurePolicy": "Fail", - "useCertManager": true, - } - - valuesBytes, err := json.Marshal(values) + // download agent file + bodyBytes, err := doBasicAuthGetRequest(agentControllerURL, "", "") if err != nil { - return []StepOutput{}, fmt.Errorf("failed to render Policy Agent HelmRepository values: %v", err) + return []StepOutput{}, fmt.Errorf("error getting Policy Agent HelmRelease: %v", err) } - agentHelmReleaseObject := helmv2.HelmRelease{ - TypeMeta: v1.TypeMeta{ - Kind: helmv2.HelmReleaseKind, - APIVersion: helmv2.GroupVersion.Identifier(), - }, - ObjectMeta: v1.ObjectMeta{ - Name: policyAgentController, - Namespace: WGEDefaultNamespace, - }, Spec: helmv2.HelmReleaseSpec{ - Chart: helmv2.HelmChartTemplate{ - Spec: helmv2.HelmChartTemplateSpec{ - Chart: agentHelmRepoName, - SourceRef: helmv2.CrossNamespaceObjectReference{ - Kind: sourcev1beta2.HelmRepositoryKind, - Name: agentHelmRepoName, - Namespace: WGEDefaultNamespace, - APIVersion: sourcev1beta2.GroupVersion.Identifier(), - }, - Version: agentVersion, - }, - }, - Install: &helmv2.Install{ - CRDs: helmv2.CreateReplace, - CreateNamespace: true, - }, - Interval: v1.Duration{ - Duration: time.Minute * 10, - }, - TargetNamespace: agentNamespace, - Values: &apiextensionsv1.JSON{Raw: valuesBytes}, - }, - } - - agentHelmReleaseFile, err := utils.CreateHelmReleaseYamlString(agentHelmReleaseObject) - if err != nil { - return []StepOutput{}, fmt.Errorf("failed to render Policy Agent HelmRelease: %v", err) - } - c.Logger.Actionf("rendered Policy Agent HelmRelease file") - - helmrepoFile := fileContent{ - Name: agentHelmRepoFileName, - Content: agentHelmRepoFile, - CommitMsg: agentHelmRepoCommitMsg, - } helmreleaseFile := fileContent{ Name: agentHelmReleaseFileName, - Content: agentHelmReleaseFile, + Content: string(bodyBytes), CommitMsg: agentHelmReleaseCommitMsg, } c.Logger.Successf(policyAgentInstallConfirmMsg) return []StepOutput{ - { - Name: agentHelmRepoFileName, - Type: typeFile, - Value: helmrepoFile, - }, { Name: agentHelmReleaseFileName, Type: typeFile, diff --git a/pkg/bootstrap/steps/policy_agent_test.go b/pkg/bootstrap/steps/policy_agent_test.go index 55c5062eff..5662b1af6e 100644 --- a/pkg/bootstrap/steps/policy_agent_test.go +++ b/pkg/bootstrap/steps/policy_agent_test.go @@ -7,100 +7,6 @@ import ( "github.com/stretchr/testify/assert" ) -const ( - testAgentHelmRepoFile = `apiVersion: source.toolkit.fluxcd.io/v1beta2 -kind: HelmRepository -metadata: - creationTimestamp: null - name: policy-agent - namespace: flux-system -spec: - interval: 1m0s - url: https://weaveworks.github.io/policy-agent/ -status: {} -` - testAgentHelmReleaseFileAdmissionDisabled = `apiVersion: helm.toolkit.fluxcd.io/v2beta1 -kind: HelmRelease -metadata: - creationTimestamp: null - name: policy-agent - namespace: flux-system -spec: - chart: - spec: - chart: policy-agent - reconcileStrategy: ChartVersion - sourceRef: - kind: HelmRepository - name: policy-agent - namespace: flux-system - version: 2.5.0 - install: - crds: CreateReplace - createNamespace: true - interval: 10m0s - targetNamespace: policy-system - values: - config: - admission: - enabled: false - sinks: - k8sEventsSink: - enabled: true - audit: - enabled: true - sinks: - k8sEventsSink: - enabled: true - excludeNamespaces: - - kube-system - - flux-system - failurePolicy: Fail - useCertManager: true -status: {} -` - testAgentHelmReleaseFileAdmissionEnabled = `apiVersion: helm.toolkit.fluxcd.io/v2beta1 -kind: HelmRelease -metadata: - creationTimestamp: null - name: policy-agent - namespace: flux-system -spec: - chart: - spec: - chart: policy-agent - reconcileStrategy: ChartVersion - sourceRef: - kind: HelmRepository - name: policy-agent - namespace: flux-system - version: 2.5.0 - install: - crds: CreateReplace - createNamespace: true - interval: 10m0s - targetNamespace: policy-system - values: - config: - admission: - enabled: true - sinks: - k8sEventsSink: - enabled: true - audit: - enabled: true - sinks: - k8sEventsSink: - enabled: true - excludeNamespaces: - - kube-system - - flux-system - failurePolicy: Fail - useCertManager: true -status: {} -` -) - func TestInstallPolicyAgent(t *testing.T) { tests := []struct { name string @@ -110,31 +16,15 @@ func TestInstallPolicyAgent(t *testing.T) { err bool }{ { - name: "install policy agent controller with admission disabled", - input: []StepInput{ - { - Name: inEnableAdmission, - Type: confirmInput, - Msg: admissionMsg, - Value: confirmNo, - }, - }, + name: "install policy agent controller", + input: []StepInput{}, output: []StepOutput{ - { - Name: agentHelmRepoFileName, - Type: typeFile, - Value: fileContent{ - Name: agentHelmRepoFileName, - Content: testAgentHelmRepoFile, - CommitMsg: agentHelmRepoCommitMsg, - }, - }, { Name: agentHelmReleaseFileName, Type: typeFile, Value: fileContent{ Name: agentHelmReleaseFileName, - Content: testAgentHelmReleaseFileAdmissionDisabled, + Content: getControllerHelmReleaseTestFile(agentControllerURL), CommitMsg: agentHelmReleaseCommitMsg, }, }, @@ -143,48 +33,8 @@ func TestInstallPolicyAgent(t *testing.T) { err: false, }, { - name: "install policy agent controller with admission enabled", - input: []StepInput{ - { - Name: inEnableAdmission, - Type: confirmInput, - Msg: admissionMsg, - Value: confirmYes, - }, - }, - output: []StepOutput{ - { - Name: agentHelmRepoFileName, - Type: typeFile, - Value: fileContent{ - Name: agentHelmRepoFileName, - Content: testAgentHelmRepoFile, - CommitMsg: agentHelmRepoCommitMsg, - }, - }, - { - Name: agentHelmReleaseFileName, - Type: typeFile, - Value: fileContent{ - Name: agentHelmReleaseFileName, - Content: testAgentHelmReleaseFileAdmissionEnabled, - CommitMsg: agentHelmReleaseCommitMsg, - }, - }, - }, - config: Config{}, - err: false, - }, - { - name: "do not install policy agent controller if it's already installed", - input: []StepInput{ - { - Name: inEnableAdmission, - Type: confirmInput, - Msg: admissionMsg, - Value: confirmYes, - }, - }, + name: "do not install policy agent controller if it's already installed", + input: []StepInput{}, output: []StepOutput{}, config: Config{ ComponentsExtra: ComponentsExtraConfig{ @@ -232,29 +82,13 @@ func TestNewInstallPolicyAgentStep(t *testing.T) { config Config want BootstrapStep }{ - { name: "return bootstrap step", - want: BootstrapStep{ - Name: "install Policy Agent", - Input: []StepInput{ - enableAdmission, - }, - }, - config: Config{}, - }, - { - name: "return bootstrap with no input in case existing installation", want: BootstrapStep{ Name: "install Policy Agent", Input: []StepInput{}, }, - config: Config{ - ComponentsExtra: ComponentsExtraConfig{ - Existing: []string{policyAgentController}, - Requested: []string{policyAgentController}, - }, - }, + config: Config{}, }, } for _, tt := range tests { diff --git a/pkg/bootstrap/steps/terraform_test.go b/pkg/bootstrap/steps/terraform_test.go index 6f4c36c937..5eaf1ccb99 100644 --- a/pkg/bootstrap/steps/terraform_test.go +++ b/pkg/bootstrap/steps/terraform_test.go @@ -1,7 +1,6 @@ package steps import ( - "fmt" "testing" "github.com/stretchr/testify/assert" @@ -73,7 +72,7 @@ func TestInstallTerraform(t *testing.T) { Type: typeFile, Value: fileContent{ Name: tfFileName, - Content: getTerrafromControllerTestFile(), + Content: getControllerHelmReleaseTestFile(tfControllerUrl), CommitMsg: tfCommitMsg, }, }, @@ -143,12 +142,3 @@ func TestInstallTerraform(t *testing.T) { } } - -func getTerrafromControllerTestFile() string { - tfHelmFile, err := doBasicAuthGetRequest(tfControllerUrl, "", "") - if err != nil { - fmt.Printf("error getting Terraform Controller HelmRelease: %v", err) - return "" - } - return string(tfHelmFile) -} From 30a4da3d0bfa85da2a0d93158d051db4ef01aff5 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Wed, 6 Dec 2023 17:11:55 +0200 Subject: [PATCH 25/32] fix comment --- pkg/bootstrap/steps/terraform.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/bootstrap/steps/terraform.go b/pkg/bootstrap/steps/terraform.go index e04d917056..a07acf3115 100644 --- a/pkg/bootstrap/steps/terraform.go +++ b/pkg/bootstrap/steps/terraform.go @@ -19,7 +19,7 @@ const ( tfFileName = "tf-controller.yaml" ) -// NewInstallTFControllerStep ask for continue installing OIDC +// NewInstallTFControllerStep creates the terraform installation step func NewInstallTFControllerStep(config Config) BootstrapStep { return BootstrapStep{ Name: "install Terraform Controller", From 09c6e998ff38084e9d032c9528d400ce768f78be Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Wed, 6 Dec 2023 17:35:51 +0200 Subject: [PATCH 26/32] add update logic to extra components --- pkg/bootstrap/steps/components_extra.go | 4 ++++ pkg/bootstrap/steps/policy_agent.go | 15 ++++++++++----- pkg/bootstrap/steps/policy_agent_test.go | 3 ++- pkg/bootstrap/steps/terraform.go | 13 +++++++++---- pkg/bootstrap/steps/terraform_test.go | 4 ++-- 5 files changed, 27 insertions(+), 12 deletions(-) diff --git a/pkg/bootstrap/steps/components_extra.go b/pkg/bootstrap/steps/components_extra.go index 937578ba15..261527f144 100644 --- a/pkg/bootstrap/steps/components_extra.go +++ b/pkg/bootstrap/steps/components_extra.go @@ -106,3 +106,7 @@ func installExtraComponents(input []StepInput, c *Config) ([]StepOutput, error) return []StepOutput{}, nil } + +func doNothingStep(input []StepInput, c *Config) ([]StepOutput, error) { + return []StepOutput{}, nil +} diff --git a/pkg/bootstrap/steps/policy_agent.go b/pkg/bootstrap/steps/policy_agent.go index bec34d8419..6355e76e36 100644 --- a/pkg/bootstrap/steps/policy_agent.go +++ b/pkg/bootstrap/steps/policy_agent.go @@ -20,6 +20,16 @@ const ( // NewInstallPolicyAgentStep creates the policy agent installation step func NewInstallPolicyAgentStep(config Config) BootstrapStep { config.Logger.Warningf("please note that the Policy Agent requires cert-manager to be installed!") + + if slices.Contains(config.ComponentsExtra.Existing, policyAgentController) { + config.Logger.Warningf("controller: %s is already installed", policyAgentController) + return BootstrapStep{ + Name: "existing policy agent installation", + Input: []StepInput{}, + Step: doNothingStep, + } + } + return BootstrapStep{ Name: "install Policy Agent", Input: []StepInput{}, @@ -29,11 +39,6 @@ func NewInstallPolicyAgentStep(config Config) BootstrapStep { // installPolicyAgent start installing policy agent helm chart func installPolicyAgent(input []StepInput, c *Config) ([]StepOutput, error) { - if slices.Contains(c.ComponentsExtra.Existing, policyAgentController) { - c.Logger.Warningf("policy agent is already installed!") - return []StepOutput{}, nil - } - c.Logger.Actionf(policyAgentInstallInfoMsg) // download agent file diff --git a/pkg/bootstrap/steps/policy_agent_test.go b/pkg/bootstrap/steps/policy_agent_test.go index 5662b1af6e..0a6dae6d39 100644 --- a/pkg/bootstrap/steps/policy_agent_test.go +++ b/pkg/bootstrap/steps/policy_agent_test.go @@ -49,7 +49,8 @@ func TestInstallPolicyAgent(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { config := makeTestConfig(t, tt.config) - out, err := installPolicyAgent(tt.input, &config) + step := NewInstallPolicyAgentStep(config) + out, err := step.Execute(&config) if err != nil { if tt.err { return diff --git a/pkg/bootstrap/steps/terraform.go b/pkg/bootstrap/steps/terraform.go index a07acf3115..fc791f489d 100644 --- a/pkg/bootstrap/steps/terraform.go +++ b/pkg/bootstrap/steps/terraform.go @@ -21,6 +21,15 @@ const ( // NewInstallTFControllerStep creates the terraform installation step func NewInstallTFControllerStep(config Config) BootstrapStep { + if slices.Contains(config.ComponentsExtra.Existing, tfController) { + config.Logger.Warningf("controller: %s is already installed", tfController) + return BootstrapStep{ + Name: "existing tf controller installation", + Input: []StepInput{}, + Step: doNothingStep, + } + } + return BootstrapStep{ Name: "install Terraform Controller", Step: installTerraform, @@ -29,10 +38,6 @@ func NewInstallTFControllerStep(config Config) BootstrapStep { // installTerraform start installing terraform controller helm release func installTerraform(input []StepInput, c *Config) ([]StepOutput, error) { - if slices.Contains(c.ComponentsExtra.Existing, tfController) { - c.Logger.Warningf("terraform controller is already installed!") - return []StepOutput{}, nil - } c.Logger.Actionf(tfInstallInfoMsg) bodyBytes, err := doBasicAuthGetRequest(tfControllerUrl, "", "") diff --git a/pkg/bootstrap/steps/terraform_test.go b/pkg/bootstrap/steps/terraform_test.go index 5eaf1ccb99..d9d8a2a905 100644 --- a/pkg/bootstrap/steps/terraform_test.go +++ b/pkg/bootstrap/steps/terraform_test.go @@ -114,8 +114,8 @@ func TestInstallTerraform(t *testing.T) { } config := makeTestConfig(t, tt.config, &wgeObject) - - out, err := installTerraform(tt.input, &config) + step := NewInstallTFControllerStep(config) + out, err := step.Execute(&config) if err != nil { if tt.err { return From a61370de06f763995ac30c67dcbe5408d065c815 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Wed, 6 Dec 2023 18:24:20 +0200 Subject: [PATCH 27/32] update acceptance testing wge version --- cmd/gitops/app/bootstrap/cmd_acceptance_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/gitops/app/bootstrap/cmd_acceptance_test.go b/cmd/gitops/app/bootstrap/cmd_acceptance_test.go index 458438b4ad..1375d4e48d 100644 --- a/cmd/gitops/app/bootstrap/cmd_acceptance_test.go +++ b/cmd/gitops/app/bootstrap/cmd_acceptance_test.go @@ -119,7 +119,7 @@ func TestBootstrapCmd(t *testing.T) { { name: "journey flux exists: should bootstrap with valid arguments", flags: []string{kubeconfigFlag, - "--version=0.36.0", + "--version=0.37.0", privateKeyFlag, privateKeyPasswordFlag, "--password=admin123", "--discovery-url=https://dex-01.wge.dev.weave.works/.well-known/openid-configuration", @@ -141,14 +141,14 @@ func TestBootstrapCmd(t *testing.T) { { name: "journey flux does not exist: should bootstrap with valid arguments", flags: []string{kubeconfigFlag, - "--version=0.36.0", + "--version=0.37.0", "--password=admin123", "--discovery-url=https://dex-01.wge.dev.weave.works/.well-known/openid-configuration", "--client-id=weave-gitops-enterprise", gitUsernameFlag, gitPasswordFlag, gitBranchFlag, gitRepoPathFlag, repoHTTPSURLFlag, oidcClientSecretFlag, "-s", - "--components-extra=\"policy-agent,tf-controller\"", + "--components-extra=policy-agent", "--bootstrap-flux", }, setup: func(t *testing.T) { From 2acd174316a6cce2997225aecccc9bf9b4d96781 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Thu, 7 Dec 2023 09:02:49 +0200 Subject: [PATCH 28/32] restore empty input instead of nil --- pkg/bootstrap/steps/install_wge.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/bootstrap/steps/install_wge.go b/pkg/bootstrap/steps/install_wge.go index 0ae6ce6d88..ec05f2e975 100644 --- a/pkg/bootstrap/steps/install_wge.go +++ b/pkg/bootstrap/steps/install_wge.go @@ -39,8 +39,9 @@ const ( // NewInstallWGEStep step to install Weave GitOps Enterprise func NewInstallWGEStep() BootstrapStep { return BootstrapStep{ - Name: "Install Weave GitOps Enterprise", - Step: installWge, + Name: "Install Weave GitOps Enterprise", + Input: []StepInput{}, + Step: installWge, } } From 507dabe0f1ff20cf38d96ff1ea96d9005fa2b7e7 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Thu, 7 Dec 2023 09:17:27 +0200 Subject: [PATCH 29/32] fix flux bootstrap --- cmd/gitops/app/bootstrap/cmd_acceptance_test.go | 2 +- pkg/bootstrap/steps/ask_bootstrap_flux.go | 9 ++++++--- pkg/bootstrap/steps/ask_bootstrap_flux_test.go | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/cmd/gitops/app/bootstrap/cmd_acceptance_test.go b/cmd/gitops/app/bootstrap/cmd_acceptance_test.go index 1375d4e48d..271765a4de 100644 --- a/cmd/gitops/app/bootstrap/cmd_acceptance_test.go +++ b/cmd/gitops/app/bootstrap/cmd_acceptance_test.go @@ -148,7 +148,7 @@ func TestBootstrapCmd(t *testing.T) { gitUsernameFlag, gitPasswordFlag, gitBranchFlag, gitRepoPathFlag, repoHTTPSURLFlag, oidcClientSecretFlag, "-s", - "--components-extra=policy-agent", + "--components-extra=policy-agent,tf-controller", "--bootstrap-flux", }, setup: func(t *testing.T) { diff --git a/pkg/bootstrap/steps/ask_bootstrap_flux.go b/pkg/bootstrap/steps/ask_bootstrap_flux.go index 074bdd20ef..1926c0f6d6 100644 --- a/pkg/bootstrap/steps/ask_bootstrap_flux.go +++ b/pkg/bootstrap/steps/ask_bootstrap_flux.go @@ -7,7 +7,7 @@ const ( ) var ( - bootstrapFLuxQuestion = StepInput{ + bootstrapFluxQuestion = StepInput{ Name: inBootstrapFlux, Type: confirmInput, Msg: bootstrapFluxMsg, @@ -18,10 +18,13 @@ var ( // NewAskBootstrapFluxStep step for asking if user want to install flux using generic method func NewAskBootstrapFluxStep(config Config) BootstrapStep { + if config.BootstrapFlux { + bootstrapFluxQuestion.DefaultValue = confirmYes + } return BootstrapStep{ Name: "bootstrap flux", Input: []StepInput{ - bootstrapFLuxQuestion, + bootstrapFluxQuestion, }, Step: askBootstrapFlux, } @@ -51,5 +54,5 @@ func askBootstrapFlux(input []StepInput, c *Config) ([]StepOutput, error) { // canAskForGitConfig if fluxInstallation is false, then can ask for git config func canAskForFluxBootstrap(input []StepInput, c *Config) bool { - return !c.FluxInstallated && !c.Silent + return !c.FluxInstallated } diff --git a/pkg/bootstrap/steps/ask_bootstrap_flux_test.go b/pkg/bootstrap/steps/ask_bootstrap_flux_test.go index e823784867..158516c22f 100644 --- a/pkg/bootstrap/steps/ask_bootstrap_flux_test.go +++ b/pkg/bootstrap/steps/ask_bootstrap_flux_test.go @@ -60,7 +60,7 @@ func TestAskBootstrapFlux(t *testing.T) { Silent: true, }, err: false, - canAsk: false, + canAsk: true, }, } for _, tt := range tests { From eec87da677d14c31f472035ae625cb63e68dea6c Mon Sep 17 00:00:00 2001 From: Eneko Fernandez Date: Thu, 7 Dec 2023 10:24:08 +0100 Subject: [PATCH 30/32] some wording suggestions --- cmd/gitops/app/bootstrap/cmd.go | 6 +++--- pkg/bootstrap/steps/admin_password.go | 2 +- pkg/bootstrap/steps/policy_agent.go | 4 ++-- pkg/bootstrap/steps/terraform.go | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cmd/gitops/app/bootstrap/cmd.go b/cmd/gitops/app/bootstrap/cmd.go index 035ae9a6c1..402a93674b 100644 --- a/cmd/gitops/app/bootstrap/cmd.go +++ b/cmd/gitops/app/bootstrap/cmd.go @@ -88,9 +88,9 @@ func Command(opts *config.Options) *cobra.Command { } cmd.Flags().StringVarP(&flags.version, "version", "v", "", "version of Weave GitOps Enterprise (should be from the latest 3 versions)") - cmd.Flags().StringSliceVar(&flags.componentsExtra, "components-extra", nil, "extra components to be installed from (policy-agent, tf-controller)") - cmd.PersistentFlags().BoolVarP(&flags.silent, "silent", "s", false, "chose the defaults with current provided information without asking any questions") - cmd.PersistentFlags().BoolVarP(&flags.bootstrapFlux, "bootstrap-flux", "", false, "chose whether you want to install flux in the generic way in case no flux installation detected") + cmd.Flags().StringSliceVar(&flags.componentsExtra, "components-extra", nil, "extra components to be installed. Supported components: policy-agent, tf-controller") + cmd.PersistentFlags().BoolVarP(&flags.silent, "silent", "s", false, "non-interactive session: it will not ask questions but rather to use default values to complete the introduced flags") + cmd.PersistentFlags().BoolVarP(&flags.bootstrapFlux, "bootstrap-flux", "", false, "flags that you want to bootstrap Flux in case is not detected") cmd.PersistentFlags().StringVarP(&flags.gitUsername, "git-username", "", "", "git username used in https authentication type") cmd.PersistentFlags().StringVarP(&flags.gitPassword, "git-password", "", "", "git password/token used in https authentication type") cmd.PersistentFlags().StringVarP(&flags.branch, "branch", "b", "", "git branch for your flux repository (example: main)") diff --git a/pkg/bootstrap/steps/admin_password.go b/pkg/bootstrap/steps/admin_password.go index 19fae4baca..5685c01896 100644 --- a/pkg/bootstrap/steps/admin_password.go +++ b/pkg/bootstrap/steps/admin_password.go @@ -14,7 +14,7 @@ const ( adminPasswordMsg = "dashboard admin password (minimum characters: 6)" secretConfirmationMsg = "admin login credentials has been created successfully!" adminSecretExistsErrorMsgFormat = "admin login credentials already exist on the cluster. To reset admin credentials please remove secret '%s' in namespace '%s'" - useExistingMessageFormat = "using existing admin login credentials from secret '%s' in namespace '%s'. To reset admin credentials please remove the secret" + useExistingMessageFormat = " using existing admin login credentials from secret '%s' in namespace '%s'. To reset admin credentials please remove the secret" ) const ( diff --git a/pkg/bootstrap/steps/policy_agent.go b/pkg/bootstrap/steps/policy_agent.go index 6355e76e36..ab02313e9a 100644 --- a/pkg/bootstrap/steps/policy_agent.go +++ b/pkg/bootstrap/steps/policy_agent.go @@ -19,10 +19,9 @@ const ( // NewInstallPolicyAgentStep creates the policy agent installation step func NewInstallPolicyAgentStep(config Config) BootstrapStep { - config.Logger.Warningf("please note that the Policy Agent requires cert-manager to be installed!") if slices.Contains(config.ComponentsExtra.Existing, policyAgentController) { - config.Logger.Warningf("controller: %s is already installed", policyAgentController) + config.Logger.Warningf(" not installing %s: found in the cluster", policyAgentController) return BootstrapStep{ Name: "existing policy agent installation", Input: []StepInput{}, @@ -40,6 +39,7 @@ func NewInstallPolicyAgentStep(config Config) BootstrapStep { // installPolicyAgent start installing policy agent helm chart func installPolicyAgent(input []StepInput, c *Config) ([]StepOutput, error) { c.Logger.Actionf(policyAgentInstallInfoMsg) + c.Logger.Warningf(" please note that the Policy Agent requires cert-manager to be installed!") // download agent file bodyBytes, err := doBasicAuthGetRequest(agentControllerURL, "", "") diff --git a/pkg/bootstrap/steps/terraform.go b/pkg/bootstrap/steps/terraform.go index fc791f489d..f134618f31 100644 --- a/pkg/bootstrap/steps/terraform.go +++ b/pkg/bootstrap/steps/terraform.go @@ -22,7 +22,7 @@ const ( // NewInstallTFControllerStep creates the terraform installation step func NewInstallTFControllerStep(config Config) BootstrapStep { if slices.Contains(config.ComponentsExtra.Existing, tfController) { - config.Logger.Warningf("controller: %s is already installed", tfController) + config.Logger.Warningf(" not installing %s: found in the cluster", tfController) return BootstrapStep{ Name: "existing tf controller installation", Input: []StepInput{}, From b110a07a40bf6f32b2984cf72b75861bd6271a6a Mon Sep 17 00:00:00 2001 From: Eneko Fernandez Date: Thu, 7 Dec 2023 11:03:43 +0100 Subject: [PATCH 31/32] using none instead of empty string --- cmd/gitops/app/bootstrap/cmd.go | 2 +- pkg/bootstrap/steps/components_extra.go | 10 +++++----- pkg/bootstrap/steps/components_extra_test.go | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cmd/gitops/app/bootstrap/cmd.go b/cmd/gitops/app/bootstrap/cmd.go index 402a93674b..ffb6aa016b 100644 --- a/cmd/gitops/app/bootstrap/cmd.go +++ b/cmd/gitops/app/bootstrap/cmd.go @@ -88,7 +88,7 @@ func Command(opts *config.Options) *cobra.Command { } cmd.Flags().StringVarP(&flags.version, "version", "v", "", "version of Weave GitOps Enterprise (should be from the latest 3 versions)") - cmd.Flags().StringSliceVar(&flags.componentsExtra, "components-extra", nil, "extra components to be installed. Supported components: policy-agent, tf-controller") + cmd.Flags().StringSliceVar(&flags.componentsExtra, "components-extra", nil, "extra components to be installed. Supported components: none, policy-agent, tf-controller") cmd.PersistentFlags().BoolVarP(&flags.silent, "silent", "s", false, "non-interactive session: it will not ask questions but rather to use default values to complete the introduced flags") cmd.PersistentFlags().BoolVarP(&flags.bootstrapFlux, "bootstrap-flux", "", false, "flags that you want to bootstrap Flux in case is not detected") cmd.PersistentFlags().StringVarP(&flags.gitUsername, "git-username", "", "", "git username used in https authentication type") diff --git a/pkg/bootstrap/steps/components_extra.go b/pkg/bootstrap/steps/components_extra.go index 261527f144..2cc5d6d2b7 100644 --- a/pkg/bootstrap/steps/components_extra.go +++ b/pkg/bootstrap/steps/components_extra.go @@ -13,12 +13,13 @@ const ( ) const ( + none = "none" policyAgentController = "policy-agent" tfController = "tf-controller" ) var ComponentsExtra = []string{ - "", + none, policyAgentController, tfController, } @@ -59,7 +60,7 @@ func NewInstallExtraComponentsStep(config ComponentsExtraConfig, silent bool) Bo Type: multiSelectionChoice, Msg: componentsExtraMsg, Values: ComponentsExtra, - DefaultValue: "", + DefaultValue: none, } if len(config.Requested) < 1 && !silent { @@ -84,6 +85,8 @@ func installExtraComponents(input []StepInput, c *Config) ([]StepOutput, error) } for _, controller := range c.ComponentsExtra.Requested { switch controller { + case none: + return []StepOutput{}, nil case policyAgentController: agentStep := NewInstallPolicyAgentStep(*c) _, err := agentStep.Execute(c) @@ -96,9 +99,6 @@ func installExtraComponents(input []StepInput, c *Config) ([]StepOutput, error) if err != nil { return []StepOutput{}, fmt.Errorf("can't install tf controller: %v", err) } - case "": - c.Logger.Successf("selected none extra components") - return []StepOutput{}, nil default: return []StepOutput{}, fmt.Errorf("unsupported component selected: %s", controller) } diff --git a/pkg/bootstrap/steps/components_extra_test.go b/pkg/bootstrap/steps/components_extra_test.go index b1b8b06b64..d8f912396a 100644 --- a/pkg/bootstrap/steps/components_extra_test.go +++ b/pkg/bootstrap/steps/components_extra_test.go @@ -24,7 +24,7 @@ func TestNewInstallExtraComponents(t *testing.T) { Type: multiSelectionChoice, Msg: componentsExtraMsg, Values: ComponentsExtra, - DefaultValue: "", + DefaultValue: none, }, }, Step: installExtraComponents, @@ -94,7 +94,7 @@ func TestInstallExtraComponents(t *testing.T) { Name: inComponentsExtra, Type: multiSelectionChoice, Msg: componentsExtraMsg, - Value: "", + Value: none, }, }, }, From 995d6bda766dda65c9827f8a2e98682e81718844 Mon Sep 17 00:00:00 2001 From: Waleed Hammam Date: Thu, 7 Dec 2023 12:22:12 +0200 Subject: [PATCH 32/32] update messages --- cmd/gitops/app/bootstrap/cmd_acceptance_test.go | 1 - pkg/bootstrap/steps/ask_bootstrap_flux.go | 2 +- pkg/bootstrap/steps/step.go | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/cmd/gitops/app/bootstrap/cmd_acceptance_test.go b/cmd/gitops/app/bootstrap/cmd_acceptance_test.go index 271765a4de..36421db642 100644 --- a/cmd/gitops/app/bootstrap/cmd_acceptance_test.go +++ b/cmd/gitops/app/bootstrap/cmd_acceptance_test.go @@ -164,7 +164,6 @@ func TestBootstrapCmd(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if tt.setup != nil { tt.setup(t) } diff --git a/pkg/bootstrap/steps/ask_bootstrap_flux.go b/pkg/bootstrap/steps/ask_bootstrap_flux.go index 1926c0f6d6..12e94559c9 100644 --- a/pkg/bootstrap/steps/ask_bootstrap_flux.go +++ b/pkg/bootstrap/steps/ask_bootstrap_flux.go @@ -35,7 +35,7 @@ func askBootstrapFlux(input []StepInput, c *Config) ([]StepOutput, error) { return []StepOutput{}, nil } if c.BootstrapFlux && c.Silent { - c.Logger.Generatef("bootstrapping flux in the generic way") + c.Logger.Actionf("bootstrapping flux in the generic way") return []StepOutput{}, nil } for _, param := range input { diff --git a/pkg/bootstrap/steps/step.go b/pkg/bootstrap/steps/step.go index 31dd089a6d..2f76dedaf2 100644 --- a/pkg/bootstrap/steps/step.go +++ b/pkg/bootstrap/steps/step.go @@ -148,7 +148,7 @@ func defaultInputStep(inputs []StepInput, c *Config, stdin io.ReadCloser) ([]Ste c.Logger.Warningf(input.StepInformation) } // if silent mode is enabled, select the default value - // if no default value select yes by default + // if no default value an error will be returned if c.Silent { defaultVal, ok := input.DefaultValue.(string) if ok {