@@ -26,13 +26,13 @@ import (
2626
2727 corev1 "k8s.io/api/core/v1"
2828 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
29+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
2930 "k8s.io/apimachinery/pkg/runtime"
3031 "k8s.io/apimachinery/pkg/runtime/serializer"
3132 "k8s.io/apimachinery/pkg/types"
3233 versionutil "k8s.io/apimachinery/pkg/util/version"
3334 "k8s.io/apimachinery/pkg/util/wait"
3435 "k8s.io/client-go/kubernetes/scheme"
35- clientgoscheme "k8s.io/client-go/kubernetes/scheme"
3636 "k8s.io/client-go/rest"
3737 operatorv1 "sigs.k8s.io/cluster-api-operator/api/v1alpha2"
3838 "sigs.k8s.io/cluster-api-operator/internal/controller/genericprovider"
@@ -48,6 +48,8 @@ import (
4848 "sigs.k8s.io/controller-runtime/pkg/client"
4949 "sigs.k8s.io/controller-runtime/pkg/log"
5050 "sigs.k8s.io/controller-runtime/pkg/reconcile"
51+
52+ utilyaml "sigs.k8s.io/cluster-api/util/yaml"
5153)
5254
5355// 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
322324 }
323325
324326 // 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+ }
326330
327331 isCustom := true
328332
@@ -564,12 +568,14 @@ func (p *phaseReconciler) store(ctx context.Context) (reconcile.Result, error) {
564568 log := ctrl .LoggerFrom (ctx )
565569 log .Info ("Storing provider in cache" )
566570
567- componentsFile , err := p .components .Yaml ()
571+ components := addNamespaceIfMissing (p .components .Objs (), p .provider .GetNamespace ())
572+
573+ componentsFile , err := utilyaml .FromUnstructured (components )
568574 if err != nil {
569575 return reconcile.Result {}, wrapPhaseError (err , operatorv1 .ComponentsCustomizationErrorReason , operatorv1 .ProviderInstalledCondition )
570576 }
571577
572- kinds , _ , err := clientgoscheme .Scheme .ObjectKinds (& corev1.ConfigMap {})
578+ kinds , _ , err := scheme .Scheme .ObjectKinds (& corev1.ConfigMap {})
573579 if err != nil || len (kinds ) == 0 {
574580 log .Error (err , "cannot fetch kind of the ConfigMap resource" )
575581 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) {
587593 Namespace : p .provider .GetNamespace (),
588594 Annotations : map [string ]string {},
589595 },
590- Data : map [string ]string {},
596+ Data : map [string ]string {},
597+ BinaryData : map [string ][]byte {},
591598 }
592599
593600 gvk := p .provider .GetObjectKind ().GroupVersionKind ()
@@ -606,7 +613,7 @@ func (p *phaseReconciler) store(ctx context.Context) (reconcile.Result, error) {
606613 configMap .Annotations [operatorv1 .CompressedAnnotation ] = "true"
607614 }
608615
609- for i , manifest := range strings .Split (string (componentsFile ), "---" ) {
616+ for i , manifest := range strings .Split (string (componentsFile ), "\n ---" ) {
610617 manifest = strings .TrimSpace (manifest )
611618
612619 if compress {
@@ -620,7 +627,7 @@ func (p *phaseReconciler) store(ctx context.Context) (reconcile.Result, error) {
620627 continue
621628 }
622629
623- configMap .Data [fmt .Sprintf ("%d" , i )] = string ( manifest )
630+ configMap .Data [fmt .Sprintf ("%d" , i )] = manifest
624631 }
625632
626633 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) {
631638
632639 // Perform template processing with variable replacement.
633640 p .options .SkipTemplateProcess = false
641+
634642 p .components , err = repository .NewComponents (repository.ComponentsInput {
635643 Provider : p .providerConfig ,
636644 ConfigClient : p .configClient ,
@@ -645,7 +653,34 @@ func (p *phaseReconciler) store(ctx context.Context) (reconcile.Result, error) {
645653 return reconcile.Result {}, nil
646654}
647655
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,
649684// and update existing components if required.
650685func (p * PhaseReconciler ) Upgrade (ctx context.Context ) (* Result , error ) {
651686 log := ctrl .LoggerFrom (ctx )
@@ -689,7 +724,7 @@ func (p *PhaseReconciler) Install(ctx context.Context) (*Result, error) {
689724 log .Info ("Installing provider" )
690725
691726 if err := clusterClient .ProviderComponents ().Create (ctx , p .components .Objs ()); err != nil {
692- reason := "Install failed! "
727+ reason := "Install failed"
693728 if wait .Interrupted (err ) {
694729 reason = "Timed out waiting for deployment to become ready"
695730 }
0 commit comments