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/bitbucket/resource_group.go b/bitbucket/resource_group.go index c9a9d31..bb875e3 100644 --- a/bitbucket/resource_group.go +++ b/bitbucket/resource_group.go @@ -10,6 +10,7 @@ func resourceGroup() *schema.Resource { return &schema.Resource{ Create: resourceGroupCreate, Read: resourceGroupRead, + Update: resourceGroupUpdate, Delete: resourceGroupDelete, Importer: &schema.ResourceImporter{ State: schema.ImportStatePassthrough, @@ -21,6 +22,11 @@ func resourceGroup() *schema.Resource { Required: true, ForceNew: true, }, + "import_if_exists": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, }, } } @@ -29,12 +35,22 @@ func resourceGroupCreate(d *schema.ResourceData, m interface{}) error { client := m.(*BitbucketServerProvider).BitbucketClient groupName := d.Get("name").(string) - _, err := client.Post(fmt.Sprintf("/rest/api/1.0/admin/groups?name=%s", url.QueryEscape(groupName)), nil) + importIfExists := d.Get("import_if_exists").(bool) + var newResource = true + response, err := client.Post(fmt.Sprintf("/rest/api/1.0/admin/groups?name=%s", url.QueryEscape(groupName)), nil) if err != nil { - return err + if importIfExists && response.StatusCode == 409 { + newResource = false + } else { + return err + } } + if newResource { + d.MarkNewResource() + } d.SetId(groupName) + return resourceGroupRead(d, m) } @@ -61,6 +77,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/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/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