Skip to content

Commit

Permalink
Merge pull request #6591 from terraform-providers/f-aws_datasync
Browse files Browse the repository at this point in the history
Support DataSync Service
  • Loading branch information
bflad authored Nov 26, 2018
2 parents e782960 + 17bac54 commit 1950977
Show file tree
Hide file tree
Showing 22 changed files with 4,463 additions and 0 deletions.
3 changes: 3 additions & 0 deletions aws/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import (
"github.com/aws/aws-sdk-go/service/cognitoidentityprovider"
"github.com/aws/aws-sdk-go/service/configservice"
"github.com/aws/aws-sdk-go/service/databasemigrationservice"
"github.com/aws/aws-sdk-go/service/datasync"
"github.com/aws/aws-sdk-go/service/dax"
"github.com/aws/aws-sdk-go/service/devicefarm"
"github.com/aws/aws-sdk-go/service/directconnect"
Expand Down Expand Up @@ -172,6 +173,7 @@ type AWSClient struct {
cognitoconn *cognitoidentity.CognitoIdentity
cognitoidpconn *cognitoidentityprovider.CognitoIdentityProvider
configconn *configservice.ConfigService
datasyncconn *datasync.DataSync
daxconn *dax.DAX
devicefarmconn *devicefarm.DeviceFarm
dlmconn *dlm.DLM
Expand Down Expand Up @@ -519,6 +521,7 @@ func (c *Config) Client() (interface{}, error) {
client.cognitoconn = cognitoidentity.New(sess)
client.cognitoidpconn = cognitoidentityprovider.New(sess)
client.codepipelineconn = codepipeline.New(sess)
client.datasyncconn = datasync.New(sess)
client.daxconn = dax.New(awsDynamoSess)
client.dlmconn = dlm.New(sess)
client.dmsconn = databasemigrationservice.New(sess)
Expand Down
144 changes: 144 additions & 0 deletions aws/datasync.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package aws

import (
"net/url"

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

func dataSyncParseLocationURI(uri string) (string, error) {
parsedURL, err := url.ParseRequestURI(uri)

if err != nil {
return "", err
}

return parsedURL.Path, nil
}

func expandDataSyncEc2Config(l []interface{}) *datasync.Ec2Config {
if len(l) == 0 || l[0] == nil {
return nil
}

m := l[0].(map[string]interface{})

ec2Config := &datasync.Ec2Config{
SecurityGroupArns: expandStringSet(m["security_group_arns"].(*schema.Set)),
SubnetArn: aws.String(m["subnet_arn"].(string)),
}

return ec2Config
}

func expandDataSyncOnPremConfig(l []interface{}) *datasync.OnPremConfig {
if len(l) == 0 || l[0] == nil {
return nil
}

m := l[0].(map[string]interface{})

onPremConfig := &datasync.OnPremConfig{
AgentArns: expandStringSet(m["agent_arns"].(*schema.Set)),
}

return onPremConfig
}

func expandDataSyncOptions(l []interface{}) *datasync.Options {
if len(l) == 0 || l[0] == nil {
return nil
}

m := l[0].(map[string]interface{})

options := &datasync.Options{
Atime: aws.String(m["atime"].(string)),
Gid: aws.String(m["gid"].(string)),
Mtime: aws.String(m["mtime"].(string)),
PreserveDeletedFiles: aws.String(m["preserve_deleted_files"].(string)),
PreserveDevices: aws.String(m["preserve_devices"].(string)),
PosixPermissions: aws.String(m["posix_permissions"].(string)),
Uid: aws.String(m["uid"].(string)),
VerifyMode: aws.String(m["verify_mode"].(string)),
}

if v, ok := m["bytes_per_second"]; ok && v.(int) > 0 {
options.BytesPerSecond = aws.Int64(int64(v.(int)))
}

return options
}

func expandDataSyncS3Config(l []interface{}) *datasync.S3Config {
if len(l) == 0 || l[0] == nil {
return nil
}

m := l[0].(map[string]interface{})

s3Config := &datasync.S3Config{
BucketAccessRoleArn: aws.String(m["bucket_access_role_arn"].(string)),
}

return s3Config
}

func flattenDataSyncEc2Config(ec2Config *datasync.Ec2Config) []interface{} {
if ec2Config == nil {
return []interface{}{}
}

m := map[string]interface{}{
"security_group_arns": schema.NewSet(schema.HashString, flattenStringList(ec2Config.SecurityGroupArns)),
"subnet_arn": aws.StringValue(ec2Config.SubnetArn),
}

return []interface{}{m}
}

func flattenDataSyncOnPremConfig(onPremConfig *datasync.OnPremConfig) []interface{} {
if onPremConfig == nil {
return []interface{}{}
}

m := map[string]interface{}{
"agent_arns": schema.NewSet(schema.HashString, flattenStringList(onPremConfig.AgentArns)),
}

return []interface{}{m}
}

func flattenDataSyncOptions(options *datasync.Options) []interface{} {
if options == nil {
return []interface{}{}
}

m := map[string]interface{}{
"atime": aws.StringValue(options.Atime),
"bytes_per_second": aws.Int64Value(options.BytesPerSecond),
"gid": aws.StringValue(options.Gid),
"mtime": aws.StringValue(options.Mtime),
"posix_permissions": aws.StringValue(options.PosixPermissions),
"preserve_deleted_files": aws.StringValue(options.PreserveDeletedFiles),
"preserve_devices": aws.StringValue(options.PreserveDevices),
"uid": aws.StringValue(options.Uid),
"verify_mode": aws.StringValue(options.VerifyMode),
}

return []interface{}{m}
}

func flattenDataSyncS3Config(s3Config *datasync.S3Config) []interface{} {
if s3Config == nil {
return []interface{}{}
}

m := map[string]interface{}{
"bucket_access_role_arn": aws.StringValue(s3Config.BucketAccessRoleArn),
}

return []interface{}{m}
}
63 changes: 63 additions & 0 deletions aws/datasync_tags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package aws

import (
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/datasync"
)

// dataSyncTagsDiff takes our tags locally and the ones remotely and returns
// the set of tags that must be created, and the set of tags that must
// be destroyed.
func dataSyncTagsDiff(oldTags, newTags []*datasync.TagListEntry) ([]*datasync.TagListEntry, []*datasync.TagListEntry) {
// First, we're creating everything we have
create := make(map[string]interface{})
for _, t := range newTags {
create[aws.StringValue(t.Key)] = aws.StringValue(t.Value)
}

// Build the list of what to remove
var remove []*datasync.TagListEntry
for _, t := range oldTags {
old, ok := create[aws.StringValue(t.Key)]
if !ok || old != aws.StringValue(t.Value) {
// Delete it!
remove = append(remove, t)
}
}

return expandDataSyncTagListEntry(create), remove
}

func dataSyncTagsKeys(tags []*datasync.TagListEntry) []*string {
keys := make([]*string, 0)

for _, tag := range tags {
if tag == nil {
continue
}
keys = append(keys, tag.Key)
}

return keys
}

func expandDataSyncTagListEntry(m map[string]interface{}) []*datasync.TagListEntry {
result := []*datasync.TagListEntry{}
for k, v := range m {
result = append(result, &datasync.TagListEntry{
Key: aws.String(k),
Value: aws.String(v.(string)),
})
}

return result
}

func flattenDataSyncTagListEntry(ts []*datasync.TagListEntry) map[string]string {
result := map[string]string{}
for _, t := range ts {
result[aws.StringValue(t.Key)] = aws.StringValue(t.Value)
}

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

import (
"reflect"
"testing"
)

func TestDataSyncTagsDiff(t *testing.T) {
cases := []struct {
Old, New map[string]interface{}
Create, Remove map[string]string
}{
// Basic add/remove
{
Old: map[string]interface{}{
"foo": "bar",
},
New: map[string]interface{}{
"bar": "baz",
},
Create: map[string]string{
"bar": "baz",
},
Remove: map[string]string{
"foo": "bar",
},
},

// Modify
{
Old: map[string]interface{}{
"foo": "bar",
},
New: map[string]interface{}{
"foo": "baz",
},
Create: map[string]string{
"foo": "baz",
},
Remove: map[string]string{
"foo": "bar",
},
},
}

for i, tc := range cases {
create, remove := dataSyncTagsDiff(expandDataSyncTagListEntry(tc.Old), expandDataSyncTagListEntry(tc.New))
createMap := flattenDataSyncTagListEntry(create)
removeMap := flattenDataSyncTagListEntry(remove)
if !reflect.DeepEqual(createMap, tc.Create) {
t.Fatalf("%d: bad create: %#v", i, createMap)
}
if !reflect.DeepEqual(removeMap, tc.Remove) {
t.Fatalf("%d: bad remove: %#v", i, removeMap)
}
}
}
47 changes: 47 additions & 0 deletions aws/datasync_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package aws

import (
"testing"
)

func TestDataSyncParseLocationURI(t *testing.T) {
testCases := []struct {
LocationURI string
Subdirectory string
}{
{
LocationURI: "efs://us-east-2.fs-abcd1234/",
Subdirectory: "/",
},
{
LocationURI: "efs://us-east-2.fs-abcd1234/path",
Subdirectory: "/path",
},
{
LocationURI: "nfs://example.com/",
Subdirectory: "/",
},
{
LocationURI: "nfs://example.com/path",
Subdirectory: "/path",
},
{
LocationURI: "s3://myBucket/",
Subdirectory: "/",
},
{
LocationURI: "s3://myBucket/path",
Subdirectory: "/path",
},
}

for i, tc := range testCases {
subdirectory, err := dataSyncParseLocationURI(tc.LocationURI)
if err != nil {
t.Fatalf("%d: received error parsing (%s): %s", i, tc.LocationURI, err)
}
if subdirectory != tc.Subdirectory {
t.Fatalf("%d: expected subdirectory (%s), received: %s", i, tc.Subdirectory, subdirectory)
}
}
}
5 changes: 5 additions & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,11 @@ func Provider() terraform.ResourceProvider {
"aws_codepipeline": resourceAwsCodePipeline(),
"aws_codepipeline_webhook": resourceAwsCodePipelineWebhook(),
"aws_customer_gateway": resourceAwsCustomerGateway(),
"aws_datasync_agent": resourceAwsDataSyncAgent(),
"aws_datasync_location_efs": resourceAwsDataSyncLocationEfs(),
"aws_datasync_location_nfs": resourceAwsDataSyncLocationNfs(),
"aws_datasync_location_s3": resourceAwsDataSyncLocationS3(),
"aws_datasync_task": resourceAwsDataSyncTask(),
"aws_dax_cluster": resourceAwsDaxCluster(),
"aws_dax_parameter_group": resourceAwsDaxParameterGroup(),
"aws_dax_subnet_group": resourceAwsDaxSubnetGroup(),
Expand Down
Loading

0 comments on commit 1950977

Please sign in to comment.