From b3ee8fd46c69be05e85837432dd01dfda80a3e55 Mon Sep 17 00:00:00 2001 From: Justin To Date: Mon, 6 Jul 2020 13:35:11 -0400 Subject: [PATCH 1/2] * Added a flag to specify whether to import groups that already exist in bitbucket along with functionality to import those groups into the terraform state * Changed the error checking when importing an existing group for bitbucket so that the duplicate group error is not thrown * Added two acceptance tests * Updated the ReadMe.md with accurate instructions since the previous ones were not working for us * Updated the Makefile to set the maximum number of files allowed to be open to 1024 since 256 was too few. We called `ulimit -n 1024` to do this for the testacc and testacc-bitbucket targets. * Changed the start-docker-compose.sh to use the bitbucket server environment variable so that it doesn't always refer to localhost * Skipped some testcases that are consistently failing in master branch * Added a version.env file to be used to control the versioning from CICD builds * Set version to 1.4.0 * In the start-docker-compose.sh if the BITBUCKET_SERVER environment variable is not set then use http://localhost:7990 In the start-docker-compose.sh if the BITBUCKET_SERVER environment variable is not set then use http://localhost:7990 --- Makefile | 10 ++- README.md | 35 ++--------- bitbucket/data_plugin_test.go | 1 + bitbucket/resource_group.go | 28 ++++++++- bitbucket/resource_group_test.go | 77 ++++++++++++++++++++++++ bitbucket/resource_plugin_config_test.go | 1 + bitbucket/resource_plugin_test.go | 1 + scripts/start-docker-compose.sh | 3 +- version.env | 10 +++ 9 files changed, 131 insertions(+), 35 deletions(-) create mode 100644 version.env diff --git a/Makefile b/Makefile index 03b3cac..397b571 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ export GO111MODULE=on export TESTARGS=-race -coverprofile=coverage.txt -covermode=atomic -export BITBUCKET_SERVER=http://localhost:7990 +export BITBUCKET_SERVER?=http://localhost:7990 export BITBUCKET_USERNAME=admin export BITBUCKET_PASSWORD=admin @@ -20,11 +20,15 @@ test: fmtcheck xargs -t -n4 go test $(TESTARGS) -timeout=30s -parallel=4 testacc: fmtcheck - TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 120m -count=1 + #The ulimit command is required to allow the tests to open more than the default 256 files as set on MacOS. The tests will fail without this. It must be done as one + #command otherwise the setting is lost + ulimit -n 1024; TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 120m -count=1 testacc-bitbucket: fmtcheck @sh scripts/start-docker-compose.sh - TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 120m -count=1 + #The ulimit command is required to allow the tests to open more than the default 256 files as set on MacOS. The tests will fail without this. It must be done as one + #command otherwise the setting is lost + ulimit -n 1024; TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 120m -count=1 @sh scripts/stop-docker-compose.sh vet: diff --git a/README.md b/README.md index b54260a..d3042eb 100644 --- a/README.md +++ b/README.md @@ -45,34 +45,13 @@ See [User Guide](https://gavinbunney.github.io/terraform-provider-bitbucketserve - [Terraform](https://www.terraform.io/downloads.html) 0.12.x - [Go](https://golang.org/doc/install) 1.11 (to build the provider plugin) -### Building The Provider - -Clone repository to: `$GOPATH/src/github.com/gavinbunney/terraform-provider-bitbucketserver` - -```sh -$ mkdir -p $GOPATH/src/github.com/terraform-providers; cd $GOPATH/src/github.com/terraform-providers -$ git clone git@github.com:gavinbunney/terraform-provider-bitbucketserver -``` - -Enter the provider directory and build the provider - -```sh -$ cd $GOPATH/src/github.com/gavinbunney/terraform-provider-bitbucketserver -$ make build -``` - ### Developing the Provider If you wish to work on the provider, you'll first need [Go](http://www.golang.org) installed on your machine (version 1.11+ is *required*). You'll also need to correctly setup a [GOPATH](http://golang.org/doc/code.html#GOPATH), as well as adding `$GOPATH/bin` to your `$PATH`. -To compile the provider, run `make build`. This will build the provider and put the provider binary in the `$GOPATH/bin` directory. +Then clone the repository [Terraform provider bitbucket](https://github.com/gavinbunney/terraform-provider-bitbucketserver) -```sh -$ make bin -... -$ $GOPATH/bin/terraform-provider-bitbucketserver -... -``` +To compile the provider, run `make build`. This will build the provider and put the provider binary in the `$GOPATH/bin` directory. In order to test the provider, you can simply run `make test`. @@ -80,10 +59,8 @@ In order to test the provider, you can simply run `make test`. $ make test ``` -In order to run the full suite of Acceptance tests, run `make testacc`. - -*Note:* Acceptance tests create real resources, and often cost money to run. +In order to run the full suite of Acceptance tests, run `make testacc-bitbucket`. Alternatively, you can run the +`scripts/start-docker-compose.sh` to start the Bitbucket docker container, run `make testacc` and then call +`scripts/stop-docker-compose.sh` when done running tests. -```sh -$ make testacc -``` +*Note:* Acceptance tests create real resources, and often cost money to run if not running locally. diff --git a/bitbucket/data_plugin_test.go b/bitbucket/data_plugin_test.go index 265525b..9bbb436 100644 --- a/bitbucket/data_plugin_test.go +++ b/bitbucket/data_plugin_test.go @@ -7,6 +7,7 @@ import ( ) func TestAccBitbucketDataPlugin_notifyer(t *testing.T) { + t.Skip("Skipping testing in CI environment") config := ` resource "bitbucketserver_plugin" "test" { key = "nl.stefankohler.stash.stash-notification-plugin" diff --git a/bitbucket/resource_group.go b/bitbucket/resource_group.go index c9a9d31..318ec20 100644 --- a/bitbucket/resource_group.go +++ b/bitbucket/resource_group.go @@ -2,14 +2,17 @@ package bitbucket import ( "fmt" - "github.com/hashicorp/terraform/helper/schema" "net/url" + "strings" + + "github.com/hashicorp/terraform/helper/schema" ) func resourceGroup() *schema.Resource { return &schema.Resource{ Create: resourceGroupCreate, Read: resourceGroupRead, + Update: resourceGroupUpdate, Delete: resourceGroupDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, @@ -21,6 +24,11 @@ func resourceGroup() *schema.Resource { Required: true, ForceNew: true, }, + "import_if_exists": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, }, } } @@ -29,12 +37,22 @@ func resourceGroupCreate(d *schema.ResourceData, m interface{}) error { client := m.(*BitbucketServerProvider).BitbucketClient groupName := d.Get("name").(string) + importIfExists := d.Get("import_if_exists").(bool) + var newResource = true _, err := client.Post(fmt.Sprintf("/rest/api/1.0/admin/groups?name=%s", url.QueryEscape(groupName)), nil) if err != nil { - return err + if importIfExists && strings.Contains(err.Error(), "API Error: 409") { + newResource = false + } else { + return err + } } + if newResource { + d.MarkNewResource() + } d.SetId(groupName) + return resourceGroupRead(d, m) } @@ -61,6 +79,12 @@ func resourceGroupRead(d *schema.ResourceData, m interface{}) error { return fmt.Errorf("unable to find a matching group %s", groupName) } +func resourceGroupUpdate(d *schema.ResourceData, m interface{}) error { + // The only attribute in the schema that does not have "ForceNew: true" is "import_if_exists", + // so we are not actually updating any groups in Bitbucket, we just need to read and return. + return resourceGroupRead(d, m) +} + func resourceGroupDelete(d *schema.ResourceData, m interface{}) error { groupName := d.Get("name").(string) client := m.(*BitbucketServerProvider).BitbucketClient diff --git a/bitbucket/resource_group_test.go b/bitbucket/resource_group_test.go index 90261f6..61ea5df 100644 --- a/bitbucket/resource_group_test.go +++ b/bitbucket/resource_group_test.go @@ -1,7 +1,13 @@ package bitbucket import ( + "fmt" "github.com/hashicorp/terraform/helper/resource" + "net/http" + "net/url" + "os" + "regexp" + "strings" "testing" ) @@ -25,3 +31,74 @@ func TestAccBitbucketResourceGroup_basic(t *testing.T) { }, }) } + +func TestAccBitbucketResourceGroup_DisallowImport(t *testing.T) { + resourceName := "duplicate_group" + groupName := "duplicate-group" + config := fmt.Sprintf(` + resource "bitbucketserver_group" "%s" { + name = "%s" + } + `, resourceName, groupName) + + createGroup(groupName) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(fmt.Sprintf("bitbucketserver_group.%s", resourceName), "name", groupName), + ), + ExpectError: regexp.MustCompile("API Error: 409"), + }, + }, + }) +} + +func TestAccBitbucketResourceGroup_AllowImport(t *testing.T) { + resourceName := "duplicate_group" + groupName := "duplicate-group" + config := fmt.Sprintf(` + resource "bitbucketserver_group" "%s" { + name = "%s" + import_if_exists = true + } + `, resourceName, groupName) + + createGroup(groupName) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr(fmt.Sprintf("bitbucketserver_group.%s", resourceName), "name", groupName), + ), + }, + }, + }) +} + +func createGroup(groupName string) { + client := newBitbucketClient() + client.Post(fmt.Sprintf("/rest/api/1.0/admin/groups?name=%s", url.QueryEscape(groupName)), nil) +} + +func newBitbucketClient() *BitbucketClient { + serverSanitized := os.Getenv("BITBUCKET_SERVER") + if strings.HasSuffix(serverSanitized, "/") { + serverSanitized = serverSanitized[0 : len(serverSanitized)-1] + } + + return &BitbucketClient{ + Server: serverSanitized, + Username: os.Getenv("BITBUCKET_USERNAME"), + Password: os.Getenv("BITBUCKET_PASSWORD"), + HTTPClient: &http.Client{}, + } +} diff --git a/bitbucket/resource_plugin_config_test.go b/bitbucket/resource_plugin_config_test.go index 734d4bd..4ed9db9 100644 --- a/bitbucket/resource_plugin_config_test.go +++ b/bitbucket/resource_plugin_config_test.go @@ -7,6 +7,7 @@ import ( ) func TestAccBitbucketPluginConfig(t *testing.T) { + t.Skip("Skipping testing in CI environment") config := ` resource "bitbucketserver_plugin" "test" { key = "de.codecentric.atlassian.oidc.bitbucket-oidc-plugin" diff --git a/bitbucket/resource_plugin_test.go b/bitbucket/resource_plugin_test.go index 17c9512..8ab559c 100644 --- a/bitbucket/resource_plugin_test.go +++ b/bitbucket/resource_plugin_test.go @@ -7,6 +7,7 @@ import ( ) func TestAccBitbucketPlugin_install(t *testing.T) { + t.Skip("Skipping testing in CI environment") config := ` resource "bitbucketserver_plugin" "test" { key = "com.plugin.commitgraph.commitgraph" diff --git a/scripts/start-docker-compose.sh b/scripts/start-docker-compose.sh index 5b3a910..37bc136 100755 --- a/scripts/start-docker-compose.sh +++ b/scripts/start-docker-compose.sh @@ -14,4 +14,5 @@ echo "--> Starting docker-compose" ${DIR}/docker-compose up -d --build echo "--> Wait for bitbucket to be ready" -bash ${DIR}/wait-for-url.sh --url http://localhost:7990/status --timeout 600 +#If the BITBUCKET_SERVER environment variable is not set then use http://localhost:7990 +bash ${DIR}/wait-for-url.sh --url ${BITBUCKET_SERVER-http://localhost:7990}/status --timeout 600 diff --git a/version.env b/version.env new file mode 100644 index 0000000..38c5c7f --- /dev/null +++ b/version.env @@ -0,0 +1,10 @@ +#We use semantic versioning: +#version x.y.z +#x is an api version and if breaking api changes are introduced this should change, otherwise it remains constant +#y is a new feature version and this only changes if new features are changed but bugs are not fixed +#z is a patch version that changes if a bug is fixed for a previous feature version. +# See https://semver.org/ for more information + +#To use this file call `source version.env` from a bash terminal + +export BITBUCKET_PROVIDER_VERSION=1.4.0 \ No newline at end of file From a38a9f4d15b848501fef375af3ad47ef012ab7c5 Mon Sep 17 00:00:00 2001 From: Cameron Crockatt Date: Fri, 17 Jul 2020 15:43:47 -0400 Subject: [PATCH 2/2] * Re-enabled ND tests * Reverted changes to README.md since there is another PR to update it. --- README.md | 35 ++++++++++++++++++++---- bitbucket/data_plugin_test.go | 1 - bitbucket/resource_group.go | 8 ++---- bitbucket/resource_plugin_config_test.go | 1 - bitbucket/resource_plugin_test.go | 1 - docusaurus/docs/resource_group.md | 1 + version.env | 10 ------- 7 files changed, 33 insertions(+), 24 deletions(-) delete mode 100644 version.env diff --git a/README.md b/README.md index d3042eb..b54260a 100644 --- a/README.md +++ b/README.md @@ -45,22 +45,45 @@ See [User Guide](https://gavinbunney.github.io/terraform-provider-bitbucketserve - [Terraform](https://www.terraform.io/downloads.html) 0.12.x - [Go](https://golang.org/doc/install) 1.11 (to build the provider plugin) +### Building The Provider + +Clone repository to: `$GOPATH/src/github.com/gavinbunney/terraform-provider-bitbucketserver` + +```sh +$ mkdir -p $GOPATH/src/github.com/terraform-providers; cd $GOPATH/src/github.com/terraform-providers +$ git clone git@github.com:gavinbunney/terraform-provider-bitbucketserver +``` + +Enter the provider directory and build the provider + +```sh +$ cd $GOPATH/src/github.com/gavinbunney/terraform-provider-bitbucketserver +$ make build +``` + ### Developing the Provider If you wish to work on the provider, you'll first need [Go](http://www.golang.org) installed on your machine (version 1.11+ is *required*). You'll also need to correctly setup a [GOPATH](http://golang.org/doc/code.html#GOPATH), as well as adding `$GOPATH/bin` to your `$PATH`. -Then clone the repository [Terraform provider bitbucket](https://github.com/gavinbunney/terraform-provider-bitbucketserver) - To compile the provider, run `make build`. This will build the provider and put the provider binary in the `$GOPATH/bin` directory. +```sh +$ make bin +... +$ $GOPATH/bin/terraform-provider-bitbucketserver +... +``` + In order to test the provider, you can simply run `make test`. ```sh $ make test ``` -In order to run the full suite of Acceptance tests, run `make testacc-bitbucket`. Alternatively, you can run the -`scripts/start-docker-compose.sh` to start the Bitbucket docker container, run `make testacc` and then call -`scripts/stop-docker-compose.sh` when done running tests. +In order to run the full suite of Acceptance tests, run `make testacc`. + +*Note:* Acceptance tests create real resources, and often cost money to run. -*Note:* Acceptance tests create real resources, and often cost money to run if not running locally. +```sh +$ make testacc +``` diff --git a/bitbucket/data_plugin_test.go b/bitbucket/data_plugin_test.go index 9bbb436..265525b 100644 --- a/bitbucket/data_plugin_test.go +++ b/bitbucket/data_plugin_test.go @@ -7,7 +7,6 @@ import ( ) func TestAccBitbucketDataPlugin_notifyer(t *testing.T) { - t.Skip("Skipping testing in CI environment") config := ` resource "bitbucketserver_plugin" "test" { key = "nl.stefankohler.stash.stash-notification-plugin" diff --git a/bitbucket/resource_group.go b/bitbucket/resource_group.go index 318ec20..bb875e3 100644 --- a/bitbucket/resource_group.go +++ b/bitbucket/resource_group.go @@ -2,10 +2,8 @@ package bitbucket import ( "fmt" - "net/url" - "strings" - "github.com/hashicorp/terraform/helper/schema" + "net/url" ) func resourceGroup() *schema.Resource { @@ -39,9 +37,9 @@ func resourceGroupCreate(d *schema.ResourceData, m interface{}) error { groupName := d.Get("name").(string) importIfExists := d.Get("import_if_exists").(bool) var newResource = true - _, err := client.Post(fmt.Sprintf("/rest/api/1.0/admin/groups?name=%s", url.QueryEscape(groupName)), nil) + response, err := client.Post(fmt.Sprintf("/rest/api/1.0/admin/groups?name=%s", url.QueryEscape(groupName)), nil) if err != nil { - if importIfExists && strings.Contains(err.Error(), "API Error: 409") { + if importIfExists && response.StatusCode == 409 { newResource = false } else { return err diff --git a/bitbucket/resource_plugin_config_test.go b/bitbucket/resource_plugin_config_test.go index 4ed9db9..734d4bd 100644 --- a/bitbucket/resource_plugin_config_test.go +++ b/bitbucket/resource_plugin_config_test.go @@ -7,7 +7,6 @@ import ( ) func TestAccBitbucketPluginConfig(t *testing.T) { - t.Skip("Skipping testing in CI environment") config := ` resource "bitbucketserver_plugin" "test" { key = "de.codecentric.atlassian.oidc.bitbucket-oidc-plugin" diff --git a/bitbucket/resource_plugin_test.go b/bitbucket/resource_plugin_test.go index 8ab559c..17c9512 100644 --- a/bitbucket/resource_plugin_test.go +++ b/bitbucket/resource_plugin_test.go @@ -7,7 +7,6 @@ import ( ) func TestAccBitbucketPlugin_install(t *testing.T) { - t.Skip("Skipping testing in CI environment") config := ` resource "bitbucketserver_plugin" "test" { key = "com.plugin.commitgraph.commitgraph" diff --git a/docusaurus/docs/resource_group.md b/docusaurus/docs/resource_group.md index 8a6684d..7a005c6 100644 --- a/docusaurus/docs/resource_group.md +++ b/docusaurus/docs/resource_group.md @@ -16,6 +16,7 @@ resource "bitbucketserver_group" "browncoats" { ## Argument Reference * `name` - Required. Group to create. +* `import_if_exists` - Optional. Import groups that already exist in bitbucket into the terraform state file. ## Import diff --git a/version.env b/version.env deleted file mode 100644 index 38c5c7f..0000000 --- a/version.env +++ /dev/null @@ -1,10 +0,0 @@ -#We use semantic versioning: -#version x.y.z -#x is an api version and if breaking api changes are introduced this should change, otherwise it remains constant -#y is a new feature version and this only changes if new features are changed but bugs are not fixed -#z is a patch version that changes if a bug is fixed for a previous feature version. -# See https://semver.org/ for more information - -#To use this file call `source version.env` from a bash terminal - -export BITBUCKET_PROVIDER_VERSION=1.4.0 \ No newline at end of file