mirror of
https://github.com/ysoftdevs/terraform-provider-bitbucketserver.git
synced 2026-04-20 15:51:20 +02:00
Added bitbucketserver_project resource and associated tests
This commit is contained in:
@@ -29,6 +29,7 @@ func Provider() terraform.ResourceProvider {
|
|||||||
},
|
},
|
||||||
ConfigureFunc: providerConfigure,
|
ConfigureFunc: providerConfigure,
|
||||||
ResourcesMap: map[string]*schema.Resource{
|
ResourcesMap: map[string]*schema.Resource{
|
||||||
|
"bitbucketserver_project": resourceProject(),
|
||||||
"bitbucketserver_repository": resourceRepository(),
|
"bitbucketserver_repository": resourceRepository(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
178
bitbucket/resource_project.go
Normal file
178
bitbucket/resource_project.go
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
package bitbucket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Project struct {
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Key string `json:"key,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
Public bool `json:"public,omitempty"`
|
||||||
|
Avatar string `json:"avatar,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceProject() *schema.Resource {
|
||||||
|
return &schema.Resource{
|
||||||
|
Create: resourceProjectCreate,
|
||||||
|
Update: resourceProjectUpdate,
|
||||||
|
Read: resourceProjectRead,
|
||||||
|
Exists: resourceProjectExists,
|
||||||
|
Delete: resourceProjectDelete,
|
||||||
|
Importer: &schema.ResourceImporter{
|
||||||
|
State: schema.ImportStatePassthrough,
|
||||||
|
},
|
||||||
|
|
||||||
|
Schema: map[string]*schema.Schema{
|
||||||
|
"name": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
"public": {
|
||||||
|
Type: schema.TypeBool,
|
||||||
|
Optional: true,
|
||||||
|
Default: false,
|
||||||
|
},
|
||||||
|
"avatar": {
|
||||||
|
Type: schema.TypeString,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newProjectFromResource(d *schema.ResourceData) *Project {
|
||||||
|
project := &Project{
|
||||||
|
Name: d.Get("name").(string),
|
||||||
|
Key: d.Get("key").(string),
|
||||||
|
Description: d.Get("description").(string),
|
||||||
|
Public: d.Get("public").(bool),
|
||||||
|
Avatar: d.Get("avatar").(string),
|
||||||
|
}
|
||||||
|
|
||||||
|
return project
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceProjectUpdate(d *schema.ResourceData, m interface{}) error {
|
||||||
|
client := m.(*BitbucketClient)
|
||||||
|
project := newProjectFromResource(d)
|
||||||
|
|
||||||
|
bytedata, err := json.Marshal(project)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = client.Put(fmt.Sprintf("/rest/api/1.0/projects/%s",
|
||||||
|
project.Key,
|
||||||
|
), bytes.NewBuffer(bytedata))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return resourceProjectRead(d, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceProjectCreate(d *schema.ResourceData, m interface{}) error {
|
||||||
|
client := m.(*BitbucketClient)
|
||||||
|
project := newProjectFromResource(d)
|
||||||
|
|
||||||
|
bytedata, err := json.Marshal(project)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = client.Post("/rest/api/1.0/projects", bytes.NewBuffer(bytedata))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
d.SetId(project.Key)
|
||||||
|
|
||||||
|
return resourceProjectRead(d, m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceProjectRead(d *schema.ResourceData, m interface{}) error {
|
||||||
|
id := d.Id()
|
||||||
|
if id != "" {
|
||||||
|
d.Set("key", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
project := d.Get("key").(string)
|
||||||
|
|
||||||
|
client := m.(*BitbucketClient)
|
||||||
|
project_req, err := client.Get(fmt.Sprintf("/rest/api/1.0/projects/%s",
|
||||||
|
project,
|
||||||
|
))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if project_req.StatusCode == 200 {
|
||||||
|
|
||||||
|
var project Project
|
||||||
|
|
||||||
|
body, readerr := ioutil.ReadAll(project_req.Body)
|
||||||
|
if readerr != nil {
|
||||||
|
return readerr
|
||||||
|
}
|
||||||
|
|
||||||
|
decodeerr := json.Unmarshal(body, &project)
|
||||||
|
if decodeerr != nil {
|
||||||
|
return decodeerr
|
||||||
|
}
|
||||||
|
|
||||||
|
d.Set("name", project.Name)
|
||||||
|
d.Set("key", project.Key)
|
||||||
|
d.Set("description", project.Description)
|
||||||
|
d.Set("public", project.Public)
|
||||||
|
d.Set("avatar", project.Avatar)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceProjectExists(d *schema.ResourceData, m interface{}) (bool, error) {
|
||||||
|
client := m.(*BitbucketClient)
|
||||||
|
project := d.Get("key").(string)
|
||||||
|
repo_req, err := client.Get(fmt.Sprintf("/rest/api/1.0/projects/%s",
|
||||||
|
project,
|
||||||
|
))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("failed to get project %s from bitbucket: %+v", project, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if repo_req.StatusCode == 200 {
|
||||||
|
return true, nil
|
||||||
|
} else {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func resourceProjectDelete(d *schema.ResourceData, m interface{}) error {
|
||||||
|
project := d.Get("key").(string)
|
||||||
|
client := m.(*BitbucketClient)
|
||||||
|
_, err := client.Delete(fmt.Sprintf("/rest/api/1.0/projects/%s",
|
||||||
|
project,
|
||||||
|
))
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
65
bitbucket/resource_project_test.go
Normal file
65
bitbucket/resource_project_test.go
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
package bitbucket
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAccBitbucketProject(t *testing.T) {
|
||||||
|
var repo Repository
|
||||||
|
|
||||||
|
testAccBitbucketProjectConfig := fmt.Sprintf(`
|
||||||
|
resource "bitbucketserver_project" "test" {
|
||||||
|
key = "TEST%v"
|
||||||
|
name = "test-repo-for-repository-test"
|
||||||
|
}
|
||||||
|
`, rand.New(rand.NewSource(time.Now().UnixNano())).Int())
|
||||||
|
|
||||||
|
resource.Test(t, resource.TestCase{
|
||||||
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
Providers: testAccProviders,
|
||||||
|
CheckDestroy: testAccCheckBitbucketProjectDestroy,
|
||||||
|
Steps: []resource.TestStep{
|
||||||
|
{
|
||||||
|
Config: testAccBitbucketProjectConfig,
|
||||||
|
Check: resource.ComposeTestCheckFunc(
|
||||||
|
testAccCheckBitbucketProjectExists("bitbucketserver_project.test", &repo),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckBitbucketProjectDestroy(s *terraform.State) error {
|
||||||
|
client := testAccProvider.Meta().(*BitbucketClient)
|
||||||
|
rs, ok := s.RootModule().Resources["bitbucketserver_project.test"]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("not found %s", "bitbucketserver_project.test")
|
||||||
|
}
|
||||||
|
|
||||||
|
response, _ := client.Get(fmt.Sprintf("/rest/api/1.0/projects/%s", rs.Primary.Attributes["key"]))
|
||||||
|
|
||||||
|
if response.StatusCode != 404 {
|
||||||
|
return fmt.Errorf("project still exists")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func testAccCheckBitbucketProjectExists(n string, repository *Repository) resource.TestCheckFunc {
|
||||||
|
return func(s *terraform.State) error {
|
||||||
|
rs, ok := s.RootModule().Resources[n]
|
||||||
|
if !ok {
|
||||||
|
return fmt.Errorf("not found %s", n)
|
||||||
|
}
|
||||||
|
if rs.Primary.ID == "" {
|
||||||
|
return fmt.Errorf("no project ID is set")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,9 @@ package bitbucket
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/helper/resource"
|
"github.com/hashicorp/terraform/helper/resource"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
@@ -11,12 +13,17 @@ import (
|
|||||||
func TestAccBitbucketRepository_basic(t *testing.T) {
|
func TestAccBitbucketRepository_basic(t *testing.T) {
|
||||||
var repo Repository
|
var repo Repository
|
||||||
|
|
||||||
testAccBitbucketRepositoryConfig := `
|
testAccBitbucketRepositoryConfig := fmt.Sprintf(`
|
||||||
resource "bitbucketserver_repository" "test_repo" {
|
resource "bitbucketserver_project" "test" {
|
||||||
project = "TEST"
|
key = "TEST%v"
|
||||||
name = "test-repo-for-repository-test"
|
name = "test-repo-for-repository-test"
|
||||||
}
|
}
|
||||||
`
|
|
||||||
|
resource "bitbucketserver_repository" "test_repo" {
|
||||||
|
project = bitbucketserver_project.test.key
|
||||||
|
name = "test-repo-for-repository-test"
|
||||||
|
}
|
||||||
|
`, rand.New(rand.NewSource(time.Now().UnixNano())).Int())
|
||||||
|
|
||||||
resource.Test(t, resource.TestCase{
|
resource.Test(t, resource.TestCase{
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
@@ -36,13 +43,18 @@ func TestAccBitbucketRepository_basic(t *testing.T) {
|
|||||||
func TestAccBitbucketRepository_namewithspaces(t *testing.T) {
|
func TestAccBitbucketRepository_namewithspaces(t *testing.T) {
|
||||||
var repo Repository
|
var repo Repository
|
||||||
|
|
||||||
testAccBitbucketRepositoryConfig := `
|
testAccBitbucketRepositoryConfig := fmt.Sprintf(`
|
||||||
|
resource "bitbucketserver_project" "test" {
|
||||||
|
key = "TEST%v"
|
||||||
|
name = "test-repo-for-repository-test"
|
||||||
|
}
|
||||||
|
|
||||||
resource "bitbucketserver_repository" "test_repo" {
|
resource "bitbucketserver_repository" "test_repo" {
|
||||||
project = "TEST"
|
project = bitbucketserver_project.test.key
|
||||||
name = "Test Repo For Repository Test"
|
name = "Test Repo For Repository Test"
|
||||||
slug = "test-repo-for-repository-test"
|
slug = "test-repo-for-repository-test"
|
||||||
}
|
}
|
||||||
`
|
`, rand.New(rand.NewSource(time.Now().UnixNano())).Int())
|
||||||
|
|
||||||
resource.Test(t, resource.TestCase{
|
resource.Test(t, resource.TestCase{
|
||||||
PreCheck: func() { testAccPreCheck(t) },
|
PreCheck: func() { testAccPreCheck(t) },
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||||
|
|
||||||
cd ${DIR}
|
cd ${DIR}
|
||||||
|
|
||||||
if [ ! -f ${DIR}/docker-compose ]; then
|
if [ ! -f ${DIR}/docker-compose ]; then
|
||||||
@@ -15,4 +14,4 @@ echo "--> Starting docker-compose"
|
|||||||
${DIR}/docker-compose up -d
|
${DIR}/docker-compose up -d
|
||||||
|
|
||||||
echo "--> Wait for bitbucket to be ready"
|
echo "--> Wait for bitbucket to be ready"
|
||||||
bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' localhost:7990/status)" != "200" ]]; do sleep 5; done'
|
bash ${DIR}/wait-for-url.sh --url http://localhost:7990/status --timeout 600
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
|
||||||
|
cd ${DIR}
|
||||||
|
|
||||||
echo "--> Stopping docker-compose"
|
echo "--> Stopping docker-compose"
|
||||||
${DIR}/docker-compose down
|
${DIR}/docker-compose down
|
||||||
|
|||||||
92
scripts/wait-for-url.sh
Executable file
92
scripts/wait-for-url.sh
Executable file
@@ -0,0 +1,92 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
echo "Usage:
|
||||||
|
-u | --url - Required. URL to wait for a 200 OK.
|
||||||
|
-c | --cookie-jar - Optional. Cookie jar to use to store cookies.
|
||||||
|
-s | --successful-requests - Optional. Number of successful requests to wait for. Default 3.
|
||||||
|
-t | --timeout - Optional. Number of seconds to wait. Default 300 (5m)."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
TIMEOUT=300
|
||||||
|
INTERVAL=2
|
||||||
|
TIMER_START=$SECONDS
|
||||||
|
WAIT_FOR_SUCCESSFUL_REQUESTS=3
|
||||||
|
|
||||||
|
while (( "$#" )); do
|
||||||
|
case "$1" in
|
||||||
|
-u|--url)
|
||||||
|
SERVICE_URL=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-c|--cookie-jar)
|
||||||
|
COOKIE_JAR=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-s|--successful-requests)
|
||||||
|
WAIT_FOR_SUCCESSFUL_REQUESTS=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-t|--timeout)
|
||||||
|
TIMEOUT=$2
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-*|--*=)
|
||||||
|
echo "Error: Unsupported option $1" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ ! ${SERVICE_URL} ]]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${INTERVAL}" -gt "${TIMEOUT}" ]]; then
|
||||||
|
INTERVAL=$TIMEOUT
|
||||||
|
fi
|
||||||
|
|
||||||
|
#
|
||||||
|
# Wait for endpoint to return a 200OK
|
||||||
|
#
|
||||||
|
|
||||||
|
SERVICE_CURL_RESULT=""
|
||||||
|
echo "> Waiting for ${SERVICE_URL} to return 200 OK (retrying every ${INTERVAL}s for ${TIMEOUT}s)"
|
||||||
|
limit=$(( ${TIMEOUT} / ${INTERVAL} ))
|
||||||
|
count=0
|
||||||
|
successful_requests=0
|
||||||
|
while : ; do
|
||||||
|
printf "."
|
||||||
|
if [ ! -z "${COOKIE_JAR}" ]; then
|
||||||
|
SERVICE_CURL_RESULT=$(curl --cookie "${COOKIE_JAR}" --cookie-jar "${COOKIE_JAR}" -H 'Cache-Control: no-cache' -L -s -o /dev/null -w '%{http_code}' ${SERVICE_URL} || true)
|
||||||
|
else
|
||||||
|
SERVICE_CURL_RESULT=$(curl -H 'Cache-Control: no-cache' -L -s -o /dev/null -w '%{http_code}' ${SERVICE_URL} || true)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${SERVICE_CURL_RESULT}" -eq 200 ]]; then
|
||||||
|
successful_requests=$[$successful_requests+1]
|
||||||
|
elif [[ "${successful_requests}" -gt 0 ]]; then
|
||||||
|
printf "\n[!] Warning: Previous request was successful, current request returned: ${SERVICE_CURL_RESULT}\n" >&2
|
||||||
|
successful_requests=$[$successful_requests-1]
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${successful_requests}" -ge "${WAIT_FOR_SUCCESSFUL_REQUESTS}" ]]; then
|
||||||
|
printf "\n"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${count}" -ge "${limit}" ]]; then
|
||||||
|
printf "\n[!] Timeout waiting for Service to return 200 OK\n" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
sleep ${INTERVAL}
|
||||||
|
count=$[$count+1]
|
||||||
|
done
|
||||||
|
|
||||||
|
TIMER_DURATION=$(( SECONDS - TIMER_START ))
|
||||||
|
|
||||||
|
echo "> ${SERVICE_URL} returned ${successful_requests} successful requests in ${TIMER_DURATION}s"
|
||||||
Reference in New Issue
Block a user