Skip to content

Commit

Permalink
add update operation on group +tests.
Browse files Browse the repository at this point in the history
restructure parent group craziness
  • Loading branch information
ack committed Mar 3, 2016
1 parent 8d5530f commit ecdf6d2
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 43 deletions.
18 changes: 16 additions & 2 deletions builtin/providers/clc/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,13 +100,13 @@ func waitStatus(client *clc.Client, id string) error {
return nil
}

func dcGroups(dcname string, meta interface{}) (map[string]string, error) {
client := meta.(*clc.Client)
func dcGroups(dcname string, client *clc.Client) (map[string]string, error) {
dc, _ := client.DC.Get(dcname)
_, id := dc.Links.GetID("group")
m := map[string]string{}
resp, _ := client.Group.Get(id)
m[resp.Name] = resp.ID // top
m[resp.ID] = resp.ID
for _, x := range resp.Groups {
deepGroups(x, &m)
}
Expand All @@ -115,11 +115,25 @@ func dcGroups(dcname string, meta interface{}) (map[string]string, error) {

func deepGroups(g group.Groups, m *map[string]string) {
(*m)[g.Name] = g.ID
(*m)[g.ID] = g.ID
for _, sg := range g.Groups {
deepGroups(sg, m)
}
}

// resolveGroupByNameOrId takes a reference to a group (either name or guid)
// and returns the guid of the group
func resolveGroupByNameOrId(ref, dc string, client *clc.Client) (string, error) {
m, err := dcGroups(dc, client)
if err != nil {
return "", fmt.Errorf("Failed pulling groups in location %v - %v", dc, err)
}
if id, ok := m[ref]; ok {
return id, nil
}
return "", fmt.Errorf("Failed resolving group '%v' in location %v", ref, dc)
}

func stateFromString(st string) server.PowerState {
switch st {
case "on", "started":
Expand Down
106 changes: 74 additions & 32 deletions builtin/providers/clc/resource_clc_group.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ package clc
import (
"fmt"
"log"
"time"

"github.com/CenturyLinkCloud/clc-sdk"
"github.com/CenturyLinkCloud/clc-sdk/api"
"github.com/CenturyLinkCloud/clc-sdk/group"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)

Expand All @@ -16,14 +19,6 @@ func resourceCLCGroup() *schema.Resource {
Update: resourceCLCGroupUpdate,
Delete: resourceCLCGroupDelete,
Schema: map[string]*schema.Schema{
"location_id": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"parent": &schema.Schema{
Type: schema.TypeString,
Optional: true,
},
"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
Expand All @@ -33,9 +28,13 @@ func resourceCLCGroup() *schema.Resource {
Optional: true,
Default: "",
},
"id": &schema.Schema{
"parent": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Required: true,
},
"location_id": &schema.Schema{
Type: schema.TypeString,
Required: true,
},
"parent_group_id": &schema.Schema{
Type: schema.TypeString,
Expand All @@ -52,30 +51,34 @@ func resourceCLCGroup() *schema.Resource {

func resourceCLCGroupCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clc.Client)
dc := d.Get("location_id").(string)
m, err := dcGroups(dc, meta)
if err != nil {
return fmt.Errorf("Failed pulling groups in location %v - %v", dc, err)
}
name := d.Get("name").(string)
// use an existing group if we have one
if id, ok := m[name]; ok {
log.Printf("[INFO] Using EXISTING group: %v => %v", name, id)
d.SetId(id)
desc := d.Get("description").(string)
parent := d.Get("parent").(string)
dc := d.Get("location_id").(string)

// clc doesn't enforce uniqueness by name
// so skip the trad'l error we'd raise
e, err := resolveGroupByNameOrId(name, dc, client)
if e != "" {
log.Printf("[INFO] Resolved existing group: %v => %v", name, e)
d.SetId(e)
return nil
}
// otherwise, we're creating one. we'll need a parent
p := d.Get("parent").(string)
if parent, ok := m[p]; ok {
d.Set("parent_group_id", parent)

var pgid string
p, err := resolveGroupByNameOrId(parent, dc, client)
if p != "" {
log.Printf("[INFO] Resolved parent group: %v => %v", parent, p)
pgid = p
} else {
return fmt.Errorf("Failed resolving parent group %s - %s", p, m)
return fmt.Errorf("Failed resolving parent group %s - %s err:%s", parent, p, err)
}

d.Set("parent_group_id", pgid)
spec := group.Group{
Name: name,
Description: d.Get("description").(string),
ParentGroupID: d.Get("parent_group_id").(string),
Description: desc,
ParentGroupID: pgid,
}
resp, err := client.Group.Create(spec)
if err != nil {
Expand All @@ -88,21 +91,60 @@ func resourceCLCGroupCreate(d *schema.ResourceData, meta interface{}) error {

func resourceCLCGroupRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*clc.Client)
id := d.Get("id").(string)
id := d.Id()
g, err := client.Group.Get(id)
if err != nil {
return fmt.Errorf("Failed to find the specified group with id: %s - %s", id, err)
log.Printf("[INFO] Failed finding group: %s - %s. Marking destroyed", id, err)
d.SetId("")
return nil
}
d.Set("name", g.Name)
d.Set("description", g.Description)
// need to traverse links?
//d.Set("parent_group_id", g.ParentGroupID)
d.Set("parent_group_id", g.ParentGroupID())
return nil
}

func resourceCLCGroupUpdate(d *schema.ResourceData, meta interface{}) error {
// unimplemented
return nil
client := meta.(*clc.Client)
id := d.Id()
var err error
var patches []api.Update

g, err := client.Group.Get(id)
if err != nil {
return fmt.Errorf("Failed fetching group: %v - %v", id, err)
}

if delta, orig := d.Get("name").(string), g.Name; delta != orig {
patches = append(patches, group.UpdateName(delta))
}
if delta, orig := d.Get("description").(string), g.Description; delta != orig {
patches = append(patches, group.UpdateDescription(delta))
}
newParent := d.Get("parent").(string)
pgid, err := resolveGroupByNameOrId(newParent, g.Locationid, client)
log.Printf("[DEBUG] PARENT current:%v new:%v resolved:%v", g.ParentGroupID(), newParent, pgid)
if pgid == "" {
return fmt.Errorf("Unable to resolve parent group %v: %v", newParent, err)
} else if newParent != g.ParentGroupID() {
patches = append(patches, group.UpdateParentGroupID(pgid))
}

if len(patches) == 0 {
return nil
}
_, err = client.Group.Update(id, patches...)
if err != nil {
return fmt.Errorf("Failed updating group %v: %v", id, err)
}
//return resourceCLCGroupRead(d, meta)
return resource.Retry(1*time.Minute, func() error {
_, err := client.Group.Get(id)
if err == nil {
return resourceCLCGroupRead(d, meta)
}
return &resource.RetryError{Err: err}
})
}

func resourceCLCGroupDelete(d *schema.ResourceData, meta interface{}) error {
Expand Down
62 changes: 54 additions & 8 deletions builtin/providers/clc/resource_clc_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,29 @@ func TestAccGroupBasic(t *testing.T) {
Config: testAccCheckGroupConfigBasic,
Check: resource.ComposeTestCheckFunc(
testAccCheckGroupExists("clc_group.acc_test_group", &resp),
testAccCheckGroupParent(&resp),
testAccCheckGroupParent(&resp, "Default Group"),
resource.TestCheckResourceAttr(
"clc_group.acc_test_group", "name", "okcomputer"),
resource.TestCheckResourceAttr(
"clc_group.acc_test_group", "location_id", "WA1"),
),
},
resource.TestStep{
Config: testAccCheckGroupConfigUpdate,
Check: resource.ComposeTestCheckFunc(
testAccCheckGroupExists("clc_group.acc_test_group", &resp),
testAccCheckGroupParent(&resp, "Default Group"),
resource.TestCheckResourceAttr(
"clc_group.acc_test_group", "name", "foobar"),
resource.TestCheckResourceAttr(
"clc_group.acc_test_group", "location_id", "WA1"),
),
},
resource.TestStep{
Config: testAccCheckGroupConfigReparent,
Check: resource.ComposeTestCheckFunc(
testAccCheckGroupExists("clc_group.acc_test_group", &resp),
testAccCheckGroupParent(&resp, "reparent"),
resource.TestCheckResourceAttr(
"clc_group.acc_test_group", "name", "foobar"),
resource.TestCheckResourceAttr(
Expand All @@ -51,19 +73,19 @@ func testAccCheckGroupDestroy(s *terraform.State) error {
return nil
}

func testAccCheckGroupParent(resp *group.Response) resource.TestCheckFunc {
func testAccCheckGroupParent(resp *group.Response, expectedName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
client := testAccProvider.Meta().(*clc.Client)
ok, l := resp.Links.GetLink("parentGroup")
if !ok {
return fmt.Errorf("Missing parent group: %v", resp)
}
resp, err := client.Group.Get(l.ID)
parent, err := client.Group.Get(l.ID)
if err != nil {
return fmt.Errorf("Failed fetching parent %v: %v", l.ID, err)
}
if resp.Name != "Default Group" {
return fmt.Errorf("Incorrect parent %v: %v", l, err)
if parent.Name != expectedName {
return fmt.Errorf("Incorrect parent found:'%v' expected:'%v'", parent.Name, expectedName)
}
// would be good to test parent but we'd have to make a bunch of calls
return nil
Expand Down Expand Up @@ -96,7 +118,31 @@ func testAccCheckGroupExists(n string, resp *group.Response) resource.TestCheckF

const testAccCheckGroupConfigBasic = `
resource "clc_group" "acc_test_group" {
location_id = "WA1"
name = "foobar"
parent = "Default Group"
location_id = "WA1"
name = "okcomputer"
description = "mishaps happening"
parent = "Default Group"
}`

const testAccCheckGroupConfigUpdate = `
resource "clc_group" "acc_test_group" {
location_id = "WA1"
name = "foobar"
description = "update test"
parent = "Default Group"
}`

const testAccCheckGroupConfigReparent = `
resource "clc_group" "acc_test_group_reparent" {
location_id = "WA1"
name = "reparent"
description = "introduce a parent group in place"
parent = "Default Group"
}
resource "clc_group" "acc_test_group" {
location_id = "WA1"
name = "foobar"
description = "update test"
parent = "${clc_group.acc_test_group_reparent.id}"
}
`
2 changes: 1 addition & 1 deletion website/source/docs/providers/clc/r/group.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ output "group_id" {

The following arguments are supported:

* `name` - (Required, string) The name of this server group. Will resolve to existing if present.
* `name` - (Required, string) The name (or GUID) of this server group. Will resolve to existing if present.
* `parent` - (Required, string) The name or ID of the parent group. Will error if absent or unable to resolve.
* `location_id` - (Required, string) The datacenter location of both parent group and this group.
Examples: "WA1", "VA1"
Expand Down

0 comments on commit ecdf6d2

Please sign in to comment.