diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..73ac8377 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,42 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: '' +assignees: '' +--- + +**Describe the bug** + + + +``` +Please paste terminal or playground output in a code block here +``` + +**What Terraform Provider Version and Terraform Version did you experience this bug?** + + + + +**What Operating System is the above Terraform Provider installed on?** + +**๐Ÿชœ Steps To Reproduce** + + + +**๐Ÿ“ธ Screenshots** + + diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..02c94671 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,33 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: '' +assignees: '' +--- + +- [ ] I have checked that a similar [feature request](https://github.com/astronomer/astronomer-terraform-provider/issues?q=is%3Aopen+is%3Aissue+label%3A%22feature+request%22) does not already exist. + +**โœ๏ธ Is your feature request related to a problem? Please describe.** + + + +**๐Ÿงฉ Describe the solution you'd like** + + + +**๐Ÿค” Describe alternatives you've considered** + + + +**๐Ÿ’ก Additional context** + + diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 80a5767a..27d2eb02 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,6 +1,6 @@ ## Description -> Describe the purpose of this pull request. + ## ๐ŸŽŸ Issue(s) @@ -8,11 +8,11 @@ Related #XXX ## ๐Ÿงช Functional Testing -> List the functional testing steps to confirm this feature or fix. + ## ๐Ÿ“ธ Screenshots -> Add screenshots to illustrate the validity of these changes. + ## ๐Ÿ“‹ Checklist diff --git a/Makefile b/Makefile index 8ec01fbe..86523808 100644 --- a/Makefile +++ b/Makefile @@ -1,14 +1,12 @@ -CORE_IAM_OPENAPI_SPEC=../astro-monorepo/apps/core/docs/iam/v1beta1/iam_v1beta1.yaml -CORE_PLATFORM_OPENAPI_SPEC=../astro-monorepo/apps/core/docs/platform/v1beta1/platform_v1beta1.yaml +CORE_IAM_OPENAPI_SPEC=../astro/apps/core/docs/iam/v1beta1/iam_v1beta1.yaml +CORE_PLATFORM_OPENAPI_SPEC=../astro/apps/core/docs/platform/v1beta1/platform_v1beta1.yaml DESIRED_OAPI_CODEGEN_VERSION=v2.1.0 -DESIRED_MOCKERY_VERSION=v2.40.2 ## Location to install dependencies to ENVTEST_ASSETS_DIR=$(shell pwd)/bin $(ENVTEST_ASSETS_DIR): mkdir -p $(ENVTEST_ASSETS_DIR) -MOCKERY ?= $(ENVTEST_ASSETS_DIR)/mockery OAPI_CODEGEN ?= $(ENVTEST_ASSETS_DIR)/oapi-codegen # Run acceptance tests @@ -20,7 +18,7 @@ testacc: .PHONY: test test: go vet ./... - go run github.com/onsi/ginkgo/v2/ginkgo run -r -v --skip-package internal/mocks --cover --covermode atomic --junit-report=report.xml --output-dir=test_results $(ARGS) + go run github.com/onsi/ginkgo/v2/ginkgo run -r -v --cover --covermode atomic --junit-report=report.xml --output-dir=test_results $(ARGS) .PHONY: fmt fmt: @@ -47,13 +45,6 @@ dep: build: go build -o ${ENVTEST_ASSETS_DIR}/terraform-provider-astronomer go generate ./... -# -#.PHONY: mock -#mock: $(ENVTEST_ASSETS_DIR) -# # Install correct mockery version if not installed -# (test -s $(MOCKERY) && $(MOCKERY) --version | grep -i $(DESIRED_MOCKERY_VERSION)) || GOBIN=$(ENVTEST_ASSETS_DIR) go install github.com/vektra/mockery/v2@$(DESIRED_MOCKERY_VERSION) -# rm -rf internal/mocks -# $(MOCKERY) --config .mockery.yaml .PHONY: api_client_gen api_client_gen: $(ENVTEST_ASSETS_DIR) diff --git a/README.md b/README.md index bc3408b1..d5104ad1 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,26 @@ go mod tidy Then commit the changes to `go.mod` and `go.sum`. ## Using the provider +1. Create an [API Token](https://docs.astronomer.io/astro/automation-authentication#step-1-create-an-api-token) to use in the provider. We recommend creating an organization API token since it is the most flexible but the type of your API token will depend on your use case. +2. Create a `main.tf` file with the following content: +```terraform +terraform { + required_providers { + astronomer = { + source = "registry.terraform.io/astronomer/astronomer" + } + } +} + +provider "astronomer" { + organization_id = "" +} +# your terraform commands here +``` +3. Run the following commands to apply the provider: ```shell +export ASTRO_API_TOKEN= terraform apply terraform plan ``` @@ -56,6 +74,45 @@ direct {} } ``` +## Example `main.tf` file for development and testing data sources and resources +```terraform +terraform { + required_providers { + astronomer = { + source = "registry.terraform.io/astronomer/astronomer" + } + } +} + +variable "token" { + type = string +} + +provider "astronomer" { + organization_id = "" + host = "https://api.astronomer-dev.io" + token = var.token +} + +data "astronomer_workspace" "example" { + id = ">" +} + +output "data_workspace_example" { + value = data.astronomer_workspace.example +} + +resource "astronomer_workspace" "tf_workspace" { + name = "my workspace" + description = "my first workspace" + cicd_enforced_default = false +} + +output "terraform_workspace" { + value = astronomer_workspace.tf_workspace +} +``` + ## Testing TODO: In order to run the full suite of Acceptance tests, run `make testacc`. diff --git a/docs/data-sources/workspaces.md b/docs/data-sources/workspaces.md new file mode 100644 index 00000000..72aa08dd --- /dev/null +++ b/docs/data-sources/workspaces.md @@ -0,0 +1,68 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "astronomer_workspaces Data Source - astronomer" +subcategory: "" +description: |- + Workspaces data source +--- + +# astronomer_workspaces (Data Source) + +Workspaces data source + + + + +## Schema + +### Optional + +- `names` (List of String) +- `workspace_ids` (List of String) + +### Read-Only + +- `workspaces` (Attributes List) (see [below for nested schema](#nestedatt--workspaces)) + + +### Nested Schema for `workspaces` + +Required: + +- `id` (String) Workspace identifier + +Read-Only: + +- `cicd_enforced_default` (Boolean) Whether new Deployments enforce CI/CD deploys by default +- `created_at` (String) Workspace creation timestamp +- `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)) + + +### Nested Schema for `workspaces.created_by` + +Read-Only: + +- `api_token_name` (String) +- `avatar_url` (String) +- `full_name` (String) +- `id` (String) +- `subject_type` (String) +- `username` (String) + + + +### Nested Schema for `workspaces.updated_by` + +Read-Only: + +- `api_token_name` (String) +- `avatar_url` (String) +- `full_name` (String) +- `id` (String) +- `subject_type` (String) +- `username` (String) diff --git a/examples/main.tf b/examples/main.tf deleted file mode 100644 index 5c75a76b..00000000 --- a/examples/main.tf +++ /dev/null @@ -1,50 +0,0 @@ -terraform { - required_providers { - astronomer = { - source = "registry.terraform.io/astronomer/astronomer" - } - } -} - -variable "token" { - type = string -} - -provider "astronomer" { - organization_id = "cljzz64cc001n01mln1pgkvpj" - host = "https://api.astronomer-dev.io" - token = var.token -} - -data "astronomer_workspace" "example" { - id = "cltj71ygr000101qafj5hhihs" -} - -output "data_workspace_example" { - value = data.astronomer_workspace.example -} - -resource "astronomer_workspace" "tf_workspace" { - name = "tf-workspace-1234" - description = "This is a Terraform created workspace" - cicd_enforced_default = false -} - -output "terraform_workspace" { - value = astronomer_workspace.tf_workspace -} - -// terraform import astronomer_workspace.imported_workspace cuid -import { - to = astronomer_workspace.imported_workspace - id = "clukhp501000401jdyc42imci" -} -resource "astronomer_workspace" "imported_workspace" { - name = "imported_workspace" - description = "hi fred" - cicd_enforced_default = false -} - -output "imported_workspace" { - value = astronomer_workspace.imported_workspace -} diff --git a/internal/provider/datasources/data_source_workspace.go b/internal/provider/datasources/data_source_workspace.go index 5f4dc026..252e5005 100644 --- a/internal/provider/datasources/data_source_workspace.go +++ b/internal/provider/datasources/data_source_workspace.go @@ -107,7 +107,11 @@ func (d *workspaceDataSource) Read( } // Populate the model with the response data - data.ReadFromResponse(ctx, workspace.JSON200) + diags := data.ReadFromResponse(ctx, workspace.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_workspaces.go b/internal/provider/datasources/data_source_workspaces.go new file mode 100644 index 00000000..e6f294ec --- /dev/null +++ b/internal/provider/datasources/data_source_workspaces.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 = &workspacesDataSource{} +var _ datasource.DataSourceWithConfigure = &workspacesDataSource{} + +func NewWorkspacesDataSource() datasource.DataSource { + return &workspacesDataSource{} +} + +// workspacesDataSource defines the data source implementation. +type workspacesDataSource struct { + PlatformClient platform.ClientWithResponsesInterface + OrganizationId string +} + +func (d *workspacesDataSource) Metadata( + ctx context.Context, + req datasource.MetadataRequest, + resp *datasource.MetadataResponse, +) { + resp.TypeName = req.ProviderTypeName + "_workspaces" +} + +func (d *workspacesDataSource) 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: "Workspaces data source", + Attributes: schemas.WorkspacesDataSourceSchemaAttributes(), + } +} + +func (d *workspacesDataSource) 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 *workspacesDataSource) Read( + ctx context.Context, + req datasource.ReadRequest, + resp *datasource.ReadResponse, +) { + var data models.WorkspacesDataSource + + // Read Terraform configuration data into the model + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + + 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 + } + + if resp.Diagnostics.HasError() { + return + } + + var workspaces []platform.Workspace + offset := 0 + for { + params.Offset = &offset + workspacesResp, err := d.PlatformClient.ListWorkspacesWithResponse( + ctx, + d.OrganizationId, + params, + ) + if err != nil { + tflog.Error(ctx, "failed to get workspace", map[string]interface{}{"error": err}) + resp.Diagnostics.AddError( + "Client Error", + fmt.Sprintf("Unable to read workspace, got error: %s", err), + ) + return + } + _, diagnostic := clients.NormalizeAPIError(ctx, workspacesResp.HTTPResponse, workspacesResp.Body) + if diagnostic != nil { + resp.Diagnostics.Append(diagnostic) + 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") + return + } + + workspaces = append(workspaces, workspacesResp.JSON200.Workspaces...) + + if workspacesResp.JSON200.TotalCount <= offset { + break + } + + offset += 1000 + } + + // Populate the model with the response data + diags := data.ReadFromResponse(ctx, workspaces) + 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/subject_profile.go b/internal/provider/models/subject_profile.go index fe81a4ae..f119b357 100644 --- a/internal/provider/models/subject_profile.go +++ b/internal/provider/models/subject_profile.go @@ -3,7 +3,7 @@ package models import ( "context" - "github.com/hashicorp/terraform-plugin-framework/attr" + "github.com/astronomer/astronomer-terraform-provider/internal/provider/schemas" "github.com/astronomer/astronomer-terraform-provider/internal/clients/iam" "github.com/astronomer/astronomer-terraform-provider/internal/clients/platform" @@ -21,15 +21,6 @@ type SubjectProfile struct { ApiTokenName types.String `tfsdk:"api_token_name"` } -var SubjectProfileTF map[string]attr.Type = map[string]attr.Type{ - "id": types.StringType, - "subject_type": types.StringType, - "username": types.StringType, - "full_name": types.StringType, - "avatar_url": types.StringType, - "api_token_name": types.StringType, -} - func SubjectProfileTypesObject( ctx context.Context, basicSubjectProfile any, @@ -92,5 +83,5 @@ func SubjectProfileTypesObject( } } } - return types.ObjectValueFrom(ctx, SubjectProfileTF, subjectProfile) + return types.ObjectValueFrom(ctx, schemas.SubjectProfileAttributeTypes(), subjectProfile) } diff --git a/internal/provider/models/workspaces.go b/internal/provider/models/workspaces.go new file mode 100644 index 00000000..7b82f905 --- /dev/null +++ b/internal/provider/models/workspaces.go @@ -0,0 +1,74 @@ +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" +) + +// WorkspacesDataSource describes the data source data model. +type WorkspacesDataSource struct { + Workspaces types.List `tfsdk:"workspaces"` + WorkspaceIds types.List `tfsdk:"workspace_ids"` // query parameter + Names types.List `tfsdk:"names"` // query parameter +} + +func (data *WorkspacesDataSource) ReadFromResponse( + ctx context.Context, + workspaces []platform.Workspace, +) diag.Diagnostics { + if len(workspaces) == 0 { + types.ListNull(types.ObjectType{AttrTypes: schemas.WorkspacesElementAttributeTypes()}) + } + + 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 + } + + objectValue, diags := types.ObjectValue(schemas.WorkspacesElementAttributeTypes(), v) + if diags.HasError() { + return diags + } + values[i] = objectValue + } + var diags diag.Diagnostics + data.Workspaces, diags = types.ListValue(types.ObjectType{AttrTypes: schemas.WorkspacesElementAttributeTypes()}, values) + if diags.HasError() { + return diags + } + + return nil +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 89788b4e..0227f425 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -130,6 +130,7 @@ func (p *AstronomerProvider) Resources(ctx context.Context) []func() resource.Re func (p *AstronomerProvider) DataSources(ctx context.Context) []func() datasource.DataSource { return []func() datasource.DataSource{ datasources.NewWorkspaceDataSource, + datasources.NewWorkspacesDataSource, } } diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index 417f44c4..6e82370f 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -43,6 +43,7 @@ var _ = Describe("Provider Test", func() { It("has expected data sources", func() { expectedDataSources := []string{ "astronomer_workspace", + "astronomer_workspaces", } dataSources := p.DataSources(ctx) diff --git a/internal/provider/schemas/provider.go b/internal/provider/schemas/provider.go index 78cbbeba..49d774e5 100644 --- a/internal/provider/schemas/provider.go +++ b/internal/provider/schemas/provider.go @@ -1,7 +1,7 @@ package schemas import ( - "github.com/astronomer/astronomer-terraform-provider/internal/validators" + "github.com/astronomer/astronomer-terraform-provider/internal/provider/validators" "github.com/hashicorp/terraform-plugin-framework/provider/schema" "github.com/hashicorp/terraform-plugin-framework/schema/validator" ) diff --git a/internal/provider/schemas/subject_profile.go b/internal/provider/schemas/subject_profile.go index 0d405776..8bc98c05 100644 --- a/internal/provider/schemas/subject_profile.go +++ b/internal/provider/schemas/subject_profile.go @@ -1,51 +1,64 @@ package schemas import ( - datasource "github.com/hashicorp/terraform-plugin-framework/datasource/schema" - resource "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/attr" + datasourceSchema "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + resourceSchema "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/types" ) -func DataSourceSubjectProfileSchema() map[string]datasource.Attribute { - return map[string]datasource.Attribute{ - "id": datasource.StringAttribute{ +func SubjectProfileAttributeTypes() map[string]attr.Type { + return map[string]attr.Type{ + "id": types.StringType, + "subject_type": types.StringType, + "username": types.StringType, + "full_name": types.StringType, + "avatar_url": types.StringType, + "api_token_name": types.StringType, + } +} + +func DataSourceSubjectProfileSchemaAttributes() map[string]datasourceSchema.Attribute { + return map[string]datasourceSchema.Attribute{ + "id": datasourceSchema.StringAttribute{ Computed: true, }, - "subject_type": datasource.StringAttribute{ + "subject_type": datasourceSchema.StringAttribute{ Computed: true, }, - "username": datasource.StringAttribute{ + "username": datasourceSchema.StringAttribute{ Computed: true, }, - "full_name": datasource.StringAttribute{ + "full_name": datasourceSchema.StringAttribute{ Computed: true, }, - "avatar_url": datasource.StringAttribute{ + "avatar_url": datasourceSchema.StringAttribute{ Computed: true, }, - "api_token_name": datasource.StringAttribute{ + "api_token_name": datasourceSchema.StringAttribute{ Computed: true, }, } } -func ResourceSubjectProfileSchema() map[string]resource.Attribute { - return map[string]resource.Attribute{ - "id": resource.StringAttribute{ +func ResourceSubjectProfileSchemaAttributes() map[string]resourceSchema.Attribute { + return map[string]resourceSchema.Attribute{ + "id": resourceSchema.StringAttribute{ Computed: true, }, - "subject_type": resource.StringAttribute{ + "subject_type": resourceSchema.StringAttribute{ Computed: true, }, - "username": resource.StringAttribute{ + "username": resourceSchema.StringAttribute{ Computed: true, }, - "full_name": resource.StringAttribute{ + "full_name": resourceSchema.StringAttribute{ Computed: true, }, - "avatar_url": resource.StringAttribute{ + "avatar_url": resourceSchema.StringAttribute{ Computed: true, }, - "api_token_name": resource.StringAttribute{ + "api_token_name": resourceSchema.StringAttribute{ Computed: true, }, } diff --git a/internal/provider/schemas/subject_profile_test.go b/internal/provider/schemas/subject_profile_test.go index 1bac4b70..7a6fdc2f 100644 --- a/internal/provider/schemas/subject_profile_test.go +++ b/internal/provider/schemas/subject_profile_test.go @@ -3,6 +3,8 @@ package schemas_test import ( "context" + "github.com/astronomer/astronomer-terraform-provider/internal/provider/schemas" + "github.com/astronomer/astronomer-terraform-provider/internal/clients/iam" "github.com/astronomer/astronomer-terraform-provider/internal/clients/platform" "github.com/astronomer/astronomer-terraform-provider/internal/provider/models" @@ -38,7 +40,7 @@ var _ = Describe("Common Test", func() { func(input any, expected models.SubjectProfile) { subjectProfileModel, diags := models.SubjectProfileTypesObject(ctx, input) Expect(diags.HasError()).To(BeFalse()) - expectedSubjectProfile, diags := types.ObjectValueFrom(ctx, models.SubjectProfileTF, expected) + expectedSubjectProfile, diags := types.ObjectValueFrom(ctx, schemas.SubjectProfileAttributeTypes(), expected) Expect(diags.HasError()).To(BeFalse()) Expect(subjectProfileModel).To(Equal(expectedSubjectProfile)) }, diff --git a/internal/provider/schemas/workspace.go b/internal/provider/schemas/workspace.go index 055cf16b..4142dfe3 100644 --- a/internal/provider/schemas/workspace.go +++ b/internal/provider/schemas/workspace.go @@ -1,63 +1,63 @@ package schemas import ( - "github.com/astronomer/astronomer-terraform-provider/internal/validators" + "github.com/astronomer/astronomer-terraform-provider/internal/provider/validators" "github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator" - datasource "github.com/hashicorp/terraform-plugin-framework/datasource/schema" - resource "github.com/hashicorp/terraform-plugin-framework/resource/schema" + datasourceSchema "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + resourceSchema "github.com/hashicorp/terraform-plugin-framework/resource/schema" "github.com/hashicorp/terraform-plugin-framework/resource/schema/objectplanmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" "github.com/hashicorp/terraform-plugin-framework/schema/validator" ) -func WorkspaceDataSourceSchemaAttributes() map[string]datasource.Attribute { - return map[string]datasource.Attribute{ - "id": datasource.StringAttribute{ +func WorkspaceDataSourceSchemaAttributes() map[string]datasourceSchema.Attribute { + return map[string]datasourceSchema.Attribute{ + "id": datasourceSchema.StringAttribute{ MarkdownDescription: "Workspace identifier", Required: true, Validators: []validator.String{validators.IsCuid()}, }, - "name": datasource.StringAttribute{ + "name": datasourceSchema.StringAttribute{ MarkdownDescription: "Workspace name", Computed: true, }, - "description": datasource.StringAttribute{ + "description": datasourceSchema.StringAttribute{ MarkdownDescription: "Workspace description", Computed: true, }, - "organization_name": datasource.StringAttribute{ + "organization_name": datasourceSchema.StringAttribute{ MarkdownDescription: "Workspace organization name", Computed: true, }, - "cicd_enforced_default": datasource.BoolAttribute{ + "cicd_enforced_default": datasourceSchema.BoolAttribute{ MarkdownDescription: "Whether new Deployments enforce CI/CD deploys by default", Computed: true, }, - "created_at": datasource.StringAttribute{ + "created_at": datasourceSchema.StringAttribute{ MarkdownDescription: "Workspace creation timestamp", Computed: true, }, - "updated_at": datasource.StringAttribute{ + "updated_at": datasourceSchema.StringAttribute{ MarkdownDescription: "Workspace last updated timestamp", Computed: true, }, - "created_by": datasource.SingleNestedAttribute{ + "created_by": datasourceSchema.SingleNestedAttribute{ MarkdownDescription: "Workspace creator", Computed: true, - Attributes: DataSourceSubjectProfileSchema(), + Attributes: DataSourceSubjectProfileSchemaAttributes(), }, - "updated_by": datasource.SingleNestedAttribute{ + "updated_by": datasourceSchema.SingleNestedAttribute{ MarkdownDescription: "Workspace updater", Computed: true, - Attributes: DataSourceSubjectProfileSchema(), + Attributes: DataSourceSubjectProfileSchemaAttributes(), }, } } -func WorkspaceResourceSchemaAttributes() map[string]resource.Attribute { - return map[string]resource.Attribute{ - "id": resource.StringAttribute{ +func WorkspaceResourceSchemaAttributes() map[string]resourceSchema.Attribute { + return map[string]resourceSchema.Attribute{ + "id": resourceSchema.StringAttribute{ MarkdownDescription: "Workspace identifier", Computed: true, Validators: []validator.String{validators.IsCuid()}, @@ -65,49 +65,49 @@ func WorkspaceResourceSchemaAttributes() map[string]resource.Attribute { stringplanmodifier.UseStateForUnknown(), }, }, - "name": resource.StringAttribute{ + "name": resourceSchema.StringAttribute{ MarkdownDescription: "Workspace name", Required: true, Validators: []validator.String{stringvalidator.LengthAtMost(50)}, }, - "description": resource.StringAttribute{ + "description": resourceSchema.StringAttribute{ MarkdownDescription: "Workspace description", Required: true, }, - "organization_name": resource.StringAttribute{ + "organization_name": resourceSchema.StringAttribute{ MarkdownDescription: "Workspace organization name", Computed: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.UseStateForUnknown(), }, }, - "cicd_enforced_default": resource.BoolAttribute{ + "cicd_enforced_default": resourceSchema.BoolAttribute{ MarkdownDescription: "Whether new Deployments enforce CI/CD deploys by default", Required: true, }, - "created_at": resource.StringAttribute{ + "created_at": resourceSchema.StringAttribute{ MarkdownDescription: "Workspace creation timestamp", Computed: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.UseStateForUnknown(), }, }, - "updated_at": resource.StringAttribute{ + "updated_at": resourceSchema.StringAttribute{ MarkdownDescription: "Workspace last updated timestamp", Computed: true, }, - "created_by": resource.SingleNestedAttribute{ + "created_by": resourceSchema.SingleNestedAttribute{ MarkdownDescription: "Workspace creator", Computed: true, - Attributes: ResourceSubjectProfileSchema(), + Attributes: ResourceSubjectProfileSchemaAttributes(), PlanModifiers: []planmodifier.Object{ objectplanmodifier.UseStateForUnknown(), }, }, - "updated_by": resource.SingleNestedAttribute{ + "updated_by": resourceSchema.SingleNestedAttribute{ MarkdownDescription: "Workspace updater", Computed: true, - Attributes: ResourceSubjectProfileSchema(), + Attributes: ResourceSubjectProfileSchemaAttributes(), }, } } diff --git a/internal/provider/schemas/workspaces.go b/internal/provider/schemas/workspaces.go new file mode 100644 index 00000000..522611fa --- /dev/null +++ b/internal/provider/schemas/workspaces.go @@ -0,0 +1,44 @@ +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 WorkspacesElementAttributeTypes() map[string]attr.Type { + return 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, + "created_by": types.ObjectType{ + AttrTypes: SubjectProfileAttributeTypes(), + }, + "updated_by": types.ObjectType{ + AttrTypes: SubjectProfileAttributeTypes(), + }, + } +} + +func WorkspacesDataSourceSchemaAttributes() map[string]schema.Attribute { + return map[string]schema.Attribute{ + "workspaces": schema.ListNestedAttribute{ + NestedObject: schema.NestedAttributeObject{ + Attributes: WorkspaceDataSourceSchemaAttributes(), + }, + Computed: true, + }, + "workspace_ids": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + }, + "names": schema.ListAttribute{ + ElementType: types.StringType, + Optional: true, + }, + } +} diff --git a/internal/validators/is_cuid.go b/internal/provider/validators/is_cuid.go similarity index 100% rename from internal/validators/is_cuid.go rename to internal/provider/validators/is_cuid.go diff --git a/internal/validators/is_cuid_test.go b/internal/provider/validators/is_cuid_test.go similarity index 91% rename from internal/validators/is_cuid_test.go rename to internal/provider/validators/is_cuid_test.go index adaa6245..34b4cc64 100644 --- a/internal/validators/is_cuid_test.go +++ b/internal/provider/validators/is_cuid_test.go @@ -1,7 +1,7 @@ package validators_test import ( - "github.com/astronomer/astronomer-terraform-provider/internal/validators" + "github.com/astronomer/astronomer-terraform-provider/internal/provider/validators" "github.com/hashicorp/terraform-plugin-framework/schema/validator" "github.com/hashicorp/terraform-plugin-framework/types" "github.com/lucsky/cuid" diff --git a/internal/validators/validators_suite_test.go b/internal/provider/validators/validators_suite_test.go similarity index 100% rename from internal/validators/validators_suite_test.go rename to internal/provider/validators/validators_suite_test.go