Skip to content

Commit

Permalink
Merge pull request #24766 from tmccombs/driectory-service-share
Browse files Browse the repository at this point in the history
Directory Service Directory Share
  • Loading branch information
YakDriver authored Jul 2, 2022
2 parents 28ce9c2 + 132a78f commit 3bc094e
Show file tree
Hide file tree
Showing 13 changed files with 939 additions and 27 deletions.
7 changes: 7 additions & 0 deletions .changelog/24766.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:new-resource
aws_directory_service_shared_directory
```

```release-note:new-resource
aws_directory_service_shared_directory_accepter
```
8 changes: 5 additions & 3 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -1267,9 +1267,11 @@ func Provider() *schema.Provider {
"aws_docdb_global_cluster": docdb.ResourceGlobalCluster(),
"aws_docdb_subnet_group": docdb.ResourceSubnetGroup(),

"aws_directory_service_conditional_forwarder": ds.ResourceConditionalForwarder(),
"aws_directory_service_directory": ds.ResourceDirectory(),
"aws_directory_service_log_subscription": ds.ResourceLogSubscription(),
"aws_directory_service_conditional_forwarder": ds.ResourceConditionalForwarder(),
"aws_directory_service_directory": ds.ResourceDirectory(),
"aws_directory_service_log_subscription": ds.ResourceLogSubscription(),
"aws_directory_service_shared_directory_accepter": ds.ResourceSharedDirectoryAccepter(),
"aws_directory_service_shared_directory": ds.ResourceSharedDirectory(),

"aws_dynamodb_contributor_insights": dynamodb.ResourceContributorInsights(),
"aws_dynamodb_global_table": dynamodb.ResourceGlobalTable(),
Expand Down
5 changes: 2 additions & 3 deletions internal/service/ds/directory.go
Original file line number Diff line number Diff line change
Expand Up @@ -395,8 +395,7 @@ func resourceDirectoryCreate(d *schema.ResourceData, meta interface{}) error {

d.SetId(directoryId)

_, err = waitDirectoryCreated(conn, d.Id())

err = waitDirectoryCreated(conn, d.Id())
if err != nil {
return fmt.Errorf("error waiting for Directory Service Directory (%s) to create: %w", d.Id(), err)
}
Expand Down Expand Up @@ -547,7 +546,7 @@ func resourceDirectoryDelete(d *schema.ResourceData, meta interface{}) error {
return fmt.Errorf("error deleting Directory Service Directory (%s): %w", d.Id(), err)
}

_, err = waitDirectoryDeleted(conn, d.Id())
err = waitDirectoryDeleted(conn, d.Id())

if err != nil {
return fmt.Errorf("error waiting for Directory Service Directory (%s) to delete: %w", d.Id(), err)
Expand Down
34 changes: 34 additions & 0 deletions internal/service/ds/find.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package ds

import (
"context"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/directoryservice"
"github.com/hashicorp/aws-sdk-go-base/v2/awsv1shim/v2/tfawserr"
Expand Down Expand Up @@ -45,3 +47,35 @@ func findDirectoryByID(conn *directoryservice.DirectoryService, id string) (*dir

return directory, nil
}

func findSharedDirectoryByIDs(ctx context.Context, conn *directoryservice.DirectoryService, ownerDirectoryId string, sharedDirectoryId string) (*directoryservice.SharedDirectory, error) { // nosemgrep:ds-in-func-name
input := &directoryservice.DescribeSharedDirectoriesInput{
OwnerDirectoryId: aws.String(ownerDirectoryId),
SharedDirectoryIds: []*string{aws.String(sharedDirectoryId)},
}

output, err := conn.DescribeSharedDirectoriesWithContext(ctx, input)

if err != nil {
return nil, err
}

if output == nil || len(output.SharedDirectories) == 0 || output.SharedDirectories[0] == nil {
return nil, tfresource.NewEmptyResultError(input)
}

if count := len(output.SharedDirectories); count > 1 {
return nil, tfresource.NewTooManyResultsError(count, input)
}

sharedDirectory := output.SharedDirectories[0]

if status := aws.StringValue(sharedDirectory.ShareStatus); status == directoryservice.ShareStatusDeleted {
return nil, &resource.NotFoundError{
Message: status,
LastRequest: input,
}
}

return sharedDirectory, nil
}
239 changes: 239 additions & 0 deletions internal/service/ds/shared_directory.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
package ds

import (
"context"
"fmt"
"log"
"strings"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/directoryservice"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/hashicorp/terraform-provider-aws/internal/conns"
"github.com/hashicorp/terraform-provider-aws/internal/tfresource"
"github.com/hashicorp/terraform-provider-aws/names"
)

const (
ResourceNameSharedDirectory = "Shared Directory"
)

func ResourceSharedDirectory() *schema.Resource {
return &schema.Resource{
CreateContext: resourceSharedDirectoryCreate,
ReadContext: resourceSharedDirectoryRead,
DeleteContext: resourceSharedDirectoryDelete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},

Schema: map[string]*schema.Schema{
"directory_id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"method": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Default: directoryservice.ShareMethodHandshake,
ValidateFunc: validation.StringInSlice(directoryservice.ShareMethod_Values(), false),
},
"notes": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Sensitive: true,
},
"shared_directory_id": {
Type: schema.TypeString,
Computed: true,
},
"target": {
Type: schema.TypeList,
MaxItems: 1,
Required: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
"type": {
Type: schema.TypeString,
Optional: true,
Default: directoryservice.TargetTypeAccount,
ValidateFunc: validation.StringInSlice(directoryservice.TargetType_Values(), false),
},
},
},
},
},
}
}

func resourceSharedDirectoryCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).DSConn

dirId := d.Get("directory_id").(string)
input := directoryservice.ShareDirectoryInput{
DirectoryId: aws.String(dirId),
ShareMethod: aws.String(d.Get("method").(string)),
ShareTarget: expandShareTarget(d.Get("target").([]interface{})[0].(map[string]interface{})),
}

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

log.Printf("[DEBUG] Creating Shared Directory: %s", input)
out, err := conn.ShareDirectoryWithContext(ctx, &input)

if err != nil {
return names.DiagError(names.DS, names.ErrActionCreating, ResourceNameSharedDirectory, d.Id(), err)
}

log.Printf("[DEBUG] Shared Directory created: %s", out)
d.SetId(sharedDirectoryID(dirId, aws.StringValue(out.SharedDirectoryId)))
d.Set("shared_directory_id", out.SharedDirectoryId)

return nil
}

func resourceSharedDirectoryRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).DSConn

ownerDirID, sharedDirID, err := parseSharedDirectoryID(d.Id())

if err != nil {
return names.DiagError(names.DS, names.ErrActionReading, ResourceNameSharedDirectory, d.Id(), err)
}

output, err := findSharedDirectoryByIDs(ctx, conn, ownerDirID, sharedDirID)

if !d.IsNewResource() && tfresource.NotFound(err) {
names.LogNotFoundRemoveState(names.DS, names.ErrActionReading, ResourceNameSharedDirectory, d.Id())
d.SetId("")
return nil
}

if err != nil {
return names.DiagError(names.DS, names.ErrActionReading, ResourceNameSharedDirectory, d.Id(), err)
}

log.Printf("[DEBUG] Received DS shared directory: %s", output)

d.Set("method", output.ShareMethod)
d.Set("notes", output.ShareNotes)

if output.SharedAccountId != nil {
if err := d.Set("target", []interface{}{flattenShareTarget(output)}); err != nil {
return names.DiagError(names.DS, names.ErrActionSetting, ResourceNameSharedDirectory, d.Id(), err)
}
} else {
d.Set("target", nil)
}

return nil
}

func resourceSharedDirectoryDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn := meta.(*conns.AWSClient).DSConn

dirId := d.Get("directory_id").(string)
sharedId := d.Get("shared_directory_id").(string)

input := directoryservice.UnshareDirectoryInput{
DirectoryId: aws.String(dirId),
UnshareTarget: expandUnshareTarget(d.Get("target").([]interface{})[0].(map[string]interface{})),
}

log.Printf("[DEBUG] Unsharing Directory Service Directory: %s", input)
output, err := conn.UnshareDirectoryWithContext(ctx, &input)

if err != nil {
return names.DiagError(names.DS, names.ErrActionDeleting, ResourceNameSharedDirectory, d.Id(), err)
}

_, err = waitSharedDirectoryDeleted(ctx, conn, dirId, sharedId)

if err != nil {
return names.DiagError(names.DS, names.ErrActionWaitingForDeletion, ResourceNameSharedDirectory, d.Id(), err)
}

log.Printf("[DEBUG] Unshared Directory Service Directory: %s", output)

return nil
}

func expandShareTarget(tfMap map[string]interface{}) *directoryservice.ShareTarget { // nosemgrep:ds-in-func-name
if tfMap == nil {
return nil
}

apiObject := &directoryservice.ShareTarget{}

if v, ok := tfMap["id"].(string); ok && len(v) > 0 {
apiObject.Id = aws.String(v)
}

if v, ok := tfMap["type"].(string); ok && len(v) > 0 {
apiObject.Type = aws.String(v)
}

return apiObject
}

func expandUnshareTarget(tfMap map[string]interface{}) *directoryservice.UnshareTarget {
if tfMap == nil {
return nil
}

apiObject := &directoryservice.UnshareTarget{}

if v, ok := tfMap["id"].(string); ok && len(v) > 0 {
apiObject.Id = aws.String(v)
}

if v, ok := tfMap["type"].(string); ok && len(v) > 0 {
apiObject.Type = aws.String(v)
}

return apiObject
}

// flattenShareTarget is not a mirror of expandShareTarget because the API data structures are
// different, with no ShareTarget returned
func flattenShareTarget(apiObject *directoryservice.SharedDirectory) map[string]interface{} {
if apiObject == nil {
return nil
}

tfMap := map[string]interface{}{}

if apiObject.SharedAccountId != nil {
tfMap["id"] = aws.StringValue(apiObject.SharedAccountId)
}

tfMap["type"] = directoryservice.TargetTypeAccount // only type available

return tfMap
}

func sharedDirectoryID(ownerDirectoryID, sharedDirectoryID string) string {
return fmt.Sprintf("%s/%s", ownerDirectoryID, sharedDirectoryID)
}

func parseSharedDirectoryID(id string) (string, string, error) {
idParts := strings.SplitN(id, "/", 2)
if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" {
return "", "", fmt.Errorf("unexpected format of ID (%q), expected <owner-directory-id>/<shared-directory-id>", id)
}

return idParts[0], idParts[1], nil
}
Loading

0 comments on commit 3bc094e

Please sign in to comment.