From e28d62283026ee19a020b7a52bc90ea7d2910860 Mon Sep 17 00:00:00 2001 From: Daniel Hilgarth Date: Sat, 20 May 2023 23:54:30 +0200 Subject: [PATCH 1/2] feat: Allow getting deployment environment by name --- bitbucket/data_source_bitbucket_deployment.go | 16 +++--- .../data_source_bitbucket_deployment_test.go | 45 +++++++++++++++- bitbucket/resource_bitbucket_deployment.go | 52 +++++++++++++++++++ docs/data-sources/bitbucket_deployment.md | 20 ++++++- 4 files changed, 123 insertions(+), 10 deletions(-) diff --git a/bitbucket/data_source_bitbucket_deployment.go b/bitbucket/data_source_bitbucket_deployment.go index e348727..634e54b 100644 --- a/bitbucket/data_source_bitbucket_deployment.go +++ b/bitbucket/data_source_bitbucket_deployment.go @@ -6,12 +6,19 @@ import ( func dataSourceBitbucketDeployment() *schema.Resource { return &schema.Resource{ - ReadContext: resourceBitbucketDeploymentRead, + ReadContext: resourceBitbucketDeploymentReadByNameOrId, Schema: map[string]*schema.Schema{ "id": { Description: "The ID of the deployment.", Type: schema.TypeString, - Required: true, + Optional: true, + Computed: true, + }, + "name": { + Description: "The name of the deployment environment.", + Type: schema.TypeString, + Optional: true, + Computed: true, }, "workspace": { Description: "The slug or UUID (including the enclosing `{}`) of the workspace.", @@ -24,11 +31,6 @@ func dataSourceBitbucketDeployment() *schema.Resource { Required: true, ValidateDiagFunc: validateRepositoryName, }, - "name": { - Description: "The name of the deployment environment.", - Type: schema.TypeString, - Computed: true, - }, "environment": { Description: "The environment of the deployment (will be one of 'Test', 'Staging', or 'Production').", Type: schema.TypeString, diff --git a/bitbucket/data_source_bitbucket_deployment_test.go b/bitbucket/data_source_bitbucket_deployment_test.go index ab9267e..4cf9378 100644 --- a/bitbucket/data_source_bitbucket_deployment_test.go +++ b/bitbucket/data_source_bitbucket_deployment_test.go @@ -103,6 +103,47 @@ func TestAccBitbucketDeploymentDataSource_basic(t *testing.T) { resource.TestCheckResourceAttrSet("data.bitbucket_deployment.testacc", "id"), ), }, + { + Config: fmt.Sprintf(` + data "bitbucket_workspace" "testacc" { + id = "%s" + } + + resource "bitbucket_project" "testacc" { + workspace = data.bitbucket_workspace.testacc.id + name = "%s" + key = "%s" + is_private = true + } + + resource "bitbucket_repository" "testacc" { + workspace = data.bitbucket_workspace.testacc.id + project_key = bitbucket_project.testacc.key + name = "%s" + enable_pipelines = true + } + + resource "bitbucket_deployment" "testacc" { + workspace = data.bitbucket_workspace.testacc.id + repository = bitbucket_repository.testacc.name + name = "%s" + environment = "Production" + } + + data "bitbucket_deployment" "testacc" { + id = bitbucket_deployment.testacc.id + workspace = data.bitbucket_workspace.testacc.id + repository = bitbucket_repository.testacc.name + }`, workspaceSlug, projectName, projectKey, repoName, deploymentName), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.bitbucket_deployment.testacc", "workspace", workspaceSlug), + resource.TestCheckResourceAttr("data.bitbucket_deployment.testacc", "repository", repoName), + resource.TestCheckResourceAttr("data.bitbucket_deployment.testacc", "name", deploymentName), + resource.TestCheckResourceAttr("data.bitbucket_deployment.testacc", "environment", "Production"), + + resource.TestCheckResourceAttrSet("data.bitbucket_deployment.testacc", "id"), + ), + }, { Config: fmt.Sprintf(` data "bitbucket_workspace" "testacc" { @@ -131,10 +172,10 @@ func TestAccBitbucketDeploymentDataSource_basic(t *testing.T) { } data "bitbucket_deployment" "testacc" { - id = bitbucket_deployment.testacc.id + name = "%s" workspace = data.bitbucket_workspace.testacc.id repository = bitbucket_repository.testacc.name - }`, workspaceSlug, projectName, projectKey, repoName, deploymentName), + }`, workspaceSlug, projectName, projectKey, repoName, deploymentName, deploymentName), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("data.bitbucket_deployment.testacc", "workspace", workspaceSlug), resource.TestCheckResourceAttr("data.bitbucket_deployment.testacc", "repository", repoName), diff --git a/bitbucket/resource_bitbucket_deployment.go b/bitbucket/resource_bitbucket_deployment.go index 49e998f..fde98f2 100644 --- a/bitbucket/resource_bitbucket_deployment.go +++ b/bitbucket/resource_bitbucket_deployment.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "strings" + "time" "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" @@ -103,6 +104,57 @@ func resourceBitbucketDeploymentRead(ctx context.Context, resourceData *schema.R return nil } +func resourceBitbucketDeploymentReadByNameOrId(ctx context.Context, resourceData *schema.ResourceData, meta interface{}) diag.Diagnostics { + id := resourceData.Get("id") + if id != nil && id != "" { + return resourceBitbucketDeploymentRead(ctx, resourceData, meta) + } + + name := resourceData.Get("name") + if name != nil && name != "" { + return resourceBitbucketDeploymentReadByName(ctx, resourceData, meta) + } + + return diag.Errorf("Either name or id must be provided") +} + +func resourceBitbucketDeploymentReadByName(ctx context.Context, resourceData *schema.ResourceData, meta interface{}) diag.Diagnostics { + // Artificial sleep due to Bitbucket's API taking time to return newly created deployments + time.Sleep(3 * time.Second) + + client := meta.(*Clients).V2 + + deployments, err := client.Repositories.Repository.ListEnvironments( + &gobb.RepositoryEnvironmentsOptions{ + Owner: resourceData.Get("workspace").(string), + RepoSlug: resourceData.Get("repository").(string), + }, + ) + if err != nil { + return diag.FromErr(fmt.Errorf("unable to get deployment variable with error: %s", err)) + } + + name := resourceData.Get("name") + + var deployment *gobb.Environment + for _, item := range deployments.Environments { + if item.Name == name.(string) { + deployment = &item + break + } + } + + if deployment == nil { + return diag.FromErr(errors.New("unable to get deployment, Bitbucket API did not return it")) + } + + _ = resourceData.Set("name", deployment.Name) + _ = resourceData.Set("environment", gobb.RepositoryEnvironmentTypeOption(deployment.Rank).String()) + resourceData.SetId(deployment.Uuid) + + return nil +} + func resourceBitbucketDeploymentDelete(ctx context.Context, resourceData *schema.ResourceData, meta interface{}) diag.Diagnostics { client := meta.(*Clients).V2 diff --git a/docs/data-sources/bitbucket_deployment.md b/docs/data-sources/bitbucket_deployment.md index 400afb3..e8ac819 100644 --- a/docs/data-sources/bitbucket_deployment.md +++ b/docs/data-sources/bitbucket_deployment.md @@ -16,14 +16,32 @@ data "bitbucket_deployment" "example" { repository = "example-repo" } ``` +```hcl +data "bitbucket_deployment" "example" { + name = "deployment-name" + workspace = "workspace-slug" + repository = "example-repo" +} +``` +```hcl +data "bitbucket_deployment" "example" { + name = "deployment-name" + workspace = "{workspace-uuid}" + repository = "example-repo" +} +``` ## Argument Reference The following arguments are supported: -* `id` - (Required) The ID of the deployment. +* `id` - (Optional) The ID of the deployment. +* `name` - (Optional) The name of the deployment. +~> **NOTE:** Either `id` or `name` must be set. If both are set, `name` will be ignored. * `workspace` - (Required) The slug or UUID (including the enclosing `{}`) of the workspace. * `repository` - (Required) The name of the repository (must consist of only lowercase ASCII letters, numbers, underscores, hyphens and periods). + ## Attribute Reference In addition to the arguments above, the following additional attributes are exported: +* `id` - The ID of the deployment environment. * `name` - The name of the deployment environment. * `environment` - The environment of the deployment (will be one of 'Test', 'Staging', or 'Production'). From 862c70efbb4223436f822443483bf1f6df1b0714 Mon Sep 17 00:00:00 2001 From: Daniel Hilgarth Date: Sun, 21 May 2023 00:02:27 +0200 Subject: [PATCH 2/2] fix: Check for deployment name case insensitive --- bitbucket/resource_bitbucket_deployment.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bitbucket/resource_bitbucket_deployment.go b/bitbucket/resource_bitbucket_deployment.go index fde98f2..26224f3 100644 --- a/bitbucket/resource_bitbucket_deployment.go +++ b/bitbucket/resource_bitbucket_deployment.go @@ -134,11 +134,11 @@ func resourceBitbucketDeploymentReadByName(ctx context.Context, resourceData *sc return diag.FromErr(fmt.Errorf("unable to get deployment variable with error: %s", err)) } - name := resourceData.Get("name") + name := resourceData.Get("name").(string) var deployment *gobb.Environment for _, item := range deployments.Environments { - if item.Name == name.(string) { + if strings.EqualFold(item.Name, name) { deployment = &item break }