From 6ee44534b599de8fda14042e8661f89e66e22c24 Mon Sep 17 00:00:00 2001 From: Tarun Chinmai Sekar Date: Fri, 28 Jun 2024 10:01:52 -0700 Subject: [PATCH 1/2] Add configurability of terraform provider --- apis/v1beta1/types.go | 36 +++++++++++++++ apis/v1beta1/zz_generated.deepcopy.go | 16 +++++++ internal/clients/linode.go | 45 +++++++++++++++++++ .../linode.upbound.io_providerconfigs.yaml | 34 ++++++++++++++ 4 files changed, 131 insertions(+) diff --git a/apis/v1beta1/types.go b/apis/v1beta1/types.go index dec7aec..c79c43d 100644 --- a/apis/v1beta1/types.go +++ b/apis/v1beta1/types.go @@ -13,6 +13,42 @@ import ( type ProviderConfigSpec struct { // Credentials required to authenticate to this provider. Credentials ProviderCredentials `json:"credentials"` + + // +kubebuilder:validation:Optional + Configuration ProviderConfiguration `json:"config"` +} + +// ProviderConfiguration for configuring the terraform provider +// see https://registry.terraform.io/providers/linode/linode/latest/docs#configuration-reference +type ProviderConfiguration struct { + // +kubebuilder:validation:Optional + UserAgentPrefix string `json:"ua_prefix"` + // +kubebuilder:validation:Optional + SkipInstanceReadyPoll bool `json:"skip_instance_ready_poll"` + // +kubebuilder:validation:Optional + SkipInstanceDeletePoll bool `json:"skip_instance_delete_poll"` + // +kubebuilder:validation:Optional + SkipImplicitReboots bool `json:"skip_implicit_reboots"` + // +kubebuilder:validation:Optional + DisableInternalCache bool `json:"disable_internal_cache"` + // +kubebuilder:validation:Optional + MinRetryDelayms int `json:"min_retry_delay_ms"` + // +kubebuilder:validation:Optional + MaxRetryDelayms int `json:"max_retry_delay_ms"` + // +kubebuilder:validation:Optional + EventPollms int `json:"event_poll_ms"` + // +kubebuilder:validation:Optional + LKEEventPollms int `json:"lke_event_poll_ms"` + // +kubebuilder:validation:Optional + LKENodeReadyPollms int `json:"lke_node_ready_poll_ms"` + // +kubebuilder:validation:Optional + ObjAccessKey string `json:"obj_access_key"` + // +kubebuilder:validation:Optional + ObjSecretKey string `json:"obj_secret_key"` + // +kubebuilder:validation:Optional + ObjUseTempKeys bool `json:"obj_use_temp_keys"` + // +kubebuilder:validation:Optional + ObjForceDelete bool `json:"obj_bucket_force_delete"` } // ProviderCredentials required to authenticate. diff --git a/apis/v1beta1/zz_generated.deepcopy.go b/apis/v1beta1/zz_generated.deepcopy.go index 09df2c1..beb2cca 100644 --- a/apis/v1beta1/zz_generated.deepcopy.go +++ b/apis/v1beta1/zz_generated.deepcopy.go @@ -75,6 +75,7 @@ func (in *ProviderConfigList) DeepCopyObject() runtime.Object { func (in *ProviderConfigSpec) DeepCopyInto(out *ProviderConfigSpec) { *out = *in in.Credentials.DeepCopyInto(&out.Credentials) + out.Configuration = in.Configuration } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProviderConfigSpec. @@ -161,6 +162,21 @@ func (in *ProviderConfigUsageList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ProviderConfiguration) DeepCopyInto(out *ProviderConfiguration) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProviderConfiguration. +func (in *ProviderConfiguration) DeepCopy() *ProviderConfiguration { + if in == nil { + return nil + } + out := new(ProviderConfiguration) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ProviderCredentials) DeepCopyInto(out *ProviderCredentials) { *out = *in diff --git a/internal/clients/linode.go b/internal/clients/linode.go index 1fd139c..2c818f9 100644 --- a/internal/clients/linode.go +++ b/internal/clients/linode.go @@ -84,6 +84,10 @@ func TerraformSetupBuilder(tfProvider *schema.Provider) terraform.SetupFn { return ps, errors.Wrap(err, errUnmarshalCredentials) } + if pc.Spec.Configuration.ObjForceDelete && !pc.Spec.Configuration.ObjUseTempKeys && (pc.Spec.Configuration.ObjAccessKey == "" || pc.Spec.Configuration.ObjSecretKey == "") { + return ps, errors.Wrap(err, "if obj_bucket_force_delete is set, then set obj_use_temp_keys or obj_access_key and obj_secret_key") + } + // set provider configuration ps.Configuration = map[string]any{} if v, ok := creds[keyToken]; ok { @@ -96,6 +100,47 @@ func TerraformSetupBuilder(tfProvider *schema.Provider) terraform.SetupFn { ps.Configuration[keyVersion] = v } + // Set the booleans as is. + ps.Configuration["obj_bucket_force_delete"] = pc.Spec.Configuration.ObjForceDelete + ps.Configuration["obj_use_temp_keys"] = pc.Spec.Configuration.ObjUseTempKeys + ps.Configuration["skip_instance_ready_poll"] = pc.Spec.Configuration.SkipInstanceReadyPoll + ps.Configuration["skip_instance_delete_poll"] = pc.Spec.Configuration.SkipInstanceDeletePoll + ps.Configuration["skip_implicit_reboots"] = pc.Spec.Configuration.SkipImplicitReboots + ps.Configuration["disable_internal_cache"] = pc.Spec.Configuration.DisableInternalCache + + // do not want to override terraform defaults + if len(pc.Spec.Configuration.UserAgentPrefix) > 0 { + ps.Configuration["ua_prefix"] = pc.Spec.Configuration.UserAgentPrefix + } + + if pc.Spec.Configuration.MinRetryDelayms > 0 { + ps.Configuration["min_retry_delay_ms"] = pc.Spec.Configuration.MinRetryDelayms + } + + if pc.Spec.Configuration.MaxRetryDelayms > 0 { + ps.Configuration["max_retry_delay_ms"] = pc.Spec.Configuration.MaxRetryDelayms + } + + if pc.Spec.Configuration.EventPollms > 0 { + ps.Configuration["event_poll_ms"] = pc.Spec.Configuration.MaxRetryDelayms + } + + if pc.Spec.Configuration.LKEEventPollms > 0 { + ps.Configuration["lke_event_poll_ms"] = pc.Spec.Configuration.LKEEventPollms + } + + if pc.Spec.Configuration.LKENodeReadyPollms > 0 { + ps.Configuration["lke_node_ready_poll_ms"] = pc.Spec.Configuration.LKENodeReadyPollms + } + + if len(pc.Spec.Configuration.ObjAccessKey) > 0 { + ps.Configuration["obj_access_key"] = pc.Spec.Configuration.ObjAccessKey + } + + if len(pc.Spec.Configuration.ObjSecretKey) > 0 { + ps.Configuration["obj_secret_key"] = pc.Spec.Configuration.ObjSecretKey + } + return ps, errors.Wrap(configureNoForkLinodeclient(ctx, &ps, *tfProvider), "failed to configure the no-fork linode client") } } diff --git a/package/crds/linode.upbound.io_providerconfigs.yaml b/package/crds/linode.upbound.io_providerconfigs.yaml index d9c77fd..8692eb7 100644 --- a/package/crds/linode.upbound.io_providerconfigs.yaml +++ b/package/crds/linode.upbound.io_providerconfigs.yaml @@ -51,6 +51,40 @@ spec: spec: description: A ProviderConfigSpec defines the desired state of a ProviderConfig. properties: + config: + description: |- + ProviderConfiguration for configuring the terraform provider + see https://registry.terraform.io/providers/linode/linode/latest/docs#configuration-reference + properties: + disable_internal_cache: + type: boolean + event_poll_ms: + type: integer + lke_event_poll_ms: + type: integer + lke_node_ready_poll_ms: + type: integer + max_retry_delay_ms: + type: integer + min_retry_delay_ms: + type: integer + obj_access_key: + type: string + obj_bucket_force_delete: + type: boolean + obj_secret_key: + type: string + obj_use_temp_keys: + type: boolean + skip_implicit_reboots: + type: boolean + skip_instance_delete_poll: + type: boolean + skip_instance_ready_poll: + type: boolean + ua_prefix: + type: string + type: object credentials: description: Credentials required to authenticate to this provider. properties: From a5d55e3e56d2ee239c6545a6e0a46f02562c2b5b Mon Sep 17 00:00:00 2001 From: Tarun Chinmai Sekar Date: Fri, 28 Jun 2024 10:55:45 -0700 Subject: [PATCH 2/2] Fix lint --- internal/clients/linode.go | 108 +++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 51 deletions(-) diff --git a/internal/clients/linode.go b/internal/clients/linode.go index 2c818f9..28e7423 100644 --- a/internal/clients/linode.go +++ b/internal/clients/linode.go @@ -55,6 +55,62 @@ type SetupConfig struct { TerraformProvider *schema.Provider } +func prepareTerraformProviderConfiguration(creds map[string]string, pc v1beta1.ProviderConfiguration) map[string]any { + var config map[string]any + + if v, ok := creds[keyToken]; ok { + config[keyToken] = v + } + if v, ok := creds[keyURL]; ok { + config[keyURL] = v + } + if v, ok := creds[keyVersion]; ok { + config[keyVersion] = v + } + + // Set the booleans as is. + config["obj_bucket_force_delete"] = pc.ObjForceDelete + config["obj_use_temp_keys"] = pc.ObjUseTempKeys + config["skip_instance_ready_poll"] = pc.SkipInstanceReadyPoll + config["skip_instance_delete_poll"] = pc.SkipInstanceDeletePoll + config["skip_implicit_reboots"] = pc.SkipImplicitReboots + config["disable_internal_cache"] = pc.DisableInternalCache + + // do not want to override terraform defaults + if len(pc.UserAgentPrefix) > 0 { + config["ua_prefix"] = pc.UserAgentPrefix + } + + if pc.MinRetryDelayms > 0 { + config["min_retry_delay_ms"] = pc.MinRetryDelayms + } + + if pc.MaxRetryDelayms > 0 { + config["max_retry_delay_ms"] = pc.MaxRetryDelayms + } + + if pc.EventPollms > 0 { + config["event_poll_ms"] = pc.MaxRetryDelayms + } + + if pc.LKEEventPollms > 0 { + config["lke_event_poll_ms"] = pc.LKEEventPollms + } + + if pc.LKENodeReadyPollms > 0 { + config["lke_node_ready_poll_ms"] = pc.LKENodeReadyPollms + } + + if len(pc.ObjAccessKey) > 0 { + config["obj_access_key"] = pc.ObjAccessKey + } + + if len(pc.ObjSecretKey) > 0 { + config["obj_secret_key"] = pc.ObjSecretKey + } + return config +} + // TerraformSetupBuilder builds Terraform a terraform.SetupFn function which // returns Terraform provider setup configuration func TerraformSetupBuilder(tfProvider *schema.Provider) terraform.SetupFn { @@ -89,57 +145,7 @@ func TerraformSetupBuilder(tfProvider *schema.Provider) terraform.SetupFn { } // set provider configuration - ps.Configuration = map[string]any{} - if v, ok := creds[keyToken]; ok { - ps.Configuration[keyToken] = v - } - if v, ok := creds[keyURL]; ok { - ps.Configuration[keyURL] = v - } - if v, ok := creds[keyVersion]; ok { - ps.Configuration[keyVersion] = v - } - - // Set the booleans as is. - ps.Configuration["obj_bucket_force_delete"] = pc.Spec.Configuration.ObjForceDelete - ps.Configuration["obj_use_temp_keys"] = pc.Spec.Configuration.ObjUseTempKeys - ps.Configuration["skip_instance_ready_poll"] = pc.Spec.Configuration.SkipInstanceReadyPoll - ps.Configuration["skip_instance_delete_poll"] = pc.Spec.Configuration.SkipInstanceDeletePoll - ps.Configuration["skip_implicit_reboots"] = pc.Spec.Configuration.SkipImplicitReboots - ps.Configuration["disable_internal_cache"] = pc.Spec.Configuration.DisableInternalCache - - // do not want to override terraform defaults - if len(pc.Spec.Configuration.UserAgentPrefix) > 0 { - ps.Configuration["ua_prefix"] = pc.Spec.Configuration.UserAgentPrefix - } - - if pc.Spec.Configuration.MinRetryDelayms > 0 { - ps.Configuration["min_retry_delay_ms"] = pc.Spec.Configuration.MinRetryDelayms - } - - if pc.Spec.Configuration.MaxRetryDelayms > 0 { - ps.Configuration["max_retry_delay_ms"] = pc.Spec.Configuration.MaxRetryDelayms - } - - if pc.Spec.Configuration.EventPollms > 0 { - ps.Configuration["event_poll_ms"] = pc.Spec.Configuration.MaxRetryDelayms - } - - if pc.Spec.Configuration.LKEEventPollms > 0 { - ps.Configuration["lke_event_poll_ms"] = pc.Spec.Configuration.LKEEventPollms - } - - if pc.Spec.Configuration.LKENodeReadyPollms > 0 { - ps.Configuration["lke_node_ready_poll_ms"] = pc.Spec.Configuration.LKENodeReadyPollms - } - - if len(pc.Spec.Configuration.ObjAccessKey) > 0 { - ps.Configuration["obj_access_key"] = pc.Spec.Configuration.ObjAccessKey - } - - if len(pc.Spec.Configuration.ObjSecretKey) > 0 { - ps.Configuration["obj_secret_key"] = pc.Spec.Configuration.ObjSecretKey - } + ps.Configuration = prepareTerraformProviderConfiguration(creds, pc.Spec.Configuration) return ps, errors.Wrap(configureNoForkLinodeclient(ctx, &ps, *tfProvider), "failed to configure the no-fork linode client") }