Skip to content

Commit

Permalink
Merge pull request #12549 from terraform-providers/ajj/add-codepipeli…
Browse files Browse the repository at this point in the history
…ne-action-region-support

Add CodePipeline cross-region action support
  • Loading branch information
gdavison committed Apr 2, 2020
2 parents 524f0f6 + 63d187a commit 5a6d202
Show file tree
Hide file tree
Showing 4 changed files with 862 additions and 335 deletions.
133 changes: 108 additions & 25 deletions aws/resource_aws_codepipeline.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package aws

import (
"errors"
"fmt"
"log"
"os"
Expand Down Expand Up @@ -40,26 +41,22 @@ func resourceAwsCodePipeline() *schema.Resource {
Type: schema.TypeString,
Required: true,
},

"artifact_store": {
Type: schema.TypeList,
Type: schema.TypeSet,
Required: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"location": {
Type: schema.TypeString,
Required: true,
},

"type": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
codepipeline.ArtifactStoreTypeS3,
}, false),
},

"encryption_key": {
Type: schema.TypeList,
MaxItems: 1,
Expand All @@ -70,7 +67,6 @@ func resourceAwsCodePipeline() *schema.Resource {
Type: schema.TypeString,
Required: true,
},

"type": {
Type: schema.TypeString,
Required: true,
Expand All @@ -81,6 +77,11 @@ func resourceAwsCodePipeline() *schema.Resource {
},
},
},
"region": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
},
},
},
Expand All @@ -102,6 +103,7 @@ func resourceAwsCodePipeline() *schema.Resource {
"configuration": {
Type: schema.TypeMap,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"category": {
Type: schema.TypeString,
Expand Down Expand Up @@ -155,6 +157,11 @@ func resourceAwsCodePipeline() *schema.Resource {
Optional: true,
Computed: true,
},
"region": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
},
},
},
Expand All @@ -168,13 +175,18 @@ func resourceAwsCodePipeline() *schema.Resource {

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

pipeline, err := expandAwsCodePipeline(d)
if err != nil {
return err
}
params := &codepipeline.CreatePipelineInput{
Pipeline: expandAwsCodePipeline(d),
Pipeline: pipeline,
Tags: keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().CodepipelineTags(),
}

var resp *codepipeline.CreatePipelineOutput
err := resource.Retry(2*time.Minute, func() *resource.RetryError {
err = resource.Retry(2*time.Minute, func() *resource.RetryError {
var err error

resp, err = conn.CreatePipeline(params)
Expand All @@ -200,21 +212,60 @@ func resourceAwsCodePipelineCreate(d *schema.ResourceData, meta interface{}) err
return resourceAwsCodePipelineRead(d, meta)
}

func expandAwsCodePipeline(d *schema.ResourceData) *codepipeline.PipelineDeclaration {
pipelineArtifactStore := expandAwsCodePipelineArtifactStore(d)
pipelineStages := expandAwsCodePipelineStages(d)

func expandAwsCodePipeline(d *schema.ResourceData) (*codepipeline.PipelineDeclaration, error) {
pipeline := codepipeline.PipelineDeclaration{
Name: aws.String(d.Get("name").(string)),
RoleArn: aws.String(d.Get("role_arn").(string)),
ArtifactStore: pipelineArtifactStore,
Stages: pipelineStages,
Name: aws.String(d.Get("name").(string)),
RoleArn: aws.String(d.Get("role_arn").(string)),
Stages: expandAwsCodePipelineStages(d),
}

pipelineArtifactStores, err := expandAwsCodePipelineArtifactStores(d.Get("artifact_store").(*schema.Set).List())
if err != nil {
return nil, err
}
if len(pipelineArtifactStores) == 1 {
for _, v := range pipelineArtifactStores {
pipeline.ArtifactStore = v
}
} else {
pipeline.ArtifactStores = pipelineArtifactStores
}

return &pipeline, nil
}

func expandAwsCodePipelineArtifactStores(configs []interface{}) (map[string]*codepipeline.ArtifactStore, error) {
if len(configs) == 0 {
return nil, nil
}

regions := make([]string, 0, len(configs))
pipelineArtifactStores := make(map[string]*codepipeline.ArtifactStore)
for _, config := range configs {
region, store := expandAwsCodePipelineArtifactStoreData(config.(map[string]interface{}))
regions = append(regions, region)
pipelineArtifactStores[region] = store
}

if len(regions) == 1 {
if regions[0] != "" {
return nil, errors.New("region cannot be set for a single-region CodePipeline")
}
} else {
for _, v := range regions {
if v == "" {
return nil, errors.New("region must be set for a cross-region CodePipeline")
}
}
if len(configs) != len(pipelineArtifactStores) {
return nil, errors.New("only one Artifact Store can be defined per region for a cross-region CodePipeline")
}
}
return &pipeline

return pipelineArtifactStores, nil
}
func expandAwsCodePipelineArtifactStore(d *schema.ResourceData) *codepipeline.ArtifactStore {
configs := d.Get("artifact_store").([]interface{})
data := configs[0].(map[string]interface{})

func expandAwsCodePipelineArtifactStoreData(data map[string]interface{}) (string, *codepipeline.ArtifactStore) {
pipelineArtifactStore := codepipeline.ArtifactStore{
Location: aws.String(data["location"].(string)),
Type: aws.String(data["type"].(string)),
Expand All @@ -228,10 +279,15 @@ func expandAwsCodePipelineArtifactStore(d *schema.ResourceData) *codepipeline.Ar
}
pipelineArtifactStore.EncryptionKey = &ek
}
return &pipelineArtifactStore

return data["region"].(string), &pipelineArtifactStore
}

func flattenAwsCodePipelineArtifactStore(artifactStore *codepipeline.ArtifactStore) []interface{} {
if artifactStore == nil {
return []interface{}{}
}

values := map[string]interface{}{}
values["type"] = *artifactStore.Type
values["location"] = *artifactStore.Location
Expand All @@ -245,6 +301,16 @@ func flattenAwsCodePipelineArtifactStore(artifactStore *codepipeline.ArtifactSto
return []interface{}{values}
}

func flattenAwsCodePipelineArtifactStores(artifactStores map[string]*codepipeline.ArtifactStore) []interface{} {
values := []interface{}{}
for region, artifactStore := range artifactStores {
store := flattenAwsCodePipelineArtifactStore(artifactStore)[0].(map[string]interface{})
store["region"] = region
values = append(values, store)
}
return values
}

func expandAwsCodePipelineStages(d *schema.ResourceData) []*codepipeline.StageDeclaration {
configs := d.Get("stage").([]interface{})
pipelineStages := []*codepipeline.StageDeclaration{}
Expand Down Expand Up @@ -319,6 +385,10 @@ func expandAwsCodePipelineActions(s []interface{}) []*codepipeline.ActionDeclara
if ro > 0 {
action.RunOrder = aws.Int64(int64(ro))
}
r := data["region"].(string)
if r != "" {
action.Region = aws.String(r)
}
actions = append(actions, &action)
}
return actions
Expand Down Expand Up @@ -360,6 +430,10 @@ func flattenAwsCodePipelineStageActions(actions []*codepipeline.ActionDeclaratio
values["run_order"] = int(*action.RunOrder)
}

if action.Region != nil {
values["region"] = *action.Region
}

actionsList = append(actionsList, values)
}
return actionsList
Expand Down Expand Up @@ -443,8 +517,14 @@ func resourceAwsCodePipelineRead(d *schema.ResourceData, meta interface{}) error
metadata := resp.Metadata
pipeline := resp.Pipeline

if err := d.Set("artifact_store", flattenAwsCodePipelineArtifactStore(pipeline.ArtifactStore)); err != nil {
return err
if pipeline.ArtifactStore != nil {
if err := d.Set("artifact_store", flattenAwsCodePipelineArtifactStore(pipeline.ArtifactStore)); err != nil {
return err
}
} else if pipeline.ArtifactStores != nil {
if err := d.Set("artifact_store", flattenAwsCodePipelineArtifactStores(pipeline.ArtifactStores)); err != nil {
return err
}
}

if err := d.Set("stage", flattenAwsCodePipelineStages(pipeline.Stages)); err != nil {
Expand Down Expand Up @@ -472,11 +552,14 @@ func resourceAwsCodePipelineRead(d *schema.ResourceData, meta interface{}) error
func resourceAwsCodePipelineUpdate(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).codepipelineconn

pipeline := expandAwsCodePipeline(d)
pipeline, err := expandAwsCodePipeline(d)
if err != nil {
return err
}
params := &codepipeline.UpdatePipelineInput{
Pipeline: pipeline,
}
_, err := conn.UpdatePipeline(params)
_, err = conn.UpdatePipeline(params)

if err != nil {
return fmt.Errorf(
Expand Down
Loading

0 comments on commit 5a6d202

Please sign in to comment.