diff --git a/README.md b/README.md index 4be5506..4439146 100644 --- a/README.md +++ b/README.md @@ -171,6 +171,42 @@ $ terraform import bitbucketserver_user.test mreynolds ``` +### Create a Bitbucket Group + +```hcl +resource "bitbucketserver_group" "browncoats" { + name = "browncoats" +} +``` + +* `name` - Required. Group to create. + +#### Import Group + +```bash +$ terraform import bitbucketserver_group.test browncoats +``` + + +### Assign a User to a Bitbucket Group + +```hcl +resource "bitbucketserver_user_group" "browncoat" { + user = "mreynolds" + group = "browncoats" +} +``` + +* `user` - Required. User to assign group to. +* `group` - Required. Group to assign to the user. + +#### Import Group + +```bash +$ terraform import bitbucketserver_user_group.browncoat mreynolds/browncoats +``` + + ### Set Server License ```hcl @@ -251,6 +287,39 @@ data "bitbucketserver_application_properties" "main" {} * `display_name` - Name of the Bitbucket instance. +### Groups + +Retrieve a list of groups, optionally matching the supplied `filter`. + +```hcl +data "bitbucketserver_groups" "all" {} +``` + +* `filter` - Optional. If specified only group names containing the supplied string will be returned. + +#### Attributes + +* `groups` - List of maps containing a `name` key. + + +### Users + +Retrieve a list of users for a group,optionally matching the supplied `filter`. + +```hcl +data "bitbucketserver_group_users" "stash-users" { + group = "stash-users" +} +``` + +* `group` - Required. Group to find the users for. +* `filter` - Optional. If specified only group names containing the supplied string will be returned. + +#### Attributes + +* `users` - List of users containing `name`, `email_address`, `display_name` and `active` keys. + + ### Project Permissions Groups Retrieve a list of groups that have been granted at least one permission for the specified project. diff --git a/bitbucket/data_application_properties.go b/bitbucket/data_application_properties.go index ce0e3ae..0190197 100644 --- a/bitbucket/data_application_properties.go +++ b/bitbucket/data_application_properties.go @@ -61,10 +61,10 @@ func dataSourceApplicationPropertiesRead(d *schema.ResourceData, m interface{}) } d.SetId(applicationProperties.Version) - d.Set("version", applicationProperties.Version) - d.Set("build_number", applicationProperties.BuildNumber) - d.Set("build_date", applicationProperties.BuildDate) - d.Set("display_name", applicationProperties.DisplayName) + _ = d.Set("version", applicationProperties.Version) + _ = d.Set("build_number", applicationProperties.BuildNumber) + _ = d.Set("build_date", applicationProperties.BuildDate) + _ = d.Set("display_name", applicationProperties.DisplayName) } return nil diff --git a/bitbucket/data_group_users.go b/bitbucket/data_group_users.go new file mode 100644 index 0000000..29fdd7c --- /dev/null +++ b/bitbucket/data_group_users.go @@ -0,0 +1,149 @@ +package bitbucket + +import ( + "encoding/json" + "fmt" + "github.com/hashicorp/terraform/helper/schema" + "net/url" +) + +type PaginatedGroupUsersValue struct { + Name string `json:"name,omitempty"` + EmailAddress string `json:"emailAddress,omitempty"` + DisplayName string `json:"displayName,omitempty"` + Active bool `json:"active,omitempty"` +} + +type GroupUser struct { + Name string + EmailAddress string + DisplayName string + Active bool +} + +type PaginatedGroupUsers struct { + Values []PaginatedGroupUsersValue `json:"values,omitempty"` + Size int `json:"size,omitempty"` + Limit int `json:"limit,omitempty"` + IsLastPage bool `json:"isLastPage,omitempty"` + Start int `json:"start,omitempty"` + NextPageStart int `json:"nextPageStart,omitempty"` +} + +func dataSourceGroupUsers() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGroupUsersRead, + + Schema: map[string]*schema.Schema{ + "group": { + Type: schema.TypeString, + Required: true, + }, + "filter": { + Type: schema.TypeString, + Optional: true, + }, + "users": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + }, + "email_address": { + Type: schema.TypeString, + Computed: true, + }, + "display_name": { + Type: schema.TypeString, + Computed: true, + }, + "active": { + Type: schema.TypeBool, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourceGroupUsersRead(d *schema.ResourceData, m interface{}) error { + users, err := readGroupUsers(m, d.Get("group").(string), d.Get("filter").(string)) + if err != nil { + return err + } + + d.SetId(d.Get("group").(string)) + + var terraformUsers []interface{} + for _, group := range users { + g := make(map[string]interface{}) + g["name"] = group.Name + g["email_address"] = group.EmailAddress + g["display_name"] = group.DisplayName + g["active"] = group.Active + terraformUsers = append(terraformUsers, g) + } + + _ = d.Set("users", terraformUsers) + return nil +} + +func readGroupUsers(m interface{}, group string, filter string) ([]GroupUser, error) { + client := m.(*BitbucketClient) + + resourceURL := fmt.Sprintf("/rest/api/1.0/admin/groups/more-members?context=%s", + url.QueryEscape(group), + ) + + if filter != "" { + resourceURL += "&filter=" + url.QueryEscape(filter) + } + + var groupUsers PaginatedGroupUsers + var users []GroupUser + + for { + resp, err := client.Get(resourceURL) + if err != nil { + return nil, err + } + + decoder := json.NewDecoder(resp.Body) + err = decoder.Decode(&groupUsers) + if err != nil { + return nil, err + } + + for _, user := range groupUsers.Values { + g := GroupUser{ + Name: user.Name, + EmailAddress: user.EmailAddress, + DisplayName: user.DisplayName, + Active: user.Active, + } + users = append(users, g) + } + + if groupUsers.IsLastPage == false { + resourceURL = fmt.Sprintf("/rest/api/1.0/projects/%s/permissions/users?start=%d", + group, + groupUsers.NextPageStart, + ) + + if filter != "" { + resourceURL += "&filter=" + url.QueryEscape(filter) + } + + groupUsers = PaginatedGroupUsers{} + } else { + break + } + } + + return users, nil +} diff --git a/bitbucket/data_group_users_test.go b/bitbucket/data_group_users_test.go new file mode 100644 index 0000000..5379e58 --- /dev/null +++ b/bitbucket/data_group_users_test.go @@ -0,0 +1,71 @@ +package bitbucket + +import ( + "github.com/hashicorp/terraform/helper/resource" + "testing" +) + +func TestAccBitbucketDataGroupUsers_check_default_included(t *testing.T) { + config := ` + data "bitbucketserver_group_users" "test" { + group = "stash-users" + } + ` + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.bitbucketserver_group_users.test", "users.#", "1"), + resource.TestCheckResourceAttr("data.bitbucketserver_group_users.test", "users.0.name", "admin"), + resource.TestCheckResourceAttr("data.bitbucketserver_group_users.test", "users.0.display_name", "Admin"), + resource.TestCheckResourceAttr("data.bitbucketserver_group_users.test", "users.0.email_address", "admin@example.com"), + resource.TestCheckResourceAttr("data.bitbucketserver_group_users.test", "users.0.active", "true"), + ), + }, + }, + }) +} + +func TestAccBitbucketDataGroupUsers_additional(t *testing.T) { + config := ` + resource "bitbucketserver_user" "mreynolds" { + name = "mreynolds" + display_name = "Malcolm Reynolds" + email_address = "browncoat@example.com" + } + + resource "bitbucketserver_user_group" "test" { + user = bitbucketserver_user.mreynolds.name + group = "stash-users" + } + + data "bitbucketserver_group_users" "test" { + group = bitbucketserver_user_group.test.group + } + ` + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.bitbucketserver_group_users.test", "users.#", "2"), + resource.TestCheckResourceAttr("data.bitbucketserver_group_users.test", "users.0.name", "admin"), + resource.TestCheckResourceAttr("data.bitbucketserver_group_users.test", "users.0.display_name", "Admin"), + resource.TestCheckResourceAttr("data.bitbucketserver_group_users.test", "users.0.email_address", "admin@example.com"), + resource.TestCheckResourceAttr("data.bitbucketserver_group_users.test", "users.0.active", "true"), + resource.TestCheckResourceAttr("data.bitbucketserver_group_users.test", "users.1.name", "mreynolds"), + resource.TestCheckResourceAttr("data.bitbucketserver_group_users.test", "users.1.display_name", "Malcolm Reynolds"), + resource.TestCheckResourceAttr("data.bitbucketserver_group_users.test", "users.1.email_address", "browncoat@example.com"), + resource.TestCheckResourceAttr("data.bitbucketserver_group_users.test", "users.1.active", "true"), + ), + }, + }, + }) +} diff --git a/bitbucket/data_groups.go b/bitbucket/data_groups.go new file mode 100644 index 0000000..5759eaf --- /dev/null +++ b/bitbucket/data_groups.go @@ -0,0 +1,110 @@ +package bitbucket + +import ( + "encoding/json" + "fmt" + "github.com/hashicorp/terraform/helper/schema" + "net/url" +) + +type PaginatedGroupsValue struct { + Name string `json:"name,omitempty"` +} + +type PaginatedGroups struct { + Values []PaginatedGroupsValue `json:"values,omitempty"` + Size int `json:"size,omitempty"` + Limit int `json:"limit,omitempty"` + IsLastPage bool `json:"isLastPage,omitempty"` + Start int `json:"start,omitempty"` + NextPageStart int `json:"nextPageStart,omitempty"` +} + +func dataSourceGroups() *schema.Resource { + return &schema.Resource{ + Read: dataSourceGroupsRead, + + Schema: map[string]*schema.Schema{ + "filter": { + Type: schema.TypeString, + Optional: true, + }, + "groups": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + }, + } +} + +func dataSourceGroupsRead(d *schema.ResourceData, m interface{}) error { + groups, err := readGroups(m, d.Get("filter").(string)) + if err != nil { + return err + } + + d.SetId("groups") + + var terraformGroups []interface{} + for _, group := range groups { + g := make(map[string]interface{}) + g["name"] = group + terraformGroups = append(terraformGroups, g) + } + + _ = d.Set("groups", terraformGroups) + return nil +} + +func readGroups(m interface{}, filter string) ([]string, error) { + client := m.(*BitbucketClient) + + resourceURL := "/rest/api/1.0/admin/groups" + if filter != "" { + resourceURL += "?filter=" + url.QueryEscape(filter) + } + + var paginatedGroups PaginatedGroups + var groups []string + + for { + resp, err := client.Get(resourceURL) + if err != nil { + return nil, err + } + + decoder := json.NewDecoder(resp.Body) + err = decoder.Decode(&paginatedGroups) + if err != nil { + return nil, err + } + + for _, group := range paginatedGroups.Values { + groups = append(groups, group.Name) + } + + if paginatedGroups.IsLastPage == false { + resourceURL = fmt.Sprintf("/rest/api/1.0/admin/groups?start=%d", + paginatedGroups.NextPageStart, + ) + + if filter != "" { + resourceURL += "&filter=" + url.QueryEscape(filter) + } + + paginatedGroups = PaginatedGroups{} + } else { + break + } + } + + return groups, nil +} diff --git a/bitbucket/data_groups_test.go b/bitbucket/data_groups_test.go new file mode 100644 index 0000000..650993b --- /dev/null +++ b/bitbucket/data_groups_test.go @@ -0,0 +1,54 @@ +package bitbucket + +import ( + "github.com/hashicorp/terraform/helper/resource" + "testing" +) + +func TestAccBitbucketDataGroups_basic(t *testing.T) { + config := ` + data "bitbucketserver_groups" "test" { + filter = "stash-users" + } + ` + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.bitbucketserver_groups.test", "groups.#", "1"), + resource.TestCheckResourceAttr("data.bitbucketserver_groups.test", "groups.0.name", "stash-users"), + ), + }, + }, + }) +} + +func TestAccBitbucketDataGroups_additional(t *testing.T) { + config := ` + resource "bitbucketserver_group" "test" { + name = "test-group" + } + + data "bitbucketserver_groups" "test" { + filter = bitbucketserver_group.test.name + } + ` + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.bitbucketserver_groups.test", "groups.#", "1"), + resource.TestCheckResourceAttr("data.bitbucketserver_groups.test", "groups.0.name", "test-group"), + ), + }, + }, + }) +} diff --git a/bitbucket/data_project_permissions_groups.go b/bitbucket/data_project_permissions_groups.go index 09b6f4e..308b5e0 100644 --- a/bitbucket/data_project_permissions_groups.go +++ b/bitbucket/data_project_permissions_groups.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "github.com/hashicorp/terraform/helper/schema" + "net/url" ) type PaginatedProjectPermissionsGroupsValue struct { @@ -76,7 +77,7 @@ func dataSourceProjectPermissionsGroupsRead(d *schema.ResourceData, m interface{ terraformGroups = append(terraformGroups, g) } - d.Set("groups", terraformGroups) + _ = d.Set("groups", terraformGroups) return nil } @@ -88,7 +89,7 @@ func readProjectPermissionsGroups(m interface{}, project string, filter string) ) if filter != "" { - resourceURL += "?filter=" + filter + resourceURL += "?filter=" + url.QueryEscape(filter) } var projectGroups PaginatedProjectPermissionsGroups @@ -121,7 +122,7 @@ func readProjectPermissionsGroups(m interface{}, project string, filter string) ) if filter != "" { - resourceURL += "&filter=" + filter + resourceURL += "&filter=" + url.QueryEscape(filter) } projectGroups = PaginatedProjectPermissionsGroups{} diff --git a/bitbucket/data_project_permissions_users.go b/bitbucket/data_project_permissions_users.go index b85ab2c..ef0b000 100644 --- a/bitbucket/data_project_permissions_users.go +++ b/bitbucket/data_project_permissions_users.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "github.com/hashicorp/terraform/helper/schema" + "net/url" ) type PaginatedProjectPermissionsUsersValue struct { @@ -97,7 +98,7 @@ func dataSourceProjectPermissionsUsersRead(d *schema.ResourceData, m interface{} terraformUsers = append(terraformUsers, g) } - d.Set("users", terraformUsers) + _ = d.Set("users", terraformUsers) return nil } @@ -109,7 +110,7 @@ func readProjectPermissionsUsers(m interface{}, project string, filter string) ( ) if filter != "" { - resourceURL += "?filter=" + filter + resourceURL += "?filter=" + url.QueryEscape(filter) } var projectUsers PaginatedProjectPermissionsUsers @@ -145,7 +146,7 @@ func readProjectPermissionsUsers(m interface{}, project string, filter string) ( ) if filter != "" { - resourceURL += "&filter=" + filter + resourceURL += "&filter=" + url.QueryEscape(filter) } projectUsers = PaginatedProjectPermissionsUsers{} diff --git a/bitbucket/provider.go b/bitbucket/provider.go index 659db50..0b51878 100644 --- a/bitbucket/provider.go +++ b/bitbucket/provider.go @@ -30,10 +30,13 @@ func Provider() terraform.ResourceProvider { ConfigureFunc: providerConfigure, DataSourcesMap: map[string]*schema.Resource{ "bitbucketserver_application_properties": dataSourceApplicationProperties(), + "bitbucketserver_groups": dataSourceGroups(), + "bitbucketserver_group_users": dataSourceGroupUsers(), "bitbucketserver_project_permissions_groups": dataSourceProjectPermissionsGroups(), "bitbucketserver_project_permissions_users": dataSourceProjectPermissionsUsers(), }, ResourcesMap: map[string]*schema.Resource{ + "bitbucketserver_group": resourceGroup(), "bitbucketserver_license": resourceLicense(), "bitbucketserver_mail_server": resourceMailServer(), "bitbucketserver_project": resourceProject(), @@ -41,6 +44,7 @@ func Provider() terraform.ResourceProvider { "bitbucketserver_project_permissions_user": resourceProjectPermissionsUser(), "bitbucketserver_repository": resourceRepository(), "bitbucketserver_user": resourceUser(), + "bitbucketserver_user_group": resourceUserGroup(), }, } } diff --git a/bitbucket/resource_group.go b/bitbucket/resource_group.go new file mode 100644 index 0000000..e455403 --- /dev/null +++ b/bitbucket/resource_group.go @@ -0,0 +1,72 @@ +package bitbucket + +import ( + "fmt" + "github.com/hashicorp/terraform/helper/schema" + "net/url" +) + +func resourceGroup() *schema.Resource { + return &schema.Resource{ + Create: resourceGroupCreate, + Read: resourceGroupRead, + Delete: resourceGroupDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + }, + } +} + +func resourceGroupCreate(d *schema.ResourceData, m interface{}) error { + client := m.(*BitbucketClient) + + groupName := d.Get("name").(string) + _, err := client.Post(fmt.Sprintf("/rest/api/1.0/admin/groups?name=%s", url.QueryEscape(groupName)), nil) + if err != nil { + return err + } + + d.SetId(groupName) + return resourceGroupRead(d, m) +} + +func resourceGroupRead(d *schema.ResourceData, m interface{}) error { + id := d.Id() + if id != "" { + _ = d.Set("name", id) + } + + groupName := d.Get("name").(string) + + groupMatches, err := readGroups(m, groupName) + if err != nil { + return err + } + + // API only filters but we need to find an exact match + for _, g := range groupMatches { + if g == groupName { + return nil + } + } + + return fmt.Errorf("unable to find a matching group %s", groupName) +} + +func resourceGroupDelete(d *schema.ResourceData, m interface{}) error { + groupName := d.Get("name").(string) + client := m.(*BitbucketClient) + _, err := client.Delete(fmt.Sprintf("/rest/api/1.0/admin/groups?name=%s", + url.QueryEscape(groupName), + )) + + return err +} diff --git a/bitbucket/resource_group_test.go b/bitbucket/resource_group_test.go new file mode 100644 index 0000000..90261f6 --- /dev/null +++ b/bitbucket/resource_group_test.go @@ -0,0 +1,27 @@ +package bitbucket + +import ( + "github.com/hashicorp/terraform/helper/resource" + "testing" +) + +func TestAccBitbucketResourceGroup_basic(t *testing.T) { + config := ` + resource "bitbucketserver_group" "test" { + name = "test-group" + } + ` + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("bitbucketserver_group.test", "name", "test-group"), + ), + }, + }, + }) +} diff --git a/bitbucket/resource_user_group.go b/bitbucket/resource_user_group.go new file mode 100644 index 0000000..964157a --- /dev/null +++ b/bitbucket/resource_user_group.go @@ -0,0 +1,133 @@ +package bitbucket + +import ( + "bytes" + "encoding/json" + "fmt" + "github.com/hashicorp/terraform/helper/schema" + "strings" +) + +type UserGroup struct { + User string + Group string +} + +func resourceUserGroup() *schema.Resource { + return &schema.Resource{ + Create: resourceUserGroupCreate, + Read: resourceUserGroupRead, + Delete: resourceUserGroupDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "user": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "group": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + }, + } +} + +func newUserGroupFromResource(d *schema.ResourceData) *UserGroup { + userGroup := &UserGroup{ + User: d.Get("user").(string), + Group: d.Get("group").(string), + } + + return userGroup +} + +func resourceUserGroupCreate(d *schema.ResourceData, m interface{}) error { + client := m.(*BitbucketClient) + + type UserGroupRequest struct { + User string `json:"user,omitempty"` + Groups []string `json:"groups,omitempty"` + } + + request := &UserGroupRequest{ + User: d.Get("user").(string), + Groups: []string{ + d.Get("group").(string), + }, + } + + bytedata, err := json.Marshal(request) + + if err != nil { + return err + } + + _, err = client.Post("/rest/api/1.0/admin/users/add-groups", bytes.NewBuffer(bytedata)) + if err != nil { + return err + } + + d.SetId(fmt.Sprintf("%s/%s", request.User, request.Groups[0])) + + return resourceUserGroupRead(d, m) +} + +func resourceUserGroupRead(d *schema.ResourceData, m interface{}) error { + id := d.Id() + if id != "" { + parts := strings.Split(id, "/") + if len(parts) == 2 { + _ = d.Set("user", parts[0]) + _ = d.Set("group", parts[1]) + } else { + return fmt.Errorf("incorrect ID format, should match `user/group`") + } + } + + userGroup := newUserGroupFromResource(d) + + groupUsers, err := readGroupUsers(m, userGroup.Group, userGroup.User) + if err != nil { + return err + } + + // API only filters but we need to find an exact match + for _, g := range groupUsers { + if g.Name == userGroup.User { + return nil + } + } + + return fmt.Errorf("unable to find a matching user %s in group %s", userGroup.User, userGroup.Group) +} + +func resourceUserGroupDelete(d *schema.ResourceData, m interface{}) error { + + userGroup := newUserGroupFromResource(d) + + client := m.(*BitbucketClient) + + type RemoveRequest struct { + User string `json:"context,omitempty"` + Group string `json:"itemName,omitempty"` + } + + removeRequest := &RemoveRequest{ + User: userGroup.User, + Group: userGroup.Group, + } + + bytedata, err := json.Marshal(removeRequest) + if err != nil { + return err + } + + _, err = client.Post("/rest/api/1.0/admin/users/remove-group", bytes.NewBuffer(bytedata)) + + return err +} diff --git a/bitbucket/resource_user_group_test.go b/bitbucket/resource_user_group_test.go new file mode 100644 index 0000000..c902f95 --- /dev/null +++ b/bitbucket/resource_user_group_test.go @@ -0,0 +1,68 @@ +package bitbucket + +import ( + "github.com/hashicorp/terraform/helper/resource" + "testing" +) + +func TestAccBitbucketResourceUserGroup_basic(t *testing.T) { + config := ` + resource "bitbucketserver_user" "mreynolds" { + name = "mreynolds" + display_name = "Malcolm Reynolds" + email_address = "browncoat@example.com" + } + + resource "bitbucketserver_user_group" "test" { + user = bitbucketserver_user.mreynolds.name + group = "stash-users" + } + ` + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("bitbucketserver_user_group.test", "user", "mreynolds"), + resource.TestCheckResourceAttr("bitbucketserver_user_group.test", "group", "stash-users"), + ), + }, + }, + }) +} + +func TestAccBitbucketResourceUserGroup_new_group(t *testing.T) { + config := ` + resource "bitbucketserver_group" "test" { + name = "test-group" + } + + resource "bitbucketserver_user" "mreynolds" { + name = "mreynolds" + display_name = "Malcolm Reynolds" + email_address = "browncoat@example.com" + } + + resource "bitbucketserver_user_group" "test" { + user = bitbucketserver_user.mreynolds.name + group = bitbucketserver_group.test.name + } + ` + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("bitbucketserver_user_group.test", "user", "mreynolds"), + resource.TestCheckResourceAttr("bitbucketserver_user_group.test", "group", "test-group"), + ), + }, + }, + }) +}