diff --git a/docs/data-sources/field.md b/docs/data-sources/field.md index a6b6ca3..5873f63 100644 --- a/docs/data-sources/field.md +++ b/docs/data-sources/field.md @@ -16,26 +16,26 @@ Represents the EPCC API [Fields Object](https://documentation.elasticpath.com/co ### Required -- **id** (String) The ID for the field you are requesting. +- **id** (String) The unique identifier for this field. ### Read-Only -- **default** (String) -- **description** (String) -- **enabled** (Boolean) -- **field_type** (String) -- **flow_id** (String) -- **name** (String) -- **omit_null** (Boolean) -- **order** (Number) +- **default** (String) A default value if none is supplied and field is not required. +- **description** (String) Any description for this field. +- **enabled** (Boolean) If this field is enabled on the flow this should be true, otherwise false. +- **field_type** (String) Specifies the type of field, such as string, integer, boolean, float, date, relationship. +- **flow_id** (String) The id of the flow that this field applies to. +- **name** (String) The name of the field. +- **omit_null** (Boolean) Hide this field from responses if the value is null. +- **order** (Number) Denotes the order in which this field is returned relative to the rest of the flow fields. - **relationship_to_many** (String) - **relationship_to_one** (String) -- **required** (Boolean) -- **slug** (String) -- **valid_float_enum** (List of Number) +- **required** (Boolean) true if required on input, false if not. Always false if the field_type is a relationship. +- **slug** (String) A unique slug identifier for the field. +- **valid_float_enum** (List of Number) A predefined collection of floats that represent the allowed value for this float field. - **valid_float_range** (List of Map of Number) -- **valid_int_enum** (List of Number) -- **valid_int_range** (List of Map of Number) -- **valid_string_enum** (List of String) -- **valid_string_format** (String) +- **valid_int_enum** (List of Number) A predefined collection of integer that represent the allowed value for this integer field. +- **valid_int_range** (List of Map of Number) A list of integers specified with from= and to= that represent the range of this value +- **valid_string_enum** (List of String) A predefined collection of strings that represent the allowed value for this string field. +- **valid_string_format** (String) Corresponds to the field validation rules for string, one of "email", "slug", or "uuid". diff --git a/docs/data-sources/flow.md b/docs/data-sources/flow.md index a40ce08..fcc7deb 100644 --- a/docs/data-sources/flow.md +++ b/docs/data-sources/flow.md @@ -16,12 +16,12 @@ Represents the EPCC API [Flow Object](https://documentation.elasticpath.com/comm ### Required -- **id** (String) The ID of this resource. +- **id** (String) The unique identifier for this flow. ### Read-Only -- **description** (String) -- **enabled** (Boolean) -- **name** (String) -- **slug** (String) +- **description** (String) Any description for this flow. +- **enabled** (Boolean) true if enabled, false if not. +- **name** (String) The name of the flow. +- **slug** (String) A unique slug identifier for the flow. diff --git a/docs/data-sources/integration.md b/docs/data-sources/integration.md index ca9c003..ca3567c 100644 --- a/docs/data-sources/integration.md +++ b/docs/data-sources/integration.md @@ -20,10 +20,14 @@ Allows to configure webhooks ### Read-Only +- **aws_access_key_id** (String) The required AWS access key ID. Note: The EPCC API only returns the 4 characters of this value +- **aws_secret_access_key** (String, Sensitive) The required AWS secret key ID. Note: The EPCC API only returns the 4 characters of this value - **description** (String) - **enabled** (Boolean) Should the event trigger or not. Default: `false` +- **integration_type** (String) Specifies how the event is delivered, either webhook or aws_sqs - **name** (String) - **observes** (List of String) [observable event type](https://documentation.elasticpath.com/commerce-cloud/docs/api/advanced/events/create-an-event.html) +- **region** (String) The required AWS region. - **secret_key** (String) Value that is passed to webhook as `X-Moltin-Secret-Key` header - **url** (String) Webhook endpoint diff --git a/docs/resources/account.md b/docs/resources/account.md index 0b1e46e..bbea617 100644 --- a/docs/resources/account.md +++ b/docs/resources/account.md @@ -16,15 +16,15 @@ Represents the EPCC API [Account resource](https://documentation.elasticpath.com ### Required -- **legal_name** (String) -- **name** (String) +- **legal_name** (String) The legal name of the account. +- **name** (String) The name of the account. ### Optional -- **parent_id** (String) -- **registration_id** (String) +- **parent_id** (String) Specifies the ID of the parent account. +- **registration_id** (String) The registration ID of the account. ### Read-Only -- **id** (String) The ID of this resource. +- **id** (String) The unique identifier for an Account diff --git a/docs/resources/field.md b/docs/resources/field.md index 9f6c39b..cae1129 100644 --- a/docs/resources/field.md +++ b/docs/resources/field.md @@ -16,29 +16,29 @@ Represents the EPCC API [Fields Object](https://documentation.elasticpath.com/co ### Required -- **description** (String) -- **enabled** (Boolean) -- **field_type** (String) -- **flow_id** (String) -- **name** (String) -- **required** (Boolean) -- **slug** (String) +- **description** (String) Any description for this field. +- **enabled** (Boolean) If this field is enabled on the flow this should be true, otherwise false. +- **field_type** (String) Specifies the type of field, such as string, integer, boolean, float, date, relationship. +- **flow_id** (String) The id of the flow that this field applies to. +- **name** (String) The name of the field. +- **required** (Boolean) true if required on input, false if not. Always false if the field_type is a relationship. +- **slug** (String) A unique slug identifier for the field. ### Optional -- **default** (String) -- **omit_null** (Boolean) -- **order** (Number) +- **default** (String) A default value if none is supplied and field is not required. +- **omit_null** (Boolean) Hide this field from responses if the value is null. +- **order** (Number) Denotes the order in which this field is returned relative to the rest of the flow fields. - **relationship_to_many** (String) - **relationship_to_one** (String) -- **valid_float_enum** (List of Number) +- **valid_float_enum** (List of Number) A predefined collection of floats that represent the allowed value for this float field. - **valid_float_range** (List of Map of Number) -- **valid_int_enum** (List of Number) -- **valid_int_range** (List of Map of Number) -- **valid_string_enum** (List of String) -- **valid_string_format** (String) +- **valid_int_enum** (List of Number) A predefined collection of integer that represent the allowed value for this integer field. +- **valid_int_range** (List of Map of Number) A list of integers specified with from= and to= that represent the range of this value +- **valid_string_enum** (List of String) A predefined collection of strings that represent the allowed value for this string field. +- **valid_string_format** (String) Corresponds to the field validation rules for string, one of "email", "slug", or "uuid". ### Read-Only -- **id** (String) The ID of this resource. +- **id** (String) The unique identifier for this field. diff --git a/docs/resources/flow.md b/docs/resources/flow.md index 9efe480..a86de0a 100644 --- a/docs/resources/flow.md +++ b/docs/resources/flow.md @@ -16,12 +16,12 @@ Represents the EPCC API [Flow Object](https://documentation.elasticpath.com/comm ### Required -- **description** (String) -- **enabled** (Boolean) -- **name** (String) -- **slug** (String) +- **description** (String) Any description for this flow. +- **enabled** (Boolean) true if enabled, false if not. +- **name** (String) The name of the flow. +- **slug** (String) A unique slug identifier for the flow. ### Read-Only -- **id** (String) The ID of this resource. +- **id** (String) The unique identifier for this flow. diff --git a/docs/resources/integration.md b/docs/resources/integration.md index 44cef9f..89eca63 100644 --- a/docs/resources/integration.md +++ b/docs/resources/integration.md @@ -16,14 +16,18 @@ Allows to configure webhooks, and corresponds to EPCC API [Event (Webhooks) Obje ### Required +- **integration_type** (String) Specifies how the event is delivered, either webhook or aws_sqs - **name** (String) - **url** (String) Webhook endpoint ### Optional +- **aws_access_key_id** (String) The required AWS access key ID. Note: The EPCC API only returns the 4 characters of this value +- **aws_secret_access_key** (String, Sensitive) The required AWS secret key ID. Note: The EPCC API only returns the 4 characters of this value - **description** (String) - **enabled** (Boolean) Should the event trigger or not. Default: `false` - **observes** (List of String) [observable event type](https://documentation.elasticpath.com/commerce-cloud/docs/api/advanced/events/create-an-event.html) +- **region** (String) The required AWS region. - **secret_key** (String) Value that is passed to webhook as `X-Moltin-Secret-Key` header ### Read-Only diff --git a/examples/resources/integration_resource/resource.tf b/examples/resources/integration_resource/resource.tf index c288eb8..e713ea2 100644 --- a/examples/resources/integration_resource/resource.tf +++ b/examples/resources/integration_resource/resource.tf @@ -9,9 +9,14 @@ terraform { resource "epcc_integration" "cart_observer" { name = "Cart Observer" - url = "http://localhost" + url = "https://sqs.us-east-2.amazonaws.com/123456789012/MyQueue" observes = [ "cart.updated", "cart.deleted", ] + integration_type = "aws_sqs" + region = "us-east-2" + aws_access_key_id = "foofoofoofoofoo" + aws_secret_access_key = "barbarbarbarbar" + enabled = true } diff --git a/external/sdk/epcc/integration.go b/external/sdk/epcc/integration.go index 234f8fe..3e735d4 100644 --- a/external/sdk/epcc/integration.go +++ b/external/sdk/epcc/integration.go @@ -16,22 +16,21 @@ type IntegrationData struct { } type IntegrationConfiguration struct { - Url string `json:"url"` - SecretKey string `json:"secret_key,omitempty"` + Url string `json:"url"` + SecretKey string `json:"secret_key,omitempty"` + AwsAccessKeyId string `json:"aws_access_key_id,omitempty"` + AwsSecretAccessKey string `json:"aws_secret_access_key,omitempty"` + Region string `json:"region,omitempty"` } -type integrationObjectType string -type integrationType string - const ( - IntegrationType integrationObjectType = "integration" - Webhook integrationType = "webhook" + IntegrationType string = "integration" ) type Integration struct { Id string `json:"id,omitempty"` - Type integrationObjectType `json:"type"` - IntegrationType integrationType `json:"integration_type"` + Type string `json:"type"` + IntegrationType string `json:"integration_type"` Name string `json:"name"` Description string `json:"description,omitempty"` Enabled bool `json:"enabled"` diff --git a/internal/provider/data_source_epcc_integration.go b/internal/provider/data_source_epcc_integration.go index 82f7df0..ef33e7d 100644 --- a/internal/provider/data_source_epcc_integration.go +++ b/internal/provider/data_source_epcc_integration.go @@ -50,6 +50,27 @@ func (ds IntegrationDataSourceProvider) DataSource() *schema.Resource { Description: "[observable event type](https://documentation.elasticpath.com/commerce-cloud/docs/api/advanced/events/create-an-event.html)", Computed: true, }, + "integration_type": { + Type: schema.TypeString, + Description: "Specifies how the event is delivered, either webhook or aws_sqs", + Computed: true, + }, + "aws_access_key_id": { + Type: schema.TypeString, + Description: "The required AWS access key ID. Note: The EPCC API only returns the 4 characters of this value", + Computed: true, + }, + "aws_secret_access_key": { + Type: schema.TypeString, + Description: "The required AWS secret key ID. Note: The EPCC API only returns the 4 characters of this value", + Computed: true, + Sensitive: true, + }, + "region": { + Type: schema.TypeString, + Description: "The required AWS region.", + Computed: true, + }, }, Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, @@ -96,5 +117,25 @@ func (ds IntegrationDataSourceProvider) read(ctx context.Context, data *schema.R return } + if err := data.Set("integration_type", result.Data.IntegrationType); err != nil { + addToDiag(ctx, diag.FromErr(err)) + return + } + + if err := data.Set("aws_access_key_id", result.Data.Configuration.AwsAccessKeyId); err != nil { + addToDiag(ctx, diag.FromErr(err)) + return + } + + if err := data.Set("aws_secret_access_key", result.Data.Configuration.AwsSecretAccessKey); err != nil { + addToDiag(ctx, diag.FromErr(err)) + return + } + + if err := data.Set("region", result.Data.Configuration.Region); err != nil { + addToDiag(ctx, diag.FromErr(err)) + return + } + data.SetId(result.Data.Id) } diff --git a/internal/provider/resource_epcc_customer_currency_test.go b/internal/provider/resource_epcc_customer_test.go similarity index 100% rename from internal/provider/resource_epcc_customer_currency_test.go rename to internal/provider/resource_epcc_customer_test.go diff --git a/internal/provider/resource_epcc_integration.go b/internal/provider/resource_epcc_integration.go index e919415..9439c6b 100644 --- a/internal/provider/resource_epcc_integration.go +++ b/internal/provider/resource_epcc_integration.go @@ -53,6 +53,27 @@ func (r IntegrationResourceProvider) Resource() *schema.Resource { Description: "[observable event type](https://documentation.elasticpath.com/commerce-cloud/docs/api/advanced/events/create-an-event.html)", Optional: true, }, + "integration_type": { + Type: schema.TypeString, + Description: "Specifies how the event is delivered, either webhook or aws_sqs", + Required: true, + }, + "aws_access_key_id": { + Type: schema.TypeString, + Description: "The required AWS access key ID. Note: The EPCC API only returns the 4 characters of this value", + Optional: true, + }, + "aws_secret_access_key": { + Type: schema.TypeString, + Description: "The required AWS secret key ID. Note: The EPCC API only returns the 4 characters of this value", + Optional: true, + Sensitive: true, + }, + "region": { + Type: schema.TypeString, + Description: "The required AWS region.", + Optional: true, + }, }, Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, @@ -66,13 +87,16 @@ func (r IntegrationResourceProvider) create(ctx context.Context, data *schema.Re observes := data.Get("observes").([]interface{}) integrationObject := &epcc.Integration{ Type: epcc.IntegrationType, - IntegrationType: epcc.Webhook, + IntegrationType: data.Get("integration_type").(string), Name: data.Get("name").(string), Description: data.Get("description").(string), Enabled: data.Get("enabled").(bool), Configuration: epcc.IntegrationConfiguration{ - Url: data.Get("url").(string), - SecretKey: data.Get("secret_key").(string), + Url: data.Get("url").(string), + SecretKey: data.Get("secret_key").(string), + AwsAccessKeyId: data.Get("aws_access_key_id").(string), + AwsSecretAccessKey: data.Get("aws_secret_access_key").(string), + Region: data.Get("region").(string), }, Observes: convertArrayToStringSlice(observes), } @@ -84,6 +108,19 @@ func (r IntegrationResourceProvider) create(ctx context.Context, data *schema.Re } data.SetId(result.Data.Id) + + // EPCC API only returns the last 4 characters for these two keys, so we will store in state the correct value from the request + if err := data.Set("aws_access_key_id", integrationObject.Configuration.AwsAccessKeyId); err != nil { + addToDiag(ctx, diag.FromErr(err)) + return + } + + if err := data.Set("aws_secret_access_key", integrationObject.Configuration.AwsSecretAccessKey); err != nil { + addToDiag(ctx, diag.FromErr(err)) + return + } + + r.read(ctx, data, m) } func (r IntegrationResourceProvider) delete(ctx context.Context, data *schema.ResourceData, m interface{}) { @@ -102,15 +139,19 @@ func (r IntegrationResourceProvider) update(ctx context.Context, data *schema.Re client := m.(*epcc.Client) observes := data.Get("observes").([]interface{}) + integrationObject := &epcc.Integration{ Type: epcc.IntegrationType, - IntegrationType: epcc.Webhook, + IntegrationType: data.Get("integration_type").(string), Name: data.Get("name").(string), Description: data.Get("description").(string), Enabled: data.Get("enabled").(bool), Configuration: epcc.IntegrationConfiguration{ - Url: data.Get("url").(string), - SecretKey: data.Get("secret_key").(string), + Url: data.Get("url").(string), + SecretKey: data.Get("secret_key").(string), + AwsAccessKeyId: data.Get("aws_access_key_id").(string), + AwsSecretAccessKey: data.Get("aws_secret_access_key").(string), + Region: data.Get("region").(string), }, Observes: convertArrayToStringSlice(observes), } @@ -123,6 +164,19 @@ func (r IntegrationResourceProvider) update(ctx context.Context, data *schema.Re } data.SetId(result.Data.Id) + + // EPCC API only returns the last 4 characters for these two keys, so we will store in state the correct value from the request + if err := data.Set("aws_access_key_id", integrationObject.Configuration.AwsAccessKeyId); err != nil { + addToDiag(ctx, diag.FromErr(err)) + return + } + + if err := data.Set("aws_secret_access_key", integrationObject.Configuration.AwsSecretAccessKey); err != nil { + addToDiag(ctx, diag.FromErr(err)) + return + } + + r.read(ctx, data, m) } func (r IntegrationResourceProvider) read(ctx context.Context, data *schema.ResourceData, m interface{}) { @@ -163,4 +217,43 @@ func (r IntegrationResourceProvider) read(ctx context.Context, data *schema.Reso addToDiag(ctx, diag.FromErr(err)) return } + + if err := data.Set("integration_type", result.Data.IntegrationType); err != nil { + addToDiag(ctx, diag.FromErr(err)) + return + } + + if err := data.Set("region", result.Data.Configuration.Region); err != nil { + addToDiag(ctx, diag.FromErr(err)) + return + } + + // Update the state to the API value only if the last 4 characters don't match. + if accessKeyIdFromState, ok := data.GetOk("aws_access_key_id"); ok { + if lastFourChars(accessKeyIdFromState.(string)) != lastFourChars(result.Data.Configuration.AwsAccessKeyId) { + if err := data.Set("aws_access_key_id", result.Data.Configuration.AwsAccessKeyId); err != nil { + addToDiag(ctx, diag.FromErr(err)) + return + } + } + } + + // Update the state to the API value only if the last 4 characters don't match. + if secretAccessKeyFromState, ok := data.GetOk("aws_secret_access_key"); ok { + if lastFourChars(secretAccessKeyFromState.(string)) != lastFourChars(result.Data.Configuration.AwsSecretAccessKey) { + if err := data.Set("aws_secret_access_key", result.Data.Configuration.AwsSecretAccessKey); err != nil { + addToDiag(ctx, diag.FromErr(err)) + return + } + } + } +} + +func lastFourChars(s string) string { + if len(s) > 4 { + // not UTF-8 safe, but who knows if AWS access keys will ever be UTF-8 + return s[len(s)-4:] + } + + return s } diff --git a/internal/provider/resource_epcc_integration_test.go b/internal/provider/resource_epcc_integration_test.go index d795e2b..4339337 100644 --- a/internal/provider/resource_epcc_integration_test.go +++ b/internal/provider/resource_epcc_integration_test.go @@ -18,6 +18,7 @@ func TestAccResourceIntegration(t *testing.T) { description = "Test Integration Description" url = "https://webhook" secret_key = "secret" + integration_type = "webhook" enabled = true observes = [ "cart.updated", @@ -31,6 +32,7 @@ func TestAccResourceIntegration(t *testing.T) { resource.TestCheckResourceAttr("epcc_integration.test", "description", "Test Integration Description"), resource.TestCheckResourceAttr("epcc_integration.test", "url", "https://webhook"), resource.TestCheckResourceAttr("epcc_integration.test", "secret_key", "secret"), + resource.TestCheckResourceAttr("epcc_integration.test", "integration_type", "webhook"), resource.TestCheckResourceAttr("epcc_integration.test", "enabled", "true"), resource.TestCheckResourceAttr("epcc_integration.test", "observes.0", "cart.updated"), resource.TestCheckResourceAttr("epcc_integration.test", "observes.1", "cart.deleted"), @@ -45,6 +47,7 @@ func TestAccResourceIntegration(t *testing.T) { description = "Test Integration Description Updated" url = "https://webhook-updated" secret_key = "secret-updated" + integration_type = "webhook" enabled = false observes = [ "order.updated", @@ -58,12 +61,46 @@ func TestAccResourceIntegration(t *testing.T) { resource.TestCheckResourceAttr("epcc_integration.test", "description", "Test Integration Description Updated"), resource.TestCheckResourceAttr("epcc_integration.test", "url", "https://webhook-updated"), resource.TestCheckResourceAttr("epcc_integration.test", "secret_key", "secret-updated"), + resource.TestCheckResourceAttr("epcc_integration.test", "integration_type", "webhook"), resource.TestCheckResourceAttr("epcc_integration.test", "enabled", "false"), resource.TestCheckResourceAttr("epcc_integration.test", "observes.0", "order.updated"), resource.TestCheckResourceAttr("epcc_integration.test", "observes.1", "order.deleted"), resource.TestCheckResourceAttr("epcc_integration.test", "observes.#", "2"), ), }, + { + // language=HCL + Config: ` + resource "epcc_integration" "test_sqs" { + name = "Test Integration Updated" + description = "Test Integration Description Updated" + url = "https://webhook-updated" + integration_type = "aws_sqs" + region = "us-west-2" + aws_access_key_id = "FOOFOOFOOFOOFOO" + aws_secret_access_key = "BARBARBARBARBAR" + enabled = false + observes = [ + "order.updated", + "order.deleted", + ] + } + `, + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttrSet("epcc_integration.test_sqs", "id"), + resource.TestCheckResourceAttr("epcc_integration.test_sqs", "name", "Test Integration Updated"), + resource.TestCheckResourceAttr("epcc_integration.test_sqs", "description", "Test Integration Description Updated"), + resource.TestCheckResourceAttr("epcc_integration.test_sqs", "url", "https://webhook-updated"), + resource.TestCheckResourceAttr("epcc_integration.test_sqs", "integration_type", "aws_sqs"), + resource.TestCheckResourceAttr("epcc_integration.test_sqs", "enabled", "false"), + resource.TestCheckResourceAttr("epcc_integration.test_sqs", "observes.0", "order.updated"), + resource.TestCheckResourceAttr("epcc_integration.test_sqs", "observes.1", "order.deleted"), + resource.TestCheckResourceAttr("epcc_integration.test_sqs", "observes.#", "2"), + resource.TestCheckResourceAttr("epcc_integration.test_sqs", "region", "us-west-2"), + resource.TestCheckResourceAttr("epcc_integration.test_sqs", "aws_access_key_id", "FOOFOOFOOFOOFOO"), + resource.TestCheckResourceAttr("epcc_integration.test_sqs", "aws_secret_access_key", "BARBARBARBARBAR"), + ), + }, }, }) }