From e3b84327b474e69972221f64b8be07f939b15507 Mon Sep 17 00:00:00 2001 From: Jerome Brown Date: Thu, 23 May 2024 14:00:40 +1200 Subject: [PATCH 1/4] `azurerm_container_app_job` Add TODO to rename secrets and registries properties in 4.0 --- internal/services/containerapps/container_app_job_resource.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/internal/services/containerapps/container_app_job_resource.go b/internal/services/containerapps/container_app_job_resource.go index d2621538acc9..19c8eeb5dce6 100644 --- a/internal/services/containerapps/container_app_job_resource.go +++ b/internal/services/containerapps/container_app_job_resource.go @@ -93,6 +93,7 @@ func (r ContainerAppJobResource) Arguments() map[string]*schema.Schema { "template": helpers.JobTemplateSchema(), + // TODO rename `secrets` to `secrets` in 4.0 "secrets": helpers.SecretsSchema(), "replica_retry_limit": { @@ -101,6 +102,7 @@ func (r ContainerAppJobResource) Arguments() map[string]*schema.Schema { ValidateFunc: validation.IntAtLeast(0), }, + // TODO rename `registries` to `registry` in 4.0 "registries": helpers.ContainerAppRegistrySchema(), "event_trigger_config": { From 718da5311fd0bc21932e0fb7dd5cb38288e14526 Mon Sep 17 00:00:00 2001 From: Jerome Brown Date: Tue, 28 May 2024 08:37:41 +1200 Subject: [PATCH 2/4] Rename plural properties to singular for consistency `secrets` to `secret` `registries` to `registry` --- .../container_app_job_resource.go | 147 ++++++++++++++++-- .../container_app_job_resource_test.go | 10 +- .../docs/r/container_app_job.html.markdown | 8 +- 3 files changed, 145 insertions(+), 20 deletions(-) diff --git a/internal/services/containerapps/container_app_job_resource.go b/internal/services/containerapps/container_app_job_resource.go index 19c8eeb5dce6..c12923a89fb5 100644 --- a/internal/services/containerapps/container_app_job_resource.go +++ b/internal/services/containerapps/container_app_job_resource.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/go-azure-helpers/lang/pointer" "github.com/hashicorp/go-azure-helpers/lang/response" + "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" "github.com/hashicorp/go-azure-helpers/resourcemanager/identity" "github.com/hashicorp/go-azure-helpers/resourcemanager/location" @@ -19,9 +20,11 @@ import ( "github.com/hashicorp/go-azure-sdk/resource-manager/containerapps/2023-05-01/jobs" "github.com/hashicorp/go-azure-sdk/resource-manager/containerapps/2023-05-01/managedenvironmentsstorages" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/hashicorp/terraform-provider-azurerm/internal/features" "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" "github.com/hashicorp/terraform-provider-azurerm/internal/services/containerapps/helpers" "github.com/hashicorp/terraform-provider-azurerm/internal/services/containerapps/validate" + keyVaultValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/keyvault/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" ) @@ -37,8 +40,10 @@ type ContainerAppJobModel struct { Template []helpers.JobTemplateModel `tfschema:"template"` ReplicaRetryLimit int64 `tfschema:"replica_retry_limit"` ReplicaTimeoutInSeconds int64 `tfschema:"replica_timeout_in_seconds"` - Secrets []helpers.Secret `tfschema:"secrets"` - Registries []helpers.Registry `tfschema:"registries"` + Secrets []helpers.Secret `tfschema:"secret"` + SecretsDeprecated []helpers.Secret `tfschema:"secrets,removedInNextMajorVersion"` + Registries []helpers.Registry `tfschema:"registry"` + RegistriesDeprecated []helpers.Registry `tfschema:"registries,removedInNextMajorVersion"` EventTriggerConfig []helpers.EventTriggerConfiguration `tfschema:"event_trigger_config"` ManualTriggerConfig []helpers.ManualTriggerConfiguration `tfschema:"manual_trigger_config"` ScheduleTriggerConfig []helpers.ScheduleTriggerConfiguration `tfschema:"schedule_trigger_config"` @@ -93,8 +98,49 @@ func (r ContainerAppJobResource) Arguments() map[string]*schema.Schema { "template": helpers.JobTemplateSchema(), - // TODO rename `secrets` to `secrets` in 4.0 - "secrets": helpers.SecretsSchema(), + "secret": helpers.SecretsSchema(), + + "secrets": { + Type: pluginsdk.TypeSet, + Optional: true, + Sensitive: true, + ConflictsWith: []string{"secret"}, + Deprecated: "`secrets` has been renamed to `secret` and will be removed in version 4.0 of the AzureRM Provider.", + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "identity": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: validation.Any( + commonids.ValidateUserAssignedIdentityID, + validation.StringInSlice([]string{"System"}, false), + ), + Description: "The identity to use for accessing key vault reference.", + }, + + "key_vault_secret_id": { + Type: pluginsdk.TypeString, + Optional: true, + ValidateFunc: keyVaultValidate.NestedItemIdWithOptionalVersion, + Description: "The Key Vault Secret ID. Could be either one of `id` or `versionless_id`.", + }, + + "name": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validate.SecretName, + Description: "The secret name.", + }, + + "value": { + Type: pluginsdk.TypeString, + Optional: true, + Sensitive: true, + Description: "The value for this secret.", + }, + }, + }, + }, "replica_retry_limit": { Type: pluginsdk.TypeInt, @@ -102,8 +148,43 @@ func (r ContainerAppJobResource) Arguments() map[string]*schema.Schema { ValidateFunc: validation.IntAtLeast(0), }, - // TODO rename `registries` to `registry` in 4.0 - "registries": helpers.ContainerAppRegistrySchema(), + "registry": helpers.ContainerAppRegistrySchema(), + + "registries": { + Type: pluginsdk.TypeList, + MinItems: 1, + Optional: true, + ConflictsWith: []string{"registry"}, + Deprecated: "`registries` has been renamed to `registry` and will be removed in version 4.0 of the AzureRM Provider.", + Elem: &pluginsdk.Resource{ + Schema: map[string]*pluginsdk.Schema{ + "server": { + Type: pluginsdk.TypeString, + Required: true, + ValidateFunc: validation.StringIsNotEmpty, + Description: "The hostname for the Container Registry.", + }, + + "username": { + Type: pluginsdk.TypeString, + Optional: true, + Description: "The username to use for this Container Registry.", + }, + + "password_secret_name": { + Type: pluginsdk.TypeString, + Optional: true, + Description: "The name of the Secret Reference containing the password value for this user on the Container Registry.", + }, + + "identity": { + Type: pluginsdk.TypeString, + Optional: true, + Description: "ID of the System or User Managed Identity used to pull images from the Container Registry", + }, + }, + }, + }, "event_trigger_config": { Type: pluginsdk.TypeList, @@ -253,6 +334,17 @@ func (r ContainerAppJobResource) Create() sdk.ResourceFunc { if err != nil { return fmt.Errorf("expanding registry config for %s: %v", id, err) } + if !features.FourPointOhBeta() && len(model.RegistriesDeprecated) > 0 { + registries, err = helpers.ExpandContainerAppJobRegistries(model.RegistriesDeprecated) + if err != nil { + return fmt.Errorf("expanding registry config for %s: %v", id, err) + } + } + + secrets := helpers.ExpandContainerAppJobSecrets(model.Secrets) + if !features.FourPointOhBeta() && len(model.SecretsDeprecated) > 0 { + secrets = helpers.ExpandContainerAppJobSecrets(model.SecretsDeprecated) + } job := jobs.Job{ Location: location.Normalize(model.Location), @@ -260,7 +352,7 @@ func (r ContainerAppJobResource) Create() sdk.ResourceFunc { Configuration: &jobs.JobConfiguration{ ReplicaRetryLimit: pointer.To(model.ReplicaRetryLimit), ReplicaTimeout: model.ReplicaTimeoutInSeconds, - Secrets: helpers.ExpandContainerAppJobSecrets(model.Secrets), + Secrets: secrets, Registries: registries, }, EnvironmentId: pointer.To(model.ContainerAppEnvironmentId), @@ -350,7 +442,11 @@ func (r ContainerAppJobResource) Read() sdk.ResourceFunc { state.ContainerAppEnvironmentId = envId.ID() state.Template = helpers.FlattenContainerAppJobTemplate(props.Template) if config := props.Configuration; config != nil { - state.Registries = helpers.FlattenContainerAppJobRegistries(config.Registries) + if !features.FourPointOhBeta() && len(state.RegistriesDeprecated) > 0 { + state.RegistriesDeprecated = helpers.FlattenContainerAppJobRegistries(config.Registries) + } else { + state.Registries = helpers.FlattenContainerAppJobRegistries(config.Registries) + } state.ReplicaTimeoutInSeconds = config.ReplicaTimeout if config.ReplicaRetryLimit != nil { state.ReplicaRetryLimit = pointer.From(config.ReplicaRetryLimit) @@ -373,7 +469,11 @@ func (r ContainerAppJobResource) Read() sdk.ResourceFunc { if err != nil { return fmt.Errorf("listing secrets for %s: %+v", *id, err) } - state.Secrets = helpers.FlattenContainerAppJobSecrets(secretResp.Model) + if !features.FourPointOhBeta() && len(state.SecretsDeprecated) > 0 { + state.SecretsDeprecated = helpers.FlattenContainerAppJobSecrets(secretResp.Model) + } else { + state.Secrets = helpers.FlattenContainerAppJobSecrets(secretResp.Model) + } return metadata.Encode(&state) }, @@ -421,11 +521,20 @@ func (r ContainerAppJobResource) Update() sdk.ResourceFunc { d := metadata.ResourceData - if metadata.ResourceData.HasChange("secrets") { + if !features.FourPointOhBeta() && d.HasChange("secrets") { + model.Properties.Configuration.Secrets = helpers.ExpandContainerAppJobSecrets(state.SecretsDeprecated) + } + if d.HasChange("secret") { model.Properties.Configuration.Secrets = helpers.ExpandContainerAppJobSecrets(state.Secrets) } - if d.HasChange("registries") { + if !features.FourPointOhBeta() && d.HasChange("registries") { + model.Properties.Configuration.Registries, err = helpers.ExpandContainerAppJobRegistries(state.RegistriesDeprecated) + if err != nil { + return fmt.Errorf("invalid registry config for %s: %v", id, err) + } + } + if d.HasChange("registry") { model.Properties.Configuration.Registries, err = helpers.ExpandContainerAppJobRegistries(state.Registries) if err != nil { return fmt.Errorf("invalid registry config for %s: %v", id, err) @@ -502,6 +611,11 @@ func (r ContainerAppJobResource) Delete() sdk.ResourceFunc { func (r ContainerAppJobResource) CustomizeDiff() sdk.ResourceFunc { return sdk.ResourceFunc{ Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { + var job ContainerAppJobModel + if err := metadata.DecodeDiff(&job); err != nil { + return err + } + if metadata.ResourceDiff != nil && metadata.ResourceDiff.HasChange("secrets") { stateSecretsRaw, configSecretsRaw := metadata.ResourceDiff.GetChange("secrets") stateSecrets := stateSecretsRaw.(*schema.Set).List() @@ -526,6 +640,17 @@ func (r ContainerAppJobResource) CustomizeDiff() sdk.ResourceFunc { } } } + + if !features.FourPointOhBeta() { + if len(job.SecretsDeprecated) > 0 && len(job.Secrets) > 0 { + return fmt.Errorf("cannot use both `secret` and `secrets` blocks in the same configuration") + } + + if len(job.RegistriesDeprecated) > 0 && len(job.Registries) > 0 { + return fmt.Errorf("cannot use both `registry` and `registries` blocks in the same configuration") + } + } + return nil }, } diff --git a/internal/services/containerapps/container_app_job_resource_test.go b/internal/services/containerapps/container_app_job_resource_test.go index aee85b1aaf88..5bc52a18eaae 100644 --- a/internal/services/containerapps/container_app_job_resource_test.go +++ b/internal/services/containerapps/container_app_job_resource_test.go @@ -637,11 +637,11 @@ resource "azurerm_container_app_job" "test" { parallelism = 4 replica_completion_count = 1 } - secrets { + secret { name = "registry-password" value = azurerm_container_registry.test.admin_password } - registries { + registry { server = azurerm_container_registry.test.login_server username = azurerm_container_registry.test.admin_username password_secret_name = "registry-password" @@ -738,17 +738,17 @@ resource "azurerm_container_app_job" "test" { replica_completion_count = 2 } - secrets { + secret { name = "registry-password" value = azurerm_container_registry.test.admin_password } - secrets { + secret { name = "foo" value = "bar" } - registries { + registry { server = azurerm_container_registry.test.login_server username = azurerm_container_registry.test.admin_username password_secret_name = "registry-password" diff --git a/website/docs/r/container_app_job.html.markdown b/website/docs/r/container_app_job.html.markdown index 45e9c8795544..317e86b69deb 100644 --- a/website/docs/r/container_app_job.html.markdown +++ b/website/docs/r/container_app_job.html.markdown @@ -102,9 +102,9 @@ The following arguments are supported: * `replica_retry_limit` - (Optional) The maximum number of times a replica is allowed to retry. -* `secrets` - (Optional) A `secrets` block as defined below. +* `secret` - (Optional) One or more `secret` blocks as defined below. -* `registries` - (Optional) A `registries` block as defined below. +* `registry` - (Optional) One or more `registry` blocks as defined below. * `manual_trigger_config` - (Optional) A `manual_trigger_config` block as defined below. @@ -312,7 +312,7 @@ A `volume` block supports the following: --- -A `secrets` block supports the following: +A `secret` block supports the following: * `name` - (required) Name of the secret. @@ -320,7 +320,7 @@ A `secrets` block supports the following: --- -A `registries` block supports the following: +A `registry` block supports the following: * `identity` - (Optional) A Managed Identity to use to authenticate with Azure Container Registry. From 6c3ea898946b806eb65f0f9d9422a04ec11b56a2 Mon Sep 17 00:00:00 2001 From: Jerome Brown Date: Tue, 28 May 2024 19:43:32 +1200 Subject: [PATCH 3/4] Update based on feedback --- .../container_app_job_resource.go | 116 +++--------------- 1 file changed, 19 insertions(+), 97 deletions(-) diff --git a/internal/services/containerapps/container_app_job_resource.go b/internal/services/containerapps/container_app_job_resource.go index c12923a89fb5..1f62c1daa511 100644 --- a/internal/services/containerapps/container_app_job_resource.go +++ b/internal/services/containerapps/container_app_job_resource.go @@ -11,7 +11,6 @@ import ( "github.com/hashicorp/go-azure-helpers/lang/pointer" "github.com/hashicorp/go-azure-helpers/lang/response" - "github.com/hashicorp/go-azure-helpers/resourcemanager/commonids" "github.com/hashicorp/go-azure-helpers/resourcemanager/commonschema" "github.com/hashicorp/go-azure-helpers/resourcemanager/identity" "github.com/hashicorp/go-azure-helpers/resourcemanager/location" @@ -24,7 +23,6 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/sdk" "github.com/hashicorp/terraform-provider-azurerm/internal/services/containerapps/helpers" "github.com/hashicorp/terraform-provider-azurerm/internal/services/containerapps/validate" - keyVaultValidate "github.com/hashicorp/terraform-provider-azurerm/internal/services/keyvault/validate" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation" ) @@ -70,7 +68,7 @@ func (r ContainerAppJobResource) IDValidationFunc() pluginsdk.SchemaValidateFunc } func (r ContainerAppJobResource) Arguments() map[string]*schema.Schema { - return map[string]*pluginsdk.Schema{ + schema := map[string]*pluginsdk.Schema{ "name": { Type: pluginsdk.TypeString, Required: true, @@ -100,48 +98,6 @@ func (r ContainerAppJobResource) Arguments() map[string]*schema.Schema { "secret": helpers.SecretsSchema(), - "secrets": { - Type: pluginsdk.TypeSet, - Optional: true, - Sensitive: true, - ConflictsWith: []string{"secret"}, - Deprecated: "`secrets` has been renamed to `secret` and will be removed in version 4.0 of the AzureRM Provider.", - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "identity": { - Type: pluginsdk.TypeString, - Optional: true, - ValidateFunc: validation.Any( - commonids.ValidateUserAssignedIdentityID, - validation.StringInSlice([]string{"System"}, false), - ), - Description: "The identity to use for accessing key vault reference.", - }, - - "key_vault_secret_id": { - Type: pluginsdk.TypeString, - Optional: true, - ValidateFunc: keyVaultValidate.NestedItemIdWithOptionalVersion, - Description: "The Key Vault Secret ID. Could be either one of `id` or `versionless_id`.", - }, - - "name": { - Type: pluginsdk.TypeString, - Required: true, - ValidateFunc: validate.SecretName, - Description: "The secret name.", - }, - - "value": { - Type: pluginsdk.TypeString, - Optional: true, - Sensitive: true, - Description: "The value for this secret.", - }, - }, - }, - }, - "replica_retry_limit": { Type: pluginsdk.TypeInt, Optional: true, @@ -150,42 +106,6 @@ func (r ContainerAppJobResource) Arguments() map[string]*schema.Schema { "registry": helpers.ContainerAppRegistrySchema(), - "registries": { - Type: pluginsdk.TypeList, - MinItems: 1, - Optional: true, - ConflictsWith: []string{"registry"}, - Deprecated: "`registries` has been renamed to `registry` and will be removed in version 4.0 of the AzureRM Provider.", - Elem: &pluginsdk.Resource{ - Schema: map[string]*pluginsdk.Schema{ - "server": { - Type: pluginsdk.TypeString, - Required: true, - ValidateFunc: validation.StringIsNotEmpty, - Description: "The hostname for the Container Registry.", - }, - - "username": { - Type: pluginsdk.TypeString, - Optional: true, - Description: "The username to use for this Container Registry.", - }, - - "password_secret_name": { - Type: pluginsdk.TypeString, - Optional: true, - Description: "The name of the Secret Reference containing the password value for this user on the Container Registry.", - }, - - "identity": { - Type: pluginsdk.TypeString, - Optional: true, - Description: "ID of the System or User Managed Identity used to pull images from the Container Registry", - }, - }, - }, - }, - "event_trigger_config": { Type: pluginsdk.TypeList, Optional: true, @@ -285,6 +205,24 @@ func (r ContainerAppJobResource) Arguments() map[string]*schema.Schema { "tags": commonschema.Tags(), } + + if !features.FourPointOhBeta() { + schema["secrets"] = helpers.SecretsSchema() + schema["secrets"].ConflictsWith = []string{"secret"} + schema["secrets"].Computed = true + schema["secrets"].Deprecated = "`secrets` has been renamed to `secret` and will be removed in version 4.0 of the AzureRM Provider." + schema["secret"].ConflictsWith = []string{"secrets"} + schema["secret"].Computed = true + + schema["registries"] = helpers.ContainerAppRegistrySchema() + schema["registries"].ConflictsWith = []string{"registry"} + schema["registries"].Computed = true + schema["registries"].Deprecated = "`registries` has been renamed to `registry` and will be removed in version 4.0 of the AzureRM Provider." + schema["registry"].ConflictsWith = []string{"registries"} + schema["registry"].Computed = true + } + + return schema } func (r ContainerAppJobResource) Attributes() map[string]*schema.Schema { @@ -611,11 +549,6 @@ func (r ContainerAppJobResource) Delete() sdk.ResourceFunc { func (r ContainerAppJobResource) CustomizeDiff() sdk.ResourceFunc { return sdk.ResourceFunc{ Func: func(ctx context.Context, metadata sdk.ResourceMetaData) error { - var job ContainerAppJobModel - if err := metadata.DecodeDiff(&job); err != nil { - return err - } - if metadata.ResourceDiff != nil && metadata.ResourceDiff.HasChange("secrets") { stateSecretsRaw, configSecretsRaw := metadata.ResourceDiff.GetChange("secrets") stateSecrets := stateSecretsRaw.(*schema.Set).List() @@ -640,17 +573,6 @@ func (r ContainerAppJobResource) CustomizeDiff() sdk.ResourceFunc { } } } - - if !features.FourPointOhBeta() { - if len(job.SecretsDeprecated) > 0 && len(job.Secrets) > 0 { - return fmt.Errorf("cannot use both `secret` and `secrets` blocks in the same configuration") - } - - if len(job.RegistriesDeprecated) > 0 && len(job.Registries) > 0 { - return fmt.Errorf("cannot use both `registry` and `registries` blocks in the same configuration") - } - } - return nil }, } From 094b0ff2dcc5000598dfb57bb118ba76a5d17edd Mon Sep 17 00:00:00 2001 From: Jerome Brown Date: Tue, 28 May 2024 21:47:43 +1200 Subject: [PATCH 4/4] Setup tests for deprecated properties Tweak logic so it all works too --- .../container_app_job_resource.go | 31 ++--- .../container_app_job_resource_test.go | 117 ++++++++++++++++++ 2 files changed, 133 insertions(+), 15 deletions(-) diff --git a/internal/services/containerapps/container_app_job_resource.go b/internal/services/containerapps/container_app_job_resource.go index 1f62c1daa511..c19b11b4a18c 100644 --- a/internal/services/containerapps/container_app_job_resource.go +++ b/internal/services/containerapps/container_app_job_resource.go @@ -380,10 +380,9 @@ func (r ContainerAppJobResource) Read() sdk.ResourceFunc { state.ContainerAppEnvironmentId = envId.ID() state.Template = helpers.FlattenContainerAppJobTemplate(props.Template) if config := props.Configuration; config != nil { - if !features.FourPointOhBeta() && len(state.RegistriesDeprecated) > 0 { + state.Registries = helpers.FlattenContainerAppJobRegistries(config.Registries) + if !features.FourPointOhBeta() { state.RegistriesDeprecated = helpers.FlattenContainerAppJobRegistries(config.Registries) - } else { - state.Registries = helpers.FlattenContainerAppJobRegistries(config.Registries) } state.ReplicaTimeoutInSeconds = config.ReplicaTimeout if config.ReplicaRetryLimit != nil { @@ -407,10 +406,9 @@ func (r ContainerAppJobResource) Read() sdk.ResourceFunc { if err != nil { return fmt.Errorf("listing secrets for %s: %+v", *id, err) } - if !features.FourPointOhBeta() && len(state.SecretsDeprecated) > 0 { + state.Secrets = helpers.FlattenContainerAppJobSecrets(secretResp.Model) + if !features.FourPointOhBeta() { state.SecretsDeprecated = helpers.FlattenContainerAppJobSecrets(secretResp.Model) - } else { - state.Secrets = helpers.FlattenContainerAppJobSecrets(secretResp.Model) } return metadata.Encode(&state) @@ -459,19 +457,10 @@ func (r ContainerAppJobResource) Update() sdk.ResourceFunc { d := metadata.ResourceData - if !features.FourPointOhBeta() && d.HasChange("secrets") { - model.Properties.Configuration.Secrets = helpers.ExpandContainerAppJobSecrets(state.SecretsDeprecated) - } if d.HasChange("secret") { model.Properties.Configuration.Secrets = helpers.ExpandContainerAppJobSecrets(state.Secrets) } - if !features.FourPointOhBeta() && d.HasChange("registries") { - model.Properties.Configuration.Registries, err = helpers.ExpandContainerAppJobRegistries(state.RegistriesDeprecated) - if err != nil { - return fmt.Errorf("invalid registry config for %s: %v", id, err) - } - } if d.HasChange("registry") { model.Properties.Configuration.Registries, err = helpers.ExpandContainerAppJobRegistries(state.Registries) if err != nil { @@ -515,6 +504,18 @@ func (r ContainerAppJobResource) Update() sdk.ResourceFunc { model.Tags = tags.Expand(state.Tags) } + if !features.FourPointOhBeta() { + if d.HasChange("secrets") { + model.Properties.Configuration.Secrets = helpers.ExpandContainerAppJobSecrets(state.SecretsDeprecated) + } + if d.HasChange("registries") { + model.Properties.Configuration.Registries, err = helpers.ExpandContainerAppJobRegistries(state.RegistriesDeprecated) + if err != nil { + return fmt.Errorf("invalid registry config for %s: %v", id, err) + } + } + } + model.Properties.Template = helpers.ExpandContainerAppJobTemplate(state.Template) if err := client.CreateOrUpdateThenPoll(ctx, *id, *model); err != nil { diff --git a/internal/services/containerapps/container_app_job_resource_test.go b/internal/services/containerapps/container_app_job_resource_test.go index 5bc52a18eaae..74b15e6f3ef9 100644 --- a/internal/services/containerapps/container_app_job_resource_test.go +++ b/internal/services/containerapps/container_app_job_resource_test.go @@ -14,6 +14,7 @@ import ( "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance" "github.com/hashicorp/terraform-provider-azurerm/internal/acceptance/check" "github.com/hashicorp/terraform-provider-azurerm/internal/clients" + "github.com/hashicorp/terraform-provider-azurerm/internal/features" "github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk" "github.com/hashicorp/terraform-provider-azurerm/utils" ) @@ -229,6 +230,24 @@ func TestAccContainerAppJob_complete(t *testing.T) { }) } +func TestAccContainerAppJob_completeDeprecated(t *testing.T) { + if features.FourPointOhBeta() { + t.Skip("Skipped as `secrets` and `registries` removed in 4.0") + } + data := acceptance.BuildTestData(t, "azurerm_container_app_job", "test") + r := ContainerAppJobResource{} + + data.ResourceTest(t, r, []acceptance.TestStep{ + { + Config: r.completeDeprecated(data), + Check: acceptance.ComposeTestCheckFunc( + check.That(data.ResourceName).ExistsInAzure(r), + ), + }, + data.ImportStep(), + }) +} + func TestAccContainerAppJob_completeUpdate(t *testing.T) { data := acceptance.BuildTestData(t, "azurerm_container_app_job", "test") r := ContainerAppJobResource{} @@ -714,6 +733,104 @@ resource "azurerm_container_app_job" "test" { `, ContainerAppResource{}.templatePlusExtras(data), data.RandomInteger) } +func (r ContainerAppJobResource) completeDeprecated(data acceptance.TestData) string { + return fmt.Sprintf(` + +%[1]s + +resource "azurerm_container_app_job" "test" { + name = "acctest-cajob%[2]d" + resource_group_name = azurerm_resource_group.test.name + location = azurerm_resource_group.test.location + container_app_environment_id = azurerm_container_app_environment.test.id + + identity { + type = "SystemAssigned" + } + + replica_timeout_in_seconds = 10 + replica_retry_limit = 10 + manual_trigger_config { + parallelism = 4 + replica_completion_count = 1 + } + secrets { + name = "registry-password" + value = azurerm_container_registry.test.admin_password + } + registries { + server = azurerm_container_registry.test.login_server + username = azurerm_container_registry.test.admin_username + password_secret_name = "registry-password" + } + + template { + volume { + name = azurerm_container_app_environment_storage.test.name + storage_type = "AzureFile" + storage_name = azurerm_container_app_environment_storage.test.name + } + container { + args = [ + "-c", + "while true; do echo hello; sleep 10;done", + ] + command = [ + "/bin/sh", + ] + image = "jackofallops/azure-containerapps-python-acctest:v0.0.1" + name = "testcontainerappsjob0" + readiness_probe { + transport = "HTTP" + port = 5000 + } + + liveness_probe { + transport = "HTTP" + port = 5000 + path = "/health" + + header { + name = "Cache-Control" + value = "no-cache" + } + + initial_delay = 5 + interval_seconds = 20 + timeout = 2 + failure_count_threshold = 1 + } + startup_probe { + transport = "TCP" + port = 5000 + } + + cpu = 0.5 + memory = "1Gi" + volume_mounts { + path = "/appsettings" + name = azurerm_container_app_environment_storage.test.name + } + } + + init_container { + name = "init-cont-%[2]d" + image = "jackofallops/azure-containerapps-python-acctest:v0.0.1" + cpu = 0.25 + memory = "0.5Gi" + volume_mounts { + name = azurerm_container_app_environment_storage.test.name + path = "/appsettings" + } + } + } + tags = { + ENV = "test" + } +} +`, ContainerAppResource{}.templatePlusExtras(data), data.RandomInteger) +} + func (r ContainerAppJobResource) completeUpdate(data acceptance.TestData) string { return fmt.Sprintf(`