Skip to content

Commit

Permalink
Merge pull request #18585 from jlamande/f-data_source-aws_iam_roles
Browse files Browse the repository at this point in the history
Create data source for aws iam roles
  • Loading branch information
anGie44 authored Aug 18, 2021
2 parents 201b2b1 + c4a413c commit 8224439
Show file tree
Hide file tree
Showing 5 changed files with 415 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/18585.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-data-source
aws_iam_roles
```
94 changes: 94 additions & 0 deletions aws/data_source_aws_iam_roles.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package aws

import (
"fmt"
"regexp"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

func dataSourceAwsIAMRoles() *schema.Resource {
return &schema.Resource{
Read: dataSourceAwsIAMRolesRead,

Schema: map[string]*schema.Schema{
"arns": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"name_regex": {
Type: schema.TypeString,
Optional: true,
ValidateFunc: validation.StringIsValidRegExp,
},
"names": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"path_prefix": {
Type: schema.TypeString,
Optional: true,
},
},
}
}

func dataSourceAwsIAMRolesRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).iamconn

input := &iam.ListRolesInput{}

if v, ok := d.GetOk("path_prefix"); ok {
input.PathPrefix = aws.String(v.(string))
}

var results []*iam.Role

err := conn.ListRolesPages(input, func(page *iam.ListRolesOutput, lastPage bool) bool {
if page == nil {
return !lastPage
}

for _, role := range page.Roles {
if role == nil {
continue
}

if v, ok := d.GetOk("name_regex"); ok && !regexp.MustCompile(v.(string)).MatchString(aws.StringValue(role.RoleName)) {
continue
}

results = append(results, role)
}

return !lastPage
})

if err != nil {
return fmt.Errorf("error reading IAM roles: %w", err)
}

d.SetId(meta.(*AWSClient).region)

var arns, names []string

for _, r := range results {
arns = append(arns, aws.StringValue(r.Arn))
names = append(names, aws.StringValue(r.RoleName))
}

if err := d.Set("arns", arns); err != nil {
return fmt.Errorf("error setting arns: %w", err)
}

if err := d.Set("names", names); err != nil {
return fmt.Errorf("error setting names: %w", err)
}

return nil
}
228 changes: 228 additions & 0 deletions aws/data_source_aws_iam_roles_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,228 @@
package aws

import (
"fmt"
"regexp"
"strconv"
"testing"

"github.com/aws/aws-sdk-go/service/iam"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestAccAWSIAMRolesDataSource_basic(t *testing.T) {
dataSourceName := "data.aws_iam_roles.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, iam.EndpointsID),
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccAWSIAMRolesConfigDataSource_basic,
Check: resource.ComposeTestCheckFunc(
resource.TestMatchResourceAttr(dataSourceName, "names.#", regexp.MustCompile("[^0].*$")),
),
},
},
})
}

func TestAccAWSIAMRolesDataSource_nameRegex(t *testing.T) {
rCount := strconv.Itoa(acctest.RandIntRange(1, 4))
rName := acctest.RandomWithPrefix("tf-acc-test")
dataSourceName := "data.aws_iam_roles.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, iam.EndpointsID),
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccAWSIAMRolesConfigDataSource_nameRegex(rCount, rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(dataSourceName, "names.#", rCount),
resource.TestCheckResourceAttr(dataSourceName, "arns.#", rCount),
),
},
},
})
}

func TestAccAWSIAMRolesDataSource_pathPrefix(t *testing.T) {
rCount := strconv.Itoa(acctest.RandIntRange(1, 4))
rName := acctest.RandomWithPrefix("tf-acc-test")
rPathPrefix := acctest.RandomWithPrefix("tf-acc-path")
dataSourceName := "data.aws_iam_roles.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, iam.EndpointsID),
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccAWSIAMRolesConfigDataSource_pathPrefix(rCount, rName, rPathPrefix),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(dataSourceName, "names.#", rCount),
resource.TestCheckResourceAttr(dataSourceName, "arns.#", rCount),
),
},
},
})
}

func TestAccAWSIAMRolesDataSource_nonExistentPathPrefix(t *testing.T) {
dataSourceName := "data.aws_iam_roles.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, iam.EndpointsID),
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccAWSIAMRolesConfigDataSource_nonExistentPathPrefix,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(dataSourceName, "arns.#", "0"),
resource.TestCheckResourceAttr(dataSourceName, "names.#", "0"),
),
},
},
})
}

func TestAccAWSIAMRolesDataSource_nameRegexAndPathPrefix(t *testing.T) {
rCount := strconv.Itoa(acctest.RandIntRange(1, 4))
rName := acctest.RandomWithPrefix("tf-acc-test")
rPathPrefix := acctest.RandomWithPrefix("tf-acc-path")
dataSourceName := "data.aws_iam_roles.test"

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ErrorCheck: testAccErrorCheck(t, iam.EndpointsID),
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccAWSIAMRolesConfigDataSource_nameRegexAndPathPrefix(rCount, rName, rPathPrefix, "0"),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(dataSourceName, "names.#", "1"),
resource.TestCheckResourceAttr(dataSourceName, "arns.#", "1"),
),
},
},
})
}

const testAccAWSIAMRolesConfigDataSource_basic = `
data "aws_iam_roles" "test" {}
`

func testAccAWSIAMRolesConfigDataSource_nameRegex(rCount, rName string) string {
return fmt.Sprintf(`
data "aws_partition" "current" {}
resource "aws_iam_role" "test" {
count = %[1]s
name = "%[2]s-${count.index}-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.${data.aws_partition.current.dns_suffix}"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
tags = {
Seed = %[2]q
}
}
data "aws_iam_roles" "test" {
name_regex = "${aws_iam_role.test[0].tags["Seed"]}-.*-role"
}
`, rCount, rName)
}

func testAccAWSIAMRolesConfigDataSource_pathPrefix(rCount, rName, rPathPrefix string) string {
return fmt.Sprintf(`
data "aws_partition" "current" {}
resource "aws_iam_role" "test" {
count = %[1]s
name = "%[2]s-${count.index}-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.${data.aws_partition.current.dns_suffix}"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
path = "/%[3]s/"
}
data "aws_iam_roles" "test" {
path_prefix = aws_iam_role.test[0].path
}
`, rCount, rName, rPathPrefix)
}

const testAccAWSIAMRolesConfigDataSource_nonExistentPathPrefix = `
data "aws_iam_roles" "test" {
path_prefix = "/dne/path"
}
`

func testAccAWSIAMRolesConfigDataSource_nameRegexAndPathPrefix(rCount, rName, rPathPrefix, rIndex string) string {
return fmt.Sprintf(`
data "aws_partition" "current" {}
resource "aws_iam_role" "test" {
count = %[1]s
name = "%[2]s-${count.index}-role"
assume_role_policy = <<EOF
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "sts:AssumeRole",
"Principal": {
"Service": "ec2.${data.aws_partition.current.dns_suffix}"
},
"Effect": "Allow",
"Sid": ""
}
]
}
EOF
path = "/%[3]s/"
tags = {
Seed = %[2]q
}
}
data "aws_iam_roles" "test" {
name_regex = "${aws_iam_role.test[0].tags["Seed"]}-%[4]s-role"
path_prefix = aws_iam_role.test[0].path
}
`, rCount, rName, rPathPrefix, rIndex)
}
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@ func Provider() *schema.Provider {
"aws_iam_policy": dataSourceAwsIAMPolicy(),
"aws_iam_policy_document": dataSourceAwsIamPolicyDocument(),
"aws_iam_role": dataSourceAwsIAMRole(),
"aws_iam_roles": dataSourceAwsIAMRoles(),
"aws_iam_server_certificate": dataSourceAwsIAMServerCertificate(),
"aws_iam_session_context": dataSourceAwsIAMSessionContext(),
"aws_iam_user": dataSourceAwsIAMUser(),
Expand Down
Loading

0 comments on commit 8224439

Please sign in to comment.