Skip to content

Commit

Permalink
adjust bitbucket datacenter resource to recent changes
Browse files Browse the repository at this point in the history
  • Loading branch information
truszkowski committed Mar 1, 2024
1 parent 832e2bd commit 0840634
Show file tree
Hide file tree
Showing 8 changed files with 237 additions and 37 deletions.
1 change: 1 addition & 0 deletions .github/workflows/test-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ jobs:
SPACELIFT_PROVIDER_TEST_SOURCECODE_BITBUCKETDATACENTER_SPACELEVEL_APIHOST: ${{ secrets.COMMON_SPACELIFT_PROVIDER_TEST_SOURCECODE_BITBUCKETDATACENTER_APIHOST }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_BITBUCKETDATACENTER_SPACELEVEL_WEBHOOKSECRET: ${{ secrets.PROD_SPACELIFT_PROVIDER_TEST_SOURCECODE_BITBUCKETDATACENTER_SPACELEVEL_WEBHOOKSECRET }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_BITBUCKETDATACENTER_SPACELEVEL_WEBHOOKURL: ${{ secrets.PROD_SPACELIFT_PROVIDER_TEST_SOURCECODE_BITBUCKETDATACENTER_SPACELEVEL_WEBHOOKURL }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_BITBUCKETDATACENTER_SPACELEVEL_ACCESSTOKEN: ${{ secrets.COMMON_SPACELIFT_PROVIDER_TEST_SOURCECODE_BITBUCKETDATACENTER_ACCESSTOKEN }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITHUBENTERPRISE_DEFAULT_NAME: "GitHub Default"
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITHUBENTERPRISE_DEFAULT_ID: "github-default"
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITHUBENTERPRISE_DEFAULT_APIHOST: ${{ secrets.COMMON_SPACELIFT_PROVIDER_TEST_SOURCECODE_GITHUBENTERPRISE_APIHOST }}
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ jobs:
SPACELIFT_PROVIDER_TEST_SOURCECODE_BITBUCKETDATACENTER_SPACELEVEL_APIHOST: ${{ secrets.COMMON_SPACELIFT_PROVIDER_TEST_SOURCECODE_BITBUCKETDATACENTER_APIHOST }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_BITBUCKETDATACENTER_SPACELEVEL_WEBHOOKSECRET: ${{ secrets.PREPROD_SPACELIFT_PROVIDER_TEST_SOURCECODE_BITBUCKETDATACENTER_SPACELEVEL_WEBHOOKSECRET }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_BITBUCKETDATACENTER_SPACELEVEL_WEBHOOKURL: ${{ secrets.PREPROD_SPACELIFT_PROVIDER_TEST_SOURCECODE_BITBUCKETDATACENTER_SPACELEVEL_WEBHOOKURL }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_BITBUCKETDATACENTER_SPACELEVEL_ACCESSTOKEN: ${{ secrets.COMMON_SPACELIFT_PROVIDER_TEST_SOURCECODE_BITBUCKETDATACENTER_ACCESSTOKEN }}
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITHUBENTERPRISE_DEFAULT_NAME: "GitHub Default"
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITHUBENTERPRISE_DEFAULT_ID: "github-default"
SPACELIFT_PROVIDER_TEST_SOURCECODE_GITHUBENTERPRISE_DEFAULT_APIHOST: ${{ secrets.COMMON_SPACELIFT_PROVIDER_TEST_SOURCECODE_GITHUBENTERPRISE_APIHOST }}
Expand Down
10 changes: 9 additions & 1 deletion docs/resources/bitbucket_datacenter_integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,20 @@ resource "spacelift_bitbucket_datacenter_integration" "example" {

- `access_token` (String, Sensitive) User access token from Bitbucket
- `api_host` (String) The API host where requests will be sent
- `is_default` (Boolean) Bitbucket Datacenter integration is default.
- `name` (String) Bitbucket Datacenter integration name
- `user_facing_host` (String) User Facing Host which will be user for all user-facing URLs displayed in the Spacelift UI
- `username` (String) Username which will be used to authenticate requests for cloning repositories

### Optional

- `description` (String) Bitbucket Datacenter integration description
- `labels` (List of String) Bitbucket Datacenter integration labels
- `space_id` (String) Bitbucket Datacenter integration space id. Defaults to `root`.

### Read-Only

- `id` (String) The ID of this resource.
- `id` (String) Bitbucket Datacenter integration id.
- `webhook_secret` (String, Sensitive) Secret for webhooks originating from Bitbucket repositories
- `webhook_url` (String) URL for webhooks originating from Bitbucket repositories

Expand Down
1 change: 1 addition & 0 deletions spacelift/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ var testConfig struct {
APIHost string
WebhookSecret string
WebhookURL string
AccessToken string
}
Repository struct {
Name string
Expand Down
39 changes: 32 additions & 7 deletions spacelift/internal/structs/bitbucket_datacenter_integration.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,37 @@
package structs

import "github.com/shurcooL/graphql"

// BitbucketDatacenterIntegration represents the bitbucket datacenter integration data relevant to the provider.
type BitbucketDatacenterIntegration struct {
Id string `graphql:"id"`
Name string `graphql:"name"`
APIHost string `graphql:"apiHost"`
Username string `graphql:"username"`
UserFacingHost string `graphql:"userFacingHost"`
WebhookSecret string `graphql:"webhookSecret"`
WebhookURL string `graphql:"webhookURL"`
ID string `graphql:"id"`
Name string `graphql:"name"`
IsDefault bool `graphql:"isDefault"`
Space struct {
ID string `graphql:"id"`
} `graphql:"space"`
Labels []string `graphql:"labels"`
Description *string `graphql:"description"`
APIHost string `graphql:"apiHost"`
Username string `graphql:"username"`
UserFacingHost string `graphql:"userFacingHost"`
WebhookSecret string `graphql:"webhookSecret"`
WebhookURL string `graphql:"webhookURL"`
}

// CustomVCSInput represents the custom VCS input data.
type CustomVCSInput struct {
Name graphql.String `json:"name"`
SpaceID graphql.ID `json:"spaceID"`
Labels *[]graphql.String `json:"labels"`
Description *graphql.String `json:"description"`
IsDefault *graphql.Boolean `json:"isDefault"`
}

// CustomVCSUpdateInput represents the custom VCS update input data.
type CustomVCSUpdateInput struct {
ID graphql.ID `json:"id"`
SpaceID graphql.ID `json:"space"`
Labels *[]graphql.String `json:"labels"`
Description *graphql.String `json:"description"`
}
85 changes: 74 additions & 11 deletions spacelift/resource_bitbucket_datacenter_integration.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (

"github.com/spacelift-io/terraform-provider-spacelift/spacelift/internal"
"github.com/spacelift-io/terraform-provider-spacelift/spacelift/internal/structs"
"github.com/spacelift-io/terraform-provider-spacelift/spacelift/internal/validations"
)

const (
Expand All @@ -24,6 +25,43 @@ func resourceBitbucketDatacenterIntegration() *schema.Resource {
DeleteContext: resourceBitbucketDatacenterIntegrationDelete,

Schema: map[string]*schema.Schema{
bitbucketDatacenterID: {
Type: schema.TypeString,
Description: "Bitbucket Datacenter integration id.",
Computed: true,
},
bitbucketDatacenterName: {
Type: schema.TypeString,
Description: "Bitbucket Datacenter integration name",
Required: true,
},
bitbucketDatacenterIsDefault: {
Type: schema.TypeBool,
Description: "Bitbucket Datacenter integration is default.",
Required: true,
},
bitbucketDatacenterSpaceID: {
Type: schema.TypeString,
Description: "Bitbucket Datacenter integration space id. Defaults to `root`.",
Optional: true,
Computed: true,
},
bitbucketDatacenterLabels: {
Type: schema.TypeSet,
Elem: &schema.Schema{
Type: schema.TypeString,
ValidateDiagFunc: validations.DisallowEmptyString,
},
Description: "Bitbucket Datacenter integration labels",
Optional: true,
Computed: true,
},
bitbucketDatacenterDescription: {
Type: schema.TypeString,
Description: "Bitbucket Datacenter integration description",
Optional: true,
Computed: true,
},
bitbucketDatacenterAPIHost: {
Type: schema.TypeString,
Description: "The API host where requests will be sent",
Expand Down Expand Up @@ -62,13 +100,20 @@ func resourceBitbucketDatacenterIntegration() *schema.Resource {

func resourceBitbucketDatacenterIntegrationCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var mutation struct {
CreateBitbucketDatacenterIntegration structs.BitbucketDatacenterIntegration `graphql:"bitbucketDatacenterIntegrationCreate(apiHost: $apiHost, userFacingHost: $userFacingHost, username: $username, accessToken: $accessToken)"`
CreateBitbucketDatacenterIntegration structs.BitbucketDatacenterIntegration `graphql:"bitbucketDatacenterIntegrationCreate(apiHost: $apiHost, userFacingHost: $userFacingHost, username: $username, accessToken: $accessToken, customInput: $customInput)"`
}

variables := map[string]interface{}{
"customInput": &structs.CustomVCSInput{
Name: toString(d.Get(bitbucketDatacenterName)),
IsDefault: toOptionalBool(d.Get(bitbucketDatacenterIsDefault)),
SpaceID: toString(d.Get(bitbucketDatacenterSpaceID)),
Labels: toOptionalStringList(d.Get(bitbucketDatacenterLabels)),
Description: toOptionalString(d.Get(bitbucketDatacenterDescription)),
},
"apiHost": toString(d.Get(bitbucketDatacenterAPIHost)),
"userFacingHost": toString(d.Get(bitbucketDatacenterUserFacingHost)),
"username": toString(d.Get(bitbucketDatacenterUsername)),
"username": toOptionalString(d.Get(bitbucketDatacenterUsername)),
"accessToken": toString(d.Get(bitbucketDatacenterAccessToken)),
}

Expand All @@ -83,10 +128,10 @@ func resourceBitbucketDatacenterIntegrationCreate(ctx context.Context, d *schema

func resourceBitbucketDatacenterIntegrationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var query struct {
BitbucketDatacenterIntegration *structs.BitbucketDatacenterIntegration `graphql:"bitbucketDatacenterIntegration"`
BitbucketDatacenterIntegration *structs.BitbucketDatacenterIntegration `graphql:"bitbucketDatacenterIntegration(id: $id)"`
}

variables := map[string]interface{}{}
variables := map[string]interface{}{"id": d.Id()}
if err := meta.(*internal.Client).Query(ctx, "BitbucketDatacenterIntegrationRead", &query, variables); err != nil {
return diag.Errorf("could not query for the bitbucket datacenter integration: %v", err)
}
Expand All @@ -102,14 +147,20 @@ func resourceBitbucketDatacenterIntegrationRead(ctx context.Context, d *schema.R

func resourceBitbucketDatacenterIntegrationUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var mutation struct {
UpdateBitbucketDatacenterIntegration structs.BitbucketDatacenterIntegration `graphql:"bitbucketDatacenterIntegrationUpdate(apiHost: $apiHost, userFacingHost: $userFacingHost, username: $username, accessToken: $accessToken)"`
UpdateBitbucketDatacenterIntegration structs.BitbucketDatacenterIntegration `graphql:"bitbucketDatacenterIntegrationUpdate(apiHost: $apiHost, userFacingHost: $userFacingHost, username: $username, accessToken: $accessToken, customInput: $customInput)"`
}

variables := map[string]interface{}{
"apiHost": toString(d.Get(bitbucketDatacenterAPIHost)),
"userFacingHost": toString(d.Get(bitbucketDatacenterUserFacingHost)),
"username": toString(d.Get(bitbucketDatacenterUsername)),
"accessToken": toString(d.Get(bitbucketDatacenterAccessToken)),
"username": toOptionalString(d.Get(bitbucketDatacenterUsername)),
"accessToken": toOptionalString(d.Get(bitbucketDatacenterAccessToken)),
"customInput": &structs.CustomVCSUpdateInput{
ID: toID(d.Id()),
SpaceID: toString(d.Get(bitbucketDatacenterSpaceID)),
Description: toOptionalString(d.Get(bitbucketDatacenterDescription)),
Labels: toOptionalStringList(d.Get(bitbucketDatacenterLabels)),
},
}

var ret diag.Diagnostics
Expand All @@ -125,10 +176,12 @@ func resourceBitbucketDatacenterIntegrationUpdate(ctx context.Context, d *schema

func resourceBitbucketDatacenterIntegrationDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
var mutation struct {
DeleteBitbucketDatacenterIntegration *structs.BitbucketDatacenterIntegration `graphql:"bitbucketDatacenterIntegrationDelete"`
DeleteBitbucketDatacenterIntegration *structs.BitbucketDatacenterIntegration `graphql:"bitbucketDatacenterIntegrationDelete(id: $id)"`
}

variables := map[string]interface{}{}
variables := map[string]interface{}{
"id": toID(d.Id()),
}

if err := meta.(*internal.Client).Mutate(ctx, "BitbucketDatacenterIntegrationDelete", &mutation, variables); err != nil {
return diag.Errorf("could not delete bitbucket datacenter integration: %v", internal.FromSpaceliftError(err))
Expand All @@ -140,11 +193,21 @@ func resourceBitbucketDatacenterIntegrationDelete(ctx context.Context, d *schema
}

func fillResults(d *schema.ResourceData, bitbucketDatacenterIntegration *structs.BitbucketDatacenterIntegration) {
d.SetId("spacelift_bitbucket_datacenter_integration_id")
// Note: the access token is not exposed in the API.
d.SetId(bitbucketDatacenterIntegration.ID)
d.Set(bitbucketDatacenterAPIHost, bitbucketDatacenterIntegration.APIHost)
d.Set(bitbucketDatacenterUsername, bitbucketDatacenterIntegration.Username)
d.Set(bitbucketDatacenterUserFacingHost, bitbucketDatacenterIntegration.UserFacingHost)
d.Set(bitbucketDatacenterWebhookURL, bitbucketDatacenterIntegration.WebhookURL)
d.Set(bitbucketDatacenterWebhookSecret, bitbucketDatacenterIntegration.WebhookSecret)
// Note: the access token is not exposed in the API.
d.Set(bitbucketDatacenterIsDefault, bitbucketDatacenterIntegration.IsDefault)
d.Set(bitbucketDatacenterSpaceID, bitbucketDatacenterIntegration.Space.ID)
d.Set(bitbucketDatacenterName, bitbucketDatacenterIntegration.Name)
d.Set(bitbucketDatacenterDescription, bitbucketDatacenterIntegration.Description)

labels := schema.NewSet(schema.HashString, []interface{}{})
for _, label := range bitbucketDatacenterIntegration.Labels {
labels.Add(label)
}
d.Set(bitbucketDatacenterLabels, labels)
}
116 changes: 99 additions & 17 deletions spacelift/resource_bitbucket_datacenter_integration_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package spacelift

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
Expand All @@ -14,39 +13,122 @@ func TestBitbucketDatacenterIntegrationResource(t *testing.T) {
const resourceName = "spacelift_bitbucket_datacenter_integration.test"

t.Run("creates and updates a bitbucket datacenter integration without an error", func(t *testing.T) {
randomChars := acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum)
random := func() string { return acctest.RandStringFromCharSet(5, acctest.CharSetAlphaNum) }

config := func(apiHost, userFacingHost, username, accessToken string) string {
return fmt.Sprintf(`
var (
name = "my-test-bitbucket-datacenter-integration-" + random()
host = "https://bitbucket.com/" + random()
token = "access-" + random()
descr = "description " + random()
labels = `["label1", "label2"]`
)

configBitbucket := func(user, host, token, descr, labels string) string {
return `
resource "spacelift_bitbucket_datacenter_integration" "test" {
api_host = "%s"
user_facing_host = "%s"
username = "%s"
access_token = "access-%s"
name = "` + name + `"
is_default = false
space_id = "root"
api_host = "` + host + `"
user_facing_host = "` + host + `"
username = "` + user + `"
access_token = "` + token + `"
description = "` + descr + `"
labels = ` + labels + `
}
`, apiHost, userFacingHost, username, accessToken)
`
}

configStack := func() string {
return `
resource "spacelift_worker_pool" "test" {
name = "Let's create a dummy worker pool to avoid running the job ` + name + `"
space_id = "` + testConfig.SourceCode.BitbucketDatacenter.SpaceLevel.Space + `"
}
resource "spacelift_stack" "test" {
name = "stack-for-` + name + `"
repository = "` + testConfig.SourceCode.BitbucketDatacenter.Repository.Name + `"
branch = "` + testConfig.SourceCode.BitbucketDatacenter.Repository.Branch + `"
space_id = "` + testConfig.SourceCode.BitbucketDatacenter.SpaceLevel.Space + `"
administrative = false
worker_pool_id = spacelift_worker_pool.test.id
bitbucket_datacenter {
namespace = "` + testConfig.SourceCode.BitbucketDatacenter.Repository.Namespace + `"
id = spacelift_bitbucket_datacenter_integration.test.id
}
}
`
}

configRun := func() string {
return `
resource "spacelift_run" "test" {
stack_id = spacelift_stack.test.id
keepers = { "branch" = "` + testConfig.SourceCode.BitbucketDatacenter.Repository.Branch + `" }
}
`
}

spaceLevel := testConfig.SourceCode.BitbucketDatacenter.SpaceLevel

testSteps(t, []resource.TestStep{
{
Config: config("https://bitbucket.com/new-"+randomChars, "https://bitbucket.com/new-"+randomChars, "userName", randomChars),
Config: configBitbucket("username", host, token, descr, "null"),
Check: Resource(
resourceName,
Attribute("id", IsNotEmpty()),
Attribute("api_host", StartsWith("https://bitbucket.com")),
Attribute("user_facing_host", StartsWith("https://bitbucket.com")),
Attribute("username", StartsWith("userName")),
Attribute("access_token", StartsWith("access-")),
Attribute("id", Equals(name)),
Attribute("api_host", Equals(host)),
Attribute("user_facing_host", Equals(host)),
Attribute("username", Equals("username")),
Attribute("access_token", Equals(token)),
Attribute("webhook_url", IsNotEmpty()),
Attribute("webhook_secret", IsNotEmpty()),
Attribute("is_default", Equals("false")),
Attribute("description", Equals(descr)),
Attribute("labels.#", Equals("0")),
),
},
{
Config: config("https://bitbucket.com/new-"+randomChars, "https://bitbucket.com/new-"+randomChars, "newUserName", randomChars),
Config: configBitbucket("newUserName", host, token, "new descr", `["new label1"]`),
Check: Resource(
resourceName,
Attribute("user_facing_host", StartsWith("https://bitbucket.com/new")),
Attribute("api_host", Equals(host)),
Attribute("user_facing_host", Equals(host)),
Attribute("is_default", Equals("false")),
Attribute("username", Equals("newUserName")),
Attribute("description", Equals("new descr")),
Attribute("labels.#", Equals("1")),
Attribute("labels.0", Equals("new label1")),
),
},
{
Config: configBitbucket(spaceLevel.Username, spaceLevel.APIHost, spaceLevel.AccessToken, descr, labels),
Check: Resource(
resourceName,
Attribute("api_host", Equals(spaceLevel.APIHost)),
Attribute("user_facing_host", Equals(spaceLevel.APIHost)),
Attribute("is_default", Equals("false")),
Attribute("username", Equals(spaceLevel.Username)),
Attribute("description", Equals(descr)),
Attribute("labels.#", Equals("2")),
Attribute("labels.0", Equals("label1")),
Attribute("labels.1", Equals("label2")),
),
},
{
Config: configBitbucket(spaceLevel.Username, spaceLevel.APIHost, spaceLevel.AccessToken, descr, labels) + configStack(),
Check: Resource(
"spacelift_stack.test",
Attribute("bitbucket_datacenter.0.id", Equals(name)),
),
},
{
Config: configBitbucket(spaceLevel.Username, spaceLevel.APIHost, spaceLevel.AccessToken, descr, labels) + configStack() + configRun(),
Check: Resource(
"spacelift_run.test",
Attribute("id", IsNotEmpty()),
Attribute("stack_id", Equals("stack-for-"+name)),
),
},
})
Expand Down
Loading

0 comments on commit 0840634

Please sign in to comment.