Skip to content

Commit

Permalink
r/aws_ram_resource_share: Add new aws_ram_resource_share resource
Browse files Browse the repository at this point in the history
  • Loading branch information
gazoakley committed Dec 28, 2018
1 parent 6cb94d4 commit 5ad9071
Show file tree
Hide file tree
Showing 8 changed files with 620 additions and 0 deletions.
5 changes: 5 additions & 0 deletions aws/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ import (
"github.com/aws/aws-sdk-go/service/organizations"
"github.com/aws/aws-sdk-go/service/pinpoint"
"github.com/aws/aws-sdk-go/service/pricing"
"github.com/aws/aws-sdk-go/service/ram"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/aws/aws-sdk-go/service/redshift"
"github.com/aws/aws-sdk-go/service/route53"
Expand Down Expand Up @@ -149,6 +150,7 @@ type Config struct {
KinesisAnalyticsEndpoint string
KmsEndpoint string
LambdaEndpoint string
RamEndpoint string
RdsEndpoint string
R53Endpoint string
S3Endpoint string
Expand Down Expand Up @@ -216,6 +218,7 @@ type AWSClient struct {
accountid string
supportedplatforms []string
region string
ramconn *ram.RAM
rdsconn *rds.RDS
iamconn *iam.IAM
kinesisconn *kinesis.Kinesis
Expand Down Expand Up @@ -436,6 +439,7 @@ func (c *Config) Client() (interface{}, error) {
awsKinesisSess := sess.Copy(&aws.Config{Endpoint: aws.String(c.KinesisEndpoint)})
awsKinesisAnalyticsSess := sess.Copy(&aws.Config{Endpoint: aws.String(c.KinesisAnalyticsEndpoint)})
awsKmsSess := sess.Copy(&aws.Config{Endpoint: aws.String(c.KmsEndpoint)})
awsRamSess := sess.Copy(&aws.Config{Endpoint: aws.String(c.RamEndpoint)})
awsRdsSess := sess.Copy(&aws.Config{Endpoint: aws.String(c.RdsEndpoint)})
awsS3Sess := sess.Copy(&aws.Config{Endpoint: aws.String(c.S3Endpoint)})
awsS3ControlSess := sess.Copy(&aws.Config{Endpoint: aws.String(c.S3ControlEndpoint)})
Expand Down Expand Up @@ -570,6 +574,7 @@ func (c *Config) Client() (interface{}, error) {
client.opsworksconn = opsworks.New(sess)
client.organizationsconn = organizations.New(sess)
client.r53conn = route53.New(r53Sess)
client.ramconn = ram.New(awsRamSess)
client.rdsconn = rds.New(awsRdsSess)
client.redshiftconn = redshift.New(sess)
client.simpledbconn = simpledb.New(sess)
Expand Down
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,7 @@ func Provider() terraform.ResourceProvider {
"aws_organizations_policy_attachment": resourceAwsOrganizationsPolicyAttachment(),
"aws_placement_group": resourceAwsPlacementGroup(),
"aws_proxy_protocol_policy": resourceAwsProxyProtocolPolicy(),
"aws_ram_resource_share": resourceAwsRamResourceShare(),
"aws_rds_cluster": resourceAwsRDSCluster(),
"aws_rds_cluster_endpoint": resourceAwsRDSClusterEndpoint(),
"aws_rds_cluster_instance": resourceAwsRDSClusterInstance(),
Expand Down
241 changes: 241 additions & 0 deletions aws/resource_aws_ram_resource_share.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,241 @@
package aws

import (
"fmt"
"log"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ram"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)

func resourceAwsRamResourceShare() *schema.Resource {
return &schema.Resource{
Create: resourceAwsRamResourceShareCreate,
Read: resourceAwsRamResourceShareRead,
Update: resourceAwsRamResourceShareUpdate,
Delete: resourceAwsRamResourceShareDelete,

Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Timeouts: &schema.ResourceTimeout{
Create: schema.DefaultTimeout(5 * time.Minute),
Delete: schema.DefaultTimeout(5 * time.Minute),
},

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
},

"allow_external_principals": {
Type: schema.TypeBool,
Optional: true,
Default: false,
},

"tags": tagsSchema(),
},
}
}

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

request := &ram.CreateResourceShareInput{
Name: aws.String(d.Get("name").(string)),
AllowExternalPrincipals: aws.Bool(d.Get("allow_external_principals").(bool)),
}

if v, ok := d.GetOk("tags"); ok {
tags := tagsFromMapRAM(v.(map[string]interface{}))
request.Tags = tags
}

log.Println("[DEBUG] Create RAM resource share request:", request)
createResp, err := conn.CreateResourceShare(request)
if err != nil {
return fmt.Errorf("Error creating RAM resource share: %s", err)
}

d.SetId(aws.StringValue(createResp.ResourceShare.ResourceShareArn))

stateConf := &resource.StateChangeConf{
Pending: []string{ram.ResourceShareStatusPending},
Target: []string{ram.ResourceShareStatusActive},
Refresh: resourceAwsRamResourceShareStateRefreshFunc(conn, d.Id()),
Timeout: d.Timeout(schema.TimeoutCreate),
}

_, err = stateConf.WaitForState()
if err != nil {
return fmt.Errorf("Error waiting for RAM resource share (%s) to become ready: %s", d.Id(), err)
}

return resourceAwsRamResourceShareRead(d, meta)
}

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

request := &ram.GetResourceSharesInput{
ResourceShareArns: []*string{aws.String(d.Id())},
ResourceOwner: aws.String(ram.ResourceOwnerSelf),
}

output, err := conn.GetResourceShares(request)
if err != nil {
if isAWSErr(err, ram.ErrCodeUnknownResourceException, "") {
log.Printf("[WARN] No RAM resource share by ARN (%s) found, removing from state", d.Id())
d.SetId("")
return nil
}
return fmt.Errorf("Error reading RAM resource share %s: %s", d.Id(), err)
}

if len(output.ResourceShares) == 0 {
log.Printf("[WARN] No RAM resource share by ARN (%s) found, removing from state", d.Id())
d.SetId("")
return nil
}

resourceShare := output.ResourceShares[0]

if aws.StringValue(resourceShare.Status) != ram.ResourceShareStatusActive {
log.Printf("[WARN] RAM resource share (%s) delet(ing|ed), removing from state", d.Id())
d.SetId("")
return nil
}

d.Set("name", resourceShare.Name)
d.Set("allow_external_principals", resourceShare.AllowExternalPrincipals)

if err := d.Set("tags", tagsToMapRAM(resourceShare.Tags)); err != nil {
return fmt.Errorf("Error setting tags: %s", err)
}

return nil
}

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

d.Partial(true)

if d.HasChange("name") || d.HasChange("allow_external_principals") {
request := &ram.UpdateResourceShareInput{
ResourceShareArn: aws.String(d.Id()),
Name: aws.String(d.Get("name").(string)),
AllowExternalPrincipals: aws.Bool(d.Get("allow_external_principals").(bool)),
}

log.Println("[DEBUG] Update RAM resource share request:", request)
_, err := conn.UpdateResourceShare(request)
if err != nil {
if isAWSErr(err, ram.ErrCodeUnknownResourceException, "") {
log.Printf("[WARN] No RAM resource share by ARN (%s) found", d.Id())
d.SetId("")
return nil
}
return fmt.Errorf("Error updating RAM resource share %s: %s", d.Id(), err)
}

d.SetPartial("name")
d.SetPartial("allow_external_principals")
}

if d.HasChange("tags") {
// Reset all tags to empty set
oraw, nraw := d.GetChange("tags")
o := oraw.(map[string]interface{})
n := nraw.(map[string]interface{})
c, r := diffTagsRAM(tagsFromMapRAM(o), tagsFromMapRAM(n))

if len(r) > 0 {
_, err := conn.UntagResource(&ram.UntagResourceInput{
ResourceShareArn: aws.String(d.Id()),
TagKeys: tagKeysRam(r),
})
if err != nil {
return fmt.Errorf("Error deleting RAM resource share tags: %s", err)
}
}

if len(c) > 0 {
input := &ram.TagResourceInput{
ResourceShareArn: aws.String(d.Id()),
Tags: c,
}
_, err := conn.TagResource(input)
if err != nil {
return fmt.Errorf("Error updating RAM resource share tags: %s", err)
}
}

d.SetPartial("tags")
}

d.Partial(false)

return resourceAwsRamResourceShareRead(d, meta)
}

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

deleteResourceShareInput := &ram.DeleteResourceShareInput{
ResourceShareArn: aws.String(d.Id()),
}

log.Println("[DEBUG] Delete RAM resource share request:", deleteResourceShareInput)
_, err := conn.DeleteResourceShare(deleteResourceShareInput)
if err != nil {
if isAWSErr(err, ram.ErrCodeUnknownResourceException, "") {
return nil
}
return fmt.Errorf("Error deleting RAM resource share %s: %s", d.Id(), err)
}

stateConf := &resource.StateChangeConf{
Pending: []string{ram.ResourceShareStatusDeleting},
Target: []string{ram.ResourceShareStatusDeleted},
Refresh: resourceAwsRamResourceShareStateRefreshFunc(conn, d.Id()),
Timeout: d.Timeout(schema.TimeoutDelete),
}

_, err = stateConf.WaitForState()
if err != nil {
return fmt.Errorf("Error waiting for RAM resource share (%s) to become ready: %s", d.Id(), err)
}

return nil
}

func resourceAwsRamResourceShareStateRefreshFunc(conn *ram.RAM, resourceShareArn string) resource.StateRefreshFunc {
return func() (interface{}, string, error) {
request := &ram.GetResourceSharesInput{
ResourceShareArns: []*string{aws.String(resourceShareArn)},
ResourceOwner: aws.String(ram.ResourceOwnerSelf),
}

output, err := conn.GetResourceShares(request)

if err != nil {
return nil, ram.ResourceShareStatusFailed, err
}

if len(output.ResourceShares) == 0 {
return nil, ram.ResourceShareStatusDeleted, nil
}

resourceShare := output.ResourceShares[0]

return resourceShare, aws.StringValue(resourceShare.Status), nil
}
}
Loading

0 comments on commit 5ad9071

Please sign in to comment.