From a309aa4d76fa3106cff77b7661bf85670498ad9f Mon Sep 17 00:00:00 2001 From: Michal Mazur Date: Thu, 3 Aug 2023 08:46:30 +0000 Subject: [PATCH 1/8] DXE-2836 Correct export of improper property activations version in cliterraform --- CHANGELOG.md | 6 + pkg/providers/papi/create_property.go | 36 +++--- pkg/providers/papi/create_property_test.go | 137 +++++++++++++++++++++ 3 files changed, 162 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd8d358..e66d06c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,10 @@ # Release Notes +## Version 1.x.x (xxxx yy, 2023) + +### Bug fixes + +* PAPI + * Fixed `export-property` command to export `akamai_property_activation` resource attributes for latest active version. ## Version 1.8.0 (August 1, 2023) diff --git a/pkg/providers/papi/create_property.go b/pkg/providers/papi/create_property.go index 6f3acee..e8009ea 100644 --- a/pkg/providers/papi/create_property.go +++ b/pkg/providers/papi/create_property.go @@ -26,6 +26,7 @@ import ( "os" "path/filepath" "regexp" + "sort" "strconv" "strings" "text/template" @@ -636,7 +637,7 @@ func fetchActiveActivationForNetwork(ctx context.Context, client papi.PAPI, prop if err != nil { return nil, err } - return getLatestActivation(activationsResponse.Activations, network, ""), nil + return getLatestActiveActivation(activationsResponse.Activations, network), nil } // getContactEmails gets list of emails from latest activation @@ -887,28 +888,29 @@ func findProduct(products *papi.GetProductsResponse, id string) (*papi.ProductIt return nil, fmt.Errorf("unable to find product: \"%s\"", id) } -// getLatestActivation gets the latest activation for the specified network -// -// Defaults to NetworkProduction. Pass in a status to check for, defaults to StatusActive -// -// This can return an activation OR a deactivation. Check activation.ActivationType and activation.Status for what you're looking for -func getLatestActivation(activations papi.ActivationsItems, network papi.ActivationNetwork, status papi.ActivationStatus) *papi.Activation { - if network == "" { - network = papi.ActivationNetworkProduction +// getLatestActiveActivation retrieves the latest active activation for the specified network. +func getLatestActiveActivation(activationItems papi.ActivationsItems, network papi.ActivationNetwork) *papi.Activation { + activations := activationItems.Items + if len(activations) == 0 { + return nil } - if status == "" { - status = papi.ActivationStatusActive - } + sort.Slice(activations, func(i, j int) bool { + return activations[i].UpdateDate > activations[j].UpdateDate + }) - var latest *papi.Activation - for _, activation := range activations.Items { - if activation.Network == network && activation.Status == status && (latest == nil || activation.PropertyVersion > latest.PropertyVersion) { - latest = activation + for _, activation := range activations { + if activation.Status == papi.ActivationStatusActive && activation.Network == network { + if activation.ActivationType == papi.ActivationTypeActivate { + return activation + } + if activation.ActivationType == papi.ActivationTypeDeactivate { + return nil + } } } - return latest + return nil } func ruleNameNormalizer() func(string) string { diff --git a/pkg/providers/papi/create_property_test.go b/pkg/providers/papi/create_property_test.go index c1b6c8a..bff12c3 100644 --- a/pkg/providers/papi/create_property_test.go +++ b/pkg/providers/papi/create_property_test.go @@ -1255,6 +1255,38 @@ func mockProcessTemplates(p *templates.MockProcessor, tfData TFData, filterFuncs } } +type activationItemData struct { + actType string + actID string + network string + status string + version int + updateDate string +} + +type activationItemsData []activationItemData + +func mockActivationsItems(items activationItemsData) papi.ActivationsItems { + var activations []*papi.Activation + for _, activationItem := range items { + activation := papi.Activation{ + ActivationID: activationItem.actID, + ActivationType: papi.ActivationType(activationItem.actType), + PropertyName: "test.edgesuite.net", + PropertyID: "prp_12345", + PropertyVersion: activationItem.version, + AcknowledgeAllWarnings: false, + Network: papi.ActivationNetwork(activationItem.network), + Status: papi.ActivationStatus(activationItem.status), + NotifyEmails: []string{"aa@aa.com"}, + Note: "example note", + UpdateDate: activationItem.updateDate, + } + activations = append(activations, &activation) + } + return papi.ActivationsItems{Items: activations} +} + func getRuleTreeResponse(dir string, t *testing.T) papi.GetRuleTreeResponse { var ruleResponse papi.GetRuleTreeResponse rules, err := os.ReadFile(fmt.Sprintf("./testdata/%s/%s", dir, "mock_rules.json")) @@ -2038,6 +2070,111 @@ func TestRuleNameNormalizer(t *testing.T) { } } +func TestGetLatestActiveActivation(t *testing.T) { + tests := map[string]struct { + activationItems activationItemsData + network papi.ActivationNetwork + expectedActiveVersion int + }{ + "one staging activation": { + activationItems: activationItemsData{ + activationItemData{ + actType: "ACTIVATE", + actID: "atv_1", + status: "ACTIVE", + network: "STAGING", + version: 1, + updateDate: "2018-03-07T23:40:45Z"}, + }, + network: papi.ActivationNetworkStaging, + expectedActiveVersion: 1, + }, + "two staging activations": { + activationItems: activationItemsData{ + activationItemData{ + actType: "ACTIVATE", + actID: "atv_2", + status: "ACTIVE", + network: "STAGING", + version: 2, + updateDate: "2018-03-12T15:40:45Z"}, + activationItemData{ + actType: "DEACTIVATE", + actID: "atv_1", + status: "INACTIVE", + network: "STAGING", + version: 1, + updateDate: "2018-03-07T10:11:45Z"}, + }, + network: papi.ActivationNetworkStaging, + expectedActiveVersion: 2, + }, + "three staging activation - 2nd active": { + activationItems: activationItemsData{ + activationItemData{ + actType: "DEACTIVATE", + actID: "atv_3", + status: "INACTIVE", + network: "STAGING", + version: 3, + updateDate: "2018-04-01T14:00:45Z"}, + activationItemData{ + actType: "ACTIVATE", + actID: "atv_2", + status: "ACTIVE", + network: "STAGING", + version: 2, + updateDate: "2018-04-20T10:00:45Z"}, + activationItemData{ + actType: "DEACTIVATE", + actID: "atv_1", + status: "INACTIVE", + network: "STAGING", + version: 1, + updateDate: "2018-03-07T08:40:45Z"}, + }, + network: papi.ActivationNetworkStaging, + expectedActiveVersion: 2, + }, + "two production activations": { + activationItems: activationItemsData{ + activationItemData{ + actType: "ACTIVATE", + actID: "atv_2", + status: "ACTIVE", + network: "PRODUCTION", + version: 2, + updateDate: "2018-03-08T12:00:45Z"}, + activationItemData{ + actType: "DEACTIVATE", + actID: "atv_1", + status: "INACTIVE", + network: "PRODUCTION", + version: 1, + updateDate: "2018-03-07T08:00:45Z"}, + }, + network: papi.ActivationNetworkProduction, + expectedActiveVersion: 2, + }, + "no activations": { + activationItems: activationItemsData{}, + network: papi.ActivationNetworkProduction, + }, + } + + for name, test := range tests { + t.Run(name, func(t *testing.T) { + items := mockActivationsItems(test.activationItems) + var activation = getLatestActiveActivation(items, test.network) + if activation != nil { + assert.Equal(t, test.expectedActiveVersion, activation.PropertyVersion) + } else { + assert.Empty(t, test.expectedActiveVersion) + } + }) + } +} + func TestTerraformName(t *testing.T) { tests := map[string]struct { given string From b5cb75eb7c8ad7196f861a6b5de749c7b9c91100 Mon Sep 17 00:00:00 2001 From: Dawid Dzhafarov Date: Mon, 14 Aug 2023 06:19:19 +0000 Subject: [PATCH 2/8] DXE-2936 add description of schema flag for ivm --- CHANGELOG.md | 3 +++ README.md | 1 + 2 files changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e66d06c..226c502 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ ### Bug fixes +* Image and Video Manager + * Added description for `--schema` flag for `export-imaging` command in `README.md` ([#56](https://github.com/akamai/cli-terraform/issues/56)) + * PAPI * Fixed `export-property` command to export `akamai_property_activation` resource attributes for latest active version. diff --git a/README.md b/README.md index 9e88e8a..0fc1575 100644 --- a/README.md +++ b/README.md @@ -292,6 +292,7 @@ $ akamai terraform export-iam Flags: --tfworkpath path Directory used to store files created when running commands. (default: current directory) --policy-json-dir path Path location for placement of policy jsons. Default: same value as tfworkpath + --schema Generate content of the policy using HCL instead of JSON file (default: false) ``` ### Export Image and Video policy configuration. From b371156624762d717352d369d8e09461daa81670 Mon Sep 17 00:00:00 2001 From: Dawid Dzhafarov Date: Wed, 16 Aug 2023 06:25:45 +0000 Subject: [PATCH 3/8] DXE-2728 Replace data sources with variables for export-property group_id and contract_id --- CHANGELOG.md | 2 ++ pkg/providers/papi/templates/property.tmpl | 16 ++++------------ pkg/providers/papi/templates/variables.tmpl | 11 +++++++++++ .../basic-rules-datasource-schema1/property.tf | 13 ++----------- .../basic-rules-datasource-schema1/variables.tf | 10 ++++++++++ .../basic-rules-datasource-schema2/property.tf | 13 ++----------- .../basic-rules-datasource-schema2/variables.tf | 10 ++++++++++ .../testdata/basic-rules-datasource/property.tf | 17 ++++------------- .../basic-rules-datasource/variables.tf | 10 ++++++++++ .../papi/testdata/basic-v1/property.tf | 8 ++++---- .../papi/testdata/basic-v1/variables.tf | 10 ++++++++++ pkg/providers/papi/testdata/basic/property.tf | 17 ++++------------- pkg/providers/papi/testdata/basic/variables.tf | 10 ++++++++++ .../property.tf | 11 ++--------- .../variables.tf | 10 ++++++++++ .../basic_property_with_include/property.tf | 17 ++++------------- .../basic_property_with_include/variables.tf | 10 ++++++++++ .../property.tf | 17 ++++------------- .../variables.tf | 10 ++++++++++ .../property.tf | 17 ++++------------- .../variables.tf | 10 ++++++++++ .../basic_with_activation_note/property.tf | 17 ++++------------- .../basic_with_activation_note/variables.tf | 10 ++++++++++ .../basic_with_both_activations/property.tf | 17 ++++------------- .../basic_with_both_activations/variables.tf | 10 ++++++++++ .../property.tf | 8 ++++---- .../variables.tf | 10 ++++++++++ .../property.tf | 17 ++++------------- .../variables.tf | 10 ++++++++++ .../testdata/basic_with_use_cases/property.tf | 17 ++++------------- .../testdata/basic_with_use_cases/variables.tf | 10 ++++++++++ .../basic_without_activation/property.tf | 17 ++++------------- .../basic_without_activation/variables.tf | 10 ++++++++++ 33 files changed, 221 insertions(+), 181 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 226c502..9900ac6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ * PAPI * Fixed `export-property` command to export `akamai_property_activation` resource attributes for latest active version. + * Fixed `export-property` command to use `group_id` and `contract_id` as terraform variables, instead of data sources, which + produced inconsistencies ([I#374](https://github.com/akamai/terraform-provider-akamai/issues/426)) ## Version 1.8.0 (August 1, 2023) diff --git a/pkg/providers/papi/templates/property.tmpl b/pkg/providers/papi/templates/property.tmpl index e1667dd..fc85c9d 100644 --- a/pkg/providers/papi/templates/property.tmpl +++ b/pkg/providers/papi/templates/property.tmpl @@ -14,14 +14,6 @@ provider "akamai" { config_section = var.config_section } -data "akamai_group" "group" { - group_name = "{{.Property.GroupName}}" - contract_id = "{{.Property.ContractID}}" -} - -data "akamai_contract" "contract" { - group_name = data.akamai_group.group.group_name -} {{- if not .RulesAsSchema}} data "akamai_property_rules_template" "rules" { @@ -29,8 +21,8 @@ data "akamai_property_rules_template" "rules" { }{{end}} {{range .Property.EdgeHostnames}} resource "akamai_edge_hostname" "{{.EdgeHostnameResourceName}}" { - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id ip_behavior = "{{.IPv6}}" edge_hostname = "{{.EdgeHostname}}" {{- if .UseCases}} @@ -40,8 +32,8 @@ resource "akamai_edge_hostname" "{{.EdgeHostnameResourceName}}" { {{end}} resource "akamai_property" "{{.Property.PropertyResourceName}}" { name = "{{.Property.PropertyName}}" - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id product_id = "prd_{{.Property.ProductName}}" {{- range .Property.Hostnames}} hostnames { diff --git a/pkg/providers/papi/templates/variables.tmpl b/pkg/providers/papi/templates/variables.tmpl index 578c53e..e3934ed 100644 --- a/pkg/providers/papi/templates/variables.tmpl +++ b/pkg/providers/papi/templates/variables.tmpl @@ -8,3 +8,14 @@ variable "config_section" { type = string default = "{{.Section}}" } +{{ if .Property.PropertyName }} +variable "contract_id" { + type = string + default = "{{.Property.ContractID}}" +} + +variable "group_id" { + type = string + default = "{{.Property.GroupID}}" +} +{{- end}} \ No newline at end of file diff --git a/pkg/providers/papi/testdata/basic-rules-datasource-schema1/property.tf b/pkg/providers/papi/testdata/basic-rules-datasource-schema1/property.tf index c44aaeb..8092c33 100644 --- a/pkg/providers/papi/testdata/basic-rules-datasource-schema1/property.tf +++ b/pkg/providers/papi/testdata/basic-rules-datasource-schema1/property.tf @@ -13,19 +13,10 @@ provider "akamai" { config_section = var.config_section } -data "akamai_group" "group" { - group_name = "test_group" - contract_id = "test_contract" -} - -data "akamai_contract" "contract" { - group_name = data.akamai_group.group.group_name -} - resource "akamai_property" "test-edgesuite-net" { name = "test.edgesuite.net" - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id product_id = "prd_HTTP_Content_Del" rule_format = data.akamai_property_rules_builder.test-edgesuite-net_rule_default.rule_format rules = data.akamai_property_rules_builder.test-edgesuite-net_rule_default.json diff --git a/pkg/providers/papi/testdata/basic-rules-datasource-schema1/variables.tf b/pkg/providers/papi/testdata/basic-rules-datasource-schema1/variables.tf index b769e45..3a31117 100644 --- a/pkg/providers/papi/testdata/basic-rules-datasource-schema1/variables.tf +++ b/pkg/providers/papi/testdata/basic-rules-datasource-schema1/variables.tf @@ -7,3 +7,13 @@ variable "config_section" { type = string default = "test_section" } + +variable "contract_id" { + type = string + default = "test_contract" +} + +variable "group_id" { + type = string + default = "grp_12345" +} \ No newline at end of file diff --git a/pkg/providers/papi/testdata/basic-rules-datasource-schema2/property.tf b/pkg/providers/papi/testdata/basic-rules-datasource-schema2/property.tf index c44aaeb..8092c33 100644 --- a/pkg/providers/papi/testdata/basic-rules-datasource-schema2/property.tf +++ b/pkg/providers/papi/testdata/basic-rules-datasource-schema2/property.tf @@ -13,19 +13,10 @@ provider "akamai" { config_section = var.config_section } -data "akamai_group" "group" { - group_name = "test_group" - contract_id = "test_contract" -} - -data "akamai_contract" "contract" { - group_name = data.akamai_group.group.group_name -} - resource "akamai_property" "test-edgesuite-net" { name = "test.edgesuite.net" - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id product_id = "prd_HTTP_Content_Del" rule_format = data.akamai_property_rules_builder.test-edgesuite-net_rule_default.rule_format rules = data.akamai_property_rules_builder.test-edgesuite-net_rule_default.json diff --git a/pkg/providers/papi/testdata/basic-rules-datasource-schema2/variables.tf b/pkg/providers/papi/testdata/basic-rules-datasource-schema2/variables.tf index b769e45..3a31117 100644 --- a/pkg/providers/papi/testdata/basic-rules-datasource-schema2/variables.tf +++ b/pkg/providers/papi/testdata/basic-rules-datasource-schema2/variables.tf @@ -7,3 +7,13 @@ variable "config_section" { type = string default = "test_section" } + +variable "contract_id" { + type = string + default = "test_contract" +} + +variable "group_id" { + type = string + default = "grp_12345" +} \ No newline at end of file diff --git a/pkg/providers/papi/testdata/basic-rules-datasource/property.tf b/pkg/providers/papi/testdata/basic-rules-datasource/property.tf index bb77e2a..689daa3 100644 --- a/pkg/providers/papi/testdata/basic-rules-datasource/property.tf +++ b/pkg/providers/papi/testdata/basic-rules-datasource/property.tf @@ -13,26 +13,17 @@ provider "akamai" { config_section = var.config_section } -data "akamai_group" "group" { - group_name = "test_group" - contract_id = "test_contract" -} - -data "akamai_contract" "contract" { - group_name = data.akamai_group.group.group_name -} - resource "akamai_edge_hostname" "test-edgesuite-net" { - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id ip_behavior = "IPV6_COMPLIANCE" edge_hostname = "test.edgesuite.net" } resource "akamai_property" "test-edgesuite-net" { name = "test.edgesuite.net" - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id product_id = "prd_HTTP_Content_Del" hostnames { cname_from = "test.edgesuite.net" diff --git a/pkg/providers/papi/testdata/basic-rules-datasource/variables.tf b/pkg/providers/papi/testdata/basic-rules-datasource/variables.tf index b769e45..3a31117 100644 --- a/pkg/providers/papi/testdata/basic-rules-datasource/variables.tf +++ b/pkg/providers/papi/testdata/basic-rules-datasource/variables.tf @@ -7,3 +7,13 @@ variable "config_section" { type = string default = "test_section" } + +variable "contract_id" { + type = string + default = "test_contract" +} + +variable "group_id" { + type = string + default = "grp_12345" +} \ No newline at end of file diff --git a/pkg/providers/papi/testdata/basic-v1/property.tf b/pkg/providers/papi/testdata/basic-v1/property.tf index cc2ed5e..e2a6069 100644 --- a/pkg/providers/papi/testdata/basic-v1/property.tf +++ b/pkg/providers/papi/testdata/basic-v1/property.tf @@ -27,16 +27,16 @@ data "akamai_property_rules_template" "rules" { } resource "akamai_edge_hostname" "test-edgesuite-net" { - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id ip_behavior = "IPV6_COMPLIANCE" edge_hostname = "test.edgesuite.net" } resource "akamai_property" "test-edgesuite-net" { name = "test.edgesuite.net" - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id product_id = "prd_HTTP_Content_Del" hostnames { cname_from = "test.edgesuite.net" diff --git a/pkg/providers/papi/testdata/basic-v1/variables.tf b/pkg/providers/papi/testdata/basic-v1/variables.tf index b769e45..3a31117 100644 --- a/pkg/providers/papi/testdata/basic-v1/variables.tf +++ b/pkg/providers/papi/testdata/basic-v1/variables.tf @@ -7,3 +7,13 @@ variable "config_section" { type = string default = "test_section" } + +variable "contract_id" { + type = string + default = "test_contract" +} + +variable "group_id" { + type = string + default = "grp_12345" +} \ No newline at end of file diff --git a/pkg/providers/papi/testdata/basic/property.tf b/pkg/providers/papi/testdata/basic/property.tf index 48f718f..8f0bdc3 100644 --- a/pkg/providers/papi/testdata/basic/property.tf +++ b/pkg/providers/papi/testdata/basic/property.tf @@ -13,30 +13,21 @@ provider "akamai" { config_section = var.config_section } -data "akamai_group" "group" { - group_name = "test_group" - contract_id = "test_contract" -} - -data "akamai_contract" "contract" { - group_name = data.akamai_group.group.group_name -} - data "akamai_property_rules_template" "rules" { template_file = abspath("${path.module}/property-snippets/main.json") } resource "akamai_edge_hostname" "test-edgesuite-net" { - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id ip_behavior = "IPV6_COMPLIANCE" edge_hostname = "test.edgesuite.net" } resource "akamai_property" "test-edgesuite-net" { name = "test.edgesuite.net" - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id product_id = "prd_HTTP_Content_Del" hostnames { cname_from = "test.edgesuite.net" diff --git a/pkg/providers/papi/testdata/basic/variables.tf b/pkg/providers/papi/testdata/basic/variables.tf index b769e45..3a31117 100644 --- a/pkg/providers/papi/testdata/basic/variables.tf +++ b/pkg/providers/papi/testdata/basic/variables.tf @@ -7,3 +7,13 @@ variable "config_section" { type = string default = "test_section" } + +variable "contract_id" { + type = string + default = "test_contract" +} + +variable "group_id" { + type = string + default = "grp_12345" +} \ No newline at end of file diff --git a/pkg/providers/papi/testdata/basic_property_with_empty_hostname_id/property.tf b/pkg/providers/papi/testdata/basic_property_with_empty_hostname_id/property.tf index ab4d83e..0b1c240 100644 --- a/pkg/providers/papi/testdata/basic_property_with_empty_hostname_id/property.tf +++ b/pkg/providers/papi/testdata/basic_property_with_empty_hostname_id/property.tf @@ -13,14 +13,7 @@ provider "akamai" { config_section = var.config_section } -data "akamai_group" "group" { - group_name = "test_group" - contract_id = "test_contract" -} -data "akamai_contract" "contract" { - group_name = data.akamai_group.group.group_name -} data "akamai_property_rules_template" "rules" { template_file = abspath("${path.module}/property-snippets/main.json") @@ -28,8 +21,8 @@ data "akamai_property_rules_template" "rules" { resource "akamai_property" "test-edgesuite-net" { name = "test.edgesuite.net" - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id product_id = "prd_HTTP_Content_Del" rule_format = "latest" hostnames { diff --git a/pkg/providers/papi/testdata/basic_property_with_empty_hostname_id/variables.tf b/pkg/providers/papi/testdata/basic_property_with_empty_hostname_id/variables.tf index b769e45..3a31117 100644 --- a/pkg/providers/papi/testdata/basic_property_with_empty_hostname_id/variables.tf +++ b/pkg/providers/papi/testdata/basic_property_with_empty_hostname_id/variables.tf @@ -7,3 +7,13 @@ variable "config_section" { type = string default = "test_section" } + +variable "contract_id" { + type = string + default = "test_contract" +} + +variable "group_id" { + type = string + default = "grp_12345" +} \ No newline at end of file diff --git a/pkg/providers/papi/testdata/basic_property_with_include/property.tf b/pkg/providers/papi/testdata/basic_property_with_include/property.tf index 48f718f..8f0bdc3 100644 --- a/pkg/providers/papi/testdata/basic_property_with_include/property.tf +++ b/pkg/providers/papi/testdata/basic_property_with_include/property.tf @@ -13,30 +13,21 @@ provider "akamai" { config_section = var.config_section } -data "akamai_group" "group" { - group_name = "test_group" - contract_id = "test_contract" -} - -data "akamai_contract" "contract" { - group_name = data.akamai_group.group.group_name -} - data "akamai_property_rules_template" "rules" { template_file = abspath("${path.module}/property-snippets/main.json") } resource "akamai_edge_hostname" "test-edgesuite-net" { - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id ip_behavior = "IPV6_COMPLIANCE" edge_hostname = "test.edgesuite.net" } resource "akamai_property" "test-edgesuite-net" { name = "test.edgesuite.net" - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id product_id = "prd_HTTP_Content_Del" hostnames { cname_from = "test.edgesuite.net" diff --git a/pkg/providers/papi/testdata/basic_property_with_include/variables.tf b/pkg/providers/papi/testdata/basic_property_with_include/variables.tf index b769e45..3a31117 100644 --- a/pkg/providers/papi/testdata/basic_property_with_include/variables.tf +++ b/pkg/providers/papi/testdata/basic_property_with_include/variables.tf @@ -7,3 +7,13 @@ variable "config_section" { type = string default = "test_section" } + +variable "contract_id" { + type = string + default = "test_contract" +} + +variable "group_id" { + type = string + default = "grp_12345" +} \ No newline at end of file diff --git a/pkg/providers/papi/testdata/basic_property_with_multiple_includes/property.tf b/pkg/providers/papi/testdata/basic_property_with_multiple_includes/property.tf index 48f718f..8f0bdc3 100644 --- a/pkg/providers/papi/testdata/basic_property_with_multiple_includes/property.tf +++ b/pkg/providers/papi/testdata/basic_property_with_multiple_includes/property.tf @@ -13,30 +13,21 @@ provider "akamai" { config_section = var.config_section } -data "akamai_group" "group" { - group_name = "test_group" - contract_id = "test_contract" -} - -data "akamai_contract" "contract" { - group_name = data.akamai_group.group.group_name -} - data "akamai_property_rules_template" "rules" { template_file = abspath("${path.module}/property-snippets/main.json") } resource "akamai_edge_hostname" "test-edgesuite-net" { - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id ip_behavior = "IPV6_COMPLIANCE" edge_hostname = "test.edgesuite.net" } resource "akamai_property" "test-edgesuite-net" { name = "test.edgesuite.net" - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id product_id = "prd_HTTP_Content_Del" hostnames { cname_from = "test.edgesuite.net" diff --git a/pkg/providers/papi/testdata/basic_property_with_multiple_includes/variables.tf b/pkg/providers/papi/testdata/basic_property_with_multiple_includes/variables.tf index b769e45..3a31117 100644 --- a/pkg/providers/papi/testdata/basic_property_with_multiple_includes/variables.tf +++ b/pkg/providers/papi/testdata/basic_property_with_multiple_includes/variables.tf @@ -7,3 +7,13 @@ variable "config_section" { type = string default = "test_section" } + +variable "contract_id" { + type = string + default = "test_contract" +} + +variable "group_id" { + type = string + default = "grp_12345" +} \ No newline at end of file diff --git a/pkg/providers/papi/testdata/basic_property_with_multiple_includes_schema/property.tf b/pkg/providers/papi/testdata/basic_property_with_multiple_includes_schema/property.tf index bb77e2a..689daa3 100644 --- a/pkg/providers/papi/testdata/basic_property_with_multiple_includes_schema/property.tf +++ b/pkg/providers/papi/testdata/basic_property_with_multiple_includes_schema/property.tf @@ -13,26 +13,17 @@ provider "akamai" { config_section = var.config_section } -data "akamai_group" "group" { - group_name = "test_group" - contract_id = "test_contract" -} - -data "akamai_contract" "contract" { - group_name = data.akamai_group.group.group_name -} - resource "akamai_edge_hostname" "test-edgesuite-net" { - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id ip_behavior = "IPV6_COMPLIANCE" edge_hostname = "test.edgesuite.net" } resource "akamai_property" "test-edgesuite-net" { name = "test.edgesuite.net" - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id product_id = "prd_HTTP_Content_Del" hostnames { cname_from = "test.edgesuite.net" diff --git a/pkg/providers/papi/testdata/basic_property_with_multiple_includes_schema/variables.tf b/pkg/providers/papi/testdata/basic_property_with_multiple_includes_schema/variables.tf index b769e45..3a31117 100644 --- a/pkg/providers/papi/testdata/basic_property_with_multiple_includes_schema/variables.tf +++ b/pkg/providers/papi/testdata/basic_property_with_multiple_includes_schema/variables.tf @@ -7,3 +7,13 @@ variable "config_section" { type = string default = "test_section" } + +variable "contract_id" { + type = string + default = "test_contract" +} + +variable "group_id" { + type = string + default = "grp_12345" +} \ No newline at end of file diff --git a/pkg/providers/papi/testdata/basic_with_activation_note/property.tf b/pkg/providers/papi/testdata/basic_with_activation_note/property.tf index e4245e3..0235fd6 100644 --- a/pkg/providers/papi/testdata/basic_with_activation_note/property.tf +++ b/pkg/providers/papi/testdata/basic_with_activation_note/property.tf @@ -13,30 +13,21 @@ provider "akamai" { config_section = var.config_section } -data "akamai_group" "group" { - group_name = "test_group" - contract_id = "test_contract" -} - -data "akamai_contract" "contract" { - group_name = data.akamai_group.group.group_name -} - data "akamai_property_rules_template" "rules" { template_file = abspath("${path.module}/property-snippets/main.json") } resource "akamai_edge_hostname" "test-edgesuite-net" { - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id ip_behavior = "IPV6_COMPLIANCE" edge_hostname = "test.edgesuite.net" } resource "akamai_property" "test-edgesuite-net" { name = "test.edgesuite.net" - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id product_id = "prd_HTTP_Content_Del" hostnames { cname_from = "test.edgesuite.net" diff --git a/pkg/providers/papi/testdata/basic_with_activation_note/variables.tf b/pkg/providers/papi/testdata/basic_with_activation_note/variables.tf index b769e45..3a31117 100644 --- a/pkg/providers/papi/testdata/basic_with_activation_note/variables.tf +++ b/pkg/providers/papi/testdata/basic_with_activation_note/variables.tf @@ -7,3 +7,13 @@ variable "config_section" { type = string default = "test_section" } + +variable "contract_id" { + type = string + default = "test_contract" +} + +variable "group_id" { + type = string + default = "grp_12345" +} \ No newline at end of file diff --git a/pkg/providers/papi/testdata/basic_with_both_activations/property.tf b/pkg/providers/papi/testdata/basic_with_both_activations/property.tf index fc4225a..0f7f320 100644 --- a/pkg/providers/papi/testdata/basic_with_both_activations/property.tf +++ b/pkg/providers/papi/testdata/basic_with_both_activations/property.tf @@ -13,30 +13,21 @@ provider "akamai" { config_section = var.config_section } -data "akamai_group" "group" { - group_name = "test_group" - contract_id = "test_contract" -} - -data "akamai_contract" "contract" { - group_name = data.akamai_group.group.group_name -} - data "akamai_property_rules_template" "rules" { template_file = abspath("${path.module}/property-snippets/main.json") } resource "akamai_edge_hostname" "test-edgesuite-net" { - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id ip_behavior = "IPV6_COMPLIANCE" edge_hostname = "test.edgesuite.net" } resource "akamai_property" "test-edgesuite-net" { name = "test.edgesuite.net" - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id product_id = "prd_HTTP_Content_Del" hostnames { cname_from = "test.edgesuite.net" diff --git a/pkg/providers/papi/testdata/basic_with_both_activations/variables.tf b/pkg/providers/papi/testdata/basic_with_both_activations/variables.tf index b769e45..3a31117 100644 --- a/pkg/providers/papi/testdata/basic_with_both_activations/variables.tf +++ b/pkg/providers/papi/testdata/basic_with_both_activations/variables.tf @@ -7,3 +7,13 @@ variable "config_section" { type = string default = "test_section" } + +variable "contract_id" { + type = string + default = "test_contract" +} + +variable "group_id" { + type = string + default = "grp_12345" +} \ No newline at end of file diff --git a/pkg/providers/papi/testdata/basic_with_cert_provisioning_type/property.tf b/pkg/providers/papi/testdata/basic_with_cert_provisioning_type/property.tf index ff19c43..aec76f0 100644 --- a/pkg/providers/papi/testdata/basic_with_cert_provisioning_type/property.tf +++ b/pkg/providers/papi/testdata/basic_with_cert_provisioning_type/property.tf @@ -27,8 +27,8 @@ data "akamai_property_rules_template" "rules" { } resource "akamai_edge_hostname" "test-edgesuite-net" { - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id ip_behavior = "IPV6_COMPLIANCE" edge_hostname = "test.edgesuite.net" use_cases = jsonencode([ @@ -42,8 +42,8 @@ resource "akamai_edge_hostname" "test-edgesuite-net" { resource "akamai_property" "test-edgesuite-net" { name = "test.edgesuite.net" - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id product_id = "prd_HTTP_Content_Del" rule_format = "latest" hostnames { diff --git a/pkg/providers/papi/testdata/basic_with_cert_provisioning_type/variables.tf b/pkg/providers/papi/testdata/basic_with_cert_provisioning_type/variables.tf index b769e45..3a31117 100644 --- a/pkg/providers/papi/testdata/basic_with_cert_provisioning_type/variables.tf +++ b/pkg/providers/papi/testdata/basic_with_cert_provisioning_type/variables.tf @@ -7,3 +7,13 @@ variable "config_section" { type = string default = "test_section" } + +variable "contract_id" { + type = string + default = "test_contract" +} + +variable "group_id" { + type = string + default = "grp_12345" +} \ No newline at end of file diff --git a/pkg/providers/papi/testdata/basic_with_production_activation/property.tf b/pkg/providers/papi/testdata/basic_with_production_activation/property.tf index aa1a880..b33b6a7 100644 --- a/pkg/providers/papi/testdata/basic_with_production_activation/property.tf +++ b/pkg/providers/papi/testdata/basic_with_production_activation/property.tf @@ -13,30 +13,21 @@ provider "akamai" { config_section = var.config_section } -data "akamai_group" "group" { - group_name = "test_group" - contract_id = "test_contract" -} - -data "akamai_contract" "contract" { - group_name = data.akamai_group.group.group_name -} - data "akamai_property_rules_template" "rules" { template_file = abspath("${path.module}/property-snippets/main.json") } resource "akamai_edge_hostname" "test-edgesuite-net" { - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id ip_behavior = "IPV6_COMPLIANCE" edge_hostname = "test.edgesuite.net" } resource "akamai_property" "test-edgesuite-net" { name = "test.edgesuite.net" - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id product_id = "prd_HTTP_Content_Del" hostnames { cname_from = "test.edgesuite.net" diff --git a/pkg/providers/papi/testdata/basic_with_production_activation/variables.tf b/pkg/providers/papi/testdata/basic_with_production_activation/variables.tf index b769e45..3a31117 100644 --- a/pkg/providers/papi/testdata/basic_with_production_activation/variables.tf +++ b/pkg/providers/papi/testdata/basic_with_production_activation/variables.tf @@ -7,3 +7,13 @@ variable "config_section" { type = string default = "test_section" } + +variable "contract_id" { + type = string + default = "test_contract" +} + +variable "group_id" { + type = string + default = "grp_12345" +} \ No newline at end of file diff --git a/pkg/providers/papi/testdata/basic_with_use_cases/property.tf b/pkg/providers/papi/testdata/basic_with_use_cases/property.tf index 9f15428..4b0d609 100644 --- a/pkg/providers/papi/testdata/basic_with_use_cases/property.tf +++ b/pkg/providers/papi/testdata/basic_with_use_cases/property.tf @@ -13,22 +13,13 @@ provider "akamai" { config_section = var.config_section } -data "akamai_group" "group" { - group_name = "test_group" - contract_id = "test_contract" -} - -data "akamai_contract" "contract" { - group_name = data.akamai_group.group.group_name -} - data "akamai_property_rules_template" "rules" { template_file = abspath("${path.module}/property-snippets/main.json") } resource "akamai_edge_hostname" "test-edgesuite-net" { - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id ip_behavior = "IPV6_COMPLIANCE" edge_hostname = "test.edgesuite.net" use_cases = jsonencode([ @@ -42,8 +33,8 @@ resource "akamai_edge_hostname" "test-edgesuite-net" { resource "akamai_property" "test-edgesuite-net" { name = "test.edgesuite.net" - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id product_id = "prd_HTTP_Content_Del" hostnames { cname_from = "test.edgesuite.net" diff --git a/pkg/providers/papi/testdata/basic_with_use_cases/variables.tf b/pkg/providers/papi/testdata/basic_with_use_cases/variables.tf index b769e45..3a31117 100644 --- a/pkg/providers/papi/testdata/basic_with_use_cases/variables.tf +++ b/pkg/providers/papi/testdata/basic_with_use_cases/variables.tf @@ -7,3 +7,13 @@ variable "config_section" { type = string default = "test_section" } + +variable "contract_id" { + type = string + default = "test_contract" +} + +variable "group_id" { + type = string + default = "grp_12345" +} \ No newline at end of file diff --git a/pkg/providers/papi/testdata/basic_without_activation/property.tf b/pkg/providers/papi/testdata/basic_without_activation/property.tf index 299199f..7b17eea 100644 --- a/pkg/providers/papi/testdata/basic_without_activation/property.tf +++ b/pkg/providers/papi/testdata/basic_without_activation/property.tf @@ -13,30 +13,21 @@ provider "akamai" { config_section = var.config_section } -data "akamai_group" "group" { - group_name = "test_group" - contract_id = "test_contract" -} - -data "akamai_contract" "contract" { - group_name = data.akamai_group.group.group_name -} - data "akamai_property_rules_template" "rules" { template_file = abspath("${path.module}/property-snippets/main.json") } resource "akamai_edge_hostname" "test-edgesuite-net" { - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id ip_behavior = "IPV6_COMPLIANCE" edge_hostname = "test.edgesuite.net" } resource "akamai_property" "test-edgesuite-net" { name = "test.edgesuite.net" - contract_id = data.akamai_contract.contract.id - group_id = data.akamai_group.group.id + contract_id = var.contract_id + group_id = var.group_id product_id = "prd_HTTP_Content_Del" hostnames { cname_from = "test.edgesuite.net" diff --git a/pkg/providers/papi/testdata/basic_without_activation/variables.tf b/pkg/providers/papi/testdata/basic_without_activation/variables.tf index b769e45..3a31117 100644 --- a/pkg/providers/papi/testdata/basic_without_activation/variables.tf +++ b/pkg/providers/papi/testdata/basic_without_activation/variables.tf @@ -7,3 +7,13 @@ variable "config_section" { type = string default = "test_section" } + +variable "contract_id" { + type = string + default = "test_contract" +} + +variable "group_id" { + type = string + default = "grp_12345" +} \ No newline at end of file From 09136c5d93c499d5b05e3485a022b4a55bdd9bfc Mon Sep 17 00:00:00 2001 From: Michal Wojcik Date: Wed, 16 Aug 2023 08:42:08 +0000 Subject: [PATCH 4/8] DXE-2937 export-property: failure with rule-format v2023-05-30 --- CHANGELOG.md | 3 +++ pkg/providers/papi/templates/rules_v2023-05-30.tmpl | 4 ++-- .../testdata/basic-rules-datasource-schema2/mock_rules.json | 4 +++- .../papi/testdata/basic-rules-datasource-schema2/rules.tf | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9900ac6..b3db9d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,5 @@ # Release Notes + ## Version 1.x.x (xxxx yy, 2023) ### Bug fixes @@ -10,6 +11,8 @@ * Fixed `export-property` command to export `akamai_property_activation` resource attributes for latest active version. * Fixed `export-property` command to use `group_id` and `contract_id` as terraform variables, instead of data sources, which produced inconsistencies ([I#374](https://github.com/akamai/terraform-provider-akamai/issues/426)) + * `logStreamName` field from `datastream` behavior has changed from string to array of strings for rule + format `v2023-05-30` ([#58](https://github.com/akamai/cli-terraform/issues/58)) ## Version 1.8.0 (August 1, 2023) diff --git a/pkg/providers/papi/templates/rules_v2023-05-30.tmpl b/pkg/providers/papi/templates/rules_v2023-05-30.tmpl index 068bef6..74d266e 100644 --- a/pkg/providers/papi/templates/rules_v2023-05-30.tmpl +++ b/pkg/providers/papi/templates/rules_v2023-05-30.tmpl @@ -2258,8 +2258,8 @@ datastream { {{- if and (eq $k "logEnabled") (ne $v nil)}} log_enabled = {{$v}} {{- end}} -{{- if and (eq $k "logStreamName") (ne $v nil)}} - log_stream_name = {{template "Text" $v}} +{{- if eq $k "logStreamName"}} + log_stream_name = [{{range $v}}"{{. | Escape}}", {{end}}] {{- end}} {{- if and (eq $k "samplingPercentage") (ne $v nil)}} sampling_percentage = {{$v | AsInt}} diff --git a/pkg/providers/papi/testdata/basic-rules-datasource-schema2/mock_rules.json b/pkg/providers/papi/testdata/basic-rules-datasource-schema2/mock_rules.json index 279f246..ced0a1f 100644 --- a/pkg/providers/papi/testdata/basic-rules-datasource-schema2/mock_rules.json +++ b/pkg/providers/papi/testdata/basic-rules-datasource-schema2/mock_rules.json @@ -16,7 +16,9 @@ "datastreamIds": "77-85-6", "enabled": true, "logEnabled": false, - "logStreamName": "60", + "logStreamName": [ + "60" + ], "logStreamTitle": "test", "samplingPercentage": 100, "streamType": "LOG" diff --git a/pkg/providers/papi/testdata/basic-rules-datasource-schema2/rules.tf b/pkg/providers/papi/testdata/basic-rules-datasource-schema2/rules.tf index b661cdb..2655081 100644 --- a/pkg/providers/papi/testdata/basic-rules-datasource-schema2/rules.tf +++ b/pkg/providers/papi/testdata/basic-rules-datasource-schema2/rules.tf @@ -11,7 +11,7 @@ data "akamai_property_rules_builder" "test-edgesuite-net_rule_default" { datastream_ids = "77-85-6" enabled = true log_enabled = false - log_stream_name = "60" + log_stream_name = ["60", ] log_stream_title = "test" sampling_percentage = 100 stream_type = "LOG" From c5fa4d929185951eb779d0bf9590234f19500b77 Mon Sep 17 00:00:00 2001 From: Michal Mazur Date: Fri, 18 Aug 2023 12:13:26 +0000 Subject: [PATCH 5/8] DXE-2688 cli terraform add export cloudwrapper subcommand --- CHANGELOG.md | 7 +- README.md | 18 + pkg/commands/commands.go | 17 + .../cloudwrapper/create_configuration.go | 170 +++++++++ .../cloudwrapper/create_configuration_test.go | 336 ++++++++++++++++++ .../cloudwrapper/templates/cloudwrapper.tmpl | 50 +++ .../cloudwrapper/templates/imports.tmpl | 6 + .../cloudwrapper/templates/variables.tmpl | 10 + .../all_fields_config/cloudwrapper.tf | 45 +++ .../testdata/all_fields_config/import.sh | 3 + .../testdata/all_fields_config/variables.tf | 9 + .../testdata/basic_req_fields/cloudwrapper.tf | 43 +++ .../testdata/basic_req_fields/import.sh | 2 + .../testdata/basic_req_fields/variables.tf | 9 + .../not_active_configuration/cloudwrapper.tf | 45 +++ .../not_active_configuration/import.sh | 2 + .../not_active_configuration/variables.tf | 9 + 17 files changed, 780 insertions(+), 1 deletion(-) create mode 100644 pkg/providers/cloudwrapper/create_configuration.go create mode 100644 pkg/providers/cloudwrapper/create_configuration_test.go create mode 100644 pkg/providers/cloudwrapper/templates/cloudwrapper.tmpl create mode 100644 pkg/providers/cloudwrapper/templates/imports.tmpl create mode 100644 pkg/providers/cloudwrapper/templates/variables.tmpl create mode 100644 pkg/providers/cloudwrapper/testdata/all_fields_config/cloudwrapper.tf create mode 100644 pkg/providers/cloudwrapper/testdata/all_fields_config/import.sh create mode 100644 pkg/providers/cloudwrapper/testdata/all_fields_config/variables.tf create mode 100644 pkg/providers/cloudwrapper/testdata/basic_req_fields/cloudwrapper.tf create mode 100644 pkg/providers/cloudwrapper/testdata/basic_req_fields/import.sh create mode 100644 pkg/providers/cloudwrapper/testdata/basic_req_fields/variables.tf create mode 100644 pkg/providers/cloudwrapper/testdata/not_active_configuration/cloudwrapper.tf create mode 100644 pkg/providers/cloudwrapper/testdata/not_active_configuration/import.sh create mode 100644 pkg/providers/cloudwrapper/testdata/not_active_configuration/variables.tf diff --git a/CHANGELOG.md b/CHANGELOG.md index b3db9d6..3c6ed6a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Release Notes -## Version 1.x.x (xxxx yy, 2023) +## Version 1.9.0 (August 29, 2023) + +### Features/Enhancements + +* CloudWrapper + * Added support for `export-cloudwrapper` command which allows export of `akamai_cloudwrapper_configuration` and `akamai_cloudwrapper_activation` resources ### Bug fixes diff --git a/README.md b/README.md index 0fc1575..00afd03 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,7 @@ Description: Administer and manage available Akamai resources with Terraform Built-In Commands: + export-cloudwrapper export-domain (alias: create-domain) export-zone (alias: create-zone) export-appsec (alias: create-appsec) @@ -226,6 +227,23 @@ Flags: $ akamai terraform export-cloudlets-policy ``` +## CloudWrapper + +### Usage + +``` + akamai terraform [global flags] export-cloudwrapper [flags] + +Flags: + --tfworkpath path Directory used to store files created when running commands. (default: current directory) +``` + +### Export CloudWrapper configuration. + +``` +$ akamai terraform export-cloudwrapper +``` + ## EdgeWorkers ### Export EdgeKV Usage diff --git a/pkg/commands/commands.go b/pkg/commands/commands.go index b56bc90..419d8ac 100644 --- a/pkg/commands/commands.go +++ b/pkg/commands/commands.go @@ -18,6 +18,7 @@ package commands import ( "github.com/akamai/cli-terraform/pkg/providers/appsec" "github.com/akamai/cli-terraform/pkg/providers/cloudlets" + "github.com/akamai/cli-terraform/pkg/providers/cloudwrapper" "github.com/akamai/cli-terraform/pkg/providers/cps" "github.com/akamai/cli-terraform/pkg/providers/dns" "github.com/akamai/cli-terraform/pkg/providers/edgeworkers" @@ -152,6 +153,22 @@ func CommandLocator() ([]*cli.Command, error) { BashComplete: autocomplete.Default, }) + commands = append(commands, &cli.Command{ + Name: "export-cloudwrapper", + Description: "Generates Terraform configuration for CloudWrapper resources", + Usage: "export-cloudwrapper", + ArgsUsage: "", + Action: validatedAction(cloudwrapper.CmdCreateCloudWrapper, requireValidWorkpath, requireNArguments(1)), + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "tfworkpath", + Usage: "Directory used to store files created when running commands.", + DefaultText: "current directory", + }, + }, + BashComplete: autocomplete.Default, + }) + commands = append(commands, &cli.Command{ Name: "export-cloudlets-policy", Aliases: []string{"create-cloudlets-policy"}, diff --git a/pkg/providers/cloudwrapper/create_configuration.go b/pkg/providers/cloudwrapper/create_configuration.go new file mode 100644 index 0000000..5b2f0e9 --- /dev/null +++ b/pkg/providers/cloudwrapper/create_configuration.go @@ -0,0 +1,170 @@ +// Package cloudwrapper contains code for exporting CloudWrapper configuration +package cloudwrapper + +import ( + "context" + "embed" + "errors" + "fmt" + "path/filepath" + "strconv" + "strings" + + "github.com/akamai/AkamaiOPEN-edgegrid-golang/v7/pkg/cloudwrapper" + "github.com/akamai/cli-terraform/pkg/edgegrid" + "github.com/akamai/cli-terraform/pkg/templates" + "github.com/akamai/cli-terraform/pkg/tools" + "github.com/akamai/cli/pkg/terminal" + "github.com/fatih/color" + "github.com/urfave/cli/v2" +) + +type ( + // TFCloudWrapperData represents the data used in CloudWrapper + TFCloudWrapperData struct { + Configuration TFCWConfiguration + Section string + } + + // TFCWConfiguration represents the data used for export CloudWrapper configuration + TFCWConfiguration struct { + ConfigurationResourceName string + ID int64 + ContractID string + Name string + PropertyIDs []string + Comments string + Status string + NotificationEmails []string + RetainIdleObjects bool + CapacityAlertsThreshold *int + Locations []Location + IsActive bool + } + + // Location represents CloudWrapper location + Location struct { + TrafficTypeID int + Comments string + Capacity Capacity + } + + // Capacity represents capacity of location + Capacity struct { + Value int64 + Unit string + } +) + +//go:embed templates/* +var templateFiles embed.FS + +var ( + // ErrFetchingConfiguration is returned when problem occurred during fetching configuration + ErrFetchingConfiguration = errors.New("problem with fetching configuration") + // ErrContainMultiCDNSettings is returned when configuration contains Multi CDN Setting + ErrContainMultiCDNSettings = errors.New("configuration contains Multi CDN Settings") + // ErrExportingCloudWrapper is returned when there is an issue related to export of CloudWrapper + ErrExportingCloudWrapper = errors.New("error exporting CloudWrapper") + // ErrSavingFiles is returned when an issue with processing templates occurs + ErrSavingFiles = errors.New("saving terraform project files") +) + +// CmdCreateCloudWrapper is an entrypoint to export-cloudwrapper command +func CmdCreateCloudWrapper(c *cli.Context) error { + ctx := c.Context + sess := edgegrid.GetSession(ctx) + client := cloudwrapper.Client(sess) + + // tfWorkPath is a target directory for generated terraform resources + var tfWorkPath = "./" + if c.IsSet("tfworkpath") { + tfWorkPath = c.String("tfworkpath") + } + cloudwrapperPath := filepath.Join(tfWorkPath, "cloudwrapper.tf") + variablesPath := filepath.Join(tfWorkPath, "variables.tf") + importPath := filepath.Join(tfWorkPath, "import.sh") + if err := tools.CheckFiles(cloudwrapperPath, variablesPath, importPath); err != nil { + return cli.Exit(color.RedString(err.Error()), 1) + } + + templateToFile := map[string]string{ + "cloudwrapper.tmpl": cloudwrapperPath, + "variables.tmpl": variablesPath, + "imports.tmpl": importPath, + } + + processor := templates.FSTemplateProcessor{ + TemplatesFS: templateFiles, + TemplateTargets: templateToFile, + } + configID, err := strconv.ParseInt(c.Args().Get(0), 10, 64) + if err != nil { + return cli.Exit(color.RedString(err.Error()), 1) + } + section := edgegrid.GetEdgercSection(c) + if err = createCloudWrapper(ctx, configID, section, client, processor); err != nil { + return cli.Exit(color.RedString(fmt.Sprintf("Error exporting cloudwraper: %s", err)), 1) + } + return nil +} + +func createCloudWrapper(ctx context.Context, configID int64, section string, client cloudwrapper.CloudWrapper, templateProcessor templates.TemplateProcessor) error { + term := terminal.Get(ctx) + term.Spinner().Start("Fetching configuration " + strconv.Itoa(int(configID))) + configuration, err := client.GetConfiguration(ctx, cloudwrapper.GetConfigurationRequest{ + ConfigID: configID, + }) + if err != nil { + term.Spinner().Fail() + return fmt.Errorf("%w: %s", ErrFetchingConfiguration, err) + } + if configuration.MultiCDNSettings != nil { + term.Spinner().Fail() + return fmt.Errorf("%s: %w", ErrExportingCloudWrapper, ErrContainMultiCDNSettings) + } + tfCloudWrapperData := populateCloudWrapperData(configID, section, configuration) + + term.Spinner().Start("Saving TF configurations ") + if err = templateProcessor.ProcessTemplates(tfCloudWrapperData); err != nil { + term.Spinner().Fail() + return fmt.Errorf("%w: %s", ErrSavingFiles, err) + } + + term.Spinner().OK() + term.Printf("Terraform configuration for CloudWrapper configuration '%d' was saved successfully\n", tfCloudWrapperData.Configuration.ID) + + return nil +} + +func populateCloudWrapperData(configID int64, section string, configuration *cloudwrapper.Configuration) TFCloudWrapperData { + tfCloudWrapperData := TFCloudWrapperData{ + Configuration: TFCWConfiguration{ + ID: configID, + ContractID: configuration.ContractID, + PropertyIDs: configuration.PropertyIDs, + Name: configuration.ConfigName, + Comments: configuration.Comments, + NotificationEmails: configuration.NotificationEmails, + ConfigurationResourceName: strings.ReplaceAll(configuration.ConfigName, "-", "_"), + RetainIdleObjects: configuration.RetainIdleObjects, + CapacityAlertsThreshold: configuration.CapacityAlertsThreshold, + }, + Section: section, + } + tfCloudWrapperData.Configuration.Status = string(configuration.Status) + for _, configLocation := range configuration.Locations { + tfCloudWrapperData.Configuration.Locations = append(tfCloudWrapperData.Configuration.Locations, Location{ + TrafficTypeID: configLocation.TrafficTypeID, + Comments: configLocation.Comments, + Capacity: Capacity{ + Unit: string(configLocation.Capacity.Unit), + Value: configLocation.Capacity.Value, + }, + }) + } + if tfCloudWrapperData.Configuration.Status == string(cloudwrapper.StatusActive) { + tfCloudWrapperData.Configuration.IsActive = true + } + return tfCloudWrapperData +} diff --git a/pkg/providers/cloudwrapper/create_configuration_test.go b/pkg/providers/cloudwrapper/create_configuration_test.go new file mode 100644 index 0000000..c1bef4c --- /dev/null +++ b/pkg/providers/cloudwrapper/create_configuration_test.go @@ -0,0 +1,336 @@ +package cloudwrapper + +import ( + "context" + "errors" + "fmt" + "io/ioutil" + "os" + "testing" + + "github.com/akamai/AkamaiOPEN-edgegrid-golang/v7/pkg/cloudwrapper" + "github.com/akamai/cli-terraform/pkg/templates" + "github.com/akamai/cli-terraform/pkg/tools" + "github.com/akamai/cli/pkg/terminal" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/require" +) + +var ( + section = "test_section" + configID = 12345 + getConfigurationReq = cloudwrapper.GetConfigurationRequest{ConfigID: int64(configID)} + getConfigurationActiveResponse = generateCloudWrapperResponseMock(cloudwrapper.StatusActive, false) + getConfigurationNoActiveResponse = generateCloudWrapperResponseMock(cloudwrapper.StatusFailed, false) + getConfigurationResponseWithMultiCDN = generateCloudWrapperResponseMock(cloudwrapper.StatusActive, true) + processor = func(testdir string) templates.FSTemplateProcessor { + return templates.FSTemplateProcessor{ + TemplatesFS: templateFiles, + TemplateTargets: map[string]string{ + "cloudwrapper.tmpl": fmt.Sprintf("./testdata/res/%s/cloudwrapper.tf", testdir), + "variables.tmpl": fmt.Sprintf("./testdata/res/%s/variables.tf", testdir), + "imports.tmpl": fmt.Sprintf("./testdata/res/%s/import.sh", testdir), + }, + } + } +) + +func TestCreateCloudWrapper(t *testing.T) { + tests := map[string]struct { + init func(*cloudwrapper.Mock, *templates.MockProcessor, string) + dir string + withError error + }{ + "configuration all fields": { + init: func(c *cloudwrapper.Mock, p *templates.MockProcessor, dir string) { + mockGetConfiguration(c, getConfigurationReq, &getConfigurationActiveResponse, nil) + mockProcessTemplates(p, (&tfCloudWrapperDataBuilder{}).withDefaults().withStatus(cloudwrapper.StatusActive).build(), nil) + }, + dir: "all_fields_config", + }, + "configuration not active status": { + init: func(c *cloudwrapper.Mock, p *templates.MockProcessor, dir string) { + mockGetConfiguration(c, getConfigurationReq, &getConfigurationNoActiveResponse, nil) + mockProcessTemplates(p, (&tfCloudWrapperDataBuilder{}).withDefaults().withStatus(cloudwrapper.StatusFailed).build(), nil) + }, + dir: "not_active_configuration", + }, + "error problem with fetching configuration": { + init: func(c *cloudwrapper.Mock, p *templates.MockProcessor, dir string) { + mockGetConfiguration(c, getConfigurationReq, nil, ErrFetchingConfiguration) + }, + dir: "all_fields_config", + withError: ErrFetchingConfiguration, + }, + "error configuration contains multi cdn": { + init: func(c *cloudwrapper.Mock, p *templates.MockProcessor, dir string) { + mockGetConfiguration(c, getConfigurationReq, &getConfigurationResponseWithMultiCDN, nil) + }, + dir: "all_fields_config", + withError: ErrContainMultiCDNSettings, + }, + } + for name, test := range tests { + t.Run(name, func(t *testing.T) { + require.NoError(t, os.MkdirAll(fmt.Sprintf("./testdata/res/%s", test.dir), 0755)) + mock := new(cloudwrapper.Mock) + templateProcessor := new(templates.MockProcessor) + test.init(mock, templateProcessor, test.dir) + ctx := terminal.Context(context.Background(), terminal.New(terminal.DiscardWriter(), nil, terminal.DiscardWriter())) + err := createCloudWrapper(ctx, int64(configID), section, mock, templateProcessor) + if test.withError != nil { + assert.True(t, errors.Is(err, test.withError), "expected: %s; got: %s", test.withError, err) + return + } + require.NoError(t, err) + mock.AssertExpectations(t) + templateProcessor.AssertExpectations(t) + }) + } +} + +func TestProcessCloudWrapperTemplates(t *testing.T) { + tests := map[string]struct { + givenData TFCloudWrapperData + dir string + filesToCheck []string + }{ + "basic configuration with required fields": { + givenData: TFCloudWrapperData{ + Configuration: TFCWConfiguration{ + ID: int64(12345), + Comments: "test", + PropertyIDs: []string{"123", "456"}, + ContractID: "1234", + ConfigurationResourceName: "test_configuration", + Name: "test_configuration", + Locations: []Location{ + { + Comments: "TestComments", + TrafficTypeID: 1, + Capacity: Capacity{ + Unit: "GB", + Value: 1, + }, + }, + { + Comments: "TestComments", + TrafficTypeID: 2, + Capacity: Capacity{ + Unit: "TB", + Value: 2, + }, + }, + }, + }, + Section: section, + }, + dir: "basic_req_fields", + filesToCheck: []string{"cloudwrapper.tf", "import.sh", "variables.tf"}, + }, + "configuration with all fields": { + givenData: TFCloudWrapperData{ + Configuration: TFCWConfiguration{ + ID: int64(12345), + Comments: "test", + PropertyIDs: []string{"123", "456"}, + ContractID: "1234", + ConfigurationResourceName: "test_configuration", + Name: "test_configuration", + NotificationEmails: []string{"testuser@akamai.com"}, + RetainIdleObjects: false, + CapacityAlertsThreshold: tools.IntPtr(75), + Status: string(cloudwrapper.StatusActive), + IsActive: true, + Locations: []Location{ + { + Comments: "TestComments", + TrafficTypeID: 1, + Capacity: Capacity{ + Unit: "GB", + Value: 1, + }, + }, + { + Comments: "TestComments", + TrafficTypeID: 2, + Capacity: Capacity{ + Unit: "TB", + Value: 2, + }, + }, + }, + }, + Section: section, + }, + dir: "all_fields_config", + filesToCheck: []string{"cloudwrapper.tf", "import.sh", "variables.tf"}, + }, + "not active configuration": { + givenData: TFCloudWrapperData{ + Configuration: TFCWConfiguration{ + ID: int64(12345), + Comments: "test", + PropertyIDs: []string{"123", "456"}, + ContractID: "1234", + ConfigurationResourceName: "test_configuration", + Name: "test_configuration", + NotificationEmails: []string{"testuser@akamai.com"}, + RetainIdleObjects: false, + CapacityAlertsThreshold: tools.IntPtr(75), + Status: string(cloudwrapper.StatusFailed), + IsActive: false, + Locations: []Location{ + { + Comments: "TestComments", + TrafficTypeID: 1, + Capacity: Capacity{ + Unit: "GB", + Value: 1, + }, + }, + { + Comments: "TestComments", + TrafficTypeID: 2, + Capacity: Capacity{ + Unit: "TB", + Value: 2, + }, + }, + }, + }, + Section: section, + }, + dir: "not_active_configuration", + filesToCheck: []string{"cloudwrapper.tf", "import.sh", "variables.tf"}, + }, + } + for name, test := range tests { + t.Run(name, func(t *testing.T) { + require.NoError(t, os.MkdirAll(fmt.Sprintf("./testdata/res/%s", test.dir), 0755)) + require.NoError(t, processor(test.dir).ProcessTemplates(test.givenData)) + for _, f := range test.filesToCheck { + expected, err := ioutil.ReadFile(fmt.Sprintf("./testdata/%s/%s", test.dir, f)) + require.NoError(t, err) + result, err := ioutil.ReadFile(fmt.Sprintf("./testdata/res/%s/%s", test.dir, f)) + require.NoError(t, err) + assert.Equal(t, string(expected), string(result)) + } + }) + } +} + +func mockGetConfiguration(c *cloudwrapper.Mock, getConfigurationRequest cloudwrapper.GetConfigurationRequest, getConfigurationResponse *cloudwrapper.Configuration, err error) { + c.On("GetConfiguration", mock.Anything, getConfigurationRequest). + Return(getConfigurationResponse, err).Once() +} + +func mockProcessTemplates(p *templates.MockProcessor, tfCloudWrapperData TFCloudWrapperData, err error) { + p.On("ProcessTemplates", tfCloudWrapperData).Return(err).Once() +} + +type tfCloudWrapperDataBuilder struct { + tfCloudWrapperData TFCloudWrapperData +} + +func (t *tfCloudWrapperDataBuilder) withDefaults() *tfCloudWrapperDataBuilder { + t.tfCloudWrapperData = TFCloudWrapperData{ + Configuration: TFCWConfiguration{ + ID: int64(12345), + Comments: "test", + PropertyIDs: []string{"123", "456"}, + ContractID: "1234", + ConfigurationResourceName: "testName", + Name: "testName", + NotificationEmails: []string{"testuser@akamai.com"}, + RetainIdleObjects: false, + CapacityAlertsThreshold: tools.IntPtr(75), + Locations: []Location{ + { + Comments: "TestComments", + TrafficTypeID: 1, + Capacity: Capacity{ + Unit: "GB", + Value: 1, + }, + }, + { + Comments: "TestComments", + TrafficTypeID: 2, + Capacity: Capacity{ + Unit: "TB", + Value: 2, + }, + }, + }, + }, + Section: "test_section", + } + return t +} + +func (t *tfCloudWrapperDataBuilder) withStatus(status cloudwrapper.StatusType) *tfCloudWrapperDataBuilder { + t.tfCloudWrapperData.Configuration.Status = string(status) + if status == cloudwrapper.StatusActive { + t.tfCloudWrapperData.Configuration.IsActive = true + } else { + t.tfCloudWrapperData.Configuration.IsActive = false + } + return t +} + +func (t *tfCloudWrapperDataBuilder) build() TFCloudWrapperData { + return t.tfCloudWrapperData +} + +func generateCloudWrapperResponseMock(status cloudwrapper.StatusType, withMultiCDNSettings bool) cloudwrapper.Configuration { + configurationResponse := cloudwrapper.Configuration{ + Status: status, + Comments: "test", + ContractID: "1234", + ConfigID: 12345, + CapacityAlertsThreshold: tools.IntPtr(75), + ConfigName: "testName", + LastActivatedBy: tools.StringPtr("user"), + LastActivatedDate: tools.StringPtr("2018-03-07T23:40:45Z"), + LastUpdatedDate: "2018-03-07T23:40:45Z", + LastUpdatedBy: "testUser", + NotificationEmails: []string{"testuser@akamai.com"}, + PropertyIDs: []string{ + "123", + "456", + }, + RetainIdleObjects: false, + Locations: []cloudwrapper.ConfigLocationResp{ + { + Comments: "TestComments", + TrafficTypeID: 1, + Capacity: cloudwrapper.Capacity{ + Unit: "GB", + Value: 1, + }, + }, + { + Comments: "TestComments", + TrafficTypeID: 2, + Capacity: cloudwrapper.Capacity{ + Unit: "TB", + Value: 2, + }, + }, + }, + } + if withMultiCDNSettings { + configurationResponse.MultiCDNSettings = + &cloudwrapper.MultiCDNSettings{ + CDNs: []cloudwrapper.CDN{ + { + CDNCode: "testCode", + }, + }, + } + } + + return configurationResponse +} diff --git a/pkg/providers/cloudwrapper/templates/cloudwrapper.tmpl b/pkg/providers/cloudwrapper/templates/cloudwrapper.tmpl new file mode 100644 index 0000000..1b76e90 --- /dev/null +++ b/pkg/providers/cloudwrapper/templates/cloudwrapper.tmpl @@ -0,0 +1,50 @@ +{{- /*gotype: github.com/akamai/cli-terraform/pkg/providers/cloudwrapper.TFCloudWrapperData*/ -}} +terraform { + required_providers { + akamai = { + source = "akamai/akamai" + version = ">= 5.2.0" + } + } + required_version = ">= 0.13" +} + +provider "akamai" { + edgerc = var.edgerc_path + config_section = var.config_section +} + +resource "akamai_cloudwrapper_configuration" "{{.Configuration.ConfigurationResourceName}}" { + config_name = "{{.Configuration.Name}}" + contract_id = "{{.Configuration.ContractID}}" + property_ids = [{{range $index, $element := .Configuration.PropertyIDs}}{{if $index}}, {{end}}"{{$element}}"{{end}}] + {{- if .Configuration.NotificationEmails }} + notification_emails = [{{range $index, $element := .Configuration.NotificationEmails}}{{if $index}}, {{end}}"{{$element}}"{{end}}] + {{- end}} + comments = "{{.Configuration.Comments}}" + retain_idle_objects = {{.Configuration.RetainIdleObjects}} + {{- if .Configuration.CapacityAlertsThreshold }} + capacity_alerts_threshold = {{.Configuration.CapacityAlertsThreshold}} + {{- end}} + {{- range $index, $element := .Configuration.Locations}} + location { + traffic_type_id = {{$element.TrafficTypeID}} + comments = "{{$element.Comments}}" + capacity { + value = {{$element.Capacity.Value}} + unit = "{{$element.Capacity.Unit}}" + } + } + {{- end}} +} +{{ if .Configuration.IsActive }} +resource "akamai_cloudwrapper_activation" "{{.Configuration.ConfigurationResourceName}}_activation" { + config_id = akamai_cloudwrapper_configuration.{{.Configuration.ConfigurationResourceName}}.id + revision = akamai_cloudwrapper_configuration.{{.Configuration.ConfigurationResourceName}}.revision +} +{{- else }} +#resource "akamai_cloudwrapper_activation" "{{.Configuration.ConfigurationResourceName}}_activation" { +# config_id = akamai_cloudwrapper_configuration.{{.Configuration.ConfigurationResourceName}}.id +# revision = akamai_cloudwrapper_configuration.{{.Configuration.ConfigurationResourceName}}.revision +#} +{{- end }} \ No newline at end of file diff --git a/pkg/providers/cloudwrapper/templates/imports.tmpl b/pkg/providers/cloudwrapper/templates/imports.tmpl new file mode 100644 index 0000000..8070fe1 --- /dev/null +++ b/pkg/providers/cloudwrapper/templates/imports.tmpl @@ -0,0 +1,6 @@ +{{- /*gotype: github.com/akamai/cli-terraform/pkg/providers/cloudwrapper.TFCloudWrapperData*/ -}} +terraform init +terraform import akamai_cloudwrapper_configuration.{{.Configuration.ConfigurationResourceName}} {{.Configuration.ID}} +{{ if .Configuration.IsActive -}} +terraform import akamai_cloudwrapper_activation.{{.Configuration.ConfigurationResourceName}}_activation {{.Configuration.ID}} +{{ end }} \ No newline at end of file diff --git a/pkg/providers/cloudwrapper/templates/variables.tmpl b/pkg/providers/cloudwrapper/templates/variables.tmpl new file mode 100644 index 0000000..61945c9 --- /dev/null +++ b/pkg/providers/cloudwrapper/templates/variables.tmpl @@ -0,0 +1,10 @@ +{{- /*gotype: github.com/akamai/cli-terraform/pkg/providers/cloudwrapper.TFCloudWrapperData*/ -}} +variable "edgerc_path" { + type = string + default = "~/.edgerc" +} + +variable "config_section" { + type = string + default = "{{.Section}}" +} diff --git a/pkg/providers/cloudwrapper/testdata/all_fields_config/cloudwrapper.tf b/pkg/providers/cloudwrapper/testdata/all_fields_config/cloudwrapper.tf new file mode 100644 index 0000000..6643fa1 --- /dev/null +++ b/pkg/providers/cloudwrapper/testdata/all_fields_config/cloudwrapper.tf @@ -0,0 +1,45 @@ +terraform { + required_providers { + akamai = { + source = "akamai/akamai" + version = ">= 5.2.0" + } + } + required_version = ">= 0.13" +} + +provider "akamai" { + edgerc = var.edgerc_path + config_section = var.config_section +} + +resource "akamai_cloudwrapper_configuration" "test_configuration" { + config_name = "test_configuration" + contract_id = "1234" + property_ids = ["123", "456"] + notification_emails = ["testuser@akamai.com"] + comments = "test" + retain_idle_objects = false + capacity_alerts_threshold = 75 + location { + traffic_type_id = 1 + comments = "TestComments" + capacity { + value = 1 + unit = "GB" + } + } + location { + traffic_type_id = 2 + comments = "TestComments" + capacity { + value = 2 + unit = "TB" + } + } +} + +resource "akamai_cloudwrapper_activation" "test_configuration_activation" { + config_id = akamai_cloudwrapper_configuration.test_configuration.id + revision = akamai_cloudwrapper_configuration.test_configuration.revision +} \ No newline at end of file diff --git a/pkg/providers/cloudwrapper/testdata/all_fields_config/import.sh b/pkg/providers/cloudwrapper/testdata/all_fields_config/import.sh new file mode 100644 index 0000000..f897c43 --- /dev/null +++ b/pkg/providers/cloudwrapper/testdata/all_fields_config/import.sh @@ -0,0 +1,3 @@ +terraform init +terraform import akamai_cloudwrapper_configuration.test_configuration 12345 +terraform import akamai_cloudwrapper_activation.test_configuration_activation 12345 diff --git a/pkg/providers/cloudwrapper/testdata/all_fields_config/variables.tf b/pkg/providers/cloudwrapper/testdata/all_fields_config/variables.tf new file mode 100644 index 0000000..b769e45 --- /dev/null +++ b/pkg/providers/cloudwrapper/testdata/all_fields_config/variables.tf @@ -0,0 +1,9 @@ +variable "edgerc_path" { + type = string + default = "~/.edgerc" +} + +variable "config_section" { + type = string + default = "test_section" +} diff --git a/pkg/providers/cloudwrapper/testdata/basic_req_fields/cloudwrapper.tf b/pkg/providers/cloudwrapper/testdata/basic_req_fields/cloudwrapper.tf new file mode 100644 index 0000000..33a87a0 --- /dev/null +++ b/pkg/providers/cloudwrapper/testdata/basic_req_fields/cloudwrapper.tf @@ -0,0 +1,43 @@ +terraform { + required_providers { + akamai = { + source = "akamai/akamai" + version = ">= 5.2.0" + } + } + required_version = ">= 0.13" +} + +provider "akamai" { + edgerc = var.edgerc_path + config_section = var.config_section +} + +resource "akamai_cloudwrapper_configuration" "test_configuration" { + config_name = "test_configuration" + contract_id = "1234" + property_ids = ["123", "456"] + comments = "test" + retain_idle_objects = false + location { + traffic_type_id = 1 + comments = "TestComments" + capacity { + value = 1 + unit = "GB" + } + } + location { + traffic_type_id = 2 + comments = "TestComments" + capacity { + value = 2 + unit = "TB" + } + } +} + +#resource "akamai_cloudwrapper_activation" "test_configuration_activation" { +# config_id = akamai_cloudwrapper_configuration.test_configuration.id +# revision = akamai_cloudwrapper_configuration.test_configuration.revision +#} \ No newline at end of file diff --git a/pkg/providers/cloudwrapper/testdata/basic_req_fields/import.sh b/pkg/providers/cloudwrapper/testdata/basic_req_fields/import.sh new file mode 100644 index 0000000..781e654 --- /dev/null +++ b/pkg/providers/cloudwrapper/testdata/basic_req_fields/import.sh @@ -0,0 +1,2 @@ +terraform init +terraform import akamai_cloudwrapper_configuration.test_configuration 12345 diff --git a/pkg/providers/cloudwrapper/testdata/basic_req_fields/variables.tf b/pkg/providers/cloudwrapper/testdata/basic_req_fields/variables.tf new file mode 100644 index 0000000..b769e45 --- /dev/null +++ b/pkg/providers/cloudwrapper/testdata/basic_req_fields/variables.tf @@ -0,0 +1,9 @@ +variable "edgerc_path" { + type = string + default = "~/.edgerc" +} + +variable "config_section" { + type = string + default = "test_section" +} diff --git a/pkg/providers/cloudwrapper/testdata/not_active_configuration/cloudwrapper.tf b/pkg/providers/cloudwrapper/testdata/not_active_configuration/cloudwrapper.tf new file mode 100644 index 0000000..b82eeae --- /dev/null +++ b/pkg/providers/cloudwrapper/testdata/not_active_configuration/cloudwrapper.tf @@ -0,0 +1,45 @@ +terraform { + required_providers { + akamai = { + source = "akamai/akamai" + version = ">= 5.2.0" + } + } + required_version = ">= 0.13" +} + +provider "akamai" { + edgerc = var.edgerc_path + config_section = var.config_section +} + +resource "akamai_cloudwrapper_configuration" "test_configuration" { + config_name = "test_configuration" + contract_id = "1234" + property_ids = ["123", "456"] + notification_emails = ["testuser@akamai.com"] + comments = "test" + retain_idle_objects = false + capacity_alerts_threshold = 75 + location { + traffic_type_id = 1 + comments = "TestComments" + capacity { + value = 1 + unit = "GB" + } + } + location { + traffic_type_id = 2 + comments = "TestComments" + capacity { + value = 2 + unit = "TB" + } + } +} + +#resource "akamai_cloudwrapper_activation" "test_configuration_activation" { +# config_id = akamai_cloudwrapper_configuration.test_configuration.id +# revision = akamai_cloudwrapper_configuration.test_configuration.revision +#} \ No newline at end of file diff --git a/pkg/providers/cloudwrapper/testdata/not_active_configuration/import.sh b/pkg/providers/cloudwrapper/testdata/not_active_configuration/import.sh new file mode 100644 index 0000000..781e654 --- /dev/null +++ b/pkg/providers/cloudwrapper/testdata/not_active_configuration/import.sh @@ -0,0 +1,2 @@ +terraform init +terraform import akamai_cloudwrapper_configuration.test_configuration 12345 diff --git a/pkg/providers/cloudwrapper/testdata/not_active_configuration/variables.tf b/pkg/providers/cloudwrapper/testdata/not_active_configuration/variables.tf new file mode 100644 index 0000000..b769e45 --- /dev/null +++ b/pkg/providers/cloudwrapper/testdata/not_active_configuration/variables.tf @@ -0,0 +1,9 @@ +variable "edgerc_path" { + type = string + default = "~/.edgerc" +} + +variable "config_section" { + type = string + default = "test_section" +} From 927780c5b7db83e04903b619f8f67a7d822d0148 Mon Sep 17 00:00:00 2001 From: Amith Halavarthy Basavanagouda Date: Mon, 7 Aug 2023 11:12:34 +0000 Subject: [PATCH 6/8] BOTMAN-11848 Added custom client sequence to export-appsec Merge in DEVEXP/cli-terraform from feature/BOTMAN-11848 to feature/sp-security-august-2023 --- CHANGELOG.md | 3 ++ pkg/providers/appsec/create_appsec.go | 30 +++++++++++++++++++ pkg/providers/appsec/create_appsec_test.go | 2 ++ pkg/providers/appsec/templates/imports.tmpl | 3 ++ .../modules-security-custom-client.tmpl | 8 +++++ pkg/providers/appsec/testdata/ase-botman.json | 4 +++ .../testdata/ase-botman/appsec-import.sh | 1 + .../modules/security/custom-client.tf | 7 +++++ 8 files changed, 58 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c6ed6a..4d7d688 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ * CloudWrapper * Added support for `export-cloudwrapper` command which allows export of `akamai_cloudwrapper_configuration` and `akamai_cloudwrapper_activation` resources +* APPSEC + * Add import support for custom client sequence + ### Bug fixes * Image and Video Manager diff --git a/pkg/providers/appsec/create_appsec.go b/pkg/providers/appsec/create_appsec.go index 6cdfb3e..22ee661 100644 --- a/pkg/providers/appsec/create_appsec.go +++ b/pkg/providers/appsec/create_appsec.go @@ -137,6 +137,7 @@ func CmdCreateAppsec(c *cli.Context) error { "exportJSONWithoutKeys": exportJSONWithoutKeys, "getCustomBotCategoryResourceNamesByIDs": getCustomBotCategoryResourceNamesByIDs, "getCustomBotCategoryNameByID": getCustomBotCategoryNameByID, + "getCustomClientResourceNamesByIDs": getCustomClientResourceNamesByIDs, } // The template processor @@ -561,3 +562,32 @@ func getCustomBotCategoryResourceNamesByIDs(customBotCategories []map[string]int } return strings.Join(categoryResourceNames, ","), nil } + +// getCustomClientResourceNamesByIDs returns comma separated custom-client resource names in the same order as the provided customClientIDs +func getCustomClientResourceNamesByIDs(customClients []map[string]interface{}, customClientIDs []string) (string, error) { + customClientMap := make(map[string]string) + for _, customClient := range customClients { + customClientName, ok := customClient["customClientName"].(string) + if !ok { + return "", fmt.Errorf("cannot convert custom client name %s to string", customClient["customClientName"]) + } + name, err := tools.EscapeName(customClientName) + if err != nil { + return "", err + } + customClientID, ok := customClient["customClientId"].(string) + if !ok { + return "", errors.New("cannot convert customClientId to string") + } + customClientMap[customClientID] = name + } + customClientResourceNames := make([]string, len(customClientIDs)) + for i, customClientID := range customClientIDs { + customClientName, ok := customClientMap[customClientID] + if !ok { + return "", fmt.Errorf("cannot find custom client name for id %s", customClientID) + } + customClientResourceNames[i] = fmt.Sprintf("akamai_botman_custom_client.%s_%s.custom_client_id", customClientName, customClientID) + } + return strings.Join(customClientResourceNames, ",\n"), nil +} diff --git a/pkg/providers/appsec/create_appsec_test.go b/pkg/providers/appsec/create_appsec_test.go index 940bca7..3b36965 100644 --- a/pkg/providers/appsec/create_appsec_test.go +++ b/pkg/providers/appsec/create_appsec_test.go @@ -300,6 +300,7 @@ func TestProcessPolicyTemplates(t *testing.T) { "exportJSONWithoutKeys": exportJSONWithoutKeys, "getCustomBotCategoryNameByID": getCustomBotCategoryNameByID, "getCustomBotCategoryResourceNamesByIDs": getCustomBotCategoryResourceNamesByIDs, + "getCustomClientResourceNamesByIDs": getCustomClientResourceNamesByIDs, } // Template to path mappings @@ -421,6 +422,7 @@ func TestProcessPolicyTemplatesWithBotman(t *testing.T) { "exportJSONWithoutKeys": exportJSONWithoutKeys, "getCustomBotCategoryNameByID": getCustomBotCategoryNameByID, "getCustomBotCategoryResourceNamesByIDs": getCustomBotCategoryResourceNamesByIDs, + "getCustomClientResourceNamesByIDs": getCustomClientResourceNamesByIDs, } // Template to path mappings diff --git a/pkg/providers/appsec/templates/imports.tmpl b/pkg/providers/appsec/templates/imports.tmpl index 35b1d6f..e964432 100644 --- a/pkg/providers/appsec/templates/imports.tmpl +++ b/pkg/providers/appsec/templates/imports.tmpl @@ -184,6 +184,9 @@ terraform import module.security.akamai_botman_custom_defined_bot.{{escapeName ( terraform import module.security.akamai_botman_custom_client.{{escapeName (index . "customClientName")}}_{{index . "customClientId"}} {{ $configID }}:{{index . "customClientId"}} {{ end -}} {{ end -}} +{{ if .CustomClientSequence -}} +terraform import module.security.akamai_botman_custom_client_sequence.sequence {{ $configID }} +{{ end -}} {{ if .ResponseActions -}} {{ if .ResponseActions.ServeAlternateActions -}} {{ range .ResponseActions.ServeAlternateActions -}} diff --git a/pkg/providers/appsec/templates/modules-security-custom-client.tmpl b/pkg/providers/appsec/templates/modules-security-custom-client.tmpl index 9cfae9a..9f0f13a 100644 --- a/pkg/providers/appsec/templates/modules-security-custom-client.tmpl +++ b/pkg/providers/appsec/templates/modules-security-custom-client.tmpl @@ -9,3 +9,11 @@ resource "akamai_botman_custom_client" "{{ escapeName (index . "customClientName {{ end -}} {{ end -}} +{{ if .CustomClientSequence -}} +resource "akamai_botman_custom_client_sequence" "sequence" { + config_id = akamai_appsec_configuration.config.config_id + custom_client_ids = [ + {{getCustomClientResourceNamesByIDs .CustomClients .CustomClientSequence}} + ] +} +{{ end -}} diff --git a/pkg/providers/appsec/testdata/ase-botman.json b/pkg/providers/appsec/testdata/ase-botman.json index 671af69..0ccc3ff 100644 --- a/pkg/providers/appsec/testdata/ase-botman.json +++ b/pkg/providers/appsec/testdata/ase-botman.json @@ -3869,6 +3869,10 @@ } } ], + "customClientSequence": [ + "a7fe489d-0354-43bd-b81c-8cabbe850cdd", + "60374346-2d1d-444d-91c1-90373e3f804a" + ], "customDefinedBots": [ { "botId": "50789280-ba99-4f8f-b4c6-ad9c1c69569a", diff --git a/pkg/providers/appsec/testdata/ase-botman/appsec-import.sh b/pkg/providers/appsec/testdata/ase-botman/appsec-import.sh index f283485..f04ad8e 100644 --- a/pkg/providers/appsec/testdata/ase-botman/appsec-import.sh +++ b/pkg/providers/appsec/testdata/ase-botman/appsec-import.sh @@ -228,6 +228,7 @@ terraform import module.security.akamai_botman_custom_defined_bot.bot_a_50789280 terraform import module.security.akamai_botman_custom_defined_bot.bot_b_da1de35e-deda-4273-933d-3131291fa3d4 79947:da1de35e-deda-4273-933d-3131291fa3d4 terraform import module.security.akamai_botman_custom_client.custom_client_a_a7fe489d-0354-43bd-b81c-8cabbe850cdd 79947:a7fe489d-0354-43bd-b81c-8cabbe850cdd terraform import module.security.akamai_botman_custom_client.custom_client_b_60374346-2d1d-444d-91c1-90373e3f804a 79947:60374346-2d1d-444d-91c1-90373e3f804a +terraform import module.security.akamai_botman_custom_client_sequence.sequence 79947 terraform import module.security.akamai_botman_serve_alternate_action.serve_alternate_action_a_action_A 79947:action_A terraform import module.security.akamai_botman_serve_alternate_action.serve_alternate_action_b_action_B 79947:action_B terraform import module.security.akamai_botman_challenge_action.challenge_action_a_action_A 79947:action_A diff --git a/pkg/providers/appsec/testdata/ase-botman/modules/security/custom-client.tf b/pkg/providers/appsec/testdata/ase-botman/modules/security/custom-client.tf index b576e5a..3b542e6 100644 --- a/pkg/providers/appsec/testdata/ase-botman/modules/security/custom-client.tf +++ b/pkg/providers/appsec/testdata/ase-botman/modules/security/custom-client.tf @@ -32,3 +32,10 @@ resource "akamai_botman_custom_client" "custom_client_b_60374346-2d1d-444d-91c1- ) } +resource "akamai_botman_custom_client_sequence" "sequence" { + config_id = akamai_appsec_configuration.config.config_id + custom_client_ids = [ + akamai_botman_custom_client.custom_client_a_a7fe489d-0354-43bd-b81c-8cabbe850cdd.custom_client_id, + akamai_botman_custom_client.custom_client_b_60374346-2d1d-444d-91c1-90373e3f804a.custom_client_id + ] +} From c08bdee65d3170b781e0e6293fa7ae570d278701 Mon Sep 17 00:00:00 2001 From: Dawid Dzhafarov Date: Fri, 25 Aug 2023 07:56:10 +0000 Subject: [PATCH 7/8] DXE-2954 Prepare release candidate for 1.9.0 release --- CHANGELOG.md | 4 ++-- cli.json | 2 +- cli/cli.go | 2 +- go.mod | 2 +- go.sum | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d7d688..055efcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,11 +4,11 @@ ### Features/Enhancements -* CloudWrapper +* [IMPORTANT] CloudWrapper * Added support for `export-cloudwrapper` command which allows export of `akamai_cloudwrapper_configuration` and `akamai_cloudwrapper_activation` resources * APPSEC - * Add import support for custom client sequence + * Added import support for custom client sequence ### Bug fixes diff --git a/cli.json b/cli.json index 69027b9..a1d5d0e 100644 --- a/cli.json +++ b/cli.json @@ -5,7 +5,7 @@ "commands": [ { "name": "terraform", - "version": "1.8.0", + "version": "1.9.0", "description": "Administer and Manage Akamai Terraform configurations", "bin": "https://github.com/akamai/cli-terraform/releases/download/v{{.Version}}/akamai-{{.Name}}-{{.Version}}-{{.OS}}{{.Arch}}{{.BinSuffix}}", "auto-complete": true, diff --git a/cli/cli.go b/cli/cli.go index c0e107c..acbbe74 100644 --- a/cli/cli.go +++ b/cli/cli.go @@ -33,7 +33,7 @@ import ( var ( // Version holds current version of cli-terraform - Version = "1.8.0" + Version = "1.9.0" ) // Run initializes the cli and runs it diff --git a/go.mod b/go.mod index 6e01c25..008ba57 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/akamai/cli-terraform go 1.18 require ( - github.com/akamai/AkamaiOPEN-edgegrid-golang/v7 v7.1.0 + github.com/akamai/AkamaiOPEN-edgegrid-golang/v7 v7.2.0 github.com/akamai/cli v1.5.5 github.com/fatih/color v1.13.0 github.com/hashicorp/hcl/v2 v2.11.1 diff --git a/go.sum b/go.sum index 423152d..54e1121 100644 --- a/go.sum +++ b/go.sum @@ -9,8 +9,8 @@ github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDO github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8= github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= -github.com/akamai/AkamaiOPEN-edgegrid-golang/v7 v7.1.0 h1:QBcW0BOSLBN2DGgs6je3L/E/S3nCKhi4Me4oijT44Dw= -github.com/akamai/AkamaiOPEN-edgegrid-golang/v7 v7.1.0/go.mod h1:zZWAMUwE4q5sVPgnjz9jiqtXA01tM3m9HYd6Wk0ev90= +github.com/akamai/AkamaiOPEN-edgegrid-golang/v7 v7.2.0 h1:sGkT91nSXjHU/s+ItP+kTgea1WCfpgAWwx+snxlP/+E= +github.com/akamai/AkamaiOPEN-edgegrid-golang/v7 v7.2.0/go.mod h1:zZWAMUwE4q5sVPgnjz9jiqtXA01tM3m9HYd6Wk0ev90= github.com/akamai/cli v1.5.5 h1:XKubVW8WOVP8qcgJRK2MOj8HeqC4kudvSOM0m8mJsj0= github.com/akamai/cli v1.5.5/go.mod h1:29wClp63PEEkpDLxtqM/JrVmnwOCSaE+itIJjCAIECE= github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI= From f97b77d395c433589877ae5de734d22d9dd74b02 Mon Sep 17 00:00:00 2001 From: Dawid Dzhafarov Date: Fri, 25 Aug 2023 12:23:37 +0000 Subject: [PATCH 8/8] DXE-2954 Bump edgegrid-golang dependency version --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 008ba57..d829d5a 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/akamai/cli-terraform go 1.18 require ( - github.com/akamai/AkamaiOPEN-edgegrid-golang/v7 v7.2.0 + github.com/akamai/AkamaiOPEN-edgegrid-golang/v7 v7.2.1 github.com/akamai/cli v1.5.5 github.com/fatih/color v1.13.0 github.com/hashicorp/hcl/v2 v2.11.1 diff --git a/go.sum b/go.sum index 54e1121..bd13e8d 100644 --- a/go.sum +++ b/go.sum @@ -9,8 +9,8 @@ github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDO github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8= github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= -github.com/akamai/AkamaiOPEN-edgegrid-golang/v7 v7.2.0 h1:sGkT91nSXjHU/s+ItP+kTgea1WCfpgAWwx+snxlP/+E= -github.com/akamai/AkamaiOPEN-edgegrid-golang/v7 v7.2.0/go.mod h1:zZWAMUwE4q5sVPgnjz9jiqtXA01tM3m9HYd6Wk0ev90= +github.com/akamai/AkamaiOPEN-edgegrid-golang/v7 v7.2.1 h1:amPKOiXDgUXQcSMMg0XXvOZkF9sQcffZXZrZT4VJ3z0= +github.com/akamai/AkamaiOPEN-edgegrid-golang/v7 v7.2.1/go.mod h1:zZWAMUwE4q5sVPgnjz9jiqtXA01tM3m9HYd6Wk0ev90= github.com/akamai/cli v1.5.5 h1:XKubVW8WOVP8qcgJRK2MOj8HeqC4kudvSOM0m8mJsj0= github.com/akamai/cli v1.5.5/go.mod h1:29wClp63PEEkpDLxtqM/JrVmnwOCSaE+itIJjCAIECE= github.com/andres-erbsen/clock v0.0.0-20160526145045-9e14626cd129 h1:MzBOUgng9orim59UnfUTLRjMpd09C5uEVQ6RPGeCaVI=