@@ -26,13 +26,13 @@ import (
26
26
27
27
corev1 "k8s.io/api/core/v1"
28
28
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
29
30
"k8s.io/apimachinery/pkg/runtime"
30
31
"k8s.io/apimachinery/pkg/runtime/serializer"
31
32
"k8s.io/apimachinery/pkg/types"
32
33
versionutil "k8s.io/apimachinery/pkg/util/version"
33
34
"k8s.io/apimachinery/pkg/util/wait"
34
35
"k8s.io/client-go/kubernetes/scheme"
35
- clientgoscheme "k8s.io/client-go/kubernetes/scheme"
36
36
"k8s.io/client-go/rest"
37
37
operatorv1 "sigs.k8s.io/cluster-api-operator/api/v1alpha2"
38
38
"sigs.k8s.io/cluster-api-operator/internal/controller/genericprovider"
@@ -48,6 +48,8 @@ import (
48
48
"sigs.k8s.io/controller-runtime/pkg/client"
49
49
"sigs.k8s.io/controller-runtime/pkg/log"
50
50
"sigs.k8s.io/controller-runtime/pkg/reconcile"
51
+
52
+ utilyaml "sigs.k8s.io/cluster-api/util/yaml"
51
53
)
52
54
53
55
// fakeURL is the stub url for custom providers, missing from clusterctl repository.
@@ -322,7 +324,9 @@ func (p *PhaseReconciler) secretReader(ctx context.Context, providers ...configc
322
324
}
323
325
324
326
// Fetch configuration variables from the secret. See API field docs for more info.
325
- initReaderVariables (ctx , p .ctrlClient , mr , p .provider )
327
+ if err := initReaderVariables (ctx , p .ctrlClient , mr , p .provider ); err != nil {
328
+ return nil , err
329
+ }
326
330
327
331
isCustom := true
328
332
@@ -564,12 +568,14 @@ func (p *phaseReconciler) store(ctx context.Context) (reconcile.Result, error) {
564
568
log := ctrl .LoggerFrom (ctx )
565
569
log .Info ("Storing provider in cache" )
566
570
567
- componentsFile , err := p .components .Yaml ()
571
+ components := addNamespaceIfMissing (p .components .Objs (), p .provider .GetNamespace ())
572
+
573
+ componentsFile , err := utilyaml .FromUnstructured (components )
568
574
if err != nil {
569
575
return reconcile.Result {}, wrapPhaseError (err , operatorv1 .ComponentsCustomizationErrorReason , operatorv1 .ProviderInstalledCondition )
570
576
}
571
577
572
- kinds , _ , err := clientgoscheme .Scheme .ObjectKinds (& corev1.ConfigMap {})
578
+ kinds , _ , err := scheme .Scheme .ObjectKinds (& corev1.ConfigMap {})
573
579
if err != nil || len (kinds ) == 0 {
574
580
log .Error (err , "cannot fetch kind of the ConfigMap resource" )
575
581
err = fmt .Errorf ("cannot fetch kind of the ConfigMap resource: %w" , err )
@@ -587,7 +593,8 @@ func (p *phaseReconciler) store(ctx context.Context) (reconcile.Result, error) {
587
593
Namespace : p .provider .GetNamespace (),
588
594
Annotations : map [string ]string {},
589
595
},
590
- Data : map [string ]string {},
596
+ Data : map [string ]string {},
597
+ BinaryData : map [string ][]byte {},
591
598
}
592
599
593
600
gvk := p .provider .GetObjectKind ().GroupVersionKind ()
@@ -606,7 +613,7 @@ func (p *phaseReconciler) store(ctx context.Context) (reconcile.Result, error) {
606
613
configMap .Annotations [operatorv1 .CompressedAnnotation ] = "true"
607
614
}
608
615
609
- for i , manifest := range strings .Split (string (componentsFile ), "---" ) {
616
+ for i , manifest := range strings .Split (string (componentsFile ), "\n ---" ) {
610
617
manifest = strings .TrimSpace (manifest )
611
618
612
619
if compress {
@@ -620,7 +627,7 @@ func (p *phaseReconciler) store(ctx context.Context) (reconcile.Result, error) {
620
627
continue
621
628
}
622
629
623
- configMap .Data [fmt .Sprintf ("%d" , i )] = string ( manifest )
630
+ configMap .Data [fmt .Sprintf ("%d" , i )] = manifest
624
631
}
625
632
626
633
if err := p .ctrlClient .Patch (ctx , configMap , client .Apply , client .ForceOwnership , client .FieldOwner (cacheOwner )); err != nil {
@@ -631,6 +638,7 @@ func (p *phaseReconciler) store(ctx context.Context) (reconcile.Result, error) {
631
638
632
639
// Perform template processing with variable replacement.
633
640
p .options .SkipTemplateProcess = false
641
+
634
642
p .components , err = repository .NewComponents (repository.ComponentsInput {
635
643
Provider : p .providerConfig ,
636
644
ConfigClient : p .configClient ,
@@ -645,7 +653,34 @@ func (p *phaseReconciler) store(ctx context.Context) (reconcile.Result, error) {
645
653
return reconcile.Result {}, nil
646
654
}
647
655
648
- // Upgrade ensure all the clusterctl CRDs are available before installing the provider,
656
+ // addNamespaceIfMissing adda a Namespace object if missing (this ensure the targetNamespace will be created).
657
+ func addNamespaceIfMissing (objs []unstructured.Unstructured , targetNamespace string ) []unstructured.Unstructured {
658
+ namespaceObjectFound := false
659
+
660
+ for _ , o := range objs {
661
+ // if the object has Kind Namespace, fix the namespace name
662
+ if o .GetKind () == namespaceKind {
663
+ namespaceObjectFound = true
664
+ }
665
+ }
666
+
667
+ // if there isn't an object with Kind Namespace, add it
668
+ if ! namespaceObjectFound {
669
+ objs = append (objs , unstructured.Unstructured {
670
+ Object : map [string ]interface {}{
671
+ "apiVersion" : "v1" ,
672
+ "kind" : namespaceKind ,
673
+ "metadata" : map [string ]interface {}{
674
+ "name" : targetNamespace ,
675
+ },
676
+ },
677
+ })
678
+ }
679
+
680
+ return objs
681
+ }
682
+
683
+ // upgrade ensure all the clusterctl CRDs are available before installing the provider,
649
684
// and update existing components if required.
650
685
func (p * PhaseReconciler ) Upgrade (ctx context.Context ) (* Result , error ) {
651
686
log := ctrl .LoggerFrom (ctx )
@@ -689,7 +724,7 @@ func (p *PhaseReconciler) Install(ctx context.Context) (*Result, error) {
689
724
log .Info ("Installing provider" )
690
725
691
726
if err := clusterClient .ProviderComponents ().Create (ctx , p .components .Objs ()); err != nil {
692
- reason := "Install failed! "
727
+ reason := "Install failed"
693
728
if wait .Interrupted (err ) {
694
729
reason = "Timed out waiting for deployment to become ready"
695
730
}
0 commit comments