From 03cabb7b7e05d0db0c81b6b29beb51c2fcd925f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Pinson?= Date: Tue, 28 Mar 2017 09:53:45 +0200 Subject: [PATCH 1/8] rancher_environment: add member support --- .../rancher/resource_rancher_environment.go | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) diff --git a/builtin/providers/rancher/resource_rancher_environment.go b/builtin/providers/rancher/resource_rancher_environment.go index 99c79c61b4..c9c06e630b 100644 --- a/builtin/providers/rancher/resource_rancher_environment.go +++ b/builtin/providers/rancher/resource_rancher_environment.go @@ -1,11 +1,13 @@ package rancher import ( + "bytes" "fmt" "log" "strings" "time" + "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/validation" @@ -41,6 +43,28 @@ func resourceRancherEnvironment() *schema.Resource { Type: schema.TypeString, Optional: true, }, + "member": &schema.Schema{ + Type: schema.TypeSet, + Optional: true, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "external_id_type": { + Type: schema.TypeString, + Required: true, + }, + "external_id": { + Type: schema.TypeString, + Required: true, + }, + "role": { + Type: schema.TypeString, + Required: true, + }, + }, + }, + Set: memberHash, + }, }, } } @@ -85,6 +109,19 @@ func resourceRancherEnvironmentCreate(d *schema.ResourceData, meta interface{}) d.SetId(newEnv.Id) log.Printf("[INFO] Environment ID: %s", d.Id()) + // Add members + envClient, err := meta.(*Config).EnvironmentClient(d.Id()) + if err != nil { + return err + } + members := d.Get("members").([]interface{}) + _, err = envClient.Project.ActionSetmembers(&newEnv, &rancherClient.SetProjectMembersInput{ + Members: members, + }) + if err != nil { + return err + } + return resourceRancherEnvironmentRead(d, meta) } @@ -118,6 +155,14 @@ func resourceRancherEnvironmentRead(d *schema.ResourceData, meta interface{}) er d.Set("name", env.Name) d.Set("orchestration", getActiveOrchestration(env)) + envClient, err := meta.(*Config).EnvironmentClient(d.Id()) + if err != nil { + return err + } + + members, _ := envClient.ProjectMember.List(NewListOpts()) + + d.Set("member", normalizeMembers(members.Data)) return nil } @@ -148,6 +193,19 @@ func resourceRancherEnvironmentUpdate(d *schema.ResourceData, meta interface{}) return err } + // Update members + envClient, err := meta.(*Config).EnvironmentClient(d.Id()) + if err != nil { + return err + } + members := d.Get("member").(*schema.Set).List() + _, err = envClient.Project.ActionSetmembers(&newEnv, &rancherClient.SetProjectMembersInput{ + Members: makeProjectMembers(members), + }) + if err != nil { + return err + } + return resourceRancherEnvironmentRead(d, meta) } @@ -203,6 +261,39 @@ func setOrchestrationFields(orchestration string, data map[string]interface{}) { data[orch] = true } +func normalizeMembers(in []rancherClient.ProjectMember) (out []interface{}) { + for _, m := range in { + mm := map[string]string{ + "external_id_type": m.ExternalIdType, + "external_id": m.ExternalId, + "role": m.Role, + } + out = append(out, mm) + } + return +} + +func makeProjectMembers(in []interface{}) (out []interface{}) { + for _, m := range in { + mMap := m.(map[string]interface{}) + mm := rancherClient.ProjectMember{ + ExternalIdType: mMap["external_id_type"].(string), + ExternalId: mMap["external_id"].(string), + Role: mMap["role"].(string), + } + out = append(out, mm) + } + return +} + +func memberHash(member interface{}) int { + var buf bytes.Buffer + m := member.(map[string]interface{}) + buf.WriteString(fmt.Sprintf("%s-", m["external_id_type"])) + buf.WriteString(fmt.Sprintf("%s-", m["external_id"])) + return hashcode.String(buf.String()) +} + // EnvironmentStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch // a Rancher Environment. func EnvironmentStateRefreshFunc(client *rancherClient.RancherClient, environmentID string) resource.StateRefreshFunc { From 01e9011231034eb3134e516046cb5af43f1383fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Pinson?= Date: Wed, 17 May 2017 10:30:16 +0200 Subject: [PATCH 2/8] rancher_environment: member doc --- .../docs/providers/rancher/r/environment.html.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/website/source/docs/providers/rancher/r/environment.html.md b/website/source/docs/providers/rancher/r/environment.html.md index cb4c1b8f68..54bfa0147e 100644 --- a/website/source/docs/providers/rancher/r/environment.html.md +++ b/website/source/docs/providers/rancher/r/environment.html.md @@ -18,6 +18,18 @@ resource "rancher_environment" "default" { name = "staging" description = "The staging environment" orchestration = "cattle" + + member { + external_id = "650430" + external_id_type = "github_user" + role = "owner" + } + + member { + external_id = "1234" + external_id_type = "github_team" + role = "member" + } } ``` @@ -28,6 +40,7 @@ The following arguments are supported: * `name` - (Required) The name of the environment. * `description` - (Optional) An environment description. * `orchestration` - (Optional) Must be one of **cattle**, **swarm**, **mesos** or **kubernetes**. Defaults to **cattle**. +* `member` - (Optional) Members to add to the environment. Each member has `external_id`, `external_id_type` and `role` values. ## Attributes Reference From d75ff931659a3aa5956fb853e789e931beb81893 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Pinson?= Date: Wed, 17 May 2017 18:20:33 +0200 Subject: [PATCH 3/8] rancher_environment: do not crash on empty members --- .../rancher/resource_rancher_environment.go | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/builtin/providers/rancher/resource_rancher_environment.go b/builtin/providers/rancher/resource_rancher_environment.go index c9c06e630b..19f098ff7f 100644 --- a/builtin/providers/rancher/resource_rancher_environment.go +++ b/builtin/providers/rancher/resource_rancher_environment.go @@ -114,12 +114,14 @@ func resourceRancherEnvironmentCreate(d *schema.ResourceData, meta interface{}) if err != nil { return err } - members := d.Get("members").([]interface{}) - _, err = envClient.Project.ActionSetmembers(&newEnv, &rancherClient.SetProjectMembersInput{ - Members: members, - }) - if err != nil { - return err + if v, ok := d.GetOk("members"); ok { + members := v.([]interface{}) + _, err = envClient.Project.ActionSetmembers(&newEnv, &rancherClient.SetProjectMembersInput{ + Members: members, + }) + if err != nil { + return err + } } return resourceRancherEnvironmentRead(d, meta) From b6c9b2dc7abde5ed00d3836477dae94bfe6202f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Pinson?= Date: Wed, 17 May 2017 18:20:47 +0200 Subject: [PATCH 4/8] Test members --- .../resource_rancher_environment_test.go | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/builtin/providers/rancher/resource_rancher_environment_test.go b/builtin/providers/rancher/resource_rancher_environment_test.go index ec8a81d7c7..6474efaf61 100644 --- a/builtin/providers/rancher/resource_rancher_environment_test.go +++ b/builtin/providers/rancher/resource_rancher_environment_test.go @@ -60,6 +60,38 @@ func TestAccRancherEnvironment_disappears(t *testing.T) { }) } +func TestAccRancherEnvironment_members(t *testing.T) { + var environment rancherClient.Project + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckRancherEnvironmentDestroy, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccRancherEnvironmentMembersConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckRancherEnvironmentExists("rancher_environment.foo", &environment), + resource.TestCheckResourceAttr("rancher_environment.foo", "name", "foo"), + resource.TestCheckResourceAttr("rancher_environment.foo", "description", "Terraform acc test group"), + resource.TestCheckResourceAttr("rancher_environment.foo", "orchestration", "cattle"), + resource.TestCheckResourceAttr("rancher_environment.foo", "member.#", "2"), + ), + }, + resource.TestStep{ + Config: testAccRancherEnvironmentMembersUpdateConfig, + Check: resource.ComposeTestCheckFunc( + testAccCheckRancherEnvironmentExists("rancher_environment.foo", &environment), + resource.TestCheckResourceAttr("rancher_environment.foo", "name", "foo2"), + resource.TestCheckResourceAttr("rancher_environment.foo", "description", "Terraform acc test group - updated"), + resource.TestCheckResourceAttr("rancher_environment.foo", "orchestration", "swarm"), + resource.TestCheckResourceAttr("rancher_environment.foo", "member.#", "1"), + ), + }, + }, + }) +} + func testAccRancherEnvironmentDisappears(env *rancherClient.Project) resource.TestCheckFunc { return func(s *terraform.State) error { client, err := testAccProvider.Meta().(*Config).GlobalClient() @@ -159,3 +191,37 @@ resource "rancher_environment" "foo" { orchestration = "swarm" } ` + +const testAccRancherEnvironmentMembersConfig = ` +resource "rancher_environment" "foo" { + name = "foo" + description = "Terraform acc test group" + orchestration = "cattle" + + member { + external_id = "1234" + external_id_type = "github_user" + role = "owner" + } + + member { + external_id = "8765" + external_id_type = "github_team" + role = "member" + } +} +` + +const testAccRancherEnvironmentMembersUpdateConfig = ` +resource "rancher_environment" "foo" { + name = "foo" + description = "Terraform acc test group" + orchestration = "cattle" + + member { + external_id = "1235" + external_id_type = "github_user" + role = "owner" + } +} +` From 4f521c74b0c4b4a06182c38cbfd501edef3d270a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Pinson?= Date: Thu, 18 May 2017 09:21:27 +0200 Subject: [PATCH 5/8] rancher_environment: do not use a custom set function for members --- .../providers/rancher/resource_rancher_environment.go | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/builtin/providers/rancher/resource_rancher_environment.go b/builtin/providers/rancher/resource_rancher_environment.go index 19f098ff7f..6b3f42e464 100644 --- a/builtin/providers/rancher/resource_rancher_environment.go +++ b/builtin/providers/rancher/resource_rancher_environment.go @@ -1,13 +1,11 @@ package rancher import ( - "bytes" "fmt" "log" "strings" "time" - "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/helper/validation" @@ -63,7 +61,6 @@ func resourceRancherEnvironment() *schema.Resource { }, }, }, - Set: memberHash, }, }, } @@ -288,14 +285,6 @@ func makeProjectMembers(in []interface{}) (out []interface{}) { return } -func memberHash(member interface{}) int { - var buf bytes.Buffer - m := member.(map[string]interface{}) - buf.WriteString(fmt.Sprintf("%s-", m["external_id_type"])) - buf.WriteString(fmt.Sprintf("%s-", m["external_id"])) - return hashcode.String(buf.String()) -} - // EnvironmentStateRefreshFunc returns a resource.StateRefreshFunc that is used to watch // a Rancher Environment. func EnvironmentStateRefreshFunc(client *rancherClient.RancherClient, environmentID string) resource.StateRefreshFunc { From 1392670a69be5eda7939f12cd1e39cd5d75a12ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Pinson?= Date: Thu, 18 May 2017 09:35:13 +0200 Subject: [PATCH 6/8] rancher_environment: initialize envClient only when members are set --- builtin/providers/rancher/resource_rancher_environment.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/builtin/providers/rancher/resource_rancher_environment.go b/builtin/providers/rancher/resource_rancher_environment.go index 6b3f42e464..593dc61986 100644 --- a/builtin/providers/rancher/resource_rancher_environment.go +++ b/builtin/providers/rancher/resource_rancher_environment.go @@ -107,11 +107,11 @@ func resourceRancherEnvironmentCreate(d *schema.ResourceData, meta interface{}) log.Printf("[INFO] Environment ID: %s", d.Id()) // Add members - envClient, err := meta.(*Config).EnvironmentClient(d.Id()) - if err != nil { - return err - } if v, ok := d.GetOk("members"); ok { + envClient, err := meta.(*Config).EnvironmentClient(d.Id()) + if err != nil { + return err + } members := v.([]interface{}) _, err = envClient.Project.ActionSetmembers(&newEnv, &rancherClient.SetProjectMembersInput{ Members: members, From 87b502d5cf13f96dbe7b7ec0772a352210acb9b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Pinson?= Date: Thu, 18 May 2017 15:20:42 +0200 Subject: [PATCH 7/8] rancher_environment: fix typo --- builtin/providers/rancher/resource_rancher_environment.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/providers/rancher/resource_rancher_environment.go b/builtin/providers/rancher/resource_rancher_environment.go index 593dc61986..39025855e7 100644 --- a/builtin/providers/rancher/resource_rancher_environment.go +++ b/builtin/providers/rancher/resource_rancher_environment.go @@ -107,7 +107,7 @@ func resourceRancherEnvironmentCreate(d *schema.ResourceData, meta interface{}) log.Printf("[INFO] Environment ID: %s", d.Id()) // Add members - if v, ok := d.GetOk("members"); ok { + if v, ok := d.GetOk("member"); ok { envClient, err := meta.(*Config).EnvironmentClient(d.Id()) if err != nil { return err From d0e5ee0a272c2342d591d6a2e2a04ad0b133eaef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Pinson?= Date: Thu, 18 May 2017 15:22:48 +0200 Subject: [PATCH 8/8] rancher_environment: member documentation details --- .../docs/providers/rancher/r/environment.html.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/website/source/docs/providers/rancher/r/environment.html.md b/website/source/docs/providers/rancher/r/environment.html.md index 54bfa0147e..0e2548b78a 100644 --- a/website/source/docs/providers/rancher/r/environment.html.md +++ b/website/source/docs/providers/rancher/r/environment.html.md @@ -40,7 +40,16 @@ The following arguments are supported: * `name` - (Required) The name of the environment. * `description` - (Optional) An environment description. * `orchestration` - (Optional) Must be one of **cattle**, **swarm**, **mesos** or **kubernetes**. Defaults to **cattle**. -* `member` - (Optional) Members to add to the environment. Each member has `external_id`, `external_id_type` and `role` values. +* `member` - (Optional) Members to add to the environment. + +### Member Parameters Reference + +A `member` takes three parameters: + +* `external_id` - (Required) The external ID of the member. +* `external_id_type` - (Required) The external ID type of the member. +* `role` - (Required) The role of the member in the environment. + ## Attributes Reference