Skip to content

Commit 7a26044

Browse files
Add bootstrap CLI controllers configurations (#3647)
* add controllers configurations with acceptance and unit tests * silent mode doesn't ask for extra controllers * use components-extra instead of extra-controllers * install components before check ui domain * remove example * use empty quotes instead of none value * remove creation timestamp * add flag to bootstrap flux to ensure the default behaviour * remove all of above option * add case for one or more controllers * add case for silent mode * fix terraform controller test * fix target namespace * handle update scenario * rename extra components to componetes extra to align with flag * fix flags * add test case for bootstrap flux in silent mode * don't use yes as default and fail if no defaults set * remove capi controller and refactor configuration * add case for silent mode * add test case for silent mode * rename comment * remove capi leftovers * use policy agent from url in the repository * fix comment * add update logic to extra components * update acceptance testing wge version * restore empty input instead of nil * fix flux bootstrap * some wording suggestions * using none instead of empty string * update messages --------- Co-authored-by: Eneko Fernandez <[email protected]>
1 parent c94cfc7 commit 7a26044

22 files changed

+883
-44
lines changed

cmd/gitops/app/bootstrap/cmd.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,13 @@ gitops bootstrap --password=hell0!
3434
gitops bootstrap --client-id <client-id> --client-secret <client-secret> --discovery-url <discovery-url>
3535
3636
# Start WGE installation with OIDC and flux bootstrap with https
37-
gitops bootstrap --version=<version> --password=<admin-password> --discovery-url=<oidc-discovery-url> --client-id=<oidc-client-id> --git-username=<git-username-https> -gitPassword=<gitPassword>--branch=<git-branch> --repo-path=<path-in-repo-for-management-cluster> --repo-url=https://<repo-url> --client-secret=<oidc-secret> -s
37+
gitops bootstrap --version=<version> --password=<admin-password> --discovery-url=<oidc-discovery-url> --client-id=<oidc-client-id> --git-username=<git-username-https> --gitPassword=<gitPassword> --bootstrap-flux --branch=<git-branch> --repo-path=<path-in-repo-for-management-cluster> --repo-url=https://<repo-url> --client-secret=<oidc-secret> -s
3838
3939
# Start WGE installation with OIDC and flux bootstrap with ssh
4040
gitops bootstrap --version=<version> --password=<admin-password> --discovery-url=<oidc-discovery-url> --client-id=<oidc-client-id> --private-key-path=<private-key-path> --private-key-password=<private-key-password> --branch=<git-branch> --repo-path=<path-in-repo-for-management-cluster> --repo-url=ssh://<repo-url> --client-secret=<oidc-secret> -s
41+
42+
# Start WGE installation with more than one extra controller
43+
gitops bootstrap --components-extra="policy-agent,tf-controller"
4144
`
4245
)
4346

@@ -65,6 +68,12 @@ type bootstrapFlags struct {
6568

6669
// modes flags
6770
silent bool
71+
72+
// flux flag
73+
bootstrapFlux bool
74+
75+
// extra controllers
76+
componentsExtra []string
6877
}
6978

7079
var flags bootstrapFlags
@@ -79,7 +88,9 @@ func Command(opts *config.Options) *cobra.Command {
7988
}
8089

8190
cmd.Flags().StringVarP(&flags.version, "version", "v", "", "version of Weave GitOps Enterprise (should be from the latest 3 versions)")
82-
cmd.PersistentFlags().BoolVarP(&flags.silent, "bootstrap-flux", "s", false, "always choose yes for interactive questions")
91+
cmd.Flags().StringSliceVar(&flags.componentsExtra, "components-extra", nil, "extra components to be installed. Supported components: none, policy-agent, tf-controller")
92+
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")
93+
cmd.PersistentFlags().BoolVarP(&flags.bootstrapFlux, "bootstrap-flux", "", false, "flags that you want to bootstrap Flux in case is not detected")
8394
cmd.PersistentFlags().StringVarP(&flags.gitUsername, "git-username", "", "", "git username used in https authentication type")
8495
cmd.PersistentFlags().StringVarP(&flags.gitPassword, "git-password", "", "", "git password/token used in https authentication type")
8596
cmd.PersistentFlags().StringVarP(&flags.branch, "branch", "b", "", "git branch for your flux repository (example: main)")
@@ -115,6 +126,8 @@ func getBootstrapCmdRun(opts *config.Options) func(*cobra.Command, []string) err
115126
).
116127
WithOIDCConfig(flags.discoveryURL, flags.clientID, flags.clientSecret, true).
117128
WithSilentFlag(flags.silent).
129+
WithBootstrapFluxFlag(flags.bootstrapFlux).
130+
WithComponentsExtra(flags.componentsExtra).
118131
Build()
119132

120133
if err != nil {

cmd/gitops/app/bootstrap/cmd_acceptance_test.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,6 @@ func TestBootstrapCmd(t *testing.T) {
7575
privateKeyFile := os.Getenv("GIT_PRIVATEKEY_PATH")
7676
g.Expect(privateKeyFile).NotTo(BeEmpty())
7777

78-
privateKeyPassword := os.Getenv("GIT_PRIVATEKEY_PASSWORD")
79-
8078
repoURLSSH := os.Getenv("GIT_REPO_URL_SSH")
8179
g.Expect(repoURLSSH).NotTo(BeEmpty())
8280
repoURLHTTPS := os.Getenv("GIT_REPO_URL_HTTPS")
@@ -89,6 +87,10 @@ func TestBootstrapCmd(t *testing.T) {
8987
g.Expect(gitBranch).NotTo(BeEmpty())
9088
gitRepoPath := os.Getenv("GIT_REPO_PATH")
9189
g.Expect(gitRepoPath).NotTo(BeEmpty())
90+
privateKeyPassword := os.Getenv("GIT_PRIVATEKEY_PASSWORD")
91+
g.Expect(privateKeyPassword).NotTo(BeEmpty())
92+
oidcClientSecret := os.Getenv("OIDC_CLIENT_SECRET")
93+
g.Expect(oidcClientSecret).NotTo(BeEmpty())
9294

9395
privateKeyFlag := fmt.Sprintf("--private-key=%s", privateKeyFile)
9496
privateKeyPasswordFlag := fmt.Sprintf("--private-key-password=%s", privateKeyPassword)
@@ -103,8 +105,6 @@ func TestBootstrapCmd(t *testing.T) {
103105
gitBranchFlag := fmt.Sprintf("--branch=%s", gitBranch)
104106
gitRepoPathFlag := fmt.Sprintf("--repo-path=%s", gitRepoPath)
105107

106-
oidcClientSecret := os.Getenv("OIDC_CLIENT_SECRET")
107-
g.Expect(oidcClientSecret).NotTo(BeEmpty())
108108
oidcClientSecretFlag := fmt.Sprintf("--client-secret=%s", oidcClientSecret)
109109

110110
_ = k8sClient.Create(context.Background(), &fluxSystemNamespace)
@@ -119,12 +119,13 @@ func TestBootstrapCmd(t *testing.T) {
119119
{
120120
name: "journey flux exists: should bootstrap with valid arguments",
121121
flags: []string{kubeconfigFlag,
122-
"--version=0.35.0",
122+
"--version=0.37.0",
123123
privateKeyFlag, privateKeyPasswordFlag,
124124
"--password=admin123",
125125
"--discovery-url=https://dex-01.wge.dev.weave.works/.well-known/openid-configuration",
126126
"--client-id=weave-gitops-enterprise",
127127
oidcClientSecretFlag,
128+
"-s",
128129
},
129130
setup: func(t *testing.T) {
130131
bootstrapFluxSsh(g, kubeconfigFlag)
@@ -140,14 +141,15 @@ func TestBootstrapCmd(t *testing.T) {
140141
{
141142
name: "journey flux does not exist: should bootstrap with valid arguments",
142143
flags: []string{kubeconfigFlag,
143-
"--version=0.35.0",
144-
privateKeyFlag, privateKeyPasswordFlag,
144+
"--version=0.37.0",
145145
"--password=admin123",
146146
"--discovery-url=https://dex-01.wge.dev.weave.works/.well-known/openid-configuration",
147147
"--client-id=weave-gitops-enterprise",
148148
gitUsernameFlag, gitPasswordFlag, gitBranchFlag, gitRepoPathFlag,
149149
repoHTTPSURLFlag,
150150
oidcClientSecretFlag, "-s",
151+
"--components-extra=policy-agent,tf-controller",
152+
"--bootstrap-flux",
151153
},
152154
setup: func(t *testing.T) {
153155
createEntitlements(t, testLog)
@@ -162,7 +164,6 @@ func TestBootstrapCmd(t *testing.T) {
162164
}
163165
for _, tt := range tests {
164166
t.Run(tt.name, func(t *testing.T) {
165-
166167
if tt.setup != nil {
167168
tt.setup(t)
168169
}
@@ -200,8 +201,9 @@ func bootstrapFluxSsh(g *WithT, kubeconfigFlag string) {
200201
fmt.Println(privateKeyFile)
201202

202203
privateKeyPassword := os.Getenv("GIT_PRIVATEKEY_PASSWORD")
204+
g.Expect(privateKeyFile).NotTo(BeEmpty())
203205

204-
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"}
206+
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"}
205207
fmt.Println(args)
206208

207209
s, err := cliRunner.Run("flux", args...)

docs/cli/bootstrap.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,16 @@ func selectWgeVersion(input []StepInput, c *Config) ([]StepOutput, error) {
274274
275275
```
276276

277+
## Default Behaviours (default value in inputs)
277278

279+
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.
278280

281+
The default values in the step input will be used while silent mode is on by providing `-s`, `--silent`
279282

283+
Examples:
284+
- Using existing credentials this will not replace the user's data and it's safe
285+
- Not to install extra controllers unless provided otherwise
286+
- Not to install OIDC unless provided otherwise
280287

281288
## Error management
282289

pkg/bootstrap/bootstrap.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ func Bootstrap(config steps.Config) error {
1616

1717
repositoryConfig := steps.NewGitRepositoryConfigStep(config.GitRepository)
1818

19+
componentesExtra := steps.NewInstallExtraComponentsStep(config.ComponentsExtra, config.Silent)
20+
1921
// 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/
2022
var steps = []steps.BootstrapStep{
2123
steps.VerifyFluxInstallation,
@@ -28,6 +30,7 @@ func Bootstrap(config steps.Config) error {
2830
steps.NewInstallWGEStep(),
2931
steps.NewInstallOIDCStep(config),
3032
steps.NewOIDCConfigStep(config),
33+
componentesExtra,
3134
steps.CheckUIDomainStep,
3235
}
3336

pkg/bootstrap/steps/admin_password.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,12 @@ import (
1313
const (
1414
adminPasswordMsg = "dashboard admin password (minimum characters: 6)"
1515
secretConfirmationMsg = "admin login credentials has been created successfully!"
16-
adminSecretExistsErrorMsgFormat = "admin login credentials already exist on the cluster. To reset admin credentials please remove secret '%s' in namespace '%s'."
17-
useExistingMessageFormat = "using existing admin login credentials from secret '%s' in namespace '%s'. To reset admin credentials please remove the secret."
16+
adminSecretExistsErrorMsgFormat = "admin login credentials already exist on the cluster. To reset admin credentials please remove secret '%s' in namespace '%s'"
17+
useExistingMessageFormat = " using existing admin login credentials from secret '%s' in namespace '%s'. To reset admin credentials please remove the secret"
1818
)
1919

2020
const (
2121
adminSecretName = "cluster-user-auth"
22-
confirmYes = "y"
2322
defaultAdminUsername = "wego-admin"
2423
)
2524

pkg/bootstrap/steps/admin_password_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ func TestNewAskAdminCredsSecretStep(t *testing.T) {
7878
Password: "password123",
7979
},
8080
want: BootstrapStep{},
81-
wantErr: "admin login credentials already exist on the cluster. To reset admin credentials please remove secret 'cluster-user-auth' in namespace 'flux-system'.",
81+
wantErr: "admin login credentials already exist on the cluster. To reset admin credentials please remove secret 'cluster-user-auth' in namespace 'flux-system'",
8282
},
8383
}
8484
for _, tt := range tests {

pkg/bootstrap/steps/ask_bootstrap_flux.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,24 @@ const (
77
)
88

99
var (
10-
bootstrapFLuxQuestion = StepInput{
11-
Name: inBootstrapFlux,
12-
Type: confirmInput,
13-
Msg: bootstrapFluxMsg,
14-
Enabled: canAskForFluxBootstrap,
10+
bootstrapFluxQuestion = StepInput{
11+
Name: inBootstrapFlux,
12+
Type: confirmInput,
13+
Msg: bootstrapFluxMsg,
14+
Enabled: canAskForFluxBootstrap,
15+
DefaultValue: confirmNo,
1516
}
1617
)
1718

1819
// NewAskBootstrapFluxStep step for asking if user want to install flux using generic method
1920
func NewAskBootstrapFluxStep(config Config) BootstrapStep {
21+
if config.BootstrapFlux {
22+
bootstrapFluxQuestion.DefaultValue = confirmYes
23+
}
2024
return BootstrapStep{
2125
Name: "bootstrap flux",
2226
Input: []StepInput{
23-
bootstrapFLuxQuestion,
27+
bootstrapFluxQuestion,
2428
},
2529
Step: askBootstrapFlux,
2630
}
@@ -30,12 +34,16 @@ func askBootstrapFlux(input []StepInput, c *Config) ([]StepOutput, error) {
3034
if !canAskForFluxBootstrap(input, c) {
3135
return []StepOutput{}, nil
3236
}
37+
if c.BootstrapFlux && c.Silent {
38+
c.Logger.Actionf("bootstrapping flux in the generic way")
39+
return []StepOutput{}, nil
40+
}
3341
for _, param := range input {
3442
if param.Name == inBootstrapFlux {
3543
fluxBootstrapRes, ok := param.Value.(string)
3644
if ok {
3745
if fluxBootstrapRes != "y" {
38-
return []StepOutput{}, fmt.Errorf("flux bootstrapped error: %s", fluxFatalErrorMsg)
46+
return []StepOutput{}, fmt.Errorf("flux error: %s", fluxFatalErrorMsg)
3947
}
4048

4149
}

pkg/bootstrap/steps/ask_bootstrap_flux_test.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func TestAskBootstrapFlux(t *testing.T) {
2828
input: []StepInput{
2929
{
3030
Name: inBootstrapFlux,
31-
Value: "n",
31+
Value: confirmNo,
3232
},
3333
},
3434
config: &Config{
@@ -51,6 +51,17 @@ func TestAskBootstrapFlux(t *testing.T) {
5151
err: false,
5252
canAsk: true,
5353
},
54+
{
55+
name: "check with silent mode and bootstrap flux flag available",
56+
input: []StepInput{},
57+
config: &Config{
58+
FluxInstallated: false,
59+
BootstrapFlux: true,
60+
Silent: true,
61+
},
62+
err: false,
63+
canAsk: true,
64+
},
5465
}
5566
for _, tt := range tests {
5667
t.Run(tt.name, func(t *testing.T) {

pkg/bootstrap/steps/common_tests.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
package steps
22

33
import (
4+
"encoding/json"
5+
"fmt"
46
"testing"
7+
"time"
58

9+
helmv2 "github.com/fluxcd/helm-controller/api/v2beta1"
10+
sourcev1beta2 "github.com/fluxcd/source-controller/api/v1beta2"
611
"github.com/weaveworks/weave-gitops-enterprise/test/utils"
12+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
13+
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
714
"k8s.io/apimachinery/pkg/runtime"
815
"sigs.k8s.io/controller-runtime/pkg/client"
916
)
@@ -56,5 +63,84 @@ func makeTestConfig(t *testing.T, config Config, objects ...runtime.Object) Conf
5663
ClientSecret: config.ClientSecret,
5764
RedirectURL: config.RedirectURL,
5865
PromptedForDiscoveryURL: config.PromptedForDiscoveryURL,
66+
Silent: config.Silent,
67+
ComponentsExtra: config.ComponentsExtra,
5968
}
6069
}
70+
71+
func createWGEHelmReleaseFakeObject(version string) (helmv2.HelmRelease, error) {
72+
values := valuesFile{
73+
TLS: map[string]interface{}{
74+
"enabled": false,
75+
},
76+
GitOpsSets: map[string]interface{}{
77+
"enabled": true,
78+
"controllerManager": map[string]interface{}{
79+
"manager": map[string]interface{}{
80+
"args": []string{
81+
fmt.Sprintf("--health-probe-bind-address=%s", gitopssetsHealthBindAddress),
82+
fmt.Sprintf("--metrics-bind-address=%s", gitopssetsBindAddress),
83+
"--leader-elect",
84+
fmt.Sprintf("--enabled-generators=%s", gitopssetsEnabledGenerators),
85+
},
86+
},
87+
},
88+
},
89+
EnablePipelines: true,
90+
ClusterController: clusterController{
91+
Enabled: true,
92+
FullNameOverride: clusterControllerFullOverrideName,
93+
ControllerManager: clusterControllerManager{
94+
Manager: clusterControllerManagerManager{
95+
Image: clusterControllerImage{
96+
Repository: clusterControllerImageName,
97+
Tag: clusterControllerImageTag,
98+
},
99+
},
100+
}},
101+
}
102+
103+
valuesBytes, err := json.Marshal(values)
104+
if err != nil {
105+
return helmv2.HelmRelease{}, err
106+
}
107+
108+
wgeHRObject := helmv2.HelmRelease{
109+
ObjectMeta: v1.ObjectMeta{
110+
Name: WgeHelmReleaseName,
111+
Namespace: WGEDefaultNamespace,
112+
}, Spec: helmv2.HelmReleaseSpec{
113+
Chart: helmv2.HelmChartTemplate{
114+
Spec: helmv2.HelmChartTemplateSpec{
115+
Chart: wgeChartName,
116+
ReconcileStrategy: sourcev1beta2.ReconcileStrategyChartVersion,
117+
SourceRef: helmv2.CrossNamespaceObjectReference{
118+
Name: wgeHelmRepositoryName,
119+
Namespace: WGEDefaultNamespace,
120+
},
121+
Version: version,
122+
},
123+
},
124+
Install: &helmv2.Install{
125+
CRDs: helmv2.CreateReplace,
126+
},
127+
Upgrade: &helmv2.Upgrade{
128+
CRDs: helmv2.CreateReplace,
129+
},
130+
Interval: v1.Duration{
131+
Duration: time.Hour,
132+
},
133+
Values: &apiextensionsv1.JSON{Raw: valuesBytes},
134+
},
135+
}
136+
return wgeHRObject, nil
137+
}
138+
139+
func getControllerHelmReleaseTestFile(url string) string {
140+
tfHelmFile, err := doBasicAuthGetRequest(url, "", "")
141+
if err != nil {
142+
fmt.Printf("error getting: %s HelmRelease: %v", url, err)
143+
return ""
144+
}
145+
return string(tfHelmFile)
146+
}

0 commit comments

Comments
 (0)