From f478704d999214d84b93ffc6ceb8f0663723369f Mon Sep 17 00:00:00 2001 From: Vandy Liu Date: Mon, 8 Apr 2024 17:04:01 -0700 Subject: [PATCH 01/11] wip --- docs/data-sources/deployment.md | 126 +++++++ docs/data-sources/deployments.md | 138 ++++++++ .../datasources/data_source_deployment.go | 118 +++++++ .../datasources/data_source_deployments.go | 155 ++++++++ internal/provider/models/deployment.go | 220 ++++++++++++ internal/provider/models/deployments.go | 48 +++ internal/provider/models/subject_profile.go | 85 ++--- internal/provider/models/workspace.go | 16 +- internal/provider/models/workspaces.go | 36 +- internal/provider/provider.go | 2 + internal/provider/schemas/deployment.go | 330 ++++++++++++++++++ internal/provider/schemas/deployments.go | 98 ++++++ .../provider/schemas/subject_profile_test.go | 40 +++ internal/utils/list.go | 38 ++ 14 files changed, 1359 insertions(+), 91 deletions(-) create mode 100644 docs/data-sources/deployment.md create mode 100644 docs/data-sources/deployments.md create mode 100644 internal/provider/datasources/data_source_deployment.go create mode 100644 internal/provider/datasources/data_source_deployments.go create mode 100644 internal/provider/models/deployment.go create mode 100644 internal/provider/models/deployments.go create mode 100644 internal/provider/schemas/deployment.go create mode 100644 internal/provider/schemas/deployments.go create mode 100644 internal/utils/list.go diff --git a/docs/data-sources/deployment.md b/docs/data-sources/deployment.md new file mode 100644 index 00000000..f9a2217f --- /dev/null +++ b/docs/data-sources/deployment.md @@ -0,0 +1,126 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "astronomer_deployment Data Source - astronomer" +subcategory: "" +description: |- + Deployment data source +--- + +# astronomer_deployment (Data Source) + +Deployment data source + + + + +## Schema + +### Required + +- `id` (String) Deployment identifier + +### Read-Only + +- `airflow_version` (String) Deployment Airflow version +- `astro_runtime_version` (String) Deployment Astro Runtime version +- `cloud_provider` (String) Deployment cloud provider +- `cluster_id` (String) Deployment cluster identifier +- `cluster_name` (String) Deployment cluster name +- `contact_emails` (List of String) Deployment contact emails +- `created_at` (String) Deployment creation timestamp +- `created_by` (Attributes) Deployment creator (see [below for nested schema](#nestedatt--created_by)) +- `dag_tarball_version` (String) Deployment DAG tarball version +- `default_task_pod_cpu` (String) Deployment default task pod CPU +- `default_task_pod_memory` (String) Deployment default task pod memory +- `description` (String) Deployment description +- `desired_dag_tarball_version` (String) Deployment desired DAG tarball version +- `environment_variables` (Attributes List) Deployment environment variables (see [below for nested schema](#nestedatt--environment_variables)) +- `executor` (String) Deployment executor +- `external_ips` (List of String) Deployment external IPs +- `image_repository` (String) Deployment image repository +- `image_tag` (String) Deployment mage tag +- `image_version` (String) Deployment image version +- `is_cicd_enforced` (Boolean) Deployment CI/CD enforced +- `is_dag_deploy_enabled` (Boolean) Deployment DAG deploy enabled +- `is_development_mode` (Boolean) Deployment development mode +- `is_high_availability` (Boolean) Deployment high availability +- `name` (String) Deployment name +- `namespace` (String) Deployment namespace +- `oidc_issuer_url` (String) Deployment OIDC issuer URL +- `region` (String) Deployment region +- `resource_quota_cpu` (String) Deployment resource quota CPU +- `resource_quota_memory` (String) Deployment resource quota memory +- `scheduler_au` (Number) Deployment scheduler AU +- `scheduler_cpu` (String) Deployment scheduler CPU +- `scheduler_memory` (String) Deployment scheduler memory +- `scheduler_replicas` (Number) Deployment scheduler replicas +- `scheduler_size` (String) Deployment scheduler size +- `status` (String) Deployment status +- `status_reason` (String) Deployment status reason +- `task_pod_node_pool_id` (String) Deployment task pod node pool identifier +- `type` (String) Deployment type +- `updated_at` (String) Deployment last updated timestamp +- `updated_by` (Attributes) Deployment updater (see [below for nested schema](#nestedatt--updated_by)) +- `webserver_airflow_api_url` (String) Deployment webserver Airflow API URL +- `webserver_cpu` (String) Deployment webserver CPU +- `webserver_ingress_hostname` (String) Deployment webserver ingress hostname +- `webserver_memory` (String) Deployment webserver memory +- `webserver_replicas` (Number) Deployment webserver replicas +- `webserver_url` (String) Deployment webserver URL +- `worker_queues` (Attributes List) Deployment worker queues (see [below for nested schema](#nestedatt--worker_queues)) +- `workload_identity` (String) Deployment workload identity +- `workspace_id` (String) Deployment workspace identifier +- `workspace_name` (String) Deployment workspace name + + +### Nested Schema for `created_by` + +Read-Only: + +- `api_token_name` (String) +- `avatar_url` (String) +- `full_name` (String) +- `id` (String) +- `subject_type` (String) +- `username` (String) + + + +### Nested Schema for `environment_variables` + +Read-Only: + +- `is_secret` (Boolean) Whether Environment variable is a secret +- `key` (String) Environment variable key +- `updated_at` (String) Environment variable last updated timestamp +- `value` (String) Environment variable value + + + +### Nested Schema for `updated_by` + +Read-Only: + +- `api_token_name` (String) +- `avatar_url` (String) +- `full_name` (String) +- `id` (String) +- `subject_type` (String) +- `username` (String) + + + +### Nested Schema for `worker_queues` + +Read-Only: + +- `astro_machine` (String) +- `id` (String) +- `is_default` (Boolean) +- `max_worker_count` (Number) +- `min_worker_count` (Number) +- `name` (String) +- `node_pool_id` (String) +- `pod_cpu` (String) +- `pod_memory` (String) +- `worker_concurrency` (Number) diff --git a/docs/data-sources/deployments.md b/docs/data-sources/deployments.md new file mode 100644 index 00000000..e98bf6de --- /dev/null +++ b/docs/data-sources/deployments.md @@ -0,0 +1,138 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "astronomer_deployments Data Source - astronomer" +subcategory: "" +description: |- + Deployments data source +--- + +# astronomer_deployments (Data Source) + +Deployments data source + + + + +## Schema + +### Optional + +- `deployment_ids` (List of String) +- `names` (List of String) + +### Read-Only + +- `deployments` (Attributes List) (see [below for nested schema](#nestedatt--deployments)) + + +### Nested Schema for `deployments` + +Required: + +- `id` (String) Deployment identifier + +Read-Only: + +- `airflow_version` (String) Deployment Airflow version +- `astro_runtime_version` (String) Deployment Astro Runtime version +- `cloud_provider` (String) Deployment cloud provider +- `cluster_id` (String) Deployment cluster identifier +- `cluster_name` (String) Deployment cluster name +- `contact_emails` (List of String) Deployment contact emails +- `created_at` (String) Deployment creation timestamp +- `created_by` (Attributes) Deployment creator (see [below for nested schema](#nestedatt--deployments--created_by)) +- `dag_tarball_version` (String) Deployment DAG tarball version +- `default_task_pod_cpu` (String) Deployment default task pod CPU +- `default_task_pod_memory` (String) Deployment default task pod memory +- `description` (String) Deployment description +- `desired_dag_tarball_version` (String) Deployment desired DAG tarball version +- `environment_variables` (Attributes List) Deployment environment variables (see [below for nested schema](#nestedatt--deployments--environment_variables)) +- `executor` (String) Deployment executor +- `external_ips` (List of String) Deployment external IPs +- `image_repository` (String) Deployment image repository +- `image_tag` (String) Deployment mage tag +- `image_version` (String) Deployment image version +- `is_cicd_enforced` (Boolean) Deployment CI/CD enforced +- `is_dag_deploy_enabled` (Boolean) Deployment DAG deploy enabled +- `is_development_mode` (Boolean) Deployment development mode +- `is_high_availability` (Boolean) Deployment high availability +- `name` (String) Deployment name +- `namespace` (String) Deployment namespace +- `oidc_issuer_url` (String) Deployment OIDC issuer URL +- `region` (String) Deployment region +- `resource_quota_cpu` (String) Deployment resource quota CPU +- `resource_quota_memory` (String) Deployment resource quota memory +- `scheduler_au` (Number) Deployment scheduler AU +- `scheduler_cpu` (String) Deployment scheduler CPU +- `scheduler_memory` (String) Deployment scheduler memory +- `scheduler_replicas` (Number) Deployment scheduler replicas +- `scheduler_size` (String) Deployment scheduler size +- `status` (String) Deployment status +- `status_reason` (String) Deployment status reason +- `task_pod_node_pool_id` (String) Deployment task pod node pool identifier +- `type` (String) Deployment type +- `updated_at` (String) Deployment last updated timestamp +- `updated_by` (Attributes) Deployment updater (see [below for nested schema](#nestedatt--deployments--updated_by)) +- `webserver_airflow_api_url` (String) Deployment webserver Airflow API URL +- `webserver_cpu` (String) Deployment webserver CPU +- `webserver_ingress_hostname` (String) Deployment webserver ingress hostname +- `webserver_memory` (String) Deployment webserver memory +- `webserver_replicas` (Number) Deployment webserver replicas +- `webserver_url` (String) Deployment webserver URL +- `worker_queues` (Attributes List) Deployment worker queues (see [below for nested schema](#nestedatt--deployments--worker_queues)) +- `workload_identity` (String) Deployment workload identity +- `workspace_id` (String) Deployment workspace identifier +- `workspace_name` (String) Deployment workspace name + + +### Nested Schema for `deployments.created_by` + +Read-Only: + +- `api_token_name` (String) +- `avatar_url` (String) +- `full_name` (String) +- `id` (String) +- `subject_type` (String) +- `username` (String) + + + +### Nested Schema for `deployments.environment_variables` + +Read-Only: + +- `is_secret` (Boolean) Whether Environment variable is a secret +- `key` (String) Environment variable key +- `updated_at` (String) Environment variable last updated timestamp +- `value` (String) Environment variable value + + + +### Nested Schema for `deployments.updated_by` + +Read-Only: + +- `api_token_name` (String) +- `avatar_url` (String) +- `full_name` (String) +- `id` (String) +- `subject_type` (String) +- `username` (String) + + + +### Nested Schema for `deployments.worker_queues` + +Read-Only: + +- `astro_machine` (String) +- `id` (String) +- `is_default` (Boolean) +- `max_worker_count` (Number) +- `min_worker_count` (Number) +- `name` (String) +- `node_pool_id` (String) +- `pod_cpu` (String) +- `pod_memory` (String) +- `worker_concurrency` (Number) diff --git a/internal/provider/datasources/data_source_deployment.go b/internal/provider/datasources/data_source_deployment.go new file mode 100644 index 00000000..2f2d8ed9 --- /dev/null +++ b/internal/provider/datasources/data_source_deployment.go @@ -0,0 +1,118 @@ +package datasources + +import ( + "context" + "fmt" + + "github.com/astronomer/astronomer-terraform-provider/internal/clients" + "github.com/astronomer/astronomer-terraform-provider/internal/clients/platform" + "github.com/astronomer/astronomer-terraform-provider/internal/provider/models" + "github.com/astronomer/astronomer-terraform-provider/internal/provider/schemas" + "github.com/astronomer/astronomer-terraform-provider/internal/utils" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-log/tflog" +) + +// Ensure provider defined types fully satisfy framework interfaces. +var _ datasource.DataSource = &deploymentDataSource{} +var _ datasource.DataSourceWithConfigure = &deploymentDataSource{} + +func NewDeploymentDataSource() datasource.DataSource { + return &deploymentDataSource{} +} + +// deploymentDataSource defines the data source implementation. +type deploymentDataSource struct { + PlatformClient platform.ClientWithResponsesInterface + OrganizationId string +} + +func (d *deploymentDataSource) Metadata( + ctx context.Context, + req datasource.MetadataRequest, + resp *datasource.MetadataResponse, +) { + resp.TypeName = req.ProviderTypeName + "_deployment" +} + +func (d *deploymentDataSource) Schema( + ctx context.Context, + req datasource.SchemaRequest, + resp *datasource.SchemaResponse, +) { + resp.Schema = schema.Schema{ + // This description is used by the documentation generator and the language server. + MarkdownDescription: "Deployment data source", + Attributes: schemas.DeploymentDataSourceSchemaAttributes(), + } +} + +func (d *deploymentDataSource) Configure( + ctx context.Context, + req datasource.ConfigureRequest, + resp *datasource.ConfigureResponse, +) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + + apiClients, ok := req.ProviderData.(models.ApiClientsModel) + if !ok { + utils.DataSourceApiClientConfigureError(ctx, req, resp) + return + } + + d.PlatformClient = apiClients.PlatformClient + d.OrganizationId = apiClients.OrganizationId +} + +func (d *deploymentDataSource) Read( + ctx context.Context, + req datasource.ReadRequest, + resp *datasource.ReadResponse, +) { + var data models.DeploymentDataSource + + // Read Terraform configuration data into the model + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + + if resp.Diagnostics.HasError() { + return + } + + deployment, err := d.PlatformClient.GetDeploymentWithResponse( + ctx, + d.OrganizationId, + data.Id.ValueString(), + ) + if err != nil { + tflog.Error(ctx, "failed to get deployment", map[string]interface{}{"error": err}) + resp.Diagnostics.AddError( + "Client Error", + fmt.Sprintf("Unable to read deployment, got error: %s", err), + ) + return + } + _, diagnostic := clients.NormalizeAPIError(ctx, deployment.HTTPResponse, deployment.Body) + if diagnostic != nil { + resp.Diagnostics.Append(diagnostic) + return + } + if deployment.JSON200 == nil { + tflog.Error(ctx, "failed to get deployment", map[string]interface{}{"error": "nil response"}) + resp.Diagnostics.AddError("Client Error", "Unable to read deployment, got nil response") + return + } + + // Populate the model with the response data + diags := data.ReadFromResponse(ctx, deployment.JSON200) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + + // Save data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} diff --git a/internal/provider/datasources/data_source_deployments.go b/internal/provider/datasources/data_source_deployments.go new file mode 100644 index 00000000..8252597b --- /dev/null +++ b/internal/provider/datasources/data_source_deployments.go @@ -0,0 +1,155 @@ +package datasources + +import ( + "context" + "fmt" + "strings" + + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/samber/lo" + + "github.com/astronomer/astronomer-terraform-provider/internal/clients" + "github.com/astronomer/astronomer-terraform-provider/internal/clients/platform" + "github.com/astronomer/astronomer-terraform-provider/internal/provider/models" + "github.com/astronomer/astronomer-terraform-provider/internal/provider/schemas" + "github.com/astronomer/astronomer-terraform-provider/internal/utils" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-log/tflog" +) + +// Ensure provider defined types fully satisfy framework interfaces. +var _ datasource.DataSource = &deploymentsDataSource{} +var _ datasource.DataSourceWithConfigure = &deploymentsDataSource{} + +func NewDeploymentsDataSource() datasource.DataSource { + return &deploymentsDataSource{} +} + +// deploymentsDataSource defines the data source implementation. +type deploymentsDataSource struct { + PlatformClient platform.ClientWithResponsesInterface + OrganizationId string +} + +func (d *deploymentsDataSource) Metadata( + ctx context.Context, + req datasource.MetadataRequest, + resp *datasource.MetadataResponse, +) { + resp.TypeName = req.ProviderTypeName + "_deployments" +} + +func (d *deploymentsDataSource) Schema( + ctx context.Context, + req datasource.SchemaRequest, + resp *datasource.SchemaResponse, +) { + resp.Schema = schema.Schema{ + // This description is used by the documentation generator and the language server. + MarkdownDescription: "Deployments data source", + Attributes: schemas.DeploymentsDataSourceSchemaAttributes(), + } +} + +func (d *deploymentsDataSource) Configure( + ctx context.Context, + req datasource.ConfigureRequest, + resp *datasource.ConfigureResponse, +) { + // Prevent panic if the provider has not been configured. + if req.ProviderData == nil { + return + } + + apiClients, ok := req.ProviderData.(models.ApiClientsModel) + if !ok { + utils.DataSourceApiClientConfigureError(ctx, req, resp) + return + } + + d.PlatformClient = apiClients.PlatformClient + d.OrganizationId = apiClients.OrganizationId +} + +func (d *deploymentsDataSource) Read( + ctx context.Context, + req datasource.ReadRequest, + resp *datasource.ReadResponse, +) { + var data models.DeploymentsDataSource + + // Read Terraform configuration data into the model + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + + params := &platform.ListDeploymentsParams{ + Limit: lo.ToPtr(1000), + } + deploymentIds := data.DeploymentIds.Elements() + if len(deploymentIds) > 0 { + deploymentIdsParam := lo.Map(deploymentIds, func(id attr.Value, _ int) string { + // Terraform includes quotes around the string, so we need to remove them + return strings.ReplaceAll(id.String(), `"`, "") + }) + params.DeploymentIds = &deploymentIdsParam + } + names := data.Names.Elements() + if len(names) > 0 { + namesParam := lo.Map(names, func(name attr.Value, _ int) string { + // Terraform includes quotes around the string, so we need to remove them + return strings.ReplaceAll(name.String(), `"`, "") + }) + params.Names = &namesParam + } + + if resp.Diagnostics.HasError() { + return + } + + var deployments []platform.Deployment + offset := 0 + for { + params.Offset = &offset + deploymentsResp, err := d.PlatformClient.ListDeploymentsWithResponse( + ctx, + d.OrganizationId, + params, + ) + if err != nil { + tflog.Error(ctx, "failed to get deployment", map[string]interface{}{"error": err}) + resp.Diagnostics.AddError( + "Client Error", + fmt.Sprintf("Unable to read deployment, got error: %s", err), + ) + return + } + _, diagnostic := clients.NormalizeAPIError(ctx, deploymentsResp.HTTPResponse, deploymentsResp.Body) + if diagnostic != nil { + resp.Diagnostics.Append(diagnostic) + return + } + if deploymentsResp.JSON200 == nil { + tflog.Error(ctx, "failed to get deployment", map[string]interface{}{"error": "nil response"}) + resp.Diagnostics.AddError("Client Error", "Unable to read deployment, got nil response") + return + } + + deployments = append(deployments, deploymentsResp.JSON200.Deployments...) + + if deploymentsResp.JSON200.TotalCount <= offset { + break + } + + offset += 1000 + } + + // Populate the model with the response data + diags := data.ReadFromResponse(ctx, deployments) + if diags.HasError() { + resp.Diagnostics.Append(diags...) + return + } + + // Save data into Terraform state + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} diff --git a/internal/provider/models/deployment.go b/internal/provider/models/deployment.go new file mode 100644 index 00000000..c54b9f1c --- /dev/null +++ b/internal/provider/models/deployment.go @@ -0,0 +1,220 @@ +package models + +import ( + "context" + "github.com/astronomer/astronomer-terraform-provider/internal/clients/platform" + "github.com/astronomer/astronomer-terraform-provider/internal/provider/schemas" + "github.com/astronomer/astronomer-terraform-provider/internal/utils" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// DeploymentDataSource describes the data source data model. +type DeploymentDataSource struct { + Id types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + Description types.String `tfsdk:"description"` + CreatedAt types.String `tfsdk:"created_at"` + UpdatedAt types.String `tfsdk:"updated_at"` + CreatedBy types.Object `tfsdk:"created_by"` + UpdatedBy types.Object `tfsdk:"updated_by"` + WorkspaceId types.String `tfsdk:"workspace_id"` + WorkspaceName types.String `tfsdk:"workspace_name"` + ClusterId types.String `tfsdk:"cluster_id"` + ClusterName types.String `tfsdk:"cluster_name"` + Region types.String `tfsdk:"region"` + CloudProvider types.String `tfsdk:"cloud_provider"` + AstroRuntimeVersion types.String `tfsdk:"astro_runtime_version"` + AirflowVersion types.String `tfsdk:"airflow_version"` + Namespace types.String `tfsdk:"namespace"` + ContactEmails types.List `tfsdk:"contact_emails"` + Executor types.String `tfsdk:"executor"` + SchedulerAu types.Int64 `tfsdk:"scheduler_au"` + SchedulerCpu types.String `tfsdk:"scheduler_cpu"` + SchedulerMemory types.String `tfsdk:"scheduler_memory"` + SchedulerReplicas types.Int64 `tfsdk:"scheduler_replicas"` + ImageTag types.String `tfsdk:"image_tag"` + ImageRepository types.String `tfsdk:"image_repository"` + ImageVersion types.String `tfsdk:"image_version"` + EnvironmentVariables types.List `tfsdk:"environment_variables"` + WebserverIngressHostname types.String `tfsdk:"webserver_ingress_hostname"` + WebserverUrl types.String `tfsdk:"webserver_url"` + WebserverAirflowApiUrl types.String `tfsdk:"webserver_airflow_api_url"` + WebserverCpu types.String `tfsdk:"webserver_cpu"` + WebserverMemory types.String `tfsdk:"webserver_memory"` + WebserverReplicas types.Int64 `tfsdk:"webserver_replicas"` + Status types.String `tfsdk:"status"` + StatusReason types.String `tfsdk:"status_reason"` + DagTarballVersion types.String `tfsdk:"dag_tarball_version"` + DesiredDagTarballVersion types.String `tfsdk:"desired_dag_tarball_version"` + WorkerQueues types.List `tfsdk:"worker_queues"` + TaskPodNodePoolId types.String `tfsdk:"task_pod_node_pool_id"` + IsCicdEnforced types.Bool `tfsdk:"is_cicd_enforced"` + Type types.String `tfsdk:"type"` + IsDagDeployEnabled types.Bool `tfsdk:"is_dag_deploy_enabled"` + SchedulerSize types.String `tfsdk:"scheduler_size"` + IsHighAvailability types.Bool `tfsdk:"is_high_availability"` + IsDevelopmentMode types.Bool `tfsdk:"is_development_mode"` + WorkloadIdentity types.String `tfsdk:"workload_identity"` + ExternalIps types.List `tfsdk:"external_ips"` + OidcIssuerUrl types.String `tfsdk:"oidc_issuer_url"` + ResourceQuotaCpu types.String `tfsdk:"resource_quota_cpu"` + ResourceQuotaMemory types.String `tfsdk:"resource_quota_memory"` + DefaultTaskPodCpu types.String `tfsdk:"default_task_pod_cpu"` + DefaultTaskPodMemory types.String `tfsdk:"default_task_pod_memory"` + //ScalingStatus types.Object `tfsdk:"scaling_status"` + //ScalingSpec types.Object `tfsdk:"scaling_spec"` +} + +type DeploymentEnvironmentVariable struct { + Key types.String `tfsdk:"key"` + Value types.String `tfsdk:"value"` + UpdatedAt types.String `tfsdk:"updated_at"` + IsSecret types.Bool `tfsdk:"is_secret"` +} + +type WorkerQueue struct { + Id types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + AstroMachine types.String `tfsdk:"astro_machine"` + IsDefault types.Bool `tfsdk:"is_default"` + MaxWorkerCount types.Int64 `tfsdk:"max_worker_count"` + MinWorkerCount types.Int64 `tfsdk:"min_worker_count"` + NodePoolId types.String `tfsdk:"node_pool_id"` + PodCpu types.String `tfsdk:"pod_cpu"` + PodMemory types.String `tfsdk:"pod_memory"` + WorkerConcurrency types.Int64 `tfsdk:"worker_concurrency"` +} + +func (data *DeploymentDataSource) ReadFromResponse( + ctx context.Context, + deployment *platform.Deployment, +) diag.Diagnostics { + data.Id = types.StringValue(deployment.Id) + data.Name = types.StringValue(deployment.Name) + data.Description = types.StringPointerValue(deployment.Description) + data.CreatedAt = types.StringValue(deployment.CreatedAt.String()) + data.UpdatedAt = types.StringValue(deployment.UpdatedAt.String()) + var diags diag.Diagnostics + data.CreatedBy, diags = SubjectProfileTypesObject(ctx, deployment.CreatedBy) + if diags.HasError() { + return diags + } + data.UpdatedBy, diags = SubjectProfileTypesObject(ctx, deployment.UpdatedBy) + if diags.HasError() { + return diags + } + data.WorkspaceId = types.StringValue(deployment.WorkspaceId) + data.WorkspaceName = types.StringPointerValue(deployment.WorkspaceName) + data.ClusterId = types.StringPointerValue(deployment.ClusterId) + data.ClusterName = types.StringPointerValue(deployment.ClusterName) + data.Region = types.StringPointerValue(deployment.Region) + data.CloudProvider = types.StringPointerValue((*string)(deployment.CloudProvider)) + data.AstroRuntimeVersion = types.StringValue(deployment.AstroRuntimeVersion) + data.AirflowVersion = types.StringValue(deployment.AirflowVersion) + data.Namespace = types.StringValue(deployment.Namespace) + if deployment.ContactEmails != nil { + data.ContactEmails, diags = utils.StringList(*deployment.ContactEmails) + if diags.HasError() { + return diags + } + } + data.Executor = types.StringPointerValue((*string)(deployment.Executor)) + if deployment.SchedulerAu != nil { + deploymentSchedulerAu := int64(*deployment.SchedulerAu) + data.SchedulerAu = types.Int64Value(deploymentSchedulerAu) + } + data.SchedulerCpu = types.StringValue(deployment.SchedulerCpu) + data.SchedulerMemory = types.StringValue(deployment.SchedulerMemory) + data.SchedulerReplicas = types.Int64Value(int64(deployment.SchedulerReplicas)) + data.ImageTag = types.StringValue(deployment.ImageTag) + data.ImageRepository = types.StringValue(deployment.ImageRepository) + data.ImageVersion = types.StringPointerValue(deployment.ImageVersion) + if deployment.EnvironmentVariables != nil { + data.EnvironmentVariables, diags = utils.ObjectList(ctx, *deployment.EnvironmentVariables, schemas.DeploymentEnvironmentVariableAttributeTypes(), DeploymentEnvironmentVariableTypesObject) + if diags.HasError() { + return diags + } + } + data.WebserverIngressHostname = types.StringValue(deployment.WebServerIngressHostname) + data.WebserverUrl = types.StringValue(deployment.WebServerUrl) + data.WebserverAirflowApiUrl = types.StringValue(deployment.WebServerAirflowApiUrl) + data.WebserverCpu = types.StringValue(deployment.WebServerCpu) + data.WebserverMemory = types.StringValue(deployment.WebServerMemory) + if deployment.WebServerReplicas != nil { + data.WebserverReplicas = types.Int64Value(int64(*deployment.WebServerReplicas)) + } + data.Status = types.StringValue(string(deployment.Status)) + data.StatusReason = types.StringPointerValue(deployment.StatusReason) + data.DagTarballVersion = types.StringPointerValue(deployment.DagTarballVersion) + data.DesiredDagTarballVersion = types.StringPointerValue(deployment.DesiredDagTarballVersion) + if deployment.WorkerQueues != nil { + data.WorkerQueues, diags = utils.ObjectList(ctx, *deployment.WorkerQueues, schemas.WorkerQueueAttributeTypes(), WorkerQueueTypesObject) + if diags.HasError() { + return diags + } + } + data.TaskPodNodePoolId = types.StringPointerValue(deployment.TaskPodNodePoolId) + data.IsCicdEnforced = types.BoolValue(deployment.IsCicdEnforced) + data.Type = types.StringPointerValue((*string)(deployment.Type)) + data.IsDagDeployEnabled = types.BoolValue(deployment.IsDagDeployEnabled) + data.SchedulerSize = types.StringPointerValue((*string)(deployment.SchedulerSize)) + data.IsHighAvailability = types.BoolPointerValue(deployment.IsHighAvailability) + data.IsDevelopmentMode = types.BoolPointerValue(deployment.IsDevelopmentMode) + data.WorkloadIdentity = types.StringPointerValue(deployment.WorkloadIdentity) + if deployment.ExternalIPs != nil { + data.ExternalIps, diags = utils.StringList(*deployment.ExternalIPs) + if diags.HasError() { + return diags + } + } + data.OidcIssuerUrl = types.StringPointerValue(deployment.OidcIssuerUrl) + data.ResourceQuotaCpu = types.StringPointerValue(deployment.ResourceQuotaCpu) + data.ResourceQuotaMemory = types.StringPointerValue(deployment.ResourceQuotaMemory) + data.DefaultTaskPodCpu = types.StringPointerValue(deployment.DefaultTaskPodCpu) + data.DefaultTaskPodMemory = types.StringPointerValue(deployment.DefaultTaskPodMemory) + //data.ScalingStatus, diags = ScalingStatusTypesObject(ctx, deployment.ScalingStatus) + //if diags.HasError() { + // return diags + //} + //data.ScalingSpec, diags = ScalingSpecTypesObject(ctx, deployment.ScalingSpec) + //if diags.HasError() { + // return diags + //} + + return nil +} + +func DeploymentEnvironmentVariableTypesObject( + ctx context.Context, + envVar platform.DeploymentEnvironmentVariable, +) (types.Object, diag.Diagnostics) { + obj := DeploymentEnvironmentVariable{ + Key: types.StringValue(envVar.Key), + Value: types.StringPointerValue(envVar.Value), + UpdatedAt: types.StringValue(envVar.UpdatedAt), + IsSecret: types.BoolValue(envVar.IsSecret), + } + + return types.ObjectValueFrom(ctx, schemas.DeploymentEnvironmentVariableAttributeTypes(), obj) +} + +func WorkerQueueTypesObject( + ctx context.Context, + workerQueue platform.WorkerQueue, +) (types.Object, diag.Diagnostics) { + obj := WorkerQueue{ + Id: types.StringValue(workerQueue.Id), + Name: types.StringValue(workerQueue.Name), + AstroMachine: types.StringPointerValue(workerQueue.AstroMachine), + IsDefault: types.BoolValue(workerQueue.IsDefault), + MaxWorkerCount: types.Int64Value(int64(workerQueue.MaxWorkerCount)), + MinWorkerCount: types.Int64Value(int64(workerQueue.MinWorkerCount)), + NodePoolId: types.StringPointerValue(workerQueue.NodePoolId), + PodCpu: types.StringValue(workerQueue.PodCpu), + PodMemory: types.StringValue(workerQueue.PodMemory), + WorkerConcurrency: types.Int64Value(int64(workerQueue.WorkerConcurrency)), + } + + return types.ObjectValueFrom(ctx, schemas.WorkerQueueAttributeTypes(), obj) +} diff --git a/internal/provider/models/deployments.go b/internal/provider/models/deployments.go new file mode 100644 index 00000000..030a76b1 --- /dev/null +++ b/internal/provider/models/deployments.go @@ -0,0 +1,48 @@ +package models + +import ( + "context" + "github.com/astronomer/astronomer-terraform-provider/internal/clients/platform" + "github.com/astronomer/astronomer-terraform-provider/internal/provider/schemas" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// DeploymentsDataSource describes the data source data model. +type DeploymentsDataSource struct { + Deployments types.List `tfsdk:"deployments"` + DeploymentIds types.List `tfsdk:"deployment_ids"` // query parameter + Names types.List `tfsdk:"names"` // query parameter +} + +func (data *DeploymentsDataSource) ReadFromResponse( + ctx context.Context, + deployments []platform.Deployment, +) diag.Diagnostics { + if len(deployments) == 0 { + types.ListNull(types.ObjectType{AttrTypes: schemas.DeploymentsElementAttributeTypes()}) + } + + values := make([]attr.Value, len(deployments)) + for i, deployment := range deployments { + var data DeploymentDataSource + diags := data.ReadFromResponse(ctx, &deployment) + if diags.HasError() { + return diags + } + + objectValue, diags := types.ObjectValueFrom(ctx, schemas.DeploymentsElementAttributeTypes(), data) + if diags.HasError() { + return diags + } + values[i] = objectValue + } + var diags diag.Diagnostics + data.Deployments, diags = types.ListValue(types.ObjectType{AttrTypes: schemas.DeploymentsElementAttributeTypes()}, values) + if diags.HasError() { + return diags + } + + return nil +} diff --git a/internal/provider/models/subject_profile.go b/internal/provider/models/subject_profile.go index f119b357..326147ae 100644 --- a/internal/provider/models/subject_profile.go +++ b/internal/provider/models/subject_profile.go @@ -2,14 +2,13 @@ package models import ( "context" - + "github.com/astronomer/astronomer-terraform-provider/internal/clients/iam" "github.com/astronomer/astronomer-terraform-provider/internal/provider/schemas" + "github.com/hashicorp/terraform-plugin-log/tflog" - "github.com/astronomer/astronomer-terraform-provider/internal/clients/iam" "github.com/astronomer/astronomer-terraform-provider/internal/clients/platform" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" - "github.com/hashicorp/terraform-plugin-log/tflog" ) type SubjectProfile struct { @@ -25,25 +24,23 @@ func SubjectProfileTypesObject( ctx context.Context, basicSubjectProfile any, ) (types.Object, diag.Diagnostics) { - // Check that the type passed in is a platform.BasicSubjectProfile or iam.BasicSubjectProfile - bsp, ok := basicSubjectProfile.(*platform.BasicSubjectProfile) - if !ok { - iamBsp, ok := basicSubjectProfile.(*iam.BasicSubjectProfile) - if !ok { - tflog.Error( - ctx, - "Unexpected type passed into subject profile", - map[string]interface{}{"value": basicSubjectProfile}, - ) - return types.Object{}, diag.Diagnostics{ - diag.NewErrorDiagnostic( - "Internal Error", - "SubjectProfileTypesObject expects a BasicSubjectProfile type but did not receive one", - ), - } + // Attempt to convert basicSubjectProfile to *platform.BasicSubjectProfile + var bspPtr *platform.BasicSubjectProfile + + switch v := basicSubjectProfile.(type) { + case platform.BasicSubjectProfile: + bspPtr = &v + case *platform.BasicSubjectProfile: + bspPtr = v + case iam.BasicSubjectProfile, *iam.BasicSubjectProfile: + var iamBsp *iam.BasicSubjectProfile + if nonPtr, ok := v.(iam.BasicSubjectProfile); ok { + iamBsp = &nonPtr + } else { + iamBsp = v.(*iam.BasicSubjectProfile) } - // Convert the iam.BasicSubjectProfile to a platform.BasicSubjectProfile for simplicity - bsp = &platform.BasicSubjectProfile{ + + bspPtr = &platform.BasicSubjectProfile{ ApiTokenName: iamBsp.ApiTokenName, AvatarUrl: iamBsp.AvatarUrl, FullName: iamBsp.FullName, @@ -51,37 +48,29 @@ func SubjectProfileTypesObject( SubjectType: (*platform.BasicSubjectProfileSubjectType)(iamBsp.SubjectType), Username: iamBsp.Username, } + default: + // Log error and return if none of the types match + tflog.Error( + ctx, + "Unexpected type passed into subject profile", + map[string]interface{}{"value": basicSubjectProfile}, + ) + return types.Object{}, diag.Diagnostics{ + diag.NewErrorDiagnostic( + "Internal Error", + "SubjectProfileTypesObject expects a BasicSubjectProfile type but did not receive one", + ), + } } subjectProfile := SubjectProfile{ - Id: types.StringValue(bsp.Id), + Id: types.StringValue(bspPtr.Id), + SubjectType: types.StringPointerValue((*string)(bspPtr.SubjectType)), + Username: types.StringPointerValue(bspPtr.Username), + FullName: types.StringPointerValue(bspPtr.FullName), + AvatarUrl: types.StringPointerValue(bspPtr.AvatarUrl), + ApiTokenName: types.StringPointerValue(bspPtr.ApiTokenName), } - if bsp.SubjectType != nil { - subjectProfile.SubjectType = types.StringValue(string(*bsp.SubjectType)) - if *bsp.SubjectType == platform.USER { - if bsp.Username != nil { - subjectProfile.Username = types.StringValue(*bsp.Username) - } else { - subjectProfile.Username = types.StringUnknown() - } - if bsp.FullName != nil { - subjectProfile.FullName = types.StringValue(*bsp.FullName) - } else { - subjectProfile.FullName = types.StringUnknown() - } - if bsp.AvatarUrl != nil { - subjectProfile.AvatarUrl = types.StringValue(*bsp.AvatarUrl) - } else { - subjectProfile.AvatarUrl = types.StringUnknown() - } - } else { - if bsp.ApiTokenName != nil { - subjectProfile.ApiTokenName = types.StringValue(*bsp.ApiTokenName) - } else { - subjectProfile.ApiTokenName = types.StringUnknown() - } - } - } return types.ObjectValueFrom(ctx, schemas.SubjectProfileAttributeTypes(), subjectProfile) } diff --git a/internal/provider/models/workspace.go b/internal/provider/models/workspace.go index 6dbdebf3..5d5a125e 100644 --- a/internal/provider/models/workspace.go +++ b/internal/provider/models/workspace.go @@ -40,12 +40,8 @@ func (data *WorkspaceResource) ReadFromResponse( ) diag.Diagnostics { data.Id = types.StringValue(workspace.Id) data.Name = types.StringValue(workspace.Name) - if workspace.Description != nil { - data.Description = types.StringValue(*workspace.Description) - } - if workspace.OrganizationName != nil { - data.OrganizationName = types.StringValue(*workspace.OrganizationName) - } + data.Description = types.StringPointerValue(workspace.Description) + data.OrganizationName = types.StringPointerValue(workspace.OrganizationName) data.CicdEnforcedDefault = types.BoolValue(workspace.CicdEnforcedDefault) data.CreatedAt = types.StringValue(workspace.CreatedAt.String()) data.UpdatedAt = types.StringValue(workspace.UpdatedAt.String()) @@ -68,12 +64,8 @@ func (data *WorkspaceDataSource) ReadFromResponse( ) diag.Diagnostics { data.Id = types.StringValue(workspace.Id) data.Name = types.StringValue(workspace.Name) - if workspace.Description != nil { - data.Description = types.StringValue(*workspace.Description) - } - if workspace.OrganizationName != nil { - data.OrganizationName = types.StringValue(*workspace.OrganizationName) - } + data.Description = types.StringPointerValue(workspace.Description) + data.OrganizationName = types.StringPointerValue(workspace.OrganizationName) data.CicdEnforcedDefault = types.BoolValue(workspace.CicdEnforcedDefault) data.CreatedAt = types.StringValue(workspace.CreatedAt.String()) data.UpdatedAt = types.StringValue(workspace.UpdatedAt.String()) diff --git a/internal/provider/models/workspaces.go b/internal/provider/models/workspaces.go index 7b82f905..d4661346 100644 --- a/internal/provider/models/workspaces.go +++ b/internal/provider/models/workspaces.go @@ -2,7 +2,6 @@ package models import ( "context" - "github.com/astronomer/astronomer-terraform-provider/internal/clients/platform" "github.com/astronomer/astronomer-terraform-provider/internal/provider/schemas" "github.com/hashicorp/terraform-plugin-framework/attr" @@ -27,38 +26,13 @@ func (data *WorkspacesDataSource) ReadFromResponse( values := make([]attr.Value, len(workspaces)) for i, workspace := range workspaces { - v := map[string]attr.Value{} - v["id"] = types.StringValue(workspace.Id) - v["name"] = types.StringValue(workspace.Name) - if workspace.Description != nil { - v["description"] = types.StringValue(*workspace.Description) - } else { - v["description"] = types.StringNull() - } - if workspace.OrganizationName != nil { - v["organization_name"] = types.StringValue(*workspace.OrganizationName) - } else { - v["organization_name"] = types.StringNull() - } - v["cicd_enforced_default"] = types.BoolValue(workspace.CicdEnforcedDefault) - v["created_at"] = types.StringValue(workspace.CreatedAt.String()) - v["updated_at"] = types.StringValue(workspace.UpdatedAt.String()) - if workspace.CreatedBy != nil { - createdBy, diags := SubjectProfileTypesObject(ctx, workspace.CreatedBy) - if diags.HasError() { - return diags - } - v["created_by"] = createdBy - } - if workspace.UpdatedBy != nil { - updatedBy, diags := SubjectProfileTypesObject(ctx, workspace.UpdatedBy) - if diags.HasError() { - return diags - } - v["updated_by"] = updatedBy + var data WorkspaceDataSource + diags := data.ReadFromResponse(ctx, &workspace) + if diags.HasError() { + return diags } - objectValue, diags := types.ObjectValue(schemas.WorkspacesElementAttributeTypes(), v) + objectValue, diags := types.ObjectValueFrom(ctx, schemas.WorkspacesElementAttributeTypes(), data) if diags.HasError() { return diags } diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 0227f425..01edf380 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -131,6 +131,8 @@ func (p *AstronomerProvider) DataSources(ctx context.Context) []func() datasourc return []func() datasource.DataSource{ datasources.NewWorkspaceDataSource, datasources.NewWorkspacesDataSource, + datasources.NewDeploymentDataSource, + datasources.NewDeploymentsDataSource, } } diff --git a/internal/provider/schemas/deployment.go b/internal/provider/schemas/deployment.go new file mode 100644 index 00000000..98d97f5a --- /dev/null +++ b/internal/provider/schemas/deployment.go @@ -0,0 +1,330 @@ +package schemas + +import ( + "github.com/astronomer/astronomer-terraform-provider/internal/provider/validators" + "github.com/hashicorp/terraform-plugin-framework/attr" + datasourceSchema "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +func DeploymentDataSourceSchemaAttributes() map[string]datasourceSchema.Attribute { + return map[string]datasourceSchema.Attribute{ + "id": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment identifier", + Required: true, + Validators: []validator.String{validators.IsCuid()}, + }, + "name": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment name", + Computed: true, + }, + "description": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment description", + Computed: true, + }, + "created_at": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment creation timestamp", + Computed: true, + }, + "updated_at": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment last updated timestamp", + Computed: true, + }, + "created_by": datasourceSchema.SingleNestedAttribute{ + MarkdownDescription: "Deployment creator", + Computed: true, + Attributes: DataSourceSubjectProfileSchemaAttributes(), + }, + "updated_by": datasourceSchema.SingleNestedAttribute{ + MarkdownDescription: "Deployment updater", + Computed: true, + Attributes: DataSourceSubjectProfileSchemaAttributes(), + }, + "workspace_id": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment workspace identifier", + Computed: true, + }, + "workspace_name": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment workspace name", + Computed: true, + }, + "cluster_id": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment cluster identifier", + Computed: true, + }, + "cluster_name": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment cluster name", + Computed: true, + }, + "region": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment region", + Computed: true, + }, + "cloud_provider": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment cloud provider", + Computed: true, + }, + "astro_runtime_version": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment Astro Runtime version", + Computed: true, + }, + "airflow_version": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment Airflow version", + Computed: true, + }, + "namespace": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment namespace", + Computed: true, + }, + "contact_emails": datasourceSchema.ListAttribute{ + ElementType: types.StringType, + MarkdownDescription: "Deployment contact emails", + Computed: true, + }, + "executor": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment executor", + Computed: true, + }, + "scheduler_au": datasourceSchema.Int64Attribute{ + MarkdownDescription: "Deployment scheduler AU", + Computed: true, + }, + "scheduler_cpu": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment scheduler CPU", + Computed: true, + }, + "scheduler_memory": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment scheduler memory", + Computed: true, + }, + "scheduler_replicas": datasourceSchema.Int64Attribute{ + MarkdownDescription: "Deployment scheduler replicas", + Computed: true, + }, + "image_tag": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment mage tag", + Computed: true, + }, + "image_repository": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment image repository", + Computed: true, + }, + "image_version": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment image version", + Computed: true, + }, + "environment_variables": datasourceSchema.ListNestedAttribute{ + NestedObject: datasourceSchema.NestedAttributeObject{ + Attributes: DeploymentEnvironmentVariableAttributes(), + }, + MarkdownDescription: "Deployment environment variables", + Computed: true, + }, + "webserver_ingress_hostname": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment webserver ingress hostname", + Computed: true, + }, + "webserver_url": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment webserver URL", + Computed: true, + }, + "webserver_airflow_api_url": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment webserver Airflow API URL", + Computed: true, + }, + "webserver_cpu": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment webserver CPU", + Computed: true, + }, + "webserver_memory": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment webserver memory", + Computed: true, + }, + "webserver_replicas": datasourceSchema.Int64Attribute{ + MarkdownDescription: "Deployment webserver replicas", + Computed: true, + }, + "status": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment status", + Computed: true, + }, + "status_reason": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment status reason", + Computed: true, + }, + "dag_tarball_version": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment DAG tarball version", + Computed: true, + }, + "desired_dag_tarball_version": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment desired DAG tarball version", + Computed: true, + }, + "worker_queues": datasourceSchema.ListNestedAttribute{ + NestedObject: datasourceSchema.NestedAttributeObject{ + Attributes: WorkerQueueSchemaAttributes(), + }, + MarkdownDescription: "Deployment worker queues", + Computed: true, + }, + "task_pod_node_pool_id": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment task pod node pool identifier", + Computed: true, + }, + "is_cicd_enforced": datasourceSchema.BoolAttribute{ + MarkdownDescription: "Deployment CI/CD enforced", + Computed: true, + }, + "type": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment type", + Computed: true, + }, + "is_dag_deploy_enabled": datasourceSchema.BoolAttribute{ + MarkdownDescription: "Deployment DAG deploy enabled", + Computed: true, + }, + "scheduler_size": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment scheduler size", + Computed: true, + }, + "is_high_availability": datasourceSchema.BoolAttribute{ + MarkdownDescription: "Deployment high availability", + Computed: true, + }, + "is_development_mode": datasourceSchema.BoolAttribute{ + MarkdownDescription: "Deployment development mode", + Computed: true, + }, + "workload_identity": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment workload identity", + Computed: true, + }, + "external_ips": datasourceSchema.ListAttribute{ + ElementType: types.StringType, + MarkdownDescription: "Deployment external IPs", + Computed: true, + }, + "oidc_issuer_url": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment OIDC issuer URL", + Computed: true, + }, + "resource_quota_cpu": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment resource quota CPU", + Computed: true, + }, + "resource_quota_memory": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment resource quota memory", + Computed: true, + }, + "default_task_pod_cpu": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment default task pod CPU", + Computed: true, + }, + "default_task_pod_memory": datasourceSchema.StringAttribute{ + MarkdownDescription: "Deployment default task pod memory", + Computed: true, + }, + //"scaling_status": datasourceSchema.SingleNestedAttribute{ + // MarkdownDescription: "Deployment scaling status", + // Computed: true, + //}, + //"scaling_spec": datasourceSchema.SingleNestedAttribute{ + // MarkdownDescription: "Deployment scaling spec", + // Computed: true, + //}, + } +} + +func DeploymentEnvironmentVariableAttributeTypes() map[string]attr.Type { + return map[string]attr.Type{ + "key": types.StringType, + "value": types.StringType, + "updated_at": types.StringType, + "is_secret": types.BoolType, + } +} + +func WorkerQueueAttributeTypes() map[string]attr.Type { + return map[string]attr.Type{ + "id": types.StringType, + "name": types.StringType, + "astro_machine": types.StringType, + "is_default": types.BoolType, + "max_worker_count": types.Int64Type, + "min_worker_count": types.Int64Type, + "node_pool_id": types.StringType, + "pod_cpu": types.StringType, + "pod_memory": types.StringType, + "worker_concurrency": types.Int64Type, + } +} + +func DeploymentEnvironmentVariableAttributes() map[string]datasourceSchema.Attribute { + return map[string]datasourceSchema.Attribute{ + "key": datasourceSchema.StringAttribute{ + MarkdownDescription: "Environment variable key", + Computed: true, + }, + "value": datasourceSchema.StringAttribute{ + MarkdownDescription: "Environment variable value", + Computed: true, + }, + "updated_at": datasourceSchema.StringAttribute{ + MarkdownDescription: "Environment variable last updated timestamp", + Computed: true, + }, + "is_secret": datasourceSchema.BoolAttribute{ + MarkdownDescription: "Whether Environment variable is a secret", + Computed: true, + }, + } +} + +func WorkerQueueSchemaAttributes() map[string]datasourceSchema.Attribute { + return map[string]datasourceSchema.Attribute{ + "id": datasourceSchema.StringAttribute{ + Computed: true, + }, + "name": datasourceSchema.StringAttribute{ + Computed: true, + }, + "astro_machine": datasourceSchema.StringAttribute{ + Computed: true, + }, + "is_default": datasourceSchema.BoolAttribute{ + Computed: true, + }, + "max_worker_count": datasourceSchema.Int64Attribute{ + Computed: true, + }, + "min_worker_count": datasourceSchema.Int64Attribute{ + Computed: true, + }, + "node_pool_id": datasourceSchema.StringAttribute{ + Computed: true, + }, + "pod_cpu": datasourceSchema.StringAttribute{ + Computed: true, + }, + "pod_memory": datasourceSchema.StringAttribute{ + Computed: true, + }, + "worker_concurrency": datasourceSchema.Int64Attribute{ + Computed: true, + }, + } +} + +//func ScalingStatusAttributeTypes() map[string]attr.Type { +// return map[string]attr.Type{ +// "hibernation_status": types.ObjectType{ +// AttrTypes: map[string]attr.Type{ +// "is_hibernating": types.StringType, +// "next_event_at": types.StringType, +// "next_event_type": types.StringType, +// "reason": types.StringType, +// }, +// }, +// } +//} diff --git a/internal/provider/schemas/deployments.go b/internal/provider/schemas/deployments.go new file mode 100644 index 00000000..017e1de5 --- /dev/null +++ b/internal/provider/schemas/deployments.go @@ -0,0 +1,98 @@ +package schemas + +import ( + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +func DeploymentsElementAttributeTypes() map[string]attr.Type { + return map[string]attr.Type{ + "id": types.StringType, + "name": types.StringType, + "description": types.StringType, + "created_at": types.StringType, + "updated_at": types.StringType, + "created_by": types.ObjectType{ + AttrTypes: SubjectProfileAttributeTypes(), + }, + "updated_by": types.ObjectType{ + AttrTypes: SubjectProfileAttributeTypes(), + }, + "workspace_id": types.StringType, + "workspace_name": types.StringType, + "cluster_id": types.StringType, + "cluster_name": types.StringType, + "region": types.StringType, + "cloud_provider": types.StringType, + "astro_runtime_version": types.StringType, + "airflow_version": types.StringType, + "namespace": types.StringType, + "contact_emails": types.ListType{ + ElemType: types.StringType, + }, + "executor": types.StringType, + "scheduler_au": types.Int64Type, + "scheduler_cpu": types.StringType, + "scheduler_memory": types.StringType, + "scheduler_replicas": types.Int64Type, + "image_tag": types.StringType, + "image_repository": types.StringType, + "image_version": types.StringType, + "environment_variables": types.ListType{ + ElemType: types.ObjectType{ + AttrTypes: DeploymentEnvironmentVariableAttributeTypes(), + }, + }, + "webserver_ingress_hostname": types.StringType, + "webserver_url": types.StringType, + "webserver_airflow_api_url": types.StringType, + "webserver_cpu": types.StringType, + "webserver_memory": types.StringType, + "webserver_replicas": types.Int64Type, + "status": types.StringType, + "status_reason": types.StringType, + "dag_tarball_version": types.StringType, + "desired_dag_tarball_version": types.StringType, + "worker_queues": types.ListType{ + ElemType: types.ObjectType{ + AttrTypes: WorkerQueueAttributeTypes(), + }, + }, + "task_pod_node_pool_id": types.StringType, + "is_cicd_enforced": types.BoolType, + "type": types.StringType, + "is_dag_deploy_enabled": types.BoolType, + "scheduler_size": types.StringType, + "is_high_availability": types.BoolType, + "is_development_mode": types.BoolType, + "workload_identity": types.StringType, + "external_ips": types.ListType{ + ElemType: types.StringType, + }, + "oidc_issuer_url": types.StringType, + "resource_quota_cpu": types.StringType, + "resource_quota_memory": types.StringType, + "default_task_pod_cpu": types.StringType, + "default_task_pod_memory": types.StringType, + } +} + +func DeploymentsDataSourceSchemaAttributes() map[string]schema.Attribute { + return map[string]schema.Attribute{ + "deployments": schema.ListNestedAttribute{ + NestedObject: schema.NestedAttributeObject{ + Attributes: DeploymentDataSourceSchemaAttributes(), + }, + Computed: true, + }, + "deployment_ids": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + }, + "names": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + }, + } +} diff --git a/internal/provider/schemas/subject_profile_test.go b/internal/provider/schemas/subject_profile_test.go index 7a6fdc2f..e2b77778 100644 --- a/internal/provider/schemas/subject_profile_test.go +++ b/internal/provider/schemas/subject_profile_test.go @@ -80,6 +80,46 @@ var _ = Describe("Common Test", func() { AvatarUrl: types.StringNull(), ApiTokenName: types.StringNull(), }), + Entry("platform.BasicSubjectProfile", platform.BasicSubjectProfile{ + Id: "id", + }, models.SubjectProfile{ + Id: types.StringValue("id"), + SubjectType: types.StringNull(), + Username: types.StringNull(), + FullName: types.StringNull(), + AvatarUrl: types.StringNull(), + ApiTokenName: types.StringNull(), + }), + Entry("*platform.BasicSubjectProfile", &platform.BasicSubjectProfile{ + Id: "id", + }, models.SubjectProfile{ + Id: types.StringValue("id"), + SubjectType: types.StringNull(), + Username: types.StringNull(), + FullName: types.StringNull(), + AvatarUrl: types.StringNull(), + ApiTokenName: types.StringNull(), + }), + Entry("iam.BasicSubjectProfile", iam.BasicSubjectProfile{ + Id: "id", + }, models.SubjectProfile{ + Id: types.StringValue("id"), + SubjectType: types.StringNull(), + Username: types.StringNull(), + FullName: types.StringNull(), + AvatarUrl: types.StringNull(), + ApiTokenName: types.StringNull(), + }), + Entry("*iam.BasicSubjectProfile", &iam.BasicSubjectProfile{ + Id: "id", + }, models.SubjectProfile{ + Id: types.StringValue("id"), + SubjectType: types.StringNull(), + Username: types.StringNull(), + FullName: types.StringNull(), + AvatarUrl: types.StringNull(), + ApiTokenName: types.StringNull(), + }), ) }) }) diff --git a/internal/utils/list.go b/internal/utils/list.go new file mode 100644 index 00000000..06d8d2d2 --- /dev/null +++ b/internal/utils/list.go @@ -0,0 +1,38 @@ +package utils + +import ( + "context" + "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/hashicorp/terraform-plugin-framework/diag" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/samber/lo" +) + +func StringList(values []string) (types.List, diag.Diagnostics) { + list, diags := types.ListValue(types.StringType, lo.Map(values, func(v string, _ int) attr.Value { + return types.StringValue(v) + })) + if diags.HasError() { + return types.List{}, diags + } + return list, nil +} + +func ObjectList[T any](ctx context.Context, values []T, objectAttributeTypes map[string]attr.Type, transformer func(context.Context, T) (types.Object, diag.Diagnostics)) (types.List, diag.Diagnostics) { + if len(values) == 0 { + return types.ListNull(types.ObjectType{AttrTypes: objectAttributeTypes}), nil + } + objs := make([]attr.Value, len(values)) + for i, envVar := range values { + obj, diags := transformer(ctx, envVar) + if diags.HasError() { + return types.List{}, diags + } + objs[i] = obj + } + objectList, diags := types.ListValue(types.ObjectType{AttrTypes: objectAttributeTypes}, objs) + if diags.HasError() { + return types.List{}, diags + } + return objectList, nil +} From d090da86fb3f884f61ff4affea36ec076d1f9294 Mon Sep 17 00:00:00 2001 From: Vandy Liu Date: Tue, 9 Apr 2024 13:34:24 -0700 Subject: [PATCH 02/11] add hibernation fields --- README.md | 2 +- docs/data-sources/deployment.md | 59 ++++++++ docs/data-sources/deployments.md | 59 ++++++++ internal/provider/models/deployment.go | 105 ++++++++++++-- internal/provider/models/subject_profile.go | 1 + internal/provider/schemas/deployment.go | 61 ++++---- internal/provider/schemas/deployments.go | 6 + internal/provider/schemas/scaling.go | 145 ++++++++++++++++++++ 8 files changed, 391 insertions(+), 47 deletions(-) create mode 100644 internal/provider/schemas/scaling.go diff --git a/README.md b/README.md index d5104ad1..3f73e16e 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ If you wish to work on the provider, you'll first need [Go](http://www.golang.or To compile the provider, see [Building The Provider](## Building The Provider). -To run terraform with the provider, create a `.terraformrc` file in your home directory with the following content to override the provider installation with the local build: +To run terraform with the provider, create a `.terraformrc` file in your home directory (`~`) with the following content to override the provider installation with the local build: ```hcl provider_installation { diff --git a/docs/data-sources/deployment.md b/docs/data-sources/deployment.md index f9a2217f..de83e59a 100644 --- a/docs/data-sources/deployment.md +++ b/docs/data-sources/deployment.md @@ -50,6 +50,8 @@ Deployment data source - `region` (String) Deployment region - `resource_quota_cpu` (String) Deployment resource quota CPU - `resource_quota_memory` (String) Deployment resource quota memory +- `scaling_spec` (Attributes) Deployment scaling spec (see [below for nested schema](#nestedatt--scaling_spec)) +- `scaling_status` (Attributes) Deployment scaling status (see [below for nested schema](#nestedatt--scaling_status)) - `scheduler_au` (Number) Deployment scheduler AU - `scheduler_cpu` (String) Deployment scheduler CPU - `scheduler_memory` (String) Deployment scheduler memory @@ -96,6 +98,63 @@ Read-Only: - `value` (String) Environment variable value + +### Nested Schema for `scaling_spec` + +Read-Only: + +- `hibernation_spec` (Attributes) (see [below for nested schema](#nestedatt--scaling_spec--hibernation_spec)) + + +### Nested Schema for `scaling_spec.hibernation_spec` + +Read-Only: + +- `override` (Attributes) (see [below for nested schema](#nestedatt--scaling_spec--hibernation_spec--override)) +- `schedules` (Attributes List) (see [below for nested schema](#nestedatt--scaling_spec--hibernation_spec--schedules)) + + +### Nested Schema for `scaling_spec.hibernation_spec.override` + +Read-Only: + +- `is_active` (Boolean) +- `is_hibernating` (Boolean) +- `override_until` (String) + + + +### Nested Schema for `scaling_spec.hibernation_spec.schedules` + +Read-Only: + +- `description` (String) +- `hibernate_at_cron` (String) +- `is_enabled` (Boolean) +- `wake_at_cron` (String) + + + + + +### Nested Schema for `scaling_status` + +Read-Only: + +- `hibernation_status` (Attributes) (see [below for nested schema](#nestedatt--scaling_status--hibernation_status)) + + +### Nested Schema for `scaling_status.hibernation_status` + +Read-Only: + +- `is_hibernating` (Boolean) +- `next_event_at` (String) +- `next_event_type` (String) +- `reason` (String) + + + ### Nested Schema for `updated_by` diff --git a/docs/data-sources/deployments.md b/docs/data-sources/deployments.md index e98bf6de..44346830 100644 --- a/docs/data-sources/deployments.md +++ b/docs/data-sources/deployments.md @@ -62,6 +62,8 @@ Read-Only: - `region` (String) Deployment region - `resource_quota_cpu` (String) Deployment resource quota CPU - `resource_quota_memory` (String) Deployment resource quota memory +- `scaling_spec` (Attributes) Deployment scaling spec (see [below for nested schema](#nestedatt--deployments--scaling_spec)) +- `scaling_status` (Attributes) Deployment scaling status (see [below for nested schema](#nestedatt--deployments--scaling_status)) - `scheduler_au` (Number) Deployment scheduler AU - `scheduler_cpu` (String) Deployment scheduler CPU - `scheduler_memory` (String) Deployment scheduler memory @@ -108,6 +110,63 @@ Read-Only: - `value` (String) Environment variable value + +### Nested Schema for `deployments.scaling_spec` + +Read-Only: + +- `hibernation_spec` (Attributes) (see [below for nested schema](#nestedatt--deployments--scaling_spec--hibernation_spec)) + + +### Nested Schema for `deployments.scaling_spec.hibernation_spec` + +Read-Only: + +- `override` (Attributes) (see [below for nested schema](#nestedatt--deployments--scaling_spec--hibernation_spec--override)) +- `schedules` (Attributes List) (see [below for nested schema](#nestedatt--deployments--scaling_spec--hibernation_spec--schedules)) + + +### Nested Schema for `deployments.scaling_spec.hibernation_spec.schedules` + +Read-Only: + +- `is_active` (Boolean) +- `is_hibernating` (Boolean) +- `override_until` (String) + + + +### Nested Schema for `deployments.scaling_spec.hibernation_spec.schedules` + +Read-Only: + +- `description` (String) +- `hibernate_at_cron` (String) +- `is_enabled` (Boolean) +- `wake_at_cron` (String) + + + + + +### Nested Schema for `deployments.scaling_status` + +Read-Only: + +- `hibernation_status` (Attributes) (see [below for nested schema](#nestedatt--deployments--scaling_status--hibernation_status)) + + +### Nested Schema for `deployments.scaling_status.hibernation_status` + +Read-Only: + +- `is_hibernating` (Boolean) +- `next_event_at` (String) +- `next_event_type` (String) +- `reason` (String) + + + ### Nested Schema for `deployments.updated_by` diff --git a/internal/provider/models/deployment.go b/internal/provider/models/deployment.go index c54b9f1c..a67794d2 100644 --- a/internal/provider/models/deployment.go +++ b/internal/provider/models/deployment.go @@ -62,8 +62,8 @@ type DeploymentDataSource struct { ResourceQuotaMemory types.String `tfsdk:"resource_quota_memory"` DefaultTaskPodCpu types.String `tfsdk:"default_task_pod_cpu"` DefaultTaskPodMemory types.String `tfsdk:"default_task_pod_memory"` - //ScalingStatus types.Object `tfsdk:"scaling_status"` - //ScalingSpec types.Object `tfsdk:"scaling_spec"` + ScalingStatus types.Object `tfsdk:"scaling_status"` + ScalingSpec types.Object `tfsdk:"scaling_spec"` } type DeploymentEnvironmentVariable struct { @@ -173,14 +173,14 @@ func (data *DeploymentDataSource) ReadFromResponse( data.ResourceQuotaMemory = types.StringPointerValue(deployment.ResourceQuotaMemory) data.DefaultTaskPodCpu = types.StringPointerValue(deployment.DefaultTaskPodCpu) data.DefaultTaskPodMemory = types.StringPointerValue(deployment.DefaultTaskPodMemory) - //data.ScalingStatus, diags = ScalingStatusTypesObject(ctx, deployment.ScalingStatus) - //if diags.HasError() { - // return diags - //} - //data.ScalingSpec, diags = ScalingSpecTypesObject(ctx, deployment.ScalingSpec) - //if diags.HasError() { - // return diags - //} + data.ScalingStatus, diags = ScalingStatusTypesObject(ctx, deployment.ScalingStatus) + if diags.HasError() { + return diags + } + data.ScalingSpec, diags = ScalingSpecTypesObject(ctx, deployment.ScalingSpec) + if diags.HasError() { + return diags + } return nil } @@ -218,3 +218,88 @@ func WorkerQueueTypesObject( return types.ObjectValueFrom(ctx, schemas.WorkerQueueAttributeTypes(), obj) } + +type DeploymentScalingSpec struct { + HibernationSpec HibernationSpec `tfsdk:"hibernation_spec"` +} + +type DeploymentStatus struct { + HibernationStatus HibernationStatus `tfsdk:"hibernation_status"` +} + +type HibernationStatus struct { + IsHibernating types.Bool `tfsdk:"is_hibernating"` + NextEventType types.String `tfsdk:"next_event_type"` + NextEventAt types.String `tfsdk:"next_event_at"` + Reason types.String `tfsdk:"reason"` +} + +type HibernationSpec struct { + Override HibernationSpecOverride `tfsdk:"override"` + Schedules []HibernationSchedule `tfsdk:"schedules"` +} + +type HibernationSpecOverride struct { + IsHibernating types.Bool `tfsdk:"is_hibernating"` + OverrideUntil types.String `tfsdk:"override_until"` + IsActive types.Bool `tfsdk:"is_active"` +} + +type HibernationSchedule struct { + Description types.String `tfsdk:"description"` + HibernateAtCron types.String `tfsdk:"hibernate_at_cron"` + IsEnabled types.Bool `tfsdk:"is_enabled"` + WakeAtCron types.String `tfsdk:"wake_at_cron"` +} + +func ScalingStatusTypesObject( + ctx context.Context, + scalingStatus *platform.DeploymentScalingStatus, +) (types.Object, diag.Diagnostics) { + if scalingStatus != nil && scalingStatus.HibernationStatus != nil { + obj := DeploymentStatus{ + HibernationStatus: HibernationStatus{ + IsHibernating: types.BoolValue(scalingStatus.HibernationStatus.IsHibernating), + NextEventType: types.StringPointerValue((*string)(scalingStatus.HibernationStatus.NextEventType)), + NextEventAt: types.StringPointerValue(scalingStatus.HibernationStatus.NextEventAt), + Reason: types.StringPointerValue(scalingStatus.HibernationStatus.Reason), + }, + } + return types.ObjectValueFrom(ctx, schemas.ScalingStatusAttributeTypes(), obj) + } + return types.ObjectNull(schemas.ScalingStatusAttributeTypes()), nil +} + +func ScalingSpecTypesObject( + ctx context.Context, + scalingSpec *platform.DeploymentScalingSpec, +) (types.Object, diag.Diagnostics) { + if scalingSpec != nil && scalingSpec.HibernationSpec != nil && (scalingSpec.HibernationSpec.Override != nil || scalingSpec.HibernationSpec.Schedules != nil) { + obj := DeploymentScalingSpec{ + HibernationSpec: HibernationSpec{}, + } + if scalingSpec.HibernationSpec.Override != nil { + obj.HibernationSpec.Override = HibernationSpecOverride{ + IsHibernating: types.BoolPointerValue(scalingSpec.HibernationSpec.Override.IsHibernating), + IsActive: types.BoolPointerValue(scalingSpec.HibernationSpec.Override.IsActive), + } + if scalingSpec.HibernationSpec.Override.OverrideUntil != nil { + obj.HibernationSpec.Override.OverrideUntil = types.StringValue(scalingSpec.HibernationSpec.Override.OverrideUntil.String()) + } + } + if scalingSpec.HibernationSpec.Schedules != nil { + schedules := make([]HibernationSchedule, 0, len(*scalingSpec.HibernationSpec.Schedules)) + for _, schedule := range *scalingSpec.HibernationSpec.Schedules { + schedules = append(schedules, HibernationSchedule{ + Description: types.StringPointerValue(schedule.Description), + HibernateAtCron: types.StringValue(schedule.HibernateAtCron), + IsEnabled: types.BoolValue(schedule.IsEnabled), + WakeAtCron: types.StringValue(schedule.WakeAtCron), + }) + } + obj.HibernationSpec.Schedules = schedules + } + return types.ObjectValueFrom(ctx, schemas.ScalingSpecAttributeTypes(), obj) + } + return types.ObjectNull(schemas.ScalingSpecAttributeTypes()), nil +} diff --git a/internal/provider/models/subject_profile.go b/internal/provider/models/subject_profile.go index 326147ae..1d320794 100644 --- a/internal/provider/models/subject_profile.go +++ b/internal/provider/models/subject_profile.go @@ -25,6 +25,7 @@ func SubjectProfileTypesObject( basicSubjectProfile any, ) (types.Object, diag.Diagnostics) { // Attempt to convert basicSubjectProfile to *platform.BasicSubjectProfile + // Our API client returns a BasicSubjectProfile, but we are unsure if it is a pointer and which package it is from var bspPtr *platform.BasicSubjectProfile switch v := basicSubjectProfile.(type) { diff --git a/internal/provider/schemas/deployment.go b/internal/provider/schemas/deployment.go index 98d97f5a..63f0b711 100644 --- a/internal/provider/schemas/deployment.go +++ b/internal/provider/schemas/deployment.go @@ -225,14 +225,16 @@ func DeploymentDataSourceSchemaAttributes() map[string]datasourceSchema.Attribut MarkdownDescription: "Deployment default task pod memory", Computed: true, }, - //"scaling_status": datasourceSchema.SingleNestedAttribute{ - // MarkdownDescription: "Deployment scaling status", - // Computed: true, - //}, - //"scaling_spec": datasourceSchema.SingleNestedAttribute{ - // MarkdownDescription: "Deployment scaling spec", - // Computed: true, - //}, + "scaling_status": datasourceSchema.SingleNestedAttribute{ + MarkdownDescription: "Deployment scaling status", + Computed: true, + Attributes: ScalingStatusAttributes(), + }, + "scaling_spec": datasourceSchema.SingleNestedAttribute{ + MarkdownDescription: "Deployment scaling spec", + Computed: true, + Attributes: ScalingSpecSchemaAttributes(), + }, } } @@ -245,21 +247,6 @@ func DeploymentEnvironmentVariableAttributeTypes() map[string]attr.Type { } } -func WorkerQueueAttributeTypes() map[string]attr.Type { - return map[string]attr.Type{ - "id": types.StringType, - "name": types.StringType, - "astro_machine": types.StringType, - "is_default": types.BoolType, - "max_worker_count": types.Int64Type, - "min_worker_count": types.Int64Type, - "node_pool_id": types.StringType, - "pod_cpu": types.StringType, - "pod_memory": types.StringType, - "worker_concurrency": types.Int64Type, - } -} - func DeploymentEnvironmentVariableAttributes() map[string]datasourceSchema.Attribute { return map[string]datasourceSchema.Attribute{ "key": datasourceSchema.StringAttribute{ @@ -281,6 +268,21 @@ func DeploymentEnvironmentVariableAttributes() map[string]datasourceSchema.Attri } } +func WorkerQueueAttributeTypes() map[string]attr.Type { + return map[string]attr.Type{ + "id": types.StringType, + "name": types.StringType, + "astro_machine": types.StringType, + "is_default": types.BoolType, + "max_worker_count": types.Int64Type, + "min_worker_count": types.Int64Type, + "node_pool_id": types.StringType, + "pod_cpu": types.StringType, + "pod_memory": types.StringType, + "worker_concurrency": types.Int64Type, + } +} + func WorkerQueueSchemaAttributes() map[string]datasourceSchema.Attribute { return map[string]datasourceSchema.Attribute{ "id": datasourceSchema.StringAttribute{ @@ -315,16 +317,3 @@ func WorkerQueueSchemaAttributes() map[string]datasourceSchema.Attribute { }, } } - -//func ScalingStatusAttributeTypes() map[string]attr.Type { -// return map[string]attr.Type{ -// "hibernation_status": types.ObjectType{ -// AttrTypes: map[string]attr.Type{ -// "is_hibernating": types.StringType, -// "next_event_at": types.StringType, -// "next_event_type": types.StringType, -// "reason": types.StringType, -// }, -// }, -// } -//} diff --git a/internal/provider/schemas/deployments.go b/internal/provider/schemas/deployments.go index 017e1de5..23dd7ab5 100644 --- a/internal/provider/schemas/deployments.go +++ b/internal/provider/schemas/deployments.go @@ -75,6 +75,12 @@ func DeploymentsElementAttributeTypes() map[string]attr.Type { "resource_quota_memory": types.StringType, "default_task_pod_cpu": types.StringType, "default_task_pod_memory": types.StringType, + "scaling_status": types.ObjectType{ + AttrTypes: ScalingStatusAttributeTypes(), + }, + "scaling_spec": types.ObjectType{ + AttrTypes: ScalingSpecAttributeTypes(), + }, } } diff --git a/internal/provider/schemas/scaling.go b/internal/provider/schemas/scaling.go new file mode 100644 index 00000000..5bfbb05f --- /dev/null +++ b/internal/provider/schemas/scaling.go @@ -0,0 +1,145 @@ +package schemas + +import ( + "github.com/hashicorp/terraform-plugin-framework/attr" + datasourceSchema "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +// ScalingSpec +func ScalingSpecAttributeTypes() map[string]attr.Type { + return map[string]attr.Type{ + "hibernation_spec": types.ObjectType{ + AttrTypes: HibernationSpecAttributeTypes(), + }, + } +} + +func HibernationSpecAttributeTypes() map[string]attr.Type { + return map[string]attr.Type{ + "override": types.ObjectType{ + AttrTypes: HibernationOverrideAttributeTypes(), + }, + "schedules": types.ListType{ + ElemType: types.ObjectType{ + AttrTypes: HibernationScheduleAttributeTypes(), + }, + }, + } +} + +func ScalingSpecSchemaAttributes() map[string]datasourceSchema.Attribute { + return map[string]datasourceSchema.Attribute{ + "hibernation_spec": datasourceSchema.SingleNestedAttribute{ + Attributes: HibernationSpecSchemaAttributes(), + Computed: true, + }, + } +} + +func HibernationSpecSchemaAttributes() map[string]datasourceSchema.Attribute { + return map[string]datasourceSchema.Attribute{ + "override": datasourceSchema.SingleNestedAttribute{ + Attributes: HibernationOverrideSchemaAttributes(), + Computed: true, + }, + "schedules": datasourceSchema.ListNestedAttribute{ + NestedObject: datasourceSchema.NestedAttributeObject{ + Attributes: HibernationScheduleSchemaAttributes(), + }, + Computed: true, + }, + } +} + +func HibernationOverrideSchemaAttributes() map[string]datasourceSchema.Attribute { + return map[string]datasourceSchema.Attribute{ + "is_active": datasourceSchema.BoolAttribute{ + Computed: true, + }, + "is_hibernating": datasourceSchema.BoolAttribute{ + Computed: true, + }, + "override_until": datasourceSchema.StringAttribute{ + Computed: true, + }, + } +} + +func HibernationScheduleSchemaAttributes() map[string]datasourceSchema.Attribute { + return map[string]datasourceSchema.Attribute{ + "description": datasourceSchema.StringAttribute{ + Computed: true, + }, + "hibernate_at_cron": datasourceSchema.StringAttribute{ + Computed: true, + }, + "is_enabled": datasourceSchema.BoolAttribute{ + Computed: true, + }, + "wake_at_cron": datasourceSchema.StringAttribute{ + Computed: true, + }, + } +} + +// ScalingStatus +func ScalingStatusAttributeTypes() map[string]attr.Type { + return map[string]attr.Type{ + "hibernation_status": types.ObjectType{ + AttrTypes: HibernationStatusAttributeTypes(), + }, + } +} + +func HibernationStatusAttributeTypes() map[string]attr.Type { + return map[string]attr.Type{ + "is_hibernating": types.BoolType, + "next_event_at": types.StringType, + "next_event_type": types.StringType, + "reason": types.StringType, + } +} + +func HibernationOverrideAttributeTypes() map[string]attr.Type { + return map[string]attr.Type{ + "is_active": types.BoolType, + "is_hibernating": types.BoolType, + "override_until": types.StringType, + } +} + +func HibernationScheduleAttributeTypes() map[string]attr.Type { + return map[string]attr.Type{ + "description": types.StringType, + "hibernate_at_cron": types.StringType, + "is_enabled": types.BoolType, + "wake_at_cron": types.StringType, + } +} + +func ScalingStatusAttributes() map[string]datasourceSchema.Attribute { + return map[string]datasourceSchema.Attribute{ + "hibernation_status": datasourceSchema.SingleNestedAttribute{ + Attributes: HibernationStatusSchemaAttributes(), + Computed: true, + }, + } +} + +func HibernationStatusSchemaAttributes() map[string]datasourceSchema.Attribute { + return map[string]datasourceSchema.Attribute{ + "is_hibernating": datasourceSchema.BoolAttribute{ + Computed: true, + }, + "next_event_at": datasourceSchema.StringAttribute{ + Computed: true, + }, + "next_event_type": datasourceSchema.StringAttribute{ + Computed: true, + }, + "reason": datasourceSchema.StringAttribute{ + Computed: true, + }, + } +} From 1d4dfe7566ff6d4e2d764e14716f45dda821d72b Mon Sep 17 00:00:00 2001 From: Vandy Liu Date: Tue, 9 Apr 2024 15:57:03 -0700 Subject: [PATCH 03/11] deployment data source --- docs/data-sources/workspace.md | 1 - docs/data-sources/workspaces.md | 1 - docs/resources/workspace.md | 1 - internal/provider/models/workspace.go | 4 ---- internal/provider/schemas/deployment.go | 4 ++-- internal/provider/schemas/scaling.go | 20 ++++++++++---------- internal/provider/schemas/workspace.go | 11 ----------- internal/provider/schemas/workspaces.go | 1 - 8 files changed, 12 insertions(+), 31 deletions(-) diff --git a/docs/data-sources/workspace.md b/docs/data-sources/workspace.md index d85e8edd..25256922 100644 --- a/docs/data-sources/workspace.md +++ b/docs/data-sources/workspace.md @@ -32,7 +32,6 @@ data "astronomer_workspace" "example" { - `created_by` (Attributes) Workspace creator (see [below for nested schema](#nestedatt--created_by)) - `description` (String) Workspace description - `name` (String) Workspace name -- `organization_name` (String) Workspace organization name - `updated_at` (String) Workspace last updated timestamp - `updated_by` (Attributes) Workspace updater (see [below for nested schema](#nestedatt--updated_by)) diff --git a/docs/data-sources/workspaces.md b/docs/data-sources/workspaces.md index 72aa08dd..3da7c743 100644 --- a/docs/data-sources/workspaces.md +++ b/docs/data-sources/workspaces.md @@ -38,7 +38,6 @@ Read-Only: - `created_by` (Attributes) Workspace creator (see [below for nested schema](#nestedatt--workspaces--created_by)) - `description` (String) Workspace description - `name` (String) Workspace name -- `organization_name` (String) Workspace organization name - `updated_at` (String) Workspace last updated timestamp - `updated_by` (Attributes) Workspace updater (see [below for nested schema](#nestedatt--workspaces--updated_by)) diff --git a/docs/resources/workspace.md b/docs/resources/workspace.md index eee67de9..8eb2dc62 100644 --- a/docs/resources/workspace.md +++ b/docs/resources/workspace.md @@ -34,7 +34,6 @@ resource "workspace_resource" "example" { - `created_at` (String) Workspace creation timestamp - `created_by` (Attributes) Workspace creator (see [below for nested schema](#nestedatt--created_by)) - `id` (String) Workspace identifier -- `organization_name` (String) Workspace organization name - `updated_at` (String) Workspace last updated timestamp - `updated_by` (Attributes) Workspace updater (see [below for nested schema](#nestedatt--updated_by)) diff --git a/internal/provider/models/workspace.go b/internal/provider/models/workspace.go index 5d5a125e..ce7e2078 100644 --- a/internal/provider/models/workspace.go +++ b/internal/provider/models/workspace.go @@ -13,7 +13,6 @@ type WorkspaceDataSource struct { Id types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` Description types.String `tfsdk:"description"` - OrganizationName types.String `tfsdk:"organization_name"` CicdEnforcedDefault types.Bool `tfsdk:"cicd_enforced_default"` CreatedAt types.String `tfsdk:"created_at"` UpdatedAt types.String `tfsdk:"updated_at"` @@ -26,7 +25,6 @@ type WorkspaceResource struct { Id types.String `tfsdk:"id"` Name types.String `tfsdk:"name"` Description types.String `tfsdk:"description"` - OrganizationName types.String `tfsdk:"organization_name"` CicdEnforcedDefault types.Bool `tfsdk:"cicd_enforced_default"` CreatedAt types.String `tfsdk:"created_at"` UpdatedAt types.String `tfsdk:"updated_at"` @@ -41,7 +39,6 @@ func (data *WorkspaceResource) ReadFromResponse( data.Id = types.StringValue(workspace.Id) data.Name = types.StringValue(workspace.Name) data.Description = types.StringPointerValue(workspace.Description) - data.OrganizationName = types.StringPointerValue(workspace.OrganizationName) data.CicdEnforcedDefault = types.BoolValue(workspace.CicdEnforcedDefault) data.CreatedAt = types.StringValue(workspace.CreatedAt.String()) data.UpdatedAt = types.StringValue(workspace.UpdatedAt.String()) @@ -65,7 +62,6 @@ func (data *WorkspaceDataSource) ReadFromResponse( data.Id = types.StringValue(workspace.Id) data.Name = types.StringValue(workspace.Name) data.Description = types.StringPointerValue(workspace.Description) - data.OrganizationName = types.StringPointerValue(workspace.OrganizationName) data.CicdEnforcedDefault = types.BoolValue(workspace.CicdEnforcedDefault) data.CreatedAt = types.StringValue(workspace.CreatedAt.String()) data.UpdatedAt = types.StringValue(workspace.UpdatedAt.String()) diff --git a/internal/provider/schemas/deployment.go b/internal/provider/schemas/deployment.go index 63f0b711..a4999b1a 100644 --- a/internal/provider/schemas/deployment.go +++ b/internal/provider/schemas/deployment.go @@ -228,12 +228,12 @@ func DeploymentDataSourceSchemaAttributes() map[string]datasourceSchema.Attribut "scaling_status": datasourceSchema.SingleNestedAttribute{ MarkdownDescription: "Deployment scaling status", Computed: true, - Attributes: ScalingStatusAttributes(), + Attributes: ScalingStatusDataSourceAttributes(), }, "scaling_spec": datasourceSchema.SingleNestedAttribute{ MarkdownDescription: "Deployment scaling spec", Computed: true, - Attributes: ScalingSpecSchemaAttributes(), + Attributes: ScalingSpecDataSourceSchemaAttributes(), }, } } diff --git a/internal/provider/schemas/scaling.go b/internal/provider/schemas/scaling.go index 5bfbb05f..1de4406c 100644 --- a/internal/provider/schemas/scaling.go +++ b/internal/provider/schemas/scaling.go @@ -28,31 +28,31 @@ func HibernationSpecAttributeTypes() map[string]attr.Type { } } -func ScalingSpecSchemaAttributes() map[string]datasourceSchema.Attribute { +func ScalingSpecDataSourceSchemaAttributes() map[string]datasourceSchema.Attribute { return map[string]datasourceSchema.Attribute{ "hibernation_spec": datasourceSchema.SingleNestedAttribute{ - Attributes: HibernationSpecSchemaAttributes(), + Attributes: HibernationSpecDataSourceSchemaAttributes(), Computed: true, }, } } -func HibernationSpecSchemaAttributes() map[string]datasourceSchema.Attribute { +func HibernationSpecDataSourceSchemaAttributes() map[string]datasourceSchema.Attribute { return map[string]datasourceSchema.Attribute{ "override": datasourceSchema.SingleNestedAttribute{ - Attributes: HibernationOverrideSchemaAttributes(), + Attributes: HibernationOverrideDataSourceSchemaAttributes(), Computed: true, }, "schedules": datasourceSchema.ListNestedAttribute{ NestedObject: datasourceSchema.NestedAttributeObject{ - Attributes: HibernationScheduleSchemaAttributes(), + Attributes: HibernationScheduleDataSourceSchemaAttributes(), }, Computed: true, }, } } -func HibernationOverrideSchemaAttributes() map[string]datasourceSchema.Attribute { +func HibernationOverrideDataSourceSchemaAttributes() map[string]datasourceSchema.Attribute { return map[string]datasourceSchema.Attribute{ "is_active": datasourceSchema.BoolAttribute{ Computed: true, @@ -66,7 +66,7 @@ func HibernationOverrideSchemaAttributes() map[string]datasourceSchema.Attribute } } -func HibernationScheduleSchemaAttributes() map[string]datasourceSchema.Attribute { +func HibernationScheduleDataSourceSchemaAttributes() map[string]datasourceSchema.Attribute { return map[string]datasourceSchema.Attribute{ "description": datasourceSchema.StringAttribute{ Computed: true, @@ -118,16 +118,16 @@ func HibernationScheduleAttributeTypes() map[string]attr.Type { } } -func ScalingStatusAttributes() map[string]datasourceSchema.Attribute { +func ScalingStatusDataSourceAttributes() map[string]datasourceSchema.Attribute { return map[string]datasourceSchema.Attribute{ "hibernation_status": datasourceSchema.SingleNestedAttribute{ - Attributes: HibernationStatusSchemaAttributes(), + Attributes: HibernationStatusDataSourceSchemaAttributes(), Computed: true, }, } } -func HibernationStatusSchemaAttributes() map[string]datasourceSchema.Attribute { +func HibernationStatusDataSourceSchemaAttributes() map[string]datasourceSchema.Attribute { return map[string]datasourceSchema.Attribute{ "is_hibernating": datasourceSchema.BoolAttribute{ Computed: true, diff --git a/internal/provider/schemas/workspace.go b/internal/provider/schemas/workspace.go index 4142dfe3..2cacb292 100644 --- a/internal/provider/schemas/workspace.go +++ b/internal/provider/schemas/workspace.go @@ -26,10 +26,6 @@ func WorkspaceDataSourceSchemaAttributes() map[string]datasourceSchema.Attribute MarkdownDescription: "Workspace description", Computed: true, }, - "organization_name": datasourceSchema.StringAttribute{ - MarkdownDescription: "Workspace organization name", - Computed: true, - }, "cicd_enforced_default": datasourceSchema.BoolAttribute{ MarkdownDescription: "Whether new Deployments enforce CI/CD deploys by default", Computed: true, @@ -74,13 +70,6 @@ func WorkspaceResourceSchemaAttributes() map[string]resourceSchema.Attribute { MarkdownDescription: "Workspace description", Required: true, }, - "organization_name": resourceSchema.StringAttribute{ - MarkdownDescription: "Workspace organization name", - Computed: true, - PlanModifiers: []planmodifier.String{ - stringplanmodifier.UseStateForUnknown(), - }, - }, "cicd_enforced_default": resourceSchema.BoolAttribute{ MarkdownDescription: "Whether new Deployments enforce CI/CD deploys by default", Required: true, diff --git a/internal/provider/schemas/workspaces.go b/internal/provider/schemas/workspaces.go index 522611fa..bd28dca0 100644 --- a/internal/provider/schemas/workspaces.go +++ b/internal/provider/schemas/workspaces.go @@ -11,7 +11,6 @@ func WorkspacesElementAttributeTypes() map[string]attr.Type { "id": types.StringType, "name": types.StringType, "description": types.StringType, - "organization_name": types.StringType, "cicd_enforced_default": types.BoolType, "created_at": types.StringType, "updated_at": types.StringType, From 98e6e6d3246a426d9578f334bd31d1c0e7deb80e Mon Sep 17 00:00:00 2001 From: Vandy Liu Date: Tue, 9 Apr 2024 16:18:19 -0700 Subject: [PATCH 04/11] update --- README.md | 2 + docs/data-sources/deployment.md | 58 +++++++++-------- docs/data-sources/deployments.md | 64 +++++++++++-------- docs/data-sources/workspaces.md | 12 ++++ .../astronomer_deployment/data-source.tf | 3 + .../astronomer_deployments/data-source.tf | 9 +++ .../astronomer_workspaces/data-source.tf | 9 +++ internal/provider/models/deployment.go | 5 +- internal/provider/models/deployments.go | 1 + internal/provider/models/subject_profile.go | 1 + internal/provider/models/workspaces.go | 1 + internal/provider/schemas/deployment.go | 46 ++++++------- internal/provider/schemas/deployments.go | 2 - internal/provider/schemas/scaling.go | 33 ++++++---- internal/utils/list.go | 1 + 15 files changed, 154 insertions(+), 93 deletions(-) create mode 100644 examples/data-sources/astronomer_deployment/data-source.tf create mode 100644 examples/data-sources/astronomer_deployments/data-source.tf create mode 100644 examples/data-sources/astronomer_workspaces/data-source.tf diff --git a/README.md b/README.md index 3f73e16e..389a6d80 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,8 @@ If you wish to work on the provider, you'll first need [Go](http://www.golang.or To compile the provider, see [Building The Provider](## Building The Provider). +To add example docs, add the correspond `.tf` files to the `examples` directory. + To run terraform with the provider, create a `.terraformrc` file in your home directory (`~`) with the following content to override the provider installation with the local build: ```hcl diff --git a/docs/data-sources/deployment.md b/docs/data-sources/deployment.md index de83e59a..cf86f487 100644 --- a/docs/data-sources/deployment.md +++ b/docs/data-sources/deployment.md @@ -10,7 +10,13 @@ description: |- Deployment data source +## Example Usage +```terraform +data "astronomer_deployment" "example" { + id = "clozc036j01to01jrlgvueo8t" +} +``` ## Schema @@ -25,7 +31,6 @@ Deployment data source - `astro_runtime_version` (String) Deployment Astro Runtime version - `cloud_provider` (String) Deployment cloud provider - `cluster_id` (String) Deployment cluster identifier -- `cluster_name` (String) Deployment cluster name - `contact_emails` (List of String) Deployment contact emails - `created_at` (String) Deployment creation timestamp - `created_by` (Attributes) Deployment creator (see [below for nested schema](#nestedatt--created_by)) @@ -40,10 +45,10 @@ Deployment data source - `image_repository` (String) Deployment image repository - `image_tag` (String) Deployment mage tag - `image_version` (String) Deployment image version -- `is_cicd_enforced` (Boolean) Deployment CI/CD enforced -- `is_dag_deploy_enabled` (Boolean) Deployment DAG deploy enabled -- `is_development_mode` (Boolean) Deployment development mode -- `is_high_availability` (Boolean) Deployment high availability +- `is_cicd_enforced` (Boolean) Whether the Deployment enforces CI/CD deploys +- `is_dag_deploy_enabled` (Boolean) Whether DAG deploy is enabled +- `is_development_mode` (Boolean) Whether Deployment is in development mode +- `is_high_availability` (Boolean) Whether Deployment has high availability - `name` (String) Deployment name - `namespace` (String) Deployment namespace - `oidc_issuer_url` (String) Deployment OIDC issuer URL @@ -72,7 +77,6 @@ Deployment data source - `worker_queues` (Attributes List) Deployment worker queues (see [below for nested schema](#nestedatt--worker_queues)) - `workload_identity` (String) Deployment workload identity - `workspace_id` (String) Deployment workspace identifier -- `workspace_name` (String) Deployment workspace name ### Nested Schema for `created_by` @@ -118,9 +122,9 @@ Read-Only: Read-Only: -- `is_active` (Boolean) -- `is_hibernating` (Boolean) -- `override_until` (String) +- `is_active` (Boolean) Whether the override is active +- `is_hibernating` (Boolean) Whether the override is hibernating +- `override_until` (String) Time until the override is active @@ -128,10 +132,10 @@ Read-Only: Read-Only: -- `description` (String) -- `hibernate_at_cron` (String) -- `is_enabled` (Boolean) -- `wake_at_cron` (String) +- `description` (String) Description of the schedule +- `hibernate_at_cron` (String) Cron expression for hibernation +- `is_enabled` (Boolean) Whether the schedule is enabled +- `wake_at_cron` (String) Cron expression for waking @@ -148,10 +152,10 @@ Read-Only: Read-Only: -- `is_hibernating` (Boolean) -- `next_event_at` (String) -- `next_event_type` (String) -- `reason` (String) +- `is_hibernating` (Boolean) Whether the deployment is hibernating +- `next_event_at` (String) Time of the next event +- `next_event_type` (String) Type of the next event +- `reason` (String) Reason for the current state @@ -173,13 +177,13 @@ Read-Only: Read-Only: -- `astro_machine` (String) -- `id` (String) -- `is_default` (Boolean) -- `max_worker_count` (Number) -- `min_worker_count` (Number) -- `name` (String) -- `node_pool_id` (String) -- `pod_cpu` (String) -- `pod_memory` (String) -- `worker_concurrency` (Number) +- `astro_machine` (String) Worker queue Astro machine value +- `id` (String) Worker queue identifier +- `is_default` (Boolean) Whether Worker queue is default +- `max_worker_count` (Number) Worker queue max worker count +- `min_worker_count` (Number) Worker queue min worker count +- `name` (String) Worker queue name +- `node_pool_id` (String) Worker queue node pool identifier +- `pod_cpu` (String) Worker queue pod CPU +- `pod_memory` (String) Worker queue pod memory +- `worker_concurrency` (Number) Worker queue worker concurrency diff --git a/docs/data-sources/deployments.md b/docs/data-sources/deployments.md index 44346830..31414e36 100644 --- a/docs/data-sources/deployments.md +++ b/docs/data-sources/deployments.md @@ -10,7 +10,19 @@ description: |- Deployments data source +## Example Usage +```terraform +data "astronomer_deployments" "example_deployments" {} + +data "astronomer_deployments" "example_deployments_filter_by_deployment_ids" { + deployment_ids = ["clozc036j01to01jrlgvueo8t", "clozc036j01to01jrlgvueo81"] +} + +data "astronomer_deployments" "example_deployments_filter_by_names" { + deployment_ids = ["my first deployment", "my second deployment"] +} +``` ## Schema @@ -37,7 +49,6 @@ Read-Only: - `astro_runtime_version` (String) Deployment Astro Runtime version - `cloud_provider` (String) Deployment cloud provider - `cluster_id` (String) Deployment cluster identifier -- `cluster_name` (String) Deployment cluster name - `contact_emails` (List of String) Deployment contact emails - `created_at` (String) Deployment creation timestamp - `created_by` (Attributes) Deployment creator (see [below for nested schema](#nestedatt--deployments--created_by)) @@ -52,10 +63,10 @@ Read-Only: - `image_repository` (String) Deployment image repository - `image_tag` (String) Deployment mage tag - `image_version` (String) Deployment image version -- `is_cicd_enforced` (Boolean) Deployment CI/CD enforced -- `is_dag_deploy_enabled` (Boolean) Deployment DAG deploy enabled -- `is_development_mode` (Boolean) Deployment development mode -- `is_high_availability` (Boolean) Deployment high availability +- `is_cicd_enforced` (Boolean) Whether the Deployment enforces CI/CD deploys +- `is_dag_deploy_enabled` (Boolean) Whether DAG deploy is enabled +- `is_development_mode` (Boolean) Whether Deployment is in development mode +- `is_high_availability` (Boolean) Whether Deployment has high availability - `name` (String) Deployment name - `namespace` (String) Deployment namespace - `oidc_issuer_url` (String) Deployment OIDC issuer URL @@ -84,7 +95,6 @@ Read-Only: - `worker_queues` (Attributes List) Deployment worker queues (see [below for nested schema](#nestedatt--deployments--worker_queues)) - `workload_identity` (String) Deployment workload identity - `workspace_id` (String) Deployment workspace identifier -- `workspace_name` (String) Deployment workspace name ### Nested Schema for `deployments.created_by` @@ -130,9 +140,9 @@ Read-Only: Read-Only: -- `is_active` (Boolean) -- `is_hibernating` (Boolean) -- `override_until` (String) +- `is_active` (Boolean) Whether the override is active +- `is_hibernating` (Boolean) Whether the override is hibernating +- `override_until` (String) Time until the override is active @@ -140,10 +150,10 @@ Read-Only: Read-Only: -- `description` (String) -- `hibernate_at_cron` (String) -- `is_enabled` (Boolean) -- `wake_at_cron` (String) +- `description` (String) Description of the schedule +- `hibernate_at_cron` (String) Cron expression for hibernation +- `is_enabled` (Boolean) Whether the schedule is enabled +- `wake_at_cron` (String) Cron expression for waking @@ -160,10 +170,10 @@ Read-Only: Read-Only: -- `is_hibernating` (Boolean) -- `next_event_at` (String) -- `next_event_type` (String) -- `reason` (String) +- `is_hibernating` (Boolean) Whether the deployment is hibernating +- `next_event_at` (String) Time of the next event +- `next_event_type` (String) Type of the next event +- `reason` (String) Reason for the current state @@ -185,13 +195,13 @@ Read-Only: Read-Only: -- `astro_machine` (String) -- `id` (String) -- `is_default` (Boolean) -- `max_worker_count` (Number) -- `min_worker_count` (Number) -- `name` (String) -- `node_pool_id` (String) -- `pod_cpu` (String) -- `pod_memory` (String) -- `worker_concurrency` (Number) +- `astro_machine` (String) Worker queue Astro machine value +- `id` (String) Worker queue identifier +- `is_default` (Boolean) Whether Worker queue is default +- `max_worker_count` (Number) Worker queue max worker count +- `min_worker_count` (Number) Worker queue min worker count +- `name` (String) Worker queue name +- `node_pool_id` (String) Worker queue node pool identifier +- `pod_cpu` (String) Worker queue pod CPU +- `pod_memory` (String) Worker queue pod memory +- `worker_concurrency` (Number) Worker queue worker concurrency diff --git a/docs/data-sources/workspaces.md b/docs/data-sources/workspaces.md index 3da7c743..2f0b960e 100644 --- a/docs/data-sources/workspaces.md +++ b/docs/data-sources/workspaces.md @@ -10,7 +10,19 @@ description: |- Workspaces data source +## Example Usage +```terraform +data "astronomer_workspaces" "example_workspaces" {} + +data "astronomer_workspaces" "example_workspaces_filter_by_workspace_ids" { + workspace_ids = ["clozc036j01to01jrlgvueo8t", "clozc036j01to01jrlgvueo81"] +} + +data "astronomer_workspaces" "example_workspaces_filter_by_names" { + workspace_ids = ["my first workspace", "my second workspace"] +} +``` ## Schema diff --git a/examples/data-sources/astronomer_deployment/data-source.tf b/examples/data-sources/astronomer_deployment/data-source.tf new file mode 100644 index 00000000..fa9333ea --- /dev/null +++ b/examples/data-sources/astronomer_deployment/data-source.tf @@ -0,0 +1,3 @@ +data "astronomer_deployment" "example" { + id = "clozc036j01to01jrlgvueo8t" +} diff --git a/examples/data-sources/astronomer_deployments/data-source.tf b/examples/data-sources/astronomer_deployments/data-source.tf new file mode 100644 index 00000000..f7920ffc --- /dev/null +++ b/examples/data-sources/astronomer_deployments/data-source.tf @@ -0,0 +1,9 @@ +data "astronomer_deployments" "example_deployments" {} + +data "astronomer_deployments" "example_deployments_filter_by_deployment_ids" { + deployment_ids = ["clozc036j01to01jrlgvueo8t", "clozc036j01to01jrlgvueo81"] +} + +data "astronomer_deployments" "example_deployments_filter_by_names" { + deployment_ids = ["my first deployment", "my second deployment"] +} \ No newline at end of file diff --git a/examples/data-sources/astronomer_workspaces/data-source.tf b/examples/data-sources/astronomer_workspaces/data-source.tf new file mode 100644 index 00000000..d9771774 --- /dev/null +++ b/examples/data-sources/astronomer_workspaces/data-source.tf @@ -0,0 +1,9 @@ +data "astronomer_workspaces" "example_workspaces" {} + +data "astronomer_workspaces" "example_workspaces_filter_by_workspace_ids" { + workspace_ids = ["clozc036j01to01jrlgvueo8t", "clozc036j01to01jrlgvueo81"] +} + +data "astronomer_workspaces" "example_workspaces_filter_by_names" { + workspace_ids = ["my first workspace", "my second workspace"] +} diff --git a/internal/provider/models/deployment.go b/internal/provider/models/deployment.go index a67794d2..9a11d731 100644 --- a/internal/provider/models/deployment.go +++ b/internal/provider/models/deployment.go @@ -2,6 +2,7 @@ package models import ( "context" + "github.com/astronomer/astronomer-terraform-provider/internal/clients/platform" "github.com/astronomer/astronomer-terraform-provider/internal/provider/schemas" "github.com/astronomer/astronomer-terraform-provider/internal/utils" @@ -19,9 +20,7 @@ type DeploymentDataSource struct { CreatedBy types.Object `tfsdk:"created_by"` UpdatedBy types.Object `tfsdk:"updated_by"` WorkspaceId types.String `tfsdk:"workspace_id"` - WorkspaceName types.String `tfsdk:"workspace_name"` ClusterId types.String `tfsdk:"cluster_id"` - ClusterName types.String `tfsdk:"cluster_name"` Region types.String `tfsdk:"region"` CloudProvider types.String `tfsdk:"cloud_provider"` AstroRuntimeVersion types.String `tfsdk:"astro_runtime_version"` @@ -105,9 +104,7 @@ func (data *DeploymentDataSource) ReadFromResponse( return diags } data.WorkspaceId = types.StringValue(deployment.WorkspaceId) - data.WorkspaceName = types.StringPointerValue(deployment.WorkspaceName) data.ClusterId = types.StringPointerValue(deployment.ClusterId) - data.ClusterName = types.StringPointerValue(deployment.ClusterName) data.Region = types.StringPointerValue(deployment.Region) data.CloudProvider = types.StringPointerValue((*string)(deployment.CloudProvider)) data.AstroRuntimeVersion = types.StringValue(deployment.AstroRuntimeVersion) diff --git a/internal/provider/models/deployments.go b/internal/provider/models/deployments.go index 030a76b1..33aa1532 100644 --- a/internal/provider/models/deployments.go +++ b/internal/provider/models/deployments.go @@ -2,6 +2,7 @@ package models import ( "context" + "github.com/astronomer/astronomer-terraform-provider/internal/clients/platform" "github.com/astronomer/astronomer-terraform-provider/internal/provider/schemas" "github.com/hashicorp/terraform-plugin-framework/attr" diff --git a/internal/provider/models/subject_profile.go b/internal/provider/models/subject_profile.go index 1d320794..823a7ab0 100644 --- a/internal/provider/models/subject_profile.go +++ b/internal/provider/models/subject_profile.go @@ -2,6 +2,7 @@ package models import ( "context" + "github.com/astronomer/astronomer-terraform-provider/internal/clients/iam" "github.com/astronomer/astronomer-terraform-provider/internal/provider/schemas" "github.com/hashicorp/terraform-plugin-log/tflog" diff --git a/internal/provider/models/workspaces.go b/internal/provider/models/workspaces.go index d4661346..d1fa3602 100644 --- a/internal/provider/models/workspaces.go +++ b/internal/provider/models/workspaces.go @@ -2,6 +2,7 @@ package models import ( "context" + "github.com/astronomer/astronomer-terraform-provider/internal/clients/platform" "github.com/astronomer/astronomer-terraform-provider/internal/provider/schemas" "github.com/hashicorp/terraform-plugin-framework/attr" diff --git a/internal/provider/schemas/deployment.go b/internal/provider/schemas/deployment.go index a4999b1a..7dd24617 100644 --- a/internal/provider/schemas/deployment.go +++ b/internal/provider/schemas/deployment.go @@ -45,18 +45,10 @@ func DeploymentDataSourceSchemaAttributes() map[string]datasourceSchema.Attribut MarkdownDescription: "Deployment workspace identifier", Computed: true, }, - "workspace_name": datasourceSchema.StringAttribute{ - MarkdownDescription: "Deployment workspace name", - Computed: true, - }, "cluster_id": datasourceSchema.StringAttribute{ MarkdownDescription: "Deployment cluster identifier", Computed: true, }, - "cluster_name": datasourceSchema.StringAttribute{ - MarkdownDescription: "Deployment cluster name", - Computed: true, - }, "region": datasourceSchema.StringAttribute{ MarkdownDescription: "Deployment region", Computed: true, @@ -173,7 +165,7 @@ func DeploymentDataSourceSchemaAttributes() map[string]datasourceSchema.Attribut Computed: true, }, "is_cicd_enforced": datasourceSchema.BoolAttribute{ - MarkdownDescription: "Deployment CI/CD enforced", + MarkdownDescription: "Whether the Deployment enforces CI/CD deploys", Computed: true, }, "type": datasourceSchema.StringAttribute{ @@ -181,7 +173,7 @@ func DeploymentDataSourceSchemaAttributes() map[string]datasourceSchema.Attribut Computed: true, }, "is_dag_deploy_enabled": datasourceSchema.BoolAttribute{ - MarkdownDescription: "Deployment DAG deploy enabled", + MarkdownDescription: "Whether DAG deploy is enabled", Computed: true, }, "scheduler_size": datasourceSchema.StringAttribute{ @@ -189,11 +181,11 @@ func DeploymentDataSourceSchemaAttributes() map[string]datasourceSchema.Attribut Computed: true, }, "is_high_availability": datasourceSchema.BoolAttribute{ - MarkdownDescription: "Deployment high availability", + MarkdownDescription: "Whether Deployment has high availability", Computed: true, }, "is_development_mode": datasourceSchema.BoolAttribute{ - MarkdownDescription: "Deployment development mode", + MarkdownDescription: "Whether Deployment is in development mode", Computed: true, }, "workload_identity": datasourceSchema.StringAttribute{ @@ -286,34 +278,44 @@ func WorkerQueueAttributeTypes() map[string]attr.Type { func WorkerQueueSchemaAttributes() map[string]datasourceSchema.Attribute { return map[string]datasourceSchema.Attribute{ "id": datasourceSchema.StringAttribute{ - Computed: true, + MarkdownDescription: "Worker queue identifier", + Computed: true, }, "name": datasourceSchema.StringAttribute{ - Computed: true, + MarkdownDescription: "Worker queue name", + Computed: true, }, "astro_machine": datasourceSchema.StringAttribute{ - Computed: true, + MarkdownDescription: "Worker queue Astro machine value", + Computed: true, }, "is_default": datasourceSchema.BoolAttribute{ - Computed: true, + MarkdownDescription: "Whether Worker queue is default", + Computed: true, }, "max_worker_count": datasourceSchema.Int64Attribute{ - Computed: true, + MarkdownDescription: "Worker queue max worker count", + Computed: true, }, "min_worker_count": datasourceSchema.Int64Attribute{ - Computed: true, + MarkdownDescription: "Worker queue min worker count", + Computed: true, }, "node_pool_id": datasourceSchema.StringAttribute{ - Computed: true, + MarkdownDescription: "Worker queue node pool identifier", + Computed: true, }, "pod_cpu": datasourceSchema.StringAttribute{ - Computed: true, + MarkdownDescription: "Worker queue pod CPU", + Computed: true, }, "pod_memory": datasourceSchema.StringAttribute{ - Computed: true, + MarkdownDescription: "Worker queue pod memory", + Computed: true, }, "worker_concurrency": datasourceSchema.Int64Attribute{ - Computed: true, + MarkdownDescription: "Worker queue worker concurrency", + Computed: true, }, } } diff --git a/internal/provider/schemas/deployments.go b/internal/provider/schemas/deployments.go index 23dd7ab5..532cf934 100644 --- a/internal/provider/schemas/deployments.go +++ b/internal/provider/schemas/deployments.go @@ -20,9 +20,7 @@ func DeploymentsElementAttributeTypes() map[string]attr.Type { AttrTypes: SubjectProfileAttributeTypes(), }, "workspace_id": types.StringType, - "workspace_name": types.StringType, "cluster_id": types.StringType, - "cluster_name": types.StringType, "region": types.StringType, "cloud_provider": types.StringType, "astro_runtime_version": types.StringType, diff --git a/internal/provider/schemas/scaling.go b/internal/provider/schemas/scaling.go index 1de4406c..1b5076a7 100644 --- a/internal/provider/schemas/scaling.go +++ b/internal/provider/schemas/scaling.go @@ -55,13 +55,16 @@ func HibernationSpecDataSourceSchemaAttributes() map[string]datasourceSchema.Att func HibernationOverrideDataSourceSchemaAttributes() map[string]datasourceSchema.Attribute { return map[string]datasourceSchema.Attribute{ "is_active": datasourceSchema.BoolAttribute{ - Computed: true, + Computed: true, + MarkdownDescription: "Whether the override is active", }, "is_hibernating": datasourceSchema.BoolAttribute{ - Computed: true, + Computed: true, + MarkdownDescription: "Whether the override is hibernating", }, "override_until": datasourceSchema.StringAttribute{ - Computed: true, + Computed: true, + MarkdownDescription: "Time until the override is active", }, } } @@ -69,16 +72,20 @@ func HibernationOverrideDataSourceSchemaAttributes() map[string]datasourceSchema func HibernationScheduleDataSourceSchemaAttributes() map[string]datasourceSchema.Attribute { return map[string]datasourceSchema.Attribute{ "description": datasourceSchema.StringAttribute{ - Computed: true, + Computed: true, + MarkdownDescription: "Description of the schedule", }, "hibernate_at_cron": datasourceSchema.StringAttribute{ - Computed: true, + Computed: true, + MarkdownDescription: "Cron expression for hibernation", }, "is_enabled": datasourceSchema.BoolAttribute{ - Computed: true, + Computed: true, + MarkdownDescription: "Whether the schedule is enabled", }, "wake_at_cron": datasourceSchema.StringAttribute{ - Computed: true, + Computed: true, + MarkdownDescription: "Cron expression for waking", }, } } @@ -130,16 +137,20 @@ func ScalingStatusDataSourceAttributes() map[string]datasourceSchema.Attribute { func HibernationStatusDataSourceSchemaAttributes() map[string]datasourceSchema.Attribute { return map[string]datasourceSchema.Attribute{ "is_hibernating": datasourceSchema.BoolAttribute{ - Computed: true, + Computed: true, + MarkdownDescription: "Whether the deployment is hibernating", }, "next_event_at": datasourceSchema.StringAttribute{ - Computed: true, + Computed: true, + MarkdownDescription: "Time of the next event", }, "next_event_type": datasourceSchema.StringAttribute{ - Computed: true, + Computed: true, + MarkdownDescription: "Type of the next event", }, "reason": datasourceSchema.StringAttribute{ - Computed: true, + Computed: true, + MarkdownDescription: "Reason for the current state", }, } } diff --git a/internal/utils/list.go b/internal/utils/list.go index 06d8d2d2..9a81ae2f 100644 --- a/internal/utils/list.go +++ b/internal/utils/list.go @@ -2,6 +2,7 @@ package utils import ( "context" + "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/diag" "github.com/hashicorp/terraform-plugin-framework/types" From d4e9ad96763dd9793a4667783730a239bec1d396 Mon Sep 17 00:00:00 2001 From: Vandy Liu Date: Tue, 9 Apr 2024 16:42:12 -0700 Subject: [PATCH 05/11] list cuid validator --- docs/data-sources/deployments.md | 5 +++ .../astronomer_deployments/data-source.tf | 4 ++ .../datasources/data_source_deployments.go | 22 ++------- .../datasources/data_source_workspaces.go | 21 +-------- internal/provider/models/deployments.go | 1 + internal/provider/provider_test.go | 2 + internal/provider/schemas/deployments.go | 12 +++++ internal/provider/validators/is_cuid.go | 45 +++++++++++++++++++ internal/utils/list.go | 17 +++++++ 9 files changed, 91 insertions(+), 38 deletions(-) diff --git a/docs/data-sources/deployments.md b/docs/data-sources/deployments.md index 31414e36..c623eb6a 100644 --- a/docs/data-sources/deployments.md +++ b/docs/data-sources/deployments.md @@ -19,6 +19,10 @@ data "astronomer_deployments" "example_deployments_filter_by_deployment_ids" { deployment_ids = ["clozc036j01to01jrlgvueo8t", "clozc036j01to01jrlgvueo81"] } +data "astronomer_deployments" "example_deployments_filter_by_workspace_ids" { + workspace_ids = ["clozc036j01to01jrlgvueo8t", "clozc036j01to01jrlgvueo81"] +} + data "astronomer_deployments" "example_deployments_filter_by_names" { deployment_ids = ["my first deployment", "my second deployment"] } @@ -31,6 +35,7 @@ data "astronomer_deployments" "example_deployments_filter_by_names" { - `deployment_ids` (List of String) - `names` (List of String) +- `workspace_ids` (List of String) ### Read-Only diff --git a/examples/data-sources/astronomer_deployments/data-source.tf b/examples/data-sources/astronomer_deployments/data-source.tf index f7920ffc..7a802b20 100644 --- a/examples/data-sources/astronomer_deployments/data-source.tf +++ b/examples/data-sources/astronomer_deployments/data-source.tf @@ -4,6 +4,10 @@ data "astronomer_deployments" "example_deployments_filter_by_deployment_ids" { deployment_ids = ["clozc036j01to01jrlgvueo8t", "clozc036j01to01jrlgvueo81"] } +data "astronomer_deployments" "example_deployments_filter_by_workspace_ids" { + workspace_ids = ["clozc036j01to01jrlgvueo8t", "clozc036j01to01jrlgvueo81"] +} + data "astronomer_deployments" "example_deployments_filter_by_names" { deployment_ids = ["my first deployment", "my second deployment"] } \ No newline at end of file diff --git a/internal/provider/datasources/data_source_deployments.go b/internal/provider/datasources/data_source_deployments.go index 8252597b..e4ff5928 100644 --- a/internal/provider/datasources/data_source_deployments.go +++ b/internal/provider/datasources/data_source_deployments.go @@ -3,9 +3,6 @@ package datasources import ( "context" "fmt" - "strings" - - "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/samber/lo" "github.com/astronomer/astronomer-terraform-provider/internal/clients" @@ -85,22 +82,9 @@ func (d *deploymentsDataSource) Read( params := &platform.ListDeploymentsParams{ Limit: lo.ToPtr(1000), } - deploymentIds := data.DeploymentIds.Elements() - if len(deploymentIds) > 0 { - deploymentIdsParam := lo.Map(deploymentIds, func(id attr.Value, _ int) string { - // Terraform includes quotes around the string, so we need to remove them - return strings.ReplaceAll(id.String(), `"`, "") - }) - params.DeploymentIds = &deploymentIdsParam - } - names := data.Names.Elements() - if len(names) > 0 { - namesParam := lo.Map(names, func(name attr.Value, _ int) string { - // Terraform includes quotes around the string, so we need to remove them - return strings.ReplaceAll(name.String(), `"`, "") - }) - params.Names = &namesParam - } + params.DeploymentIds = utils.TypesListToStringSlice(data.DeploymentIds) + params.WorkspaceIds = utils.TypesListToStringSlice(data.WorkspaceIds) + params.Names = utils.TypesListToStringSlice(data.Names) if resp.Diagnostics.HasError() { return diff --git a/internal/provider/datasources/data_source_workspaces.go b/internal/provider/datasources/data_source_workspaces.go index e6f294ec..679a5845 100644 --- a/internal/provider/datasources/data_source_workspaces.go +++ b/internal/provider/datasources/data_source_workspaces.go @@ -3,9 +3,6 @@ package datasources import ( "context" "fmt" - "strings" - - "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/samber/lo" "github.com/astronomer/astronomer-terraform-provider/internal/clients" @@ -85,22 +82,8 @@ func (d *workspacesDataSource) Read( params := &platform.ListWorkspacesParams{ Limit: lo.ToPtr(1000), } - workspaceIds := data.WorkspaceIds.Elements() - if len(workspaceIds) > 0 { - workspaceIdsParam := lo.Map(workspaceIds, func(id attr.Value, _ int) string { - // Terraform includes quotes around the string, so we need to remove them - return strings.ReplaceAll(id.String(), `"`, "") - }) - params.WorkspaceIds = &workspaceIdsParam - } - names := data.Names.Elements() - if len(names) > 0 { - namesParam := lo.Map(names, func(name attr.Value, _ int) string { - // Terraform includes quotes around the string, so we need to remove them - return strings.ReplaceAll(name.String(), `"`, "") - }) - params.Names = &namesParam - } + params.WorkspaceIds = utils.TypesListToStringSlice(data.WorkspaceIds) + params.Names = utils.TypesListToStringSlice(data.Names) if resp.Diagnostics.HasError() { return diff --git a/internal/provider/models/deployments.go b/internal/provider/models/deployments.go index 33aa1532..cc2ca25e 100644 --- a/internal/provider/models/deployments.go +++ b/internal/provider/models/deployments.go @@ -13,6 +13,7 @@ import ( // DeploymentsDataSource describes the data source data model. type DeploymentsDataSource struct { Deployments types.List `tfsdk:"deployments"` + WorkspaceIds types.List `tfsdk:"workspace_ids"` // query parameter DeploymentIds types.List `tfsdk:"deployment_ids"` // query parameter Names types.List `tfsdk:"names"` // query parameter } diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index 6e82370f..ab186d83 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -44,6 +44,8 @@ var _ = Describe("Provider Test", func() { expectedDataSources := []string{ "astronomer_workspace", "astronomer_workspaces", + "astronomer_deployment", + "astronomer_deployments", } dataSources := p.DataSources(ctx) diff --git a/internal/provider/schemas/deployments.go b/internal/provider/schemas/deployments.go index 532cf934..d7fb5e4c 100644 --- a/internal/provider/schemas/deployments.go +++ b/internal/provider/schemas/deployments.go @@ -1,8 +1,10 @@ package schemas import ( + "github.com/astronomer/astronomer-terraform-provider/internal/provider/validators" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" ) @@ -93,6 +95,16 @@ func DeploymentsDataSourceSchemaAttributes() map[string]schema.Attribute { "deployment_ids": schema.ListAttribute{ ElementType: types.StringType, Optional: true, + Validators: []validator.List{ + validators.ListIsCuids(), + }, + }, + "workspace_ids": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + Validators: []validator.List{ + validators.ListIsCuids(), + }, }, "names": schema.ListAttribute{ ElementType: types.StringType, diff --git a/internal/provider/validators/is_cuid.go b/internal/provider/validators/is_cuid.go index e8ef5da6..3daed155 100644 --- a/internal/provider/validators/is_cuid.go +++ b/internal/provider/validators/is_cuid.go @@ -45,3 +45,48 @@ func (v isCuidValidator) ValidateString( func IsCuid() validator.String { return isCuidValidator{} } + +var _ validator.List = listIsCuidsValidator{} + +type listIsCuidsValidator struct{} + +func (v listIsCuidsValidator) Description(ctx context.Context) string { + return v.MarkdownDescription(ctx) +} + +func (v listIsCuidsValidator) MarkdownDescription(_ context.Context) string { + return "each value in list must be a cuid" +} + +func (v listIsCuidsValidator) ValidateList( + ctx context.Context, + request validator.ListRequest, + response *validator.ListResponse, +) { + if request.ConfigValue.IsNull() || request.ConfigValue.IsUnknown() { + return + } + + value := request.ConfigValue.Elements() + for i, elem := range value { + if elem.IsNull() || elem.IsUnknown() { + response.Diagnostics.Append(validatordiag.InvalidAttributeValueMatchDiagnostic( + request.Path.AtListIndex(i), + v.Description(ctx), + elem.String(), + )) + } + + if err := cuid.IsCuid(elem.String()); err != nil { + response.Diagnostics.Append(validatordiag.InvalidAttributeValueMatchDiagnostic( + request.Path.AtListIndex(i), + v.Description(ctx), + elem.String(), + )) + } + } +} + +func ListIsCuids() validator.List { + return listIsCuidsValidator{} +} diff --git a/internal/utils/list.go b/internal/utils/list.go index 9a81ae2f..dcdb9a05 100644 --- a/internal/utils/list.go +++ b/internal/utils/list.go @@ -2,6 +2,7 @@ package utils import ( "context" + "strings" "github.com/hashicorp/terraform-plugin-framework/attr" "github.com/hashicorp/terraform-plugin-framework/diag" @@ -9,6 +10,7 @@ import ( "github.com/samber/lo" ) +// StringList is a helper that creates a types.List of string values func StringList(values []string) (types.List, diag.Diagnostics) { list, diags := types.ListValue(types.StringType, lo.Map(values, func(v string, _ int) attr.Value { return types.StringValue(v) @@ -19,6 +21,7 @@ func StringList(values []string) (types.List, diag.Diagnostics) { return list, nil } +// ObjectList is a helper that creates a types.List of objects where each types.Object is created by the transformer function func ObjectList[T any](ctx context.Context, values []T, objectAttributeTypes map[string]attr.Type, transformer func(context.Context, T) (types.Object, diag.Diagnostics)) (types.List, diag.Diagnostics) { if len(values) == 0 { return types.ListNull(types.ObjectType{AttrTypes: objectAttributeTypes}), nil @@ -37,3 +40,17 @@ func ObjectList[T any](ctx context.Context, values []T, objectAttributeTypes map } return objectList, nil } + +// TypesListToStringSlice converts a types.List to a pointer to a slice of strings +// This is useful for converting a list of strings from the Terraform framework to a slice of strings used for calling the API +func TypesListToStringSlice(list types.List) *[]string { + elements := list.Elements() + if len(elements) == 0 { + return nil + } + slice := lo.Map(elements, func(id attr.Value, _ int) string { + // Terraform includes quotes around the string, so we need to remove them + return strings.ReplaceAll(id.String(), `"`, "") + }) + return &slice +} From 5e87a11294ea8370bc26914df860a145d89680fc Mon Sep 17 00:00:00 2001 From: Vandy Liu Date: Tue, 9 Apr 2024 16:44:11 -0700 Subject: [PATCH 06/11] go imports --- internal/provider/datasources/data_source_deployments.go | 1 + internal/provider/datasources/data_source_workspaces.go | 1 + 2 files changed, 2 insertions(+) diff --git a/internal/provider/datasources/data_source_deployments.go b/internal/provider/datasources/data_source_deployments.go index e4ff5928..b2a4a816 100644 --- a/internal/provider/datasources/data_source_deployments.go +++ b/internal/provider/datasources/data_source_deployments.go @@ -3,6 +3,7 @@ package datasources import ( "context" "fmt" + "github.com/samber/lo" "github.com/astronomer/astronomer-terraform-provider/internal/clients" diff --git a/internal/provider/datasources/data_source_workspaces.go b/internal/provider/datasources/data_source_workspaces.go index 679a5845..debe9a6f 100644 --- a/internal/provider/datasources/data_source_workspaces.go +++ b/internal/provider/datasources/data_source_workspaces.go @@ -3,6 +3,7 @@ package datasources import ( "context" "fmt" + "github.com/samber/lo" "github.com/astronomer/astronomer-terraform-provider/internal/clients" From 5bb89e429c49bb196fe99b8d4ca2e35e61fad971 Mon Sep 17 00:00:00 2001 From: Vandy Liu Date: Tue, 9 Apr 2024 23:28:29 -0700 Subject: [PATCH 07/11] pr comments --- .../data-sources/astronomer_deployments/data-source.tf | 2 +- .../data-sources/astronomer_workspaces/data-source.tf | 2 +- internal/provider/datasources/data_source_deployments.go | 8 ++++---- internal/provider/datasources/data_source_workspaces.go | 8 ++++---- internal/provider/schemas/deployment.go | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/examples/data-sources/astronomer_deployments/data-source.tf b/examples/data-sources/astronomer_deployments/data-source.tf index 7a802b20..cba8eb08 100644 --- a/examples/data-sources/astronomer_deployments/data-source.tf +++ b/examples/data-sources/astronomer_deployments/data-source.tf @@ -9,5 +9,5 @@ data "astronomer_deployments" "example_deployments_filter_by_workspace_ids" { } data "astronomer_deployments" "example_deployments_filter_by_names" { - deployment_ids = ["my first deployment", "my second deployment"] + names = ["my first deployment", "my second deployment"] } \ No newline at end of file diff --git a/examples/data-sources/astronomer_workspaces/data-source.tf b/examples/data-sources/astronomer_workspaces/data-source.tf index d9771774..e56ad1af 100644 --- a/examples/data-sources/astronomer_workspaces/data-source.tf +++ b/examples/data-sources/astronomer_workspaces/data-source.tf @@ -5,5 +5,5 @@ data "astronomer_workspaces" "example_workspaces_filter_by_workspace_ids" { } data "astronomer_workspaces" "example_workspaces_filter_by_names" { - workspace_ids = ["my first workspace", "my second workspace"] + names = ["my first workspace", "my second workspace"] } diff --git a/internal/provider/datasources/data_source_deployments.go b/internal/provider/datasources/data_source_deployments.go index b2a4a816..d3fc02af 100644 --- a/internal/provider/datasources/data_source_deployments.go +++ b/internal/provider/datasources/data_source_deployments.go @@ -101,10 +101,10 @@ func (d *deploymentsDataSource) Read( params, ) if err != nil { - tflog.Error(ctx, "failed to get deployment", map[string]interface{}{"error": err}) + tflog.Error(ctx, "failed to list deployments", map[string]interface{}{"error": err}) resp.Diagnostics.AddError( "Client Error", - fmt.Sprintf("Unable to read deployment, got error: %s", err), + fmt.Sprintf("Unable to read deployments, got error: %s", err), ) return } @@ -114,8 +114,8 @@ func (d *deploymentsDataSource) Read( return } if deploymentsResp.JSON200 == nil { - tflog.Error(ctx, "failed to get deployment", map[string]interface{}{"error": "nil response"}) - resp.Diagnostics.AddError("Client Error", "Unable to read deployment, got nil response") + tflog.Error(ctx, "failed to list deployments", map[string]interface{}{"error": "nil response"}) + resp.Diagnostics.AddError("Client Error", "Unable to read deployments, got nil response") return } diff --git a/internal/provider/datasources/data_source_workspaces.go b/internal/provider/datasources/data_source_workspaces.go index debe9a6f..35d97caf 100644 --- a/internal/provider/datasources/data_source_workspaces.go +++ b/internal/provider/datasources/data_source_workspaces.go @@ -100,10 +100,10 @@ func (d *workspacesDataSource) Read( params, ) if err != nil { - tflog.Error(ctx, "failed to get workspace", map[string]interface{}{"error": err}) + tflog.Error(ctx, "failed to list workspaces", map[string]interface{}{"error": err}) resp.Diagnostics.AddError( "Client Error", - fmt.Sprintf("Unable to read workspace, got error: %s", err), + fmt.Sprintf("Unable to read workspaces, got error: %s", err), ) return } @@ -113,8 +113,8 @@ func (d *workspacesDataSource) Read( return } if workspacesResp.JSON200 == nil { - tflog.Error(ctx, "failed to get workspace", map[string]interface{}{"error": "nil response"}) - resp.Diagnostics.AddError("Client Error", "Unable to read workspace, got nil response") + tflog.Error(ctx, "failed to list workspaces", map[string]interface{}{"error": "nil response"}) + resp.Diagnostics.AddError("Client Error", "Unable to read workspaces, got nil response") return } diff --git a/internal/provider/schemas/deployment.go b/internal/provider/schemas/deployment.go index 7dd24617..a5ca9c32 100644 --- a/internal/provider/schemas/deployment.go +++ b/internal/provider/schemas/deployment.go @@ -95,7 +95,7 @@ func DeploymentDataSourceSchemaAttributes() map[string]datasourceSchema.Attribut Computed: true, }, "image_tag": datasourceSchema.StringAttribute{ - MarkdownDescription: "Deployment mage tag", + MarkdownDescription: "Deployment image tag", Computed: true, }, "image_repository": datasourceSchema.StringAttribute{ From a3a6964446a9c5d89b6bcbf9062d560ddba5d3d4 Mon Sep 17 00:00:00 2001 From: Vandy Liu Date: Tue, 9 Apr 2024 23:30:18 -0700 Subject: [PATCH 08/11] docs --- docs/data-sources/deployment.md | 2 +- docs/data-sources/deployments.md | 4 ++-- docs/data-sources/workspaces.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/data-sources/deployment.md b/docs/data-sources/deployment.md index cf86f487..f9f8ed29 100644 --- a/docs/data-sources/deployment.md +++ b/docs/data-sources/deployment.md @@ -43,7 +43,7 @@ data "astronomer_deployment" "example" { - `executor` (String) Deployment executor - `external_ips` (List of String) Deployment external IPs - `image_repository` (String) Deployment image repository -- `image_tag` (String) Deployment mage tag +- `image_tag` (String) Deployment image tag - `image_version` (String) Deployment image version - `is_cicd_enforced` (Boolean) Whether the Deployment enforces CI/CD deploys - `is_dag_deploy_enabled` (Boolean) Whether DAG deploy is enabled diff --git a/docs/data-sources/deployments.md b/docs/data-sources/deployments.md index c623eb6a..ae618a7e 100644 --- a/docs/data-sources/deployments.md +++ b/docs/data-sources/deployments.md @@ -24,7 +24,7 @@ data "astronomer_deployments" "example_deployments_filter_by_workspace_ids" { } data "astronomer_deployments" "example_deployments_filter_by_names" { - deployment_ids = ["my first deployment", "my second deployment"] + names = ["my first deployment", "my second deployment"] } ``` @@ -66,7 +66,7 @@ Read-Only: - `executor` (String) Deployment executor - `external_ips` (List of String) Deployment external IPs - `image_repository` (String) Deployment image repository -- `image_tag` (String) Deployment mage tag +- `image_tag` (String) Deployment image tag - `image_version` (String) Deployment image version - `is_cicd_enforced` (Boolean) Whether the Deployment enforces CI/CD deploys - `is_dag_deploy_enabled` (Boolean) Whether DAG deploy is enabled diff --git a/docs/data-sources/workspaces.md b/docs/data-sources/workspaces.md index 2f0b960e..baccb85d 100644 --- a/docs/data-sources/workspaces.md +++ b/docs/data-sources/workspaces.md @@ -20,7 +20,7 @@ data "astronomer_workspaces" "example_workspaces_filter_by_workspace_ids" { } data "astronomer_workspaces" "example_workspaces_filter_by_names" { - workspace_ids = ["my first workspace", "my second workspace"] + names = ["my first workspace", "my second workspace"] } ``` From ce58807bea856d1a9d1cae1d4acb53f325749703 Mon Sep 17 00:00:00 2001 From: Vandy Liu Date: Tue, 9 Apr 2024 23:39:53 -0700 Subject: [PATCH 09/11] add pre-commit to repo --- .githooks/pre-commit | 8 ++++++++ Makefile | 1 + 2 files changed, 9 insertions(+) create mode 100755 .githooks/pre-commit diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 00000000..f92e8bf2 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,8 @@ +echo "Running pre-commit hook" +make fmt +make build +go generate ./... +# Add examples and docs files to git after documentation is generated +git add examples/ +git add docs/ +echo "Pre-commit hook finished" \ No newline at end of file diff --git a/Makefile b/Makefile index 86523808..512855d1 100644 --- a/Makefile +++ b/Makefile @@ -37,6 +37,7 @@ validate-fmt: .PHONY: dep dep: + git config core.hooksPath .githooks go mod download go install golang.org/x/tools/cmd/goimports go mod tidy From 40cac56e053ad267a29f9faf956e2fdc89b48fb7 Mon Sep 17 00:00:00 2001 From: Vandy Liu Date: Tue, 9 Apr 2024 23:40:48 -0700 Subject: [PATCH 10/11] rename var in helper --- internal/utils/list.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/utils/list.go b/internal/utils/list.go index dcdb9a05..c1ffefb3 100644 --- a/internal/utils/list.go +++ b/internal/utils/list.go @@ -27,8 +27,8 @@ func ObjectList[T any](ctx context.Context, values []T, objectAttributeTypes map return types.ListNull(types.ObjectType{AttrTypes: objectAttributeTypes}), nil } objs := make([]attr.Value, len(values)) - for i, envVar := range values { - obj, diags := transformer(ctx, envVar) + for i, value := range values { + obj, diags := transformer(ctx, value) if diags.HasError() { return types.List{}, diags } From d0eda6b676499644edeed3cbe89709886a3cc3ca Mon Sep 17 00:00:00 2001 From: Vandy Liu Date: Wed, 10 Apr 2024 00:01:33 -0700 Subject: [PATCH 11/11] add comment and rename helper function --- internal/provider/datasources/data_source_deployments.go | 6 +++--- internal/provider/datasources/data_source_workspaces.go | 4 ++-- internal/utils/list.go | 6 ++++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/internal/provider/datasources/data_source_deployments.go b/internal/provider/datasources/data_source_deployments.go index d3fc02af..f9f413a5 100644 --- a/internal/provider/datasources/data_source_deployments.go +++ b/internal/provider/datasources/data_source_deployments.go @@ -83,9 +83,9 @@ func (d *deploymentsDataSource) Read( params := &platform.ListDeploymentsParams{ Limit: lo.ToPtr(1000), } - params.DeploymentIds = utils.TypesListToStringSlice(data.DeploymentIds) - params.WorkspaceIds = utils.TypesListToStringSlice(data.WorkspaceIds) - params.Names = utils.TypesListToStringSlice(data.Names) + params.DeploymentIds = utils.TypesListToStringSlicePtr(data.DeploymentIds) + params.WorkspaceIds = utils.TypesListToStringSlicePtr(data.WorkspaceIds) + params.Names = utils.TypesListToStringSlicePtr(data.Names) if resp.Diagnostics.HasError() { return diff --git a/internal/provider/datasources/data_source_workspaces.go b/internal/provider/datasources/data_source_workspaces.go index 35d97caf..f36ad8d0 100644 --- a/internal/provider/datasources/data_source_workspaces.go +++ b/internal/provider/datasources/data_source_workspaces.go @@ -83,8 +83,8 @@ func (d *workspacesDataSource) Read( params := &platform.ListWorkspacesParams{ Limit: lo.ToPtr(1000), } - params.WorkspaceIds = utils.TypesListToStringSlice(data.WorkspaceIds) - params.Names = utils.TypesListToStringSlice(data.Names) + params.WorkspaceIds = utils.TypesListToStringSlicePtr(data.WorkspaceIds) + params.Names = utils.TypesListToStringSlicePtr(data.Names) if resp.Diagnostics.HasError() { return diff --git a/internal/utils/list.go b/internal/utils/list.go index c1ffefb3..37541e24 100644 --- a/internal/utils/list.go +++ b/internal/utils/list.go @@ -41,9 +41,11 @@ func ObjectList[T any](ctx context.Context, values []T, objectAttributeTypes map return objectList, nil } -// TypesListToStringSlice converts a types.List to a pointer to a slice of strings +// TypesListToStringSlicePtr converts a types.List to a pointer to a slice of strings // This is useful for converting a list of strings from the Terraform framework to a slice of strings used for calling the API -func TypesListToStringSlice(list types.List) *[]string { +// We prefer to use a pointer to a slice of strings because our API client query params usually have type *[]string +// and we can easily assign the query param to the result of this function (regardless if the result is nil or not) +func TypesListToStringSlicePtr(list types.List) *[]string { elements := list.Elements() if len(elements) == 0 { return nil