From 6f7cded41dc3eec8e9d43a7c444ba164f02806e7 Mon Sep 17 00:00:00 2001 From: Dana Fallon <8871189+danafallon@users.noreply.github.com> Date: Mon, 22 Jul 2024 13:12:29 -0700 Subject: [PATCH 1/6] Set up deployments datasource --- examples/deployments/main.tf | 18 +++ internal/provider/deployments_data_source.go | 144 +++++++++++++++++++ internal/provider/provider.go | 16 ++- 3 files changed, 171 insertions(+), 7 deletions(-) create mode 100644 examples/deployments/main.tf create mode 100644 internal/provider/deployments_data_source.go diff --git a/examples/deployments/main.tf b/examples/deployments/main.tf new file mode 100644 index 0000000..4bba78f --- /dev/null +++ b/examples/deployments/main.tf @@ -0,0 +1,18 @@ +terraform { + required_providers { + artie = { + source = "artie.com/terraform/artie" + } + } +} + +provider "artie" { + endpoint = "http://0.0.0.0:8000" + api_key = "api-key" +} + +data "artie_deployments" "example" {} + +output "deployments" { + value = data.artie_deployments.example.deployments +} \ No newline at end of file diff --git a/internal/provider/deployments_data_source.go b/internal/provider/deployments_data_source.go new file mode 100644 index 0000000..b3a0363 --- /dev/null +++ b/internal/provider/deployments_data_source.go @@ -0,0 +1,144 @@ +package provider + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" + "github.com/hashicorp/terraform-plugin-framework/types/basetypes" + "github.com/hashicorp/terraform-plugin-log/tflog" +) + +// Ensure the implementation satisfies the expected interfaces. +var ( + _ datasource.DataSource = &deploymentsDataSource{} + _ datasource.DataSourceWithConfigure = &deploymentsDataSource{} +) + +// NewDeploymentsDataSource is a helper function to simplify the provider implementation. +func NewDeploymentsDataSource() datasource.DataSource { + return &deploymentsDataSource{} +} + +type deploymentsModel struct { + UUID string `tfsdk:"uuid"` + Name string `tfsdk:"name"` +} + +type deploymentsDataSourceModel struct { + Deployments []deploymentsModel `tfsdk:"deployments"` +} + +type deploymentsResponse struct { + Deployments []deploymentsModel `json:"items"` +} + +// deploymentsDataSource is the data source implementation. +type deploymentsDataSource struct { + endpoint basetypes.StringValue + apiKey basetypes.StringValue +} + +// Metadata returns the data source type name. +func (d *deploymentsDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_deployments" +} + +// Configure adds the provider configured client to the data source. +func (d *deploymentsDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) { + // Add a nil check when handling ProviderData because Terraform + // sets that data after it calls the ConfigureProvider RPC. + if req.ProviderData == nil { + return + } + + providerData, ok := req.ProviderData.(ArtieProviderModel) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Data Source Configure Type", + fmt.Sprintf("Expected *http.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + + return + } + + d.endpoint = providerData.Endpoint + d.apiKey = providerData.APIKey +} + +// Schema defines the schema for the data source. +func (d *deploymentsDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { + resp.Schema = schema.Schema{ + Attributes: map[string]schema.Attribute{ + "deployments": schema.ListNestedAttribute{ + Computed: true, + NestedObject: schema.NestedAttributeObject{ + Attributes: map[string]schema.Attribute{ + "uuid": schema.StringAttribute{ + Computed: true, + }, + "name": schema.StringAttribute{ + Computed: true, + }, + }, + }, + }, + }, + } +} + +// Read refreshes the Terraform state with the latest data. +func (d *deploymentsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) { + tflog.Info(ctx, fmt.Sprintf("Endpoint: %s", d.endpoint.ValueString())) + var state deploymentsDataSourceModel + + apiReq, err := http.NewRequest("GET", fmt.Sprintf("%s/deployments", d.endpoint.ValueString()), nil) + if err != nil { + resp.Diagnostics.AddError("Unable to Read Deployments", err.Error()) + return + } + + apiReq.Header.Set("Authorization", fmt.Sprintf("Bearer %s", d.apiKey.ValueString())) + apiResp, err := http.DefaultClient.Do(apiReq) + if err != nil { + resp.Diagnostics.AddError("Unable to Read Deployments", err.Error()) + return + } + + if apiResp.StatusCode != http.StatusOK { + resp.Diagnostics.AddError("Unable to Read Deployments", fmt.Sprintf("Received status code %d", apiResp.StatusCode)) + return + } + + bodyBytes, err := io.ReadAll(apiResp.Body) + if err != nil { + resp.Diagnostics.AddError("Unable to Read Deployments", err.Error()) + return + } + + var deploymentsResp deploymentsResponse + err = json.Unmarshal(bodyBytes, &deploymentsResp) + if err != nil { + resp.Diagnostics.AddError("Unable to Read Deployments", err.Error()) + return + } + + for _, deployment := range deploymentsResp.Deployments { + deploymentState := deploymentsModel{ + UUID: deployment.UUID, + Name: deployment.Name, + } + state.Deployments = append(state.Deployments, deploymentState) + } + + // Set state + diags := resp.State.Set(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } +} diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 17aaeef..0eb3539 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -5,7 +5,6 @@ package provider import ( "context" - "net/http" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/function" @@ -30,6 +29,7 @@ type ArtieProvider struct { // ArtieProviderModel describes the provider data model. type ArtieProviderModel struct { Endpoint types.String `tfsdk:"endpoint"` + APIKey types.String `tfsdk:"api_key"` } func (p *ArtieProvider) Metadata(ctx context.Context, req provider.MetadataRequest, resp *provider.MetadataResponse) { @@ -41,7 +41,11 @@ func (p *ArtieProvider) Schema(ctx context.Context, req provider.SchemaRequest, resp.Schema = schema.Schema{ Attributes: map[string]schema.Attribute{ "endpoint": schema.StringAttribute{ - MarkdownDescription: "Example provider attribute", + MarkdownDescription: "Artie API endpoint", + Optional: true, + }, + "api_key": schema.StringAttribute{ + MarkdownDescription: "Artie API key", Optional: true, }, }, @@ -60,10 +64,8 @@ func (p *ArtieProvider) Configure(ctx context.Context, req provider.ConfigureReq // Configuration values are now available. // if data.Endpoint.IsNull() { /* ... */ } - // Example client configuration for data sources and resources - client := http.DefaultClient - resp.DataSourceData = client - resp.ResourceData = client + resp.DataSourceData = data + resp.ResourceData = data } func (p *ArtieProvider) Resources(ctx context.Context) []func() resource.Resource { @@ -74,7 +76,7 @@ func (p *ArtieProvider) Resources(ctx context.Context) []func() resource.Resourc func (p *ArtieProvider) DataSources(ctx context.Context) []func() datasource.DataSource { return []func() datasource.DataSource{ - NewExampleDataSource, + NewDeploymentsDataSource, } } From 93697a351d18cf1c6990e747cd09509cbcc87c60 Mon Sep 17 00:00:00 2001 From: Dana Fallon <8871189+danafallon@users.noreply.github.com> Date: Mon, 22 Jul 2024 13:14:06 -0700 Subject: [PATCH 2/6] Generate docs --- docs/data-sources/deployments.md | 28 ++++++++++++++++++++++++++++ docs/data-sources/example.md | 24 ------------------------ docs/index.md | 3 ++- examples/deployments/main.tf | 18 +++++++++--------- 4 files changed, 39 insertions(+), 34 deletions(-) create mode 100644 docs/data-sources/deployments.md delete mode 100644 docs/data-sources/example.md diff --git a/docs/data-sources/deployments.md b/docs/data-sources/deployments.md new file mode 100644 index 0000000..4cf27a3 --- /dev/null +++ b/docs/data-sources/deployments.md @@ -0,0 +1,28 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "artie_deployments Data Source - artie" +subcategory: "" +description: |- + +--- + +# artie_deployments (Data Source) + + + + + + +## Schema + +### Read-Only + +- `deployments` (Attributes List) (see [below for nested schema](#nestedatt--deployments)) + + +### Nested Schema for `deployments` + +Read-Only: + +- `name` (String) +- `uuid` (String) diff --git a/docs/data-sources/example.md b/docs/data-sources/example.md deleted file mode 100644 index ec1fd54..0000000 --- a/docs/data-sources/example.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -# generated by https://github.com/hashicorp/terraform-plugin-docs -page_title: "artie_example Data Source - artie" -subcategory: "" -description: |- - Example data source ---- - -# artie_example (Data Source) - -Example data source - - - - -## Schema - -### Optional - -- `configurable_attribute` (String) Example configurable attribute - -### Read-Only - -- `id` (String) Example identifier diff --git a/docs/index.md b/docs/index.md index f938291..8b9a51d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -23,4 +23,5 @@ provider "artie" { ### Optional -- `endpoint` (String) Example provider attribute +- `api_key` (String) Artie API key +- `endpoint` (String) Artie API endpoint diff --git a/examples/deployments/main.tf b/examples/deployments/main.tf index 4bba78f..45be905 100644 --- a/examples/deployments/main.tf +++ b/examples/deployments/main.tf @@ -1,18 +1,18 @@ terraform { - required_providers { - artie = { - source = "artie.com/terraform/artie" - } - } + required_providers { + artie = { + source = "artie.com/terraform/artie" + } + } } provider "artie" { - endpoint = "http://0.0.0.0:8000" - api_key = "api-key" + endpoint = "http://0.0.0.0:8000" + api_key = "api-key" } data "artie_deployments" "example" {} output "deployments" { - value = data.artie_deployments.example.deployments -} \ No newline at end of file + value = data.artie_deployments.example.deployments +} From 33b9c7fbb872546be6ee068eb512fe294412cc90 Mon Sep 17 00:00:00 2001 From: Dana Fallon <8871189+danafallon@users.noreply.github.com> Date: Mon, 22 Jul 2024 13:18:42 -0700 Subject: [PATCH 3/6] Add back example data source for tests --- internal/provider/provider.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 0eb3539..4073d4c 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -76,6 +76,7 @@ func (p *ArtieProvider) Resources(ctx context.Context) []func() resource.Resourc func (p *ArtieProvider) DataSources(ctx context.Context) []func() datasource.DataSource { return []func() datasource.DataSource{ + NewExampleDataSource, NewDeploymentsDataSource, } } From cd8e7c954f36673619eb7ad991541d18f4b5c513 Mon Sep 17 00:00:00 2001 From: Dana Fallon <8871189+danafallon@users.noreply.github.com> Date: Mon, 22 Jul 2024 13:36:23 -0700 Subject: [PATCH 4/6] Remove example acceptance tests that depended on example provider --- internal/provider/example_data_source_test.go | 32 ----------- internal/provider/example_resource_test.go | 56 ------------------- 2 files changed, 88 deletions(-) delete mode 100644 internal/provider/example_data_source_test.go delete mode 100644 internal/provider/example_resource_test.go diff --git a/internal/provider/example_data_source_test.go b/internal/provider/example_data_source_test.go deleted file mode 100644 index deebb1f..0000000 --- a/internal/provider/example_data_source_test.go +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package provider - -import ( - "testing" - - "github.com/hashicorp/terraform-plugin-testing/helper/resource" -) - -func TestAccExampleDataSource(t *testing.T) { - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, - Steps: []resource.TestStep{ - // Read testing - { - Config: testAccExampleDataSourceConfig, - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("data.artie_example.test", "id", "example-id"), - ), - }, - }, - }) -} - -const testAccExampleDataSourceConfig = ` -data "artie_example" "test" { - configurable_attribute = "example" -} -` diff --git a/internal/provider/example_resource_test.go b/internal/provider/example_resource_test.go deleted file mode 100644 index b18a087..0000000 --- a/internal/provider/example_resource_test.go +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) HashiCorp, Inc. -// SPDX-License-Identifier: MPL-2.0 - -package provider - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform-plugin-testing/helper/resource" -) - -func TestAccExampleResource(t *testing.T) { - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - ProtoV6ProviderFactories: testAccProtoV6ProviderFactories, - Steps: []resource.TestStep{ - // Create and Read testing - { - Config: testAccExampleResourceConfig("one"), - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("artie_example.test", "configurable_attribute", "one"), - resource.TestCheckResourceAttr("artie_example.test", "defaulted", "example value when not configured"), - resource.TestCheckResourceAttr("artie_example.test", "id", "example-id"), - ), - }, - // ImportState testing - { - ResourceName: "artie_example.test", - ImportState: true, - ImportStateVerify: true, - // This is not normally necessary, but is here because this - // example code does not have an actual upstream service. - // Once the Read method is able to refresh information from - // the upstream service, this can be removed. - ImportStateVerifyIgnore: []string{"configurable_attribute", "defaulted"}, - }, - // Update and Read testing - { - Config: testAccExampleResourceConfig("two"), - Check: resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr("artie_example.test", "configurable_attribute", "two"), - ), - }, - // Delete testing automatically occurs in TestCase - }, - }) -} - -func testAccExampleResourceConfig(configurableAttribute string) string { - return fmt.Sprintf(` -resource "artie_example" "test" { - configurable_attribute = %[1]q -} -`, configurableAttribute) -} From a651ed6e25f4514d9b40820b700f5ced92a0557a Mon Sep 17 00:00:00 2001 From: Dana Fallon <8871189+danafallon@users.noreply.github.com> Date: Mon, 22 Jul 2024 13:39:57 -0700 Subject: [PATCH 5/6] Lint, add data source description --- docs/data-sources/deployments.md | 4 ++-- docs/data-sources/example.md | 24 ++++++++++++++++++++ internal/provider/deployments_data_source.go | 2 +- internal/provider/provider_test.go | 12 ++++------ 4 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 docs/data-sources/example.md diff --git a/docs/data-sources/deployments.md b/docs/data-sources/deployments.md index 4cf27a3..854e2db 100644 --- a/docs/data-sources/deployments.md +++ b/docs/data-sources/deployments.md @@ -3,12 +3,12 @@ page_title: "artie_deployments Data Source - artie" subcategory: "" description: |- - + Artie Deployments Data Source --- # artie_deployments (Data Source) - +Artie Deployments Data Source diff --git a/docs/data-sources/example.md b/docs/data-sources/example.md new file mode 100644 index 0000000..ec1fd54 --- /dev/null +++ b/docs/data-sources/example.md @@ -0,0 +1,24 @@ +--- +# generated by https://github.com/hashicorp/terraform-plugin-docs +page_title: "artie_example Data Source - artie" +subcategory: "" +description: |- + Example data source +--- + +# artie_example (Data Source) + +Example data source + + + + +## Schema + +### Optional + +- `configurable_attribute` (String) Example configurable attribute + +### Read-Only + +- `id` (String) Example identifier diff --git a/internal/provider/deployments_data_source.go b/internal/provider/deployments_data_source.go index b3a0363..a551254 100644 --- a/internal/provider/deployments_data_source.go +++ b/internal/provider/deployments_data_source.go @@ -70,9 +70,9 @@ func (d *deploymentsDataSource) Configure(_ context.Context, req datasource.Conf d.apiKey = providerData.APIKey } -// Schema defines the schema for the data source. func (d *deploymentsDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) { resp.Schema = schema.Schema{ + MarkdownDescription: "Artie Deployments Data Source", Attributes: map[string]schema.Attribute{ "deployments": schema.ListNestedAttribute{ Computed: true, diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index 2fa09c1..c69b762 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -4,8 +4,6 @@ package provider import ( - "testing" - "github.com/hashicorp/terraform-plugin-framework/providerserver" "github.com/hashicorp/terraform-plugin-go/tfprotov6" ) @@ -18,8 +16,8 @@ var testAccProtoV6ProviderFactories = map[string]func() (tfprotov6.ProviderServe "artie": providerserver.NewProtocol6WithError(New("test")()), } -func testAccPreCheck(t *testing.T) { - // You can add code here to run prior to any test case execution, for example assertions - // about the appropriate environment variables being set are common to see in a pre-check - // function. -} +// func testAccPreCheck(t *testing.T) { +// // You can add code here to run prior to any test case execution, for example assertions +// // about the appropriate environment variables being set are common to see in a pre-check +// // function. +// } From 9a28717c0a6800d000c8886f0f07b6180f87c4b5 Mon Sep 17 00:00:00 2001 From: Dana Fallon <8871189+danafallon@users.noreply.github.com> Date: Mon, 22 Jul 2024 13:42:13 -0700 Subject: [PATCH 6/6] Remove unused --- internal/provider/provider_test.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index c69b762..1d3dc75 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -15,9 +15,3 @@ import ( var testAccProtoV6ProviderFactories = map[string]func() (tfprotov6.ProviderServer, error){ "artie": providerserver.NewProtocol6WithError(New("test")()), } - -// func testAccPreCheck(t *testing.T) { -// // You can add code here to run prior to any test case execution, for example assertions -// // about the appropriate environment variables being set are common to see in a pre-check -// // function. -// }