@@ -22,11 +22,14 @@ import (
22
22
"os"
23
23
"path/filepath"
24
24
"strings"
25
+ "time"
25
26
26
27
"github.com/spf13/cobra"
27
28
28
29
appsv1 "k8s.io/api/apps/v1"
30
+ corev1 "k8s.io/api/core/v1"
29
31
apierrors "k8s.io/apimachinery/pkg/api/errors"
32
+ "k8s.io/apimachinery/pkg/util/wait"
30
33
clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3"
31
34
"sigs.k8s.io/cluster-api/cmd/clusterctl/client/cluster"
32
35
configclient "sigs.k8s.io/cluster-api/cmd/clusterctl/client/config"
@@ -123,13 +126,13 @@ func init() {
123
126
"Context to be used within the kubeconfig file. If empty, current context will be used." )
124
127
initCmd .PersistentFlags ().StringVar (& initOpts .operatorVersion , "operator-version" , "" ,
125
128
"CAPI Operator version (e.g. v0.7.0) to install on the management cluster. If unspecified, the latest release is used." )
126
- initCmd .PersistentFlags ().StringVar (& initOpts .coreProvider , "core" , "cluster-api " ,
129
+ initCmd .PersistentFlags ().StringVar (& initOpts .coreProvider , "core" , "" ,
127
130
"Core provider version (e.g. cluster-api:v1.1.5) to add to the management cluster. If unspecified, Cluster API's latest release is used." )
128
131
initCmd .PersistentFlags ().StringSliceVarP (& initOpts .infrastructureProviders , "infrastructure" , "i" , []string {},
129
132
"Infrastructure providers and versions (e.g. aws:v0.5.0) to add to the management cluster." )
130
- initCmd .PersistentFlags ().StringSliceVarP (& initOpts .bootstrapProviders , "bootstrap" , "b" , []string {"kubeadm" },
133
+ initCmd .PersistentFlags ().StringSliceVarP (& initOpts .bootstrapProviders , "bootstrap" , "b" , []string {},
131
134
"Bootstrap providers and versions (e.g. kubeadm:v1.1.5) to add to the management cluster. If unspecified, Kubeadm bootstrap provider's latest release is used." )
132
- initCmd .PersistentFlags ().StringSliceVarP (& initOpts .controlPlaneProviders , "control-plane" , "c" , []string {"kubeadm" },
135
+ initCmd .PersistentFlags ().StringSliceVarP (& initOpts .controlPlaneProviders , "control-plane" , "c" , []string {},
133
136
"Control plane providers and versions (e.g. kubeadm:v1.1.5) to add to the management cluster. If unspecified, the Kubeadm control plane provider's latest release is used." )
134
137
// initCmd.PersistentFlags().StringSliceVar(&initOpts.ipamProviders, "ipam", nil,
135
138
// "IPAM providers and versions (e.g. infoblox:v0.0.1) to add to the management cluster.")
@@ -157,8 +160,16 @@ func runInit() error {
157
160
return fmt .Errorf ("cannot create a client: %w" , err )
158
161
}
159
162
160
- // Checking if CAPI operator deployment exists.
161
- deploymentExists , err := checkCAPIOpearatorAvailability (ctx , client )
163
+ log .Info ("Checking that Cert Manager is installed and running." )
164
+
165
+ // Ensure that cert manager is installed.
166
+ if err := ensureCertManager (initOpts ); err != nil {
167
+ return fmt .Errorf ("cannot ensure that cert manager is installed: %w" , err )
168
+ }
169
+
170
+ log .Info ("Checking that CAPI Operator is installed and running." )
171
+
172
+ deploymentExists , err := checkCAPIOperatorAvailability (ctx , client )
162
173
if err != nil {
163
174
return fmt .Errorf ("cannot check CAPI operator availability: %w" , err )
164
175
}
@@ -167,16 +178,32 @@ func runInit() error {
167
178
return fmt .Errorf ("cannot specify an operator version when the CAPI operator is already installed" )
168
179
}
169
180
170
- // Ensure that cert manager is installed.
171
- if err := ensureCertManager (initOpts ); err != nil {
172
- return fmt .Errorf ("cannot ensure that cert manager is installed: %w" , err )
173
- }
174
-
175
181
// Deploy CAPI operator if it doesn't exist.
176
182
if ! deploymentExists {
183
+ log .Info ("Installing CAPI operator" , "Version" , initOpts .operatorVersion )
184
+
177
185
if err := deployCAPIOperator (initOpts ); err != nil {
178
186
return fmt .Errorf ("cannot deploy CAPI operator: %w" , err )
179
187
}
188
+
189
+ opts := wait.Backoff {
190
+ Duration : 500 * time .Millisecond ,
191
+ Factor : 1.5 ,
192
+ Steps : 10 ,
193
+ Jitter : 0.4 ,
194
+ }
195
+
196
+ log .Info ("Waiting for CAPI Operator to be available..." )
197
+
198
+ if err := wait .ExponentialBackoff (opts , func () (bool , error ) {
199
+ return checkCAPIOperatorAvailability (ctx , client )
200
+ }); err != nil {
201
+ return fmt .Errorf ("cannot check CAPI operator availability: %w" , err )
202
+ }
203
+
204
+ log .Info ("CAPI Operator is successfully installed." )
205
+ } else {
206
+ log .Info ("Skipping installing CAPI Operator as it is already installed." )
180
207
}
181
208
182
209
return initProviders (ctx , client , initOpts )
@@ -221,8 +248,8 @@ func initProviders(ctx context.Context, client ctrlclient.Client, initOpts *init
221
248
return nil
222
249
}
223
250
224
- // checkCAPIOpearatorAvailability checks if the CAPI operator is available on the management cluster.
225
- func checkCAPIOpearatorAvailability (ctx context.Context , client ctrlclient.Client ) (bool , error ) {
251
+ // checkCAPIOperatorAvailability checks if the CAPI operator is available on the management cluster.
252
+ func checkCAPIOperatorAvailability (ctx context.Context , client ctrlclient.Client ) (bool , error ) {
226
253
var deploymentList appsv1.DeploymentList
227
254
228
255
// Search deployments with desired labels in all namespaces.
@@ -234,7 +261,19 @@ func checkCAPIOpearatorAvailability(ctx context.Context, client ctrlclient.Clien
234
261
return false , fmt .Errorf ("more than one CAPI Operator deployments were found" )
235
262
}
236
263
237
- return len (deploymentList .Items ) == 1 , nil
264
+ if len (deploymentList .Items ) == 0 {
265
+ return false , nil
266
+ }
267
+
268
+ deployment := deploymentList .Items [0 ]
269
+
270
+ for _ , cond := range deployment .Status .Conditions {
271
+ if cond .Type == appsv1 .DeploymentAvailable && cond .Status == corev1 .ConditionTrue {
272
+ return true , nil
273
+ }
274
+ }
275
+
276
+ return false , nil
238
277
}
239
278
240
279
func ensureCertManager (opts * initOptions ) error {
@@ -378,16 +417,24 @@ func createGenericProvider(ctx context.Context, client ctrlclient.Client, provid
378
417
spec := provider .GetSpec ()
379
418
spec .Version = version
380
419
provider .SetSpec (spec )
420
+ } else {
421
+ version = "latest"
381
422
}
382
423
383
424
// Ensure that desired namespace exists
384
425
if err := EnsureNamespaceExists (ctx , client , namespace ); err != nil {
385
426
return fmt .Errorf ("cannot ensure that namespace exists: %w" , err )
386
427
}
387
428
429
+ log .Info ("Installing provider" , "Type" , provider .GetType (), "Name" , name , "Version" , version , "Namespace" , namespace )
430
+
388
431
// Create the provider
389
- if err := client .Create (ctx , provider .GetObject ()); err != nil && ! apierrors .IsAlreadyExists (err ) {
390
- return fmt .Errorf ("cannot create provider: %w" , err )
432
+ if err := client .Create (ctx , provider .GetObject ()); err != nil {
433
+ if ! apierrors .IsAlreadyExists (err ) {
434
+ return fmt .Errorf ("cannot create provider: %w" , err )
435
+ }
436
+
437
+ log .Info ("Provider already exists, skipping creation" , "Type" , provider .GetType (), "Name" , name , "Version" , version , "Namespace" , namespace )
391
438
}
392
439
393
440
return nil
0 commit comments