From 5b4cc6e7e3bd0e5114230ee86f6ebfac30773e1a Mon Sep 17 00:00:00 2001 From: Yisheng Cai Date: Sat, 23 Nov 2024 00:28:27 +0800 Subject: [PATCH] feat: Support specify annotations for cloud environments (#78) ```hcl resource "streamnative_cloud_environment" "test" { cloud_connection_name = "test" region = "us-east-1" organization = "test" environment_type = "dev" network { cidr = "10.0.0.0/16" } annotations = { "cloud.streamnative.io/test" = "true" } } ``` --- cloud/helper.go | 9 +++++++++ cloud/provider.go | 1 + cloud/resource_cloud_environment.go | 27 +++++++++++++++++++-------- cloud/validate_helpers.go | 15 +++++++++++++++ 4 files changed, 44 insertions(+), 8 deletions(-) create mode 100644 cloud/helper.go diff --git a/cloud/helper.go b/cloud/helper.go new file mode 100644 index 0000000..d0ba6f3 --- /dev/null +++ b/cloud/helper.go @@ -0,0 +1,9 @@ +package cloud + +func convertToStringMap(m map[string]interface{}) map[string]string { + result := make(map[string]string) + for k, v := range m { + result[k] = v.(string) + } + return result +} diff --git a/cloud/provider.go b/cloud/provider.go index 2224e72..7d43863 100644 --- a/cloud/provider.go +++ b/cloud/provider.go @@ -166,6 +166,7 @@ func init() { "and the aliases of PrivateLinkService in Azure.", "oauth2_issuer_url": "The issuer url of the oauth2", "oauth2_audience": "The audience of the oauth2", + "annotations": "The metadata annotations of the resource", } } diff --git a/cloud/resource_cloud_environment.go b/cloud/resource_cloud_environment.go index dcb63fe..513a513 100644 --- a/cloud/resource_cloud_environment.go +++ b/cloud/resource_cloud_environment.go @@ -23,11 +23,11 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/retry" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - cloudv1alpha1 "github.com/streamnative/cloud-api-server/pkg/apis/cloud/v1alpha1" - cloudclient "github.com/streamnative/cloud-api-server/pkg/client/clientset_generated/clientset" - "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + cloudv1alpha1 "github.com/streamnative/cloud-api-server/pkg/apis/cloud/v1alpha1" + cloudclient "github.com/streamnative/cloud-api-server/pkg/client/clientset_generated/clientset" ) func resourceCloudEnvironment() *schema.Resource { @@ -157,6 +157,13 @@ func resourceCloudEnvironment() *schema.Resource { }, }, }, + "annotations": { + Type: schema.TypeMap, + Description: descriptions["annotations"], + Optional: true, + Elem: &schema.Schema{Type: schema.TypeString}, + ValidateFunc: validateAnnotations, + }, "wait_for_completion": { Type: schema.TypeBool, Optional: true, @@ -178,12 +185,18 @@ func resourceCloudEnvironmentCreate(ctx context.Context, d *schema.ResourceData, zone := d.Get("zone").(string) cloudConnectionName := d.Get("cloud_connection_name").(string) network := d.Get("network").([]interface{}) + rawAnnotations := d.Get("annotations").(map[string]interface{}) waitForCompletion := d.Get("wait_for_completion") clientSet, err := getClientSet(getFactoryFromMeta(meta)) if err != nil { return diag.FromErr(fmt.Errorf("ERROR_INIT_CLIENT_ON_CLOUD_ENVIRONMENT: %w", err)) } + annotations := make(map[string]string) + if len(rawAnnotations) > 0 { + annotations = convertToStringMap(rawAnnotations) + } + annotations["cloud.streamnative.io/environment-type"] = cloudEnvironmentType cloudEnvironment := &cloudv1alpha1.CloudEnvironment{ TypeMeta: metav1.TypeMeta{ @@ -191,10 +204,8 @@ func resourceCloudEnvironmentCreate(ctx context.Context, d *schema.ResourceData, APIVersion: cloudv1alpha1.SchemeGroupVersion.String(), }, ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Annotations: map[string]string{ - "cloud.streamnative.io/environment-type": cloudEnvironmentType, - }, + Namespace: namespace, + Annotations: annotations, }, Spec: cloudv1alpha1.CloudEnvironmentSpec{ CloudConnectionName: cloudConnectionName, @@ -407,7 +418,7 @@ func retryUntilCloudEnvironmentIsProvisioned(ctx context.Context, clientSet *clo return func() *retry.RetryError { ce, err := clientSet.CloudV1alpha1().CloudEnvironments(ns).Get(ctx, name, metav1.GetOptions{}) if err != nil { - if statusErr, ok := err.(*errors.StatusError); ok && errors.IsNotFound(statusErr) { + if statusErr, ok := err.(*apierrors.StatusError); ok && apierrors.IsNotFound(statusErr) { return nil } return retry.NonRetryableError(err) diff --git a/cloud/validate_helpers.go b/cloud/validate_helpers.go index d123768..11f9d59 100644 --- a/cloud/validate_helpers.go +++ b/cloud/validate_helpers.go @@ -18,6 +18,8 @@ import ( "fmt" "strconv" "strings" + + utilValidation "k8s.io/apimachinery/pkg/util/validation" ) func validateNotBlank(val interface{}, key string) (warns []string, errs []error) { @@ -125,6 +127,19 @@ func validateCidrRange(val interface{}, key string) (warns []string, errs []erro return } +func validateAnnotations(value interface{}, key string) (ws []string, es []error) { + m := value.(map[string]interface{}) + for k := range m { + errors := utilValidation.IsQualifiedName(strings.ToLower(k)) + if len(errors) > 0 { + for _, e := range errors { + es = append(es, fmt.Errorf("%s (%q) %s", key, k, e)) + } + } + } + return +} + func contains(s []string, e string) bool { for _, a := range s { if a == e {