From 1ce55b4e1cc842f63045b305fb6fca2253bdac28 Mon Sep 17 00:00:00 2001 From: Craig Squire <677724+csquire@users.noreply.github.com> Date: Thu, 5 Dec 2024 13:53:03 -0600 Subject: [PATCH 1/7] Migrate azure_dev_ops_project from SDKv2 to Framework --- .../azure_dev_ops_project/data_source.go | 75 +++++++++++++++++++ .../objects/azure_dev_ops_project/model.go | 9 +++ .../objects/azure_dev_ops_project/schema.go | 35 +++++++++ pkg/provider/framework_provider.go | 2 + pkg/provider/sdk_provider.go | 1 - .../data_sources/azure_dev_ops_project.go | 69 ----------------- 6 files changed, 121 insertions(+), 70 deletions(-) create mode 100644 pkg/framework/objects/azure_dev_ops_project/data_source.go create mode 100644 pkg/framework/objects/azure_dev_ops_project/model.go create mode 100644 pkg/framework/objects/azure_dev_ops_project/schema.go delete mode 100644 pkg/sdkv2/data_sources/azure_dev_ops_project.go diff --git a/pkg/framework/objects/azure_dev_ops_project/data_source.go b/pkg/framework/objects/azure_dev_ops_project/data_source.go new file mode 100644 index 0000000..0c25a02 --- /dev/null +++ b/pkg/framework/objects/azure_dev_ops_project/data_source.go @@ -0,0 +1,75 @@ +package azure_dev_ops_project + +import ( + "context" + "fmt" + + "github.com/dbt-labs/terraform-provider-dbtcloud/pkg/dbt_cloud" + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/types" +) + +var ( + _ datasource.DataSource = &azureDevOpsProjectDataSource{} + _ datasource.DataSourceWithConfigure = &azureDevOpsProjectDataSource{} +) + +func AzureDevOpsProjectDataSource() datasource.DataSource { + return &azureDevOpsProjectDataSource{} +} + +type azureDevOpsProjectDataSource struct { + client *dbt_cloud.Client +} + +func (d *azureDevOpsProjectDataSource) Metadata( + _ context.Context, + req datasource.MetadataRequest, + resp *datasource.MetadataResponse, +) { + resp.TypeName = req.ProviderTypeName + "azure_dev_ops_project" +} + +func (d *azureDevOpsProjectDataSource) Read( + ctx context.Context, + req datasource.ReadRequest, + resp *datasource.ReadResponse, +) { + var state AzureDevOpsProjectDataSourceModel + + resp.Diagnostics.Append(req.Config.Get(ctx, &state)...) + + projectName := state.Name.ValueString() + + azureDevOpsProject, err := d.client.GetAzureDevOpsProject(projectName) + + if err != nil { + resp.Diagnostics.AddError( + fmt.Sprintf("Did not find Azure DevOps Project with name: %s", state.Name), + err.Error(), + ) + return + } + + state.Name = types.StringValue(azureDevOpsProject.Name) + state.ID = types.StringValue(azureDevOpsProject.ID) + state.URL = types.StringValue(azureDevOpsProject.URL) + + diags := resp.State.Set(ctx, &state) + resp.Diagnostics.Append(diags...) + if resp.Diagnostics.HasError() { + return + } +} + +func (d *azureDevOpsProjectDataSource) Configure( + _ context.Context, + req datasource.ConfigureRequest, + _ *datasource.ConfigureResponse, +) { + if req.ProviderData == nil { + return + } + + d.client = req.ProviderData.(*dbt_cloud.Client) +} diff --git a/pkg/framework/objects/azure_dev_ops_project/model.go b/pkg/framework/objects/azure_dev_ops_project/model.go new file mode 100644 index 0000000..975eb90 --- /dev/null +++ b/pkg/framework/objects/azure_dev_ops_project/model.go @@ -0,0 +1,9 @@ +package azure_dev_ops_project + +import "github.com/hashicorp/terraform-plugin-framework/types" + +type AzureDevOpsProjectDataSourceModel struct { + ID types.String `tfsdk:"id"` + Name types.String `tfsdk:"name"` + URL types.String `tfsdk:"url"` +} diff --git a/pkg/framework/objects/azure_dev_ops_project/schema.go b/pkg/framework/objects/azure_dev_ops_project/schema.go new file mode 100644 index 0000000..a0b7b64 --- /dev/null +++ b/pkg/framework/objects/azure_dev_ops_project/schema.go @@ -0,0 +1,35 @@ +package azure_dev_ops_project + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/datasource" + "github.com/hashicorp/terraform-plugin-framework/datasource/schema" +) + +func (r *azureDevOpsProjectDataSource) Schema( + _ context.Context, + _ datasource.SchemaRequest, + resp *datasource.SchemaResponse, +) { + resp.Schema = schema.Schema{ + Description: `Use this data source to retrieve the ID of an Azure Dev Ops project +based on its name. + +This data source requires connecting with a user token and doesn't work with a service token.`, + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Required: true, + Description: "The internal Azure Dev Ops ID of the ADO Project", + }, + "name": schema.StringAttribute{ + Required: true, + Description: "The name of the ADO project", + }, + "url": schema.StringAttribute{ + Required: true, + Description: "The URL of the ADO project", + }, + }, + } +} diff --git a/pkg/provider/framework_provider.go b/pkg/provider/framework_provider.go index 79e08c3..846ef69 100644 --- a/pkg/provider/framework_provider.go +++ b/pkg/provider/framework_provider.go @@ -2,6 +2,7 @@ package provider import ( "context" + "github.com/dbt-labs/terraform-provider-dbtcloud/pkg/framework/objects/azure_dev_ops_project" "os" "strconv" @@ -181,6 +182,7 @@ func (p *dbtCloudProvider) Configure( func (p *dbtCloudProvider) DataSources(_ context.Context) []func() datasource.DataSource { return []func() datasource.DataSource{ + azure_dev_ops_project.AzureDevOpsProjectDataSource, user.UserDataSource, user.UsersDataSource, notification.NotificationDataSource, diff --git a/pkg/provider/sdk_provider.go b/pkg/provider/sdk_provider.go index dc822a9..801822e 100644 --- a/pkg/provider/sdk_provider.go +++ b/pkg/provider/sdk_provider.go @@ -51,7 +51,6 @@ func SDKProvider(version string) func() *schema.Provider { "dbtcloud_user_groups": data_sources.DatasourceUserGroups(), "dbtcloud_extended_attributes": data_sources.DatasourceExtendedAttributes(), "dbtcloud_group_users": data_sources.DatasourceGroupUsers(), - "dbtcloud_azure_dev_ops_project": data_sources.DatasourceAzureDevOpsProject(), "dbtcloud_azure_dev_ops_repository": data_sources.DatasourceAzureDevOpsRepository(), }, ResourcesMap: map[string]*schema.Resource{ diff --git a/pkg/sdkv2/data_sources/azure_dev_ops_project.go b/pkg/sdkv2/data_sources/azure_dev_ops_project.go deleted file mode 100644 index 015ec2b..0000000 --- a/pkg/sdkv2/data_sources/azure_dev_ops_project.go +++ /dev/null @@ -1,69 +0,0 @@ -package data_sources - -import ( - "context" - - "github.com/dbt-labs/terraform-provider-dbtcloud/pkg/dbt_cloud" - "github.com/hashicorp/terraform-plugin-sdk/v2/diag" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" -) - -var azureDevOpsProjectSchema = map[string]*schema.Schema{ - "id": { - Type: schema.TypeString, - Computed: true, - Description: "The internal Azure Dev Ops ID of the ADO Project", - }, - "name": { - Type: schema.TypeString, - Required: true, - Description: "The name of the ADO project", - }, - "url": { - Type: schema.TypeString, - Computed: true, - Description: "The URL of the ADO project", - }, -} - -func DatasourceAzureDevOpsProject() *schema.Resource { - return &schema.Resource{ - ReadContext: datasourceAzureDevOpsProjectRead, - Schema: azureDevOpsProjectSchema, - Description: `Use this data source to retrieve the ID of an Azure Dev Ops project -based on its name. - -This data source requires connecting with a user token and doesn't work with a service token.`, - } -} - -func datasourceAzureDevOpsProjectRead( - ctx context.Context, - d *schema.ResourceData, - m interface{}, -) diag.Diagnostics { - c := m.(*dbt_cloud.Client) - - var diags diag.Diagnostics - - projectName := d.Get("name").(string) - - azureDevOpsProject, err := c.GetAzureDevOpsProject(projectName) - if err != nil { - return diag.FromErr(err) - } - - if err := d.Set("id", azureDevOpsProject.ID); err != nil { - return diag.FromErr(err) - } - if err := d.Set("name", azureDevOpsProject.Name); err != nil { - return diag.FromErr(err) - } - if err := d.Set("url", azureDevOpsProject.URL); err != nil { - return diag.FromErr(err) - } - - d.SetId(azureDevOpsProject.ID) - - return diags -} From e340fc6bce67f629a23e7445fe0e28fe26c5155c Mon Sep 17 00:00:00 2001 From: Craig Squire <677724+csquire@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:41:54 -0600 Subject: [PATCH 2/7] Fix name and schema --- pkg/framework/objects/azure_dev_ops_project/data_source.go | 3 +-- pkg/framework/objects/azure_dev_ops_project/schema.go | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pkg/framework/objects/azure_dev_ops_project/data_source.go b/pkg/framework/objects/azure_dev_ops_project/data_source.go index 0c25a02..3abfb87 100644 --- a/pkg/framework/objects/azure_dev_ops_project/data_source.go +++ b/pkg/framework/objects/azure_dev_ops_project/data_source.go @@ -3,7 +3,6 @@ package azure_dev_ops_project import ( "context" "fmt" - "github.com/dbt-labs/terraform-provider-dbtcloud/pkg/dbt_cloud" "github.com/hashicorp/terraform-plugin-framework/datasource" "github.com/hashicorp/terraform-plugin-framework/types" @@ -27,7 +26,7 @@ func (d *azureDevOpsProjectDataSource) Metadata( req datasource.MetadataRequest, resp *datasource.MetadataResponse, ) { - resp.TypeName = req.ProviderTypeName + "azure_dev_ops_project" + resp.TypeName = req.ProviderTypeName + "_azure_dev_ops_project" } func (d *azureDevOpsProjectDataSource) Read( diff --git a/pkg/framework/objects/azure_dev_ops_project/schema.go b/pkg/framework/objects/azure_dev_ops_project/schema.go index a0b7b64..ea2996c 100644 --- a/pkg/framework/objects/azure_dev_ops_project/schema.go +++ b/pkg/framework/objects/azure_dev_ops_project/schema.go @@ -19,7 +19,7 @@ based on its name. This data source requires connecting with a user token and doesn't work with a service token.`, Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ - Required: true, + Computed: true, Description: "The internal Azure Dev Ops ID of the ADO Project", }, "name": schema.StringAttribute{ @@ -27,7 +27,7 @@ This data source requires connecting with a user token and doesn't work with a s Description: "The name of the ADO project", }, "url": schema.StringAttribute{ - Required: true, + Computed: true, Description: "The URL of the ADO project", }, }, From 65523ce3048579d7af1e55731f87c5ae00a0305a Mon Sep 17 00:00:00 2001 From: Craig Squire <677724+csquire@users.noreply.github.com> Date: Fri, 6 Dec 2024 09:27:07 -0600 Subject: [PATCH 3/7] Improve checking in Configure method --- .../objects/azure_dev_ops_project/data_source.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/pkg/framework/objects/azure_dev_ops_project/data_source.go b/pkg/framework/objects/azure_dev_ops_project/data_source.go index 3abfb87..5fe0e5b 100644 --- a/pkg/framework/objects/azure_dev_ops_project/data_source.go +++ b/pkg/framework/objects/azure_dev_ops_project/data_source.go @@ -64,11 +64,16 @@ func (d *azureDevOpsProjectDataSource) Read( func (d *azureDevOpsProjectDataSource) Configure( _ context.Context, req datasource.ConfigureRequest, - _ *datasource.ConfigureResponse, + resp *datasource.ConfigureResponse, ) { - if req.ProviderData == nil { - return + switch c := req.ProviderData.(type) { + case nil: // do nothing + case *dbt_cloud.Client: + d.client = c + default: + resp.Diagnostics.AddError( + "Missing client", + "A client is required to configure the Azure DevOps Project data source", + ) } - - d.client = req.ProviderData.(*dbt_cloud.Client) } From b2fd17fa27793f12bc9e9a3307ec9ad50ab61807 Mon Sep 17 00:00:00 2001 From: Craig Squire <677724+csquire@users.noreply.github.com> Date: Wed, 11 Dec 2024 08:58:11 -0600 Subject: [PATCH 4/7] test --- .../data_source_acceptance_test.go | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 pkg/framework/objects/azure_dev_ops_project/data_source_acceptance_test.go diff --git a/pkg/framework/objects/azure_dev_ops_project/data_source_acceptance_test.go b/pkg/framework/objects/azure_dev_ops_project/data_source_acceptance_test.go new file mode 100644 index 0000000..2f2408a --- /dev/null +++ b/pkg/framework/objects/azure_dev_ops_project/data_source_acceptance_test.go @@ -0,0 +1,61 @@ +package azure_dev_ops_project_test + +import ( + "testing" + + "github.com/dbt-labs/terraform-provider-dbtcloud/pkg/framework/acctest_helper" + "github.com/hashicorp/terraform-plugin-testing/config" + "github.com/hashicorp/terraform-plugin-testing/helper/resource" +) + +func TestAccDbtCloudAzureDevOpsProject(t *testing.T) { + if acctest_helper.IsDbtCloudPR() { + t.Skip("Skipping Azure DevOps Project datasource test in CI until a Personal Access Token is available") + } + + adoProjectName := "dbt-cloud-ado-project" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { acctest_helper.TestAccPreCheck(t) }, + + ProtoV6ProviderFactories: acctest_helper.TestAccProtoV6ProviderFactories, + Steps: []resource.TestStep{ + { + ConfigVariables: config.Variables{ + "dbt_token": config.StringVariable("this-will-come-from-somewhere-else-eventually"), // Cannot be a Service Token + "ado_project_name": config.StringVariable(adoProjectName), + }, + Config: ` + variable "dbt_token" { + type = string + sensitive = true + } + + provider "dbtcloud" { + token = var.dbt_token + } + + variable "ado_project_name" { + type = string + } + + data dbtcloud_azure_dev_ops_project test { + name = var.ado_project_name + } + `, + // we check the computed values, for the other ones the test suite already checks that the plan and state are the same + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet( + "data.dbtcloud_azure_dev_ops_project.test", + "id", + ), + resource.TestCheckResourceAttrSet( + "data.dbtcloud_azure_dev_ops_project.test", + "url", + ), + ), + }, + }, + }) + +} From d2dc5c20573209edec6dffbb1baa89e99999b627 Mon Sep 17 00:00:00 2001 From: Craig Squire <677724+csquire@users.noreply.github.com> Date: Wed, 11 Dec 2024 10:48:34 -0600 Subject: [PATCH 5/7] Add acceptance test --- .../azure_dev_ops_project/data_source_acceptance_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/framework/objects/azure_dev_ops_project/data_source_acceptance_test.go b/pkg/framework/objects/azure_dev_ops_project/data_source_acceptance_test.go index 2f2408a..c3ce28e 100644 --- a/pkg/framework/objects/azure_dev_ops_project/data_source_acceptance_test.go +++ b/pkg/framework/objects/azure_dev_ops_project/data_source_acceptance_test.go @@ -1,6 +1,7 @@ package azure_dev_ops_project_test import ( + "os" "testing" "github.com/dbt-labs/terraform-provider-dbtcloud/pkg/framework/acctest_helper" @@ -13,7 +14,9 @@ func TestAccDbtCloudAzureDevOpsProject(t *testing.T) { t.Skip("Skipping Azure DevOps Project datasource test in CI until a Personal Access Token is available") } + //TODO: Parameterize these values when a standard method is available for parameterization adoProjectName := "dbt-cloud-ado-project" + personalAccessToken := os.Getenv("DBT_CLOUD_PERSONAL_ACCESS_TOKEN") resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { acctest_helper.TestAccPreCheck(t) }, @@ -22,7 +25,7 @@ func TestAccDbtCloudAzureDevOpsProject(t *testing.T) { Steps: []resource.TestStep{ { ConfigVariables: config.Variables{ - "dbt_token": config.StringVariable("this-will-come-from-somewhere-else-eventually"), // Cannot be a Service Token + "dbt_token": config.StringVariable(personalAccessToken), "ado_project_name": config.StringVariable(adoProjectName), }, Config: ` From 532b0709558b5b624f70a1e52f75ee134a894641 Mon Sep 17 00:00:00 2001 From: Craig Squire <677724+csquire@users.noreply.github.com> Date: Wed, 11 Dec 2024 10:59:11 -0600 Subject: [PATCH 6/7] Skip azure devops project test for real --- .../azure_dev_ops_project/data_source_acceptance_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/framework/objects/azure_dev_ops_project/data_source_acceptance_test.go b/pkg/framework/objects/azure_dev_ops_project/data_source_acceptance_test.go index c3ce28e..3841866 100644 --- a/pkg/framework/objects/azure_dev_ops_project/data_source_acceptance_test.go +++ b/pkg/framework/objects/azure_dev_ops_project/data_source_acceptance_test.go @@ -10,8 +10,9 @@ import ( ) func TestAccDbtCloudAzureDevOpsProject(t *testing.T) { - if acctest_helper.IsDbtCloudPR() { - t.Skip("Skipping Azure DevOps Project datasource test in CI until a Personal Access Token is available") + if os.Getenv("CI") != "" { + t.Skip("Skipping Azure DevOps Project datasource test in CI " + + "until Azure integration and a personal access token are available") } //TODO: Parameterize these values when a standard method is available for parameterization From 99f58ad40aeb51e6a8beee4665a858c726f624f8 Mon Sep 17 00:00:00 2001 From: Craig Squire <677724+csquire@users.noreply.github.com> Date: Wed, 11 Dec 2024 11:43:38 -0600 Subject: [PATCH 7/7] Skip azure devops project test when no PAT is available --- .../azure_dev_ops_project/data_source_acceptance_test.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/framework/objects/azure_dev_ops_project/data_source_acceptance_test.go b/pkg/framework/objects/azure_dev_ops_project/data_source_acceptance_test.go index 3841866..6e9b931 100644 --- a/pkg/framework/objects/azure_dev_ops_project/data_source_acceptance_test.go +++ b/pkg/framework/objects/azure_dev_ops_project/data_source_acceptance_test.go @@ -10,11 +10,16 @@ import ( ) func TestAccDbtCloudAzureDevOpsProject(t *testing.T) { + //TODO: Remove both env var checks when this gets configurted in CI and the variables are parameterized if os.Getenv("CI") != "" { t.Skip("Skipping Azure DevOps Project datasource test in CI " + "until Azure integration and a personal access token are available") } + if os.Getenv("DBT_CLOUD_PERSONAL_ACCESS_TOKEN") == "" { + t.Skip("Skipping Azure DevOps Project datasource because no personal access token is available") + } + //TODO: Parameterize these values when a standard method is available for parameterization adoProjectName := "dbt-cloud-ado-project" personalAccessToken := os.Getenv("DBT_CLOUD_PERSONAL_ACCESS_TOKEN")