Skip to content

Commit

Permalink
Merge pull request #5864 from spirius/feature/iot-policy-attachment
Browse files Browse the repository at this point in the history
New resource: aws_iot_policy_attachment
  • Loading branch information
bflad committed Oct 29, 2018
2 parents 5aaf64f + 0c2a0e6 commit 12ee9cb
Show file tree
Hide file tree
Showing 5 changed files with 511 additions and 0 deletions.
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -483,6 +483,7 @@ func Provider() terraform.ResourceProvider {
"aws_internet_gateway": resourceAwsInternetGateway(),
"aws_iot_certificate": resourceAwsIotCertificate(),
"aws_iot_policy": resourceAwsIotPolicy(),
"aws_iot_policy_attachment": resourceAwsIotPolicyAttachment(),
"aws_iot_thing": resourceAwsIotThing(),
"aws_iot_thing_type": resourceAwsIotThingType(),
"aws_iot_topic_rule": resourceAwsIotTopicRule(),
Expand Down
137 changes: 137 additions & 0 deletions aws/resource_aws_iot_policy_attachment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package aws

import (
"fmt"
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/iot"
"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsIotPolicyAttachment() *schema.Resource {
return &schema.Resource{
Create: resourceAwsIotPolicyAttachmentCreate,
Read: resourceAwsIotPolicyAttachmentRead,
Delete: resourceAwsIotPolicyAttachmentDelete,
Schema: map[string]*schema.Schema{
"policy": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"target": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
},
}
}

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

policyName := d.Get("policy").(string)
target := d.Get("target").(string)

_, err := conn.AttachPolicy(&iot.AttachPolicyInput{
PolicyName: aws.String(policyName),
Target: aws.String(target),
})

if err != nil {
return fmt.Errorf("error attaching policy %s to target %s: %s", policyName, target, err)
}

d.SetId(fmt.Sprintf("%s|%s", policyName, target))
return resourceAwsIotPolicyAttachmentRead(d, meta)
}

func listIotPolicyAttachmentPages(conn *iot.IoT, input *iot.ListAttachedPoliciesInput,
fn func(out *iot.ListAttachedPoliciesOutput, lastPage bool) bool) error {
for {
page, err := conn.ListAttachedPolicies(input)
if err != nil {
return err
}
lastPage := page.NextMarker == nil

shouldContinue := fn(page, lastPage)
if !shouldContinue || lastPage {
break
}
input.Marker = page.NextMarker
}
return nil
}

func getIotPolicyAttachment(conn *iot.IoT, target, policyName string) (*iot.Policy, error) {
var policy *iot.Policy

input := &iot.ListAttachedPoliciesInput{
PageSize: aws.Int64(250),
Recursive: aws.Bool(false),
Target: aws.String(target),
}

err := listIotPolicyAttachmentPages(conn, input, func(out *iot.ListAttachedPoliciesOutput, lastPage bool) bool {
for _, att := range out.Policies {
if policyName == aws.StringValue(att.PolicyName) {
policy = att
return false
}
}
return true
})

return policy, err
}

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

policyName := d.Get("policy").(string)
target := d.Get("target").(string)

var policy *iot.Policy

policy, err := getIotPolicyAttachment(conn, target, policyName)

if err != nil {
return fmt.Errorf("error listing policy attachments for target %s: %s", target, err)
}

if policy == nil {
log.Printf("[WARN] IOT Policy Attachment (%s) not found, removing from state", d.Id())
d.SetId("")
return nil
}

return nil
}

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

policyName := d.Get("policy").(string)
target := d.Get("target").(string)

_, err := conn.DetachPolicy(&iot.DetachPolicyInput{
PolicyName: aws.String(policyName),
Target: aws.String(target),
})

// DetachPolicy doesn't return an error if the policy doesn't exist,
// but it returns an error if the Target is not found.
if isAWSErr(err, iot.ErrCodeInvalidRequestException, "Invalid Target") {
log.Printf("[WARN] IOT target (%s) not found, removing attachment to policy (%s) from state", target, policyName)
return nil
}

if err != nil {
return fmt.Errorf("error detaching policy %s from target %s: %s", policyName, target, err)
}

return nil
}
Loading

0 comments on commit 12ee9cb

Please sign in to comment.