Skip to content

Commit

Permalink
data_source/ecr_lifecycle_policy_document: adding new data source for…
Browse files Browse the repository at this point in the history
… ECR
  • Loading branch information
slapula committed Oct 12, 2018
1 parent a213157 commit 08da208
Show file tree
Hide file tree
Showing 3 changed files with 283 additions and 0 deletions.
202 changes: 202 additions & 0 deletions aws/data_source_aws_ecr_lifecycle_policy_document.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
package aws

import (
"encoding/json"
"strconv"

"github.com/hashicorp/terraform/helper/hashcode"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
)

type EcrLifecyclePolicyDoc struct {
Rules []*EcrLifecyclePolicyStatement `json:"rules"`
}

type EcrLifecyclePolicyStatement struct {
RulePriority int `json:"rulePriority,omitempty"`
Description string `json:"description,omitempty"`
Selection EcrLifecyclePolicyStatementSelectionSet `json:"selection,omitempty"`
Action EcrLifecyclePolicyAction `json:"action"`
}

type EcrLifecyclePolicySelection struct {
TagStatus string `json:"tagStatus,omitempty"`
TagPrefixList []interface{} `json:"tagPrefixList,omitempty"`
CountType string `json:"countType,omitempty"`
CountUnit string `json:"countUnit,omitempty"`
CountNumber int `json:"countNumber,omitempty"`
}

type EcrLifecyclePolicyAction struct {
Type string `json:"type"`
}

type EcrLifecyclePolicyStatementSelectionSet EcrLifecyclePolicySelection

func dataSourceAwsEcrLifecyclePolicyDocument() *schema.Resource {

return &schema.Resource{
Read: dataSourceAwsEcrLifecyclePolicyDocumentRead,

Schema: map[string]*schema.Schema{
"rule": {
Type: schema.TypeList,
Required: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"priority": {
Type: schema.TypeInt,
Required: true,
},
"description": {
Type: schema.TypeString,
Required: false,
Optional: true,
},
"selection": {
Type: schema.TypeSet,
Required: false,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"tag_status": {
Type: schema.TypeString,
Required: false,
Optional: true,
Default: "any",
ValidateFunc: validation.StringInSlice([]string{"tagged", "untagged", "any"}, false),
},
"tag_prefix_list": {
Type: schema.TypeList,
Required: false,
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"count_type": {
Type: schema.TypeString,
Required: false,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"imageCountMoreThan", "sinceImagePushed", "any"}, false),
},
"count_unit": {
Type: schema.TypeString,
Required: false,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{"days"}, false),
},
"count_number": {
Type: schema.TypeInt,
Required: false,
Optional: true,
},
},
},
},
"action": {
Type: schema.TypeSet,
Required: false,
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"type": {
Type: schema.TypeString,
Optional: true,
Default: "expire",
},
},
},
},
},
},
},
"json": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func dataSourceAwsEcrLifecyclePolicyDocumentRead(d *schema.ResourceData, meta interface{}) error {
mergedDoc := &EcrLifecyclePolicyDoc{}

// process the current document
doc := &EcrLifecyclePolicyDoc{}

var cfgStmts = d.Get("rule").([]interface{})
stmts := make([]*EcrLifecyclePolicyStatement, len(cfgStmts))
for i, stmtI := range cfgStmts {
cfgStmt := stmtI.(map[string]interface{})

stmt := &EcrLifecyclePolicyStatement{
RulePriority: cfgStmt["priority"].(int),
}

if description, ok := cfgStmt["description"]; ok {
stmt.Description = description.(string)
}

if selection := cfgStmt["selection"].(*schema.Set).List(); len(selection) > 0 {
stmt.Selection = dataSourceAwsEcrLifecyclePolicyDocumentMakeSelection(selection)
}

stmt.Action = EcrLifecyclePolicyAction{
Type: "expire",
}

stmts[i] = stmt
}

doc.Rules = stmts

// merge our current document into mergedDoc
mergedDoc.Merge(doc)

jsonDoc, err := json.MarshalIndent(mergedDoc, "", " ")
if err != nil {
// should never happen if the above code is correct
return err
}
jsonString := string(jsonDoc)

d.Set("json", jsonString)
d.SetId(strconv.Itoa(hashcode.String(jsonString)))

return nil
}

func dataSourceAwsEcrLifecyclePolicyDocumentMakeSelection(in []interface{}) EcrLifecyclePolicyStatementSelectionSet {
out := EcrLifecyclePolicySelection{}
item := in[0].(map[string]interface{})
out = EcrLifecyclePolicySelection{
TagStatus: item["tag_status"].(string),
TagPrefixList: item["tag_prefix_list"].([]interface{}),
CountType: item["count_type"].(string),
CountUnit: item["count_unit"].(string),
CountNumber: item["count_number"].(int),
}
return EcrLifecyclePolicyStatementSelectionSet(out)
}

func (self *EcrLifecyclePolicyDoc) Merge(newDoc *EcrLifecyclePolicyDoc) {
// merge in newDoc's statements, overwriting any existing Sids
var seen bool
for _, newRule := range newDoc.Rules {
if newRule.RulePriority == 0 {
self.Rules = append(self.Rules, newRule)
continue
}
seen = false
for i, existingRule := range self.Rules {
if existingRule.RulePriority == newRule.RulePriority {
self.Rules[i] = newRule
seen = true
break
}
}
if !seen {
self.Rules = append(self.Rules, newRule)
}
}
}
80 changes: 80 additions & 0 deletions aws/data_source_aws_ecr_lifecycle_policy_document_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package aws

import (
"fmt"
"testing"

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

func TestAccAWSDataSourceEcrLifecyclePolicyDocument_basic(t *testing.T) {
// This really ought to be able to be a unit test rather than an
// acceptance test, but just instantiating the AWS provider requires
// some AWS API calls, and so this needs valid AWS credentials to work.
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccAWSEcrLifecyclePolicyDocumentConfig,
Check: resource.ComposeTestCheckFunc(
testAccCheckEcrLifecyclePolicyValue("data.aws_ecr_lifecycle_policy_document.test", "json",
testAccAWSEcrLifecyclePolicyDocumentExpectedJSON,
),
),
},
},
})
}

func testAccCheckEcrLifecyclePolicyValue(id, name, value string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[id]
if !ok {
return fmt.Errorf("Not found: %s", id)
}
if rs.Primary.ID == "" {
return fmt.Errorf("No ID is set")
}

v := rs.Primary.Attributes[name]
if v != value {
return fmt.Errorf(
"Value for %s is %s, not %s", name, v, value)
}

return nil
}
}

var testAccAWSEcrLifecyclePolicyDocumentConfig = `
data "aws_ecr_lifecycle_policy_document" "test" {
rule {
priority = 1
description = "This is a test."
tag_status = "tagged"
tag_prefix_list = ["prod"]
count_type = "imageCountMoreThan"
count_number = 100
}
}
`

var testAccAWSEcrLifecyclePolicyDocumentExpectedJSON = `{
"rules": [
{
"rulePriority": 1,
"description": "This is a test.",
"selection": [
"tagStatus": "tagged",
"tagPrefixList": ["prod"],
"countType": "imageCountMoreThan",
"countNumber": 100
],
"action": [
"type": "expire"
]
}
]
}`
1 change: 1 addition & 0 deletions aws/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ func Provider() terraform.ResourceProvider {
"aws_ebs_snapshot": dataSourceAwsEbsSnapshot(),
"aws_ebs_snapshot_ids": dataSourceAwsEbsSnapshotIds(),
"aws_ebs_volume": dataSourceAwsEbsVolume(),
"aws_ecr_lifecycle_policy_document": dataSourceAwsEcrLifecyclePolicyDocument(),
"aws_ecr_repository": dataSourceAwsEcrRepository(),
"aws_ecs_cluster": dataSourceAwsEcsCluster(),
"aws_ecs_container_definition": dataSourceAwsEcsContainerDefinition(),
Expand Down

0 comments on commit 08da208

Please sign in to comment.