diff --git a/controllers/configuration/configuration.go b/controllers/configuration/configuration.go index ad9e7dab..a100a4fc 100644 --- a/controllers/configuration/configuration.go +++ b/controllers/configuration/configuration.go @@ -1,12 +1,19 @@ package configuration import ( + "context" + "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/oam-dev/terraform-controller/api/types" - "github.com/oam-dev/terraform-controller/api/v1beta1" "github.com/pkg/errors" v1 "k8s.io/api/core/v1" + kerrors "k8s.io/apimachinery/pkg/api/errors" + apitypes "k8s.io/apimachinery/pkg/types" + "k8s.io/klog/v2" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/oam-dev/terraform-controller/api/types" + "github.com/oam-dev/terraform-controller/api/v1beta1" ) // ValidConfigurationObject will validate a Configuration @@ -68,3 +75,34 @@ func CompareTwoContainerEnvs(s1 []v1.EnvVar, s2 []v1.EnvVar) bool { } return cmp.Diff(s1, s2, cmpopts.SortSlices(less)) == "" } + +// SetRegion will set the region for Configuration +func SetRegion(ctx context.Context, k8sClient client.Client, namespace, name string, providerObj *v1beta1.Provider) (string, error) { + configuration, err := Get(ctx, k8sClient, apitypes.NamespacedName{Namespace: namespace, Name: name}) + if err != nil { + return "", errors.Wrap(err, "failed to get configuration") + } + if configuration.Spec.Region != "" { + return configuration.Spec.Region, nil + } + + configuration.Spec.Region = providerObj.Spec.Region + return providerObj.Spec.Region, Update(ctx, k8sClient, &configuration) +} + +// Update will update the Configuration +func Update(ctx context.Context, k8sClient client.Client, configuration *v1beta1.Configuration) error { + return k8sClient.Update(ctx, configuration) +} + +// Get will get the Configuration +func Get(ctx context.Context, k8sClient client.Client, namespacedName apitypes.NamespacedName) (v1beta1.Configuration, error) { + configuration := &v1beta1.Configuration{} + if err := k8sClient.Get(ctx, namespacedName, configuration); err != nil { + if kerrors.IsNotFound(err) { + klog.ErrorS(err, "unable to fetch Configuration", "NamespacedName", namespacedName) + } + return *configuration, err + } + return *configuration, nil +} diff --git a/controllers/configuration_controller.go b/controllers/configuration_controller.go index 3250e150..48430a53 100644 --- a/controllers/configuration_controller.go +++ b/controllers/configuration_controller.go @@ -124,7 +124,6 @@ type TFConfigurationMeta struct { VariableSecretData map[string][]byte DeleteResource bool Credentials map[string]string - Region string } // +kubebuilder:rbac:groups=terraform.core.oam.dev,resources=configurations,verbs=get;list;watch;create;update;patch;delete @@ -132,17 +131,12 @@ type TFConfigurationMeta struct { // Reconcile will reconcile periodically func (r *ConfigurationReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { - var ( - configuration v1beta1.Configuration - ctx = context.Background() - ) + var ctx = context.Background() + klog.InfoS("reconciling Terraform Configuration...", "NamespacedName", req.NamespacedName) - if err := r.Get(ctx, req.NamespacedName, &configuration); err != nil { - if kerrors.IsNotFound(err) { - klog.ErrorS(err, "unable to fetch Configuration", "NamespacedName", req.NamespacedName) - err = nil - } + configuration, err := tfcfg.Get(ctx, r.Client, req.NamespacedName) + if err != nil { return ctrl.Result{}, err } @@ -226,7 +220,6 @@ func initTFConfigurationMeta(req ctrl.Request, configuration v1beta1.Configurati VariableSecretName: fmt.Sprintf(TFVariableSecret, req.Name), ApplyJobName: req.Name + "-" + string(TerraformApply), DestroyJobName: req.Name + "-" + string(TerraformDestroy), - Region: configuration.Spec.Region, } meta.RemoteGit = configuration.Spec.Remote @@ -241,8 +234,8 @@ func initTFConfigurationMeta(req ctrl.Request, configuration v1beta1.Configurati meta.ProviderReference = configuration.Spec.ProviderReference } else { meta.ProviderReference = &crossplane.Reference{ - Name: provider.ProviderDefaultName, - Namespace: provider.ProviderDefaultNamespace, + Name: provider.DefaultName, + Namespace: provider.DefaultNamespace, } } @@ -921,7 +914,15 @@ func (meta *TFConfigurationMeta) CheckWhetherConfigurationChanges(ctx context.Co // checkProver will check the Provider and get credentials from secret of the Provider func (meta *TFConfigurationMeta) checkProvider(ctx context.Context, k8sClient client.Client) error { - credentials, err := provider.GetProviderCredentials(ctx, k8sClient, meta.ProviderReference.Namespace, meta.ProviderReference.Name, meta.Region) + providerObj, err := provider.GetProviderFromConfiguration(ctx, k8sClient, meta.ProviderReference.Namespace, meta.ProviderReference.Name) + if err != nil { + return errors.Wrap(err, "failed to get the region from the provider") + } + region, err := tfcfg.SetRegion(ctx, k8sClient, meta.Namespace, meta.Name, providerObj) + if err != nil { + return err + } + credentials, err := provider.GetProviderCredentials(ctx, k8sClient, providerObj, region) if err != nil { return err } diff --git a/controllers/provider/credentials.go b/controllers/provider/credentials.go index 162973b8..d1a71885 100644 --- a/controllers/provider/credentials.go +++ b/controllers/provider/credentials.go @@ -16,10 +16,10 @@ import ( ) const ( - // ProviderDefaultName is the name of Provider object - ProviderDefaultName = "default" - // ProviderDefaultNamespace is the namespace of Provider object - ProviderDefaultNamespace = "default" + // DefaultName is the name of Provider object + DefaultName = "default" + // DefaultNamespace is the namespace of Provider object + DefaultNamespace = "default" ) // CloudProvider is a type for mark a Cloud Provider @@ -121,24 +121,7 @@ type ECCredentials struct { } // GetProviderCredentials gets provider credentials by cloud provider name -func GetProviderCredentials(ctx context.Context, k8sClient client.Client, providerNamespace, providerName, configurationRegion string) (map[string]string, error) { - var region string - provider, err := GetProviderFromConfiguration(ctx, k8sClient, providerNamespace, providerName) - if err != nil { - return nil, err - } - - if provider.Status.State != types.ProviderIsReady { - err := fmt.Errorf("provider is not ready: %s/%s", provider.Namespace, provider.Name) - klog.ErrorS(err, "failed to get credential") - return nil, err - } - - if configurationRegion != "" { - region = configurationRegion - } else { - region = provider.Spec.Region - } +func GetProviderCredentials(ctx context.Context, k8sClient client.Client, provider *v1beta1.Provider, region string) (map[string]string, error) { switch provider.Spec.Credentials.Source { case "Secret": var secret v1.Secret @@ -235,8 +218,8 @@ func GetProviderCredentials(ctx context.Context, k8sClient client.Client, provid }, nil default: errMsg := "unsupported provider" - klog.ErrorS(err, errMsg, "Provider", provider.Spec.Provider) - return nil, errors.Wrap(err, errMsg) + klog.InfoS(errMsg, "Provider", provider.Spec.Provider) + return nil, errors.New(errMsg) } default: errMsg := "the credentials type is not supported." @@ -267,13 +250,18 @@ func ValidateProviderCredentials(ctx context.Context, k8sClient client.Client, p } // GetProviderFromConfiguration gets provider object from Configuration -func GetProviderFromConfiguration(ctx context.Context, k8sClient client.Client, namespace, providerName string) (*v1beta1.Provider, error) { +func GetProviderFromConfiguration(ctx context.Context, k8sClient client.Client, namespace, name string) (*v1beta1.Provider, error) { var provider = &v1beta1.Provider{} - if err := k8sClient.Get(ctx, client.ObjectKey{Name: providerName, Namespace: namespace}, provider); err != nil { + if err := k8sClient.Get(ctx, client.ObjectKey{Name: name, Namespace: namespace}, provider); err != nil { errMsg := "failed to get Provider object" - klog.ErrorS(err, errMsg, "Name", providerName) + klog.ErrorS(err, errMsg, "Name", name) return nil, errors.Wrap(err, errMsg) } + if provider.Status.State != types.ProviderIsReady { + err := fmt.Errorf("provider is not ready: %s/%s", provider.Namespace, provider.Name) + klog.ErrorS(err, "failed to get credential") + return nil, err + } return provider, nil }