feat: add organization resource

This commit is contained in:
Jeff Malnick committed 2020-08-28 07:03:11 -07:00
1 parent cace004114
commit dfec34e669
2 files changed
+281

No files matched your search

+167
View File
@@ -0,0 +1,167 @@
package provider
import (
"fmt"
"github.com/hashicorp/boundary/api/scopes"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
)
const (
organizationDescriptionKey = "description"
organizationNameKey = "name"
)
func resourceOrganization() *schema.Resource {
return &schema.Resource{
Create: resourceOrganizationCreate,
Read: resourceOrganizationRead,
Update: resourceOrganizationUpdate,
Delete: resourceOrganizationDelete,
Schema: map[string]*schema.Schema{
organizationNameKey: {
Type: schema.TypeString,
Optional: true,
},
organizationDescriptionKey: {
Type: schema.TypeString,
Optional: true,
},
},
}
}
// convertOrganizationToResourceData populates the provided ResourceData with the appropriate values from the provided Project.
// The organization passed into thie function should be one read from the boundary API with all fields populated.
func convertOrganizationToResourceData(o *scopes.Scope, d *schema.ResourceData) error {
if o.Name != "" {
if err := d.Set(organizationNameKey, o.Name); err != nil {
return err
}
}
if o.Description != "" {
if err := d.Set(organizationDescriptionKey, o.Description); err != nil {
return err
}
}
d.SetId(o.Id)
return nil
}
// convertResourceDataToOrganization returns a localy built Project using the values provided in the ResourceData.
func convertResourceDataToOrganization(d *schema.ResourceData) (*scopes.Scope, error) {
o := &scopes.Scope{Scope: &scopes.ScopeInfo{}}
if descVal, ok := d.GetOk(organizationDescriptionKey); ok {
o.Description = descVal.(string)
}
if nameVal, ok := d.GetOk(organizationNameKey); ok {
o.Name = nameVal.(string)
}
if d.Id() != "" {
o.Id = d.Id()
}
return o, nil
}
func resourceOrganizationCreate(d *schema.ResourceData, meta interface{}) error {
md := meta.(*metaData)
client := md.client
ctx := md.ctx
scp := scopes.NewScopesClient(client)
o, err := convertResourceDataToOrganization(d)
if err != nil {
return err
}
o, _, err = scp.Create(
ctx,
client.ScopeId(),
scopes.WithName(o.Name),
scopes.WithDescription(o.Description))
if err != nil {
return err
}
d.SetId(o.Id)
return nil
}
func resourceOrganizationRead(d *schema.ResourceData, meta interface{}) error {
md := meta.(*metaData)
client := md.client
ctx := md.ctx
scp := scopes.NewScopesClient(client)
o, _, err := scp.Read(ctx, d.Id())
if err != nil {
return err
}
return convertOrganizationToResourceData(o, d)
}
func resourceOrganizationUpdate(d *schema.ResourceData, meta interface{}) error {
md := meta.(*metaData)
client := md.client
ctx := md.ctx
projClient := client.Clone()
projClient.SetScopeId(d.Id())
scp := scopes.NewScopesClient(projClient)
o, err := convertResourceDataToOrganization(d)
if err != nil {
return err
}
if d.HasChange(organizationDescriptionKey) {
desc := d.Get(organizationDescriptionKey).(string)
o.Description = desc
}
if d.HasChange(organizationNameKey) {
name := d.Get(organizationNameKey).(string)
o.Name = name
}
o, _, err = scp.Update(
ctx,
d.Id(),
0,
scopes.WithAutomaticVersioning(),
scopes.WithDescription(o.Description),
scopes.WithName(o.Name),
)
if err != nil {
return err
}
return convertOrganizationToResourceData(o, d)
}
func resourceOrganizationDelete(d *schema.ResourceData, meta interface{}) error {
md := meta.(*metaData)
client := md.client
ctx := md.ctx
projClient := client.Clone()
projClient.SetScopeId(d.Id())
scp := scopes.NewScopesClient(projClient)
o, err := convertResourceDataToOrganization(d)
if err != nil {
return err
}
_, _, err = scp.Delete(ctx, o.Id)
if err != nil {
return fmt.Errorf("failed deleting organization: %w", err)
}
return nil
}
@@ -0,0 +1,114 @@
package provider
import (
"fmt"
"net/http"
"strings"
"testing"
"github.com/hashicorp/boundary/api/scopes"
"github.com/hashicorp/boundary/testing/controller"
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/terraform"
)
const (
orgFooName = "foo"
orgFooDescription = "foo description"
orgFooDescriptionUpdate = "foo bar description"
)
var (
fooOrg = `
resource "boundary_organization" "foo" {}`
orgFoo = fmt.Sprintf(`
resource "boundary_organization" "foo" {
name = "%s"
description = "%s"
}`, orgFooName, orgFooDescription)
orgFooUpdate = fmt.Sprintf(`
resource "boundary_organization" "foo" {
name = "%s"
description = "%s"
}`, orgFooName, orgFooDescriptionUpdate)
)
func TestAccOrganizationCreation(t *testing.T) {
tc := controller.NewTestController(t, tcConfig...)
defer tc.Shutdown()
url := tc.ApiAddrs()[0]
resource.Test(t, resource.TestCase{
Providers: testProviders,
CheckDestroy: testAccCheckOrganizationResourceDestroy(t),
Steps: []resource.TestStep{
// test create
{
Config: testConfig(url, orgFoo),
Check: resource.ComposeTestCheckFunc(
testAccCheckOrganizationResourceExists("boundary_organization.foo"),
resource.TestCheckResourceAttr("boundary_organization.foo", organizationNameKey, orgFooName),
resource.TestCheckResourceAttr("boundary_organization.foo", organizationDescriptionKey, orgFooDescription),
),
},
// test update
{
Config: testConfig(url, orgFooUpdate),
Check: resource.ComposeTestCheckFunc(
testAccCheckOrganizationResourceExists("boundary_organization.foo"),
resource.TestCheckResourceAttr("boundary_organization.foo", organizationNameKey, orgFooName),
resource.TestCheckResourceAttr("boundary_organization.foo", organizationDescriptionKey, orgFooDescriptionUpdate),
),
},
},
})
}
func testAccCheckOrganizationResourceExists(name string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[name]
if !ok {
return fmt.Errorf("Not found: %s", name)
}
id := rs.Primary.ID
if id == "" {
return fmt.Errorf("No ID is set")
}
if !strings.HasPrefix(id, "o_") {
return fmt.Errorf("ID not formatted as expected, expected prefix 'o_', got %s", id)
}
md := testProvider.Meta().(*metaData)
scp := scopes.NewScopesClient(md.client)
if _, _, err := scp.Read(md.ctx, id); err != nil {
return fmt.Errorf("Got an error when reading organization %q: %v", id, err)
}
return nil
}
}
func testAccCheckOrganizationResourceDestroy(t *testing.T) resource.TestCheckFunc {
return func(s *terraform.State) error {
// retrieve the connection established in Provider configuration
md := testProvider.Meta().(*metaData)
scp := scopes.NewScopesClient(md.client)
for _, rs := range s.RootModule().Resources {
id := rs.Primary.ID
switch rs.Type {
case "boundary_organization":
if _, apiErr, _ := scp.Read(md.ctx, id); apiErr == nil || apiErr.Status != http.StatusNotFound && apiErr.Status != http.StatusForbidden {
return fmt.Errorf("Didn't get a 404 or 403 when reading destroyed organization %q: %v", id, apiErr)
}
default:
t.Logf("Got unknown resource type %q", rs.Type)
}
}
return nil
}
}