Skip to content

Commit

Permalink
Add node_identities support to consul_acl_role
Browse files Browse the repository at this point in the history
  • Loading branch information
remilapeyre committed Sep 19, 2021
1 parent 3a5800a commit 144bf26
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 106 deletions.
58 changes: 38 additions & 20 deletions consul/data_source_consul_acl_role.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,19 @@ func dataSourceConsulACLRole() *schema.Resource {
Type: schema.TypeString,
Required: true,
},
"namespace": {
Type: schema.TypeString,
Optional: true,
},

// Out parameters
"description": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},

"policies": {
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Expand All @@ -39,10 +42,9 @@ func dataSourceConsulACLRole() *schema.Resource {
},
},
},

"service_identities": {
Type: schema.TypeList,
Optional: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"service_name": {
Expand All @@ -58,10 +60,21 @@ func dataSourceConsulACLRole() *schema.Resource {
},
},
},

"namespace": {
Type: schema.TypeString,
Optional: true,
"node_identities": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"node_name": {
Type: schema.TypeString,
Computed: true,
},
"datacenter": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
}
Expand All @@ -79,21 +92,13 @@ func datasourceConsulACLRoleRead(d *schema.ResourceData, meta interface{}) error
return fmt.Errorf("Could not find role '%s'", name)
}

d.SetId(role.ID)
if err = d.Set("description", role.Description); err != nil {
return fmt.Errorf("Failed to set 'description': %v", err)
}

policies := make([]map[string]interface{}, len(role.Policies))
for i, p := range role.Policies {
policies[i] = map[string]interface{}{
"name": p.Name,
"id": p.ID,
}
}
if err = d.Set("policies", policies); err != nil {
return fmt.Errorf("Failed to set 'policies': %v", err)
}

identities := make([]map[string]interface{}, len(role.ServiceIdentities))
for i, si := range role.ServiceIdentities {
Expand All @@ -102,9 +107,22 @@ func datasourceConsulACLRoleRead(d *schema.ResourceData, meta interface{}) error
"datacenters": si.Datacenters,
}
}
if err = d.Set("service_identities", identities); err != nil {
return fmt.Errorf("Failed to set 'service_identities': %v", err)

nodeIdentities := make([]interface{}, len(role.NodeIdentities))
for i, ni := range role.NodeIdentities {
nodeIdentities[i] = map[string]interface{}{
"node_name": ni.NodeName,
"datacenter": ni.Datacenter,
}
}

return nil
d.SetId(role.ID)

sw := newStateWriter(d)
sw.set("description", role.Description)
sw.set("policies", policies)
sw.set("service_identities", identities)
sw.set("node_identities", nodeIdentities)

return sw.error()
}
27 changes: 18 additions & 9 deletions consul/data_source_consul_acl_role_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,19 @@ func TestAccDataACLRole_basic(t *testing.T) {
},
{
Config: testAccDataSourceACLRoleConfigBasic,
Check: resource.ComposeTestCheckFunc(
testAccCheckDataSourceValue("data.consul_acl_role.test", "name", "foo"),
testAccCheckDataSourceValue("data.consul_acl_role.test", "description", "bar"),
testAccCheckDataSourceValue("data.consul_acl_role.test", "policies.#", "1"),
testAccCheckDataSourceValue("data.consul_acl_role.test", "policies.0.id", "<any>"),
testAccCheckDataSourceValue("data.consul_acl_role.test", "policies.0.name", "test"),
testAccCheckDataSourceValue("data.consul_acl_role.test", "service_identities.#", "1"),
testAccCheckDataSourceValue("data.consul_acl_role.test", "service_identities.0.service_name", "foo"),
testAccCheckDataSourceValue("data.consul_acl_role.test", "service_identities.0.datacenters.#", "0"),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("data.consul_acl_role.test", "description", "bar"),
resource.TestCheckResourceAttrSet("data.consul_acl_role.test", "id"),
resource.TestCheckResourceAttr("data.consul_acl_role.test", "name", "foo"),
resource.TestCheckResourceAttr("data.consul_acl_role.test", "node_identities.#", "1"),
resource.TestCheckResourceAttr("data.consul_acl_role.test", "node_identities.0.datacenter", "world"),
resource.TestCheckResourceAttr("data.consul_acl_role.test", "node_identities.0.node_name", "hello"),
resource.TestCheckResourceAttr("data.consul_acl_role.test", "policies.#", "1"),
resource.TestCheckResourceAttrSet("data.consul_acl_role.test", "policies.0.id"),
resource.TestCheckResourceAttr("data.consul_acl_role.test", "policies.0.name", "test"),
resource.TestCheckResourceAttr("data.consul_acl_role.test", "service_identities.#", "1"),
resource.TestCheckResourceAttr("data.consul_acl_role.test", "service_identities.0.datacenters.#", "0"),
resource.TestCheckResourceAttr("data.consul_acl_role.test", "service_identities.0.service_name", "foo"),
),
},
},
Expand Down Expand Up @@ -82,6 +86,11 @@ resource "consul_acl_role" "test" {
service_identities {
service_name = "foo"
}
node_identities {
node_name = "hello"
datacenter = "world"
}
}
data "consul_acl_role" "test" {
Expand Down
80 changes: 52 additions & 28 deletions consul/resource_consul_acl_role.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,11 @@ func resourceConsulACLRole() *schema.Resource {
Required: true,
Description: "The name of the ACL role.",
},

"description": {
Type: schema.TypeString,
Optional: true,
Description: "A free form human readable description of the role.",
},

"policies": {
Type: schema.TypeSet,
Optional: true,
Expand All @@ -38,7 +36,6 @@ func resourceConsulACLRole() *schema.Resource {
},
Description: "The list of policies that should be applied to the role.",
},

"service_identities": {
Type: schema.TypeSet,
Optional: true,
Expand All @@ -60,7 +57,25 @@ func resourceConsulACLRole() *schema.Resource {
},
Description: "The list of service identities that should be applied to the role.",
},

"node_identities": {
Type: schema.TypeList,
Optional: true,
Description: "The list of node identities that should be applied to the role.",
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"node_name": {
Type: schema.TypeString,
Required: true,
Description: "The name of the node.",
},
"datacenter": {
Type: schema.TypeString,
Required: true,
Description: "Specifies the node's datacenter.",
},
},
},
},
"namespace": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -98,28 +113,10 @@ func resourceConsulACLRoleRead(d *schema.ResourceData, meta interface{}) error {
return nil
}

if err = d.Set("name", role.Name); err != nil {
return fmt.Errorf("Failed to set 'name': %s", err)
}

if err = d.Set("description", role.Description); err != nil {
return fmt.Errorf("Failed to set 'description': %s", err)
}
// Consul Enterprise will change "" to "default" but Community Edition only
// understands the first one.
if d.Get("namespace").(string) != "" || role.Namespace != "default" {
if err = d.Set("namespace", role.Namespace); err != nil {
return fmt.Errorf("failed to set 'namespace': %v", err)
}
}

policies := make([]string, len(role.Policies))
for i, policy := range role.Policies {
policies[i] = policy.ID
}
if err = d.Set("policies", policies); err != nil {
return fmt.Errorf("Failed to set 'policies': %s", err)
}

serviceIdentities := make([]map[string]interface{}, len(role.ServiceIdentities))
for i, serviceIdentity := range role.ServiceIdentities {
Expand All @@ -128,11 +125,32 @@ func resourceConsulACLRoleRead(d *schema.ResourceData, meta interface{}) error {
"datacenters": serviceIdentity.Datacenters,
}
}
if err = d.Set("service_identities", serviceIdentities); err != nil {
return fmt.Errorf("Failed to set 'service_identities': %s", err)

nodeIdentities := make([]interface{}, len(role.NodeIdentities))
for i, ni := range role.NodeIdentities {
nodeIdentities[i] = map[string]interface{}{
"node_name": ni.NodeName,
"datacenter": ni.Datacenter,
}
}

return nil
sw := newStateWriter(d)

// Consul Enterprise will change "" to "default" but Community Edition only
// understands the first one.
if d.Get("namespace").(string) != "" || role.Namespace != "default" {
if err = d.Set("namespace", role.Namespace); err != nil {
return fmt.Errorf("failed to set 'namespace': %v", err)
}
}

sw.set("name", role.Name)
sw.set("description", role.Description)
sw.set("policies", policies)
sw.set("service_identities", serviceIdentities)
sw.set("node_identities", nodeIdentities)

return sw.error()
}

func resourceConsulACLRoleUpdate(d *schema.ResourceData, meta interface{}) error {
Expand Down Expand Up @@ -179,7 +197,6 @@ func getRole(d *schema.ResourceData, meta interface{}) *consulapi.ACLRole {
}
role.Policies = policies

serviceIdentities := make([]*consulapi.ACLServiceIdentity, 0)
for _, raw := range d.Get("service_identities").(*schema.Set).List() {
s := raw.(map[string]interface{})

Expand All @@ -188,12 +205,19 @@ func getRole(d *schema.ResourceData, meta interface{}) *consulapi.ACLRole {
datacenters[i] = d.(string)
}

serviceIdentities = append(serviceIdentities, &consulapi.ACLServiceIdentity{
role.ServiceIdentities = append(role.ServiceIdentities, &consulapi.ACLServiceIdentity{
ServiceName: s["service_name"].(string),
Datacenters: datacenters,
})
}
role.ServiceIdentities = serviceIdentities

for _, ni := range d.Get("node_identities").([]interface{}) {
n := ni.(map[string]interface{})
role.NodeIdentities = append(role.NodeIdentities, &consulapi.ACLNodeIdentity{
NodeName: n["node_name"].(string),
Datacenter: n["datacenter"].(string),
})
}

return role
}
64 changes: 25 additions & 39 deletions consul/resource_consul_acl_role_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,58 +18,39 @@ func TestAccConsulACLRole_basic(t *testing.T) {
Steps: []resource.TestStep{
{
Config: testResourceACLRoleConfigBasic,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("consul_acl_role.test", "name", "foo"),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("consul_acl_role.test", "description", "bar"),
resource.TestCheckResourceAttrSet("consul_acl_role.test", "id"),
resource.TestCheckResourceAttr("consul_acl_role.test", "name", "foo"),
resource.TestCheckResourceAttr("consul_acl_role.test", "namespace", ""),
resource.TestCheckResourceAttr("consul_acl_role.test", "node_identities.#", "0"),
resource.TestCheckResourceAttr("consul_acl_role.test", "policies.#", "1"),
resource.TestCheckResourceAttr("consul_acl_role.test", "service_identities.#", "1"),
resource.TestCheckResourceAttr("consul_acl_role.test", "service_identities.3690720679.datacenters.#", "0"),
resource.TestCheckResourceAttr("consul_acl_role.test", "service_identities.3690720679.service_name", "foo"),
),
},
{
Config: testResourceACLRoleConfigUpdate,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("consul_acl_role.test", "name", "baz"),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr("consul_acl_role.test", "description", ""),
resource.TestCheckResourceAttrSet("consul_acl_role.test", "id"),
resource.TestCheckResourceAttr("consul_acl_role.test", "name", "baz"),
resource.TestCheckResourceAttr("consul_acl_role.test", "namespace", ""),
resource.TestCheckResourceAttr("consul_acl_role.test", "node_identities.#", "1"),
resource.TestCheckResourceAttr("consul_acl_role.test", "node_identities.0.datacenter", "world"),
resource.TestCheckResourceAttr("consul_acl_role.test", "node_identities.0.node_name", "hello"),
resource.TestCheckResourceAttr("consul_acl_role.test", "policies.#", "0"),
resource.TestCheckResourceAttr("consul_acl_role.test", "service_identities.#", "1"),
resource.TestCheckResourceAttr("consul_acl_role.test", "service_identities.2708159462.datacenters.#", "0"),
resource.TestCheckResourceAttr("consul_acl_role.test", "service_identities.2708159462.service_name", "bar"),
),
},
},
})
}

func TestAccConsulACLRole_import(t *testing.T) {
checkFn := func(s []*terraform.InstanceState) error {
if len(s) != 1 {
return fmt.Errorf("bad state: %s", s)
}
v, ok := s[0].Attributes["name"]
if !ok || v != "foo" {
return fmt.Errorf("bad name: %s", s)
}
v, ok = s[0].Attributes["description"]
if !ok || v != "bar" {
return fmt.Errorf("bad description: %s", s)
}
v, ok = s[0].Attributes["policies.#"]
if !ok || v != "1" {
return fmt.Errorf("bad policies: %s", s)
}

return nil
}

resource.Test(t, resource.TestCase{
Providers: testAccProviders,
PreCheck: func() { testAccPreCheck(t) },
Steps: []resource.TestStep{
{
Config: testResourceACLRoleConfigBasic,
},
{
ResourceName: "consul_acl_role.test",
ImportState: true,
ImportStateCheck: checkFn,
Config: testResourceACLRoleConfigUpdate,
ResourceName: "consul_acl_role.test",
ImportState: true,
ImportStateVerify: true,
},
},
})
Expand Down Expand Up @@ -143,6 +124,11 @@ resource "consul_acl_role" "test" {
service_identities {
service_name = "bar"
}
node_identities {
node_name = "hello"
datacenter = "world"
}
}`

const testResourceACLRoleNamespaceCE = `
Expand Down
9 changes: 5 additions & 4 deletions website/docs/d/acl_role.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ The following arguments are supported:

The following attributes are exported:

* `name` - The name of the ACL Role.
* `namespace` - The namespace to lookup the role.
* `description` - The description of the ACL Role.
* `policies` - The list of policies associated with the ACL Role. Each entry has
an `id` and a `name` attribute.
* `service_identities` - The list of service identities associated with the ACL
Role. Each entry has a `service_name` attribute and a list of `datacenters`.
* `policies` - The list of policies associated with the ACL Role. Each entry has an `id` and a `name` attribute.
* `service_identities` - The list of service identities associated with the ACL Role. Each entry has a `service_name` attribute and a list of `datacenters`.
* `node_identities` - The list of node identities associated with the ACL Role. Each entry has a `node_name` and a `datacenter` attributes.
Loading

0 comments on commit 144bf26

Please sign in to comment.