Skip to content

Commit

Permalink
azurerm_container_app_environment: Add support for `workload_profil…
Browse files Browse the repository at this point in the history
…e` (#23478)

* temp env apex

* containerapps: Add support for workload_profile

* fix go fmt

* Add doc

* fix tflint

* Fix test

* rename workload profile attributes

* Modify workload_profile structure

* Fix docs of workload profile attributes

* Update tests
  • Loading branch information
jiaweitao001 authored Dec 7, 2023
1 parent 65af40a commit aa51826
Show file tree
Hide file tree
Showing 5 changed files with 241 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"github.com/hashicorp/go-azure-sdk/resource-manager/containerapps/2023-05-01/managedenvironments"
"github.com/hashicorp/go-azure-sdk/resource-manager/operationalinsights/2020-08-01/workspaces"
"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"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
Expand All @@ -25,15 +26,16 @@ import (
type ContainerAppEnvironmentResource struct{}

type ContainerAppEnvironmentModel struct {
Name string `tfschema:"name"`
ResourceGroup string `tfschema:"resource_group_name"`
Location string `tfschema:"location"`
DaprApplicationInsightsConnectionString string `tfschema:"dapr_application_insights_connection_string"`
LogAnalyticsWorkspaceId string `tfschema:"log_analytics_workspace_id"`
InfrastructureSubnetId string `tfschema:"infrastructure_subnet_id"`
InternalLoadBalancerEnabled bool `tfschema:"internal_load_balancer_enabled"`
ZoneRedundant bool `tfschema:"zone_redundancy_enabled"`
Tags map[string]interface{} `tfschema:"tags"`
Name string `tfschema:"name"`
ResourceGroup string `tfschema:"resource_group_name"`
Location string `tfschema:"location"`
DaprApplicationInsightsConnectionString string `tfschema:"dapr_application_insights_connection_string"`
LogAnalyticsWorkspaceId string `tfschema:"log_analytics_workspace_id"`
InfrastructureSubnetId string `tfschema:"infrastructure_subnet_id"`
InternalLoadBalancerEnabled bool `tfschema:"internal_load_balancer_enabled"`
ZoneRedundant bool `tfschema:"zone_redundancy_enabled"`
Tags map[string]interface{} `tfschema:"tags"`
WorkloadProfiles []helpers.WorkloadProfileModel `tfschema:"workload_profile"`

DefaultDomain string `tfschema:"default_domain"`
DockerBridgeCidr string `tfschema:"docker_bridge_cidr"`
Expand Down Expand Up @@ -104,6 +106,8 @@ func (r ContainerAppEnvironmentResource) Arguments() map[string]*pluginsdk.Schem
Description: "Should the Container Environment operate in Internal Load Balancing Mode? Defaults to `false`. **Note:** can only be set to `true` if `infrastructure_subnet_id` is specified.",
},

"workload_profile": helpers.WorkloadProfileSchema(),

"zone_redundancy_enabled": {
Type: pluginsdk.TypeBool,
Optional: true,
Expand Down Expand Up @@ -231,6 +235,8 @@ func (r ContainerAppEnvironmentResource) Create() sdk.ResourceFunc {
managedEnvironment.Properties.VnetConfiguration.Internal = pointer.To(containerAppEnvironment.InternalLoadBalancerEnabled)
}

managedEnvironment.Properties.WorkloadProfiles = helpers.ExpandWorkloadProfiles(containerAppEnvironment.WorkloadProfiles)

if err := client.CreateOrUpdateThenPoll(ctx, id, managedEnvironment); err != nil {
return fmt.Errorf("creating %s: %+v", id, err)
}
Expand Down Expand Up @@ -279,6 +285,7 @@ func (r ContainerAppEnvironmentResource) Read() sdk.ResourceFunc {
state.ZoneRedundant = pointer.From(props.ZoneRedundant)
state.StaticIP = pointer.From(props.StaticIP)
state.DefaultDomain = pointer.From(props.DefaultDomain)
state.WorkloadProfiles = helpers.FlattenWorkloadProfiles(props.WorkloadProfiles)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,50 @@ func TestAccContainerAppEnvironment_complete(t *testing.T) {
})
}

func TestAccContainerAppEnvironment_withWorkloadProfile(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_container_app_environment", "test")
r := ContainerAppEnvironmentResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.completeWithWorkloadProfile(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("log_analytics_workspace_id"),
})
}

func TestAccContainerAppEnvironment_updateWorkloadProfile(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_container_app_environment", "test")
r := ContainerAppEnvironmentResource{}

data.ResourceTest(t, r, []acceptance.TestStep{
{
Config: r.complete(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("log_analytics_workspace_id"),
{
Config: r.completeWithWorkloadProfile(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("log_analytics_workspace_id"),
{
Config: r.completeUpdate(data),
Check: acceptance.ComposeTestCheckFunc(
check.That(data.ResourceName).ExistsInAzure(r),
),
},
data.ImportStep("log_analytics_workspace_id"),
})
}

func TestAccContainerAppEnvironment_completeUpdate(t *testing.T) {
data := acceptance.BuildTestData(t, "azurerm_container_app_environment", "test")
r := ContainerAppEnvironmentResource{}
Expand Down Expand Up @@ -189,6 +233,59 @@ resource "azurerm_container_app_environment" "test" {
`, r.templateVNet(data), data.RandomInteger)
}

func (r ContainerAppEnvironmentResource) completeWithWorkloadProfile(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
features {}
}
%[1]s
resource "azurerm_virtual_network" "test" {
name = "acctestvirtnet%[2]d"
address_space = ["10.0.0.0/16"]
location = azurerm_resource_group.test.location
resource_group_name = azurerm_resource_group.test.name
}
resource "azurerm_subnet" "control" {
name = "control-plane"
resource_group_name = azurerm_resource_group.test.name
virtual_network_name = azurerm_virtual_network.test.name
address_prefixes = ["10.0.0.0/23"]
delegation {
name = "acctestdelegation%[2]d"
service_delegation {
actions = ["Microsoft.Network/virtualNetworks/subnets/join/action"]
name = "Microsoft.App/environments"
}
}
}
resource "azurerm_container_app_environment" "test" {
name = "acctest-CAEnv%[2]d"
resource_group_name = azurerm_resource_group.test.name
location = azurerm_resource_group.test.location
infrastructure_subnet_id = azurerm_subnet.control.id
workload_profile {
maximum_count = 2
minimum_count = 0
name = "My-GP-01"
workload_profile_type = "D4"
}
zone_redundancy_enabled = true
tags = {
Foo = "Bar"
secret = "sauce"
}
}
`, r.template(data), data.RandomInteger)

}

func (r ContainerAppEnvironmentResource) completeUpdate(data acceptance.TestData) string {
return fmt.Sprintf(`
provider "azurerm" {
Expand Down
113 changes: 113 additions & 0 deletions internal/services/containerapps/helpers/container_app_environment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package helpers

import (
"strings"

"github.com/hashicorp/go-azure-helpers/lang/pointer"
"github.com/hashicorp/go-azure-sdk/resource-manager/containerapps/2023-05-01/managedenvironments"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/pluginsdk"
"github.com/hashicorp/terraform-provider-azurerm/internal/tf/validation"
)

const consumption = "Consumption"

type WorkloadProfileModel struct {
MaximumCount int `tfschema:"maximum_count"`
MinimumCount int `tfschema:"minimum_count"`
Name string `tfschema:"name"`
WorkloadProfileType string `tfschema:"workload_profile_type"`
}

func WorkloadProfileSchema() *pluginsdk.Schema {
return &pluginsdk.Schema{
Type: pluginsdk.TypeSet,
Optional: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringIsNotEmpty,
},

"workload_profile_type": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringInSlice([]string{
"D4",
"D8",
"D16",
"D32",
"E4",
"E8",
"E16",
"E32",
}, false),
},

"maximum_count": {
Type: pluginsdk.TypeInt,
Required: true,
},

"minimum_count": {
Type: pluginsdk.TypeInt,
Required: true,
},
},
},
}
}

func ExpandWorkloadProfiles(input []WorkloadProfileModel) *[]managedenvironments.WorkloadProfile {
if len(input) == 0 {
return nil
}

result := make([]managedenvironments.WorkloadProfile, 0)

for _, v := range input {
r := managedenvironments.WorkloadProfile{
Name: v.Name,
WorkloadProfileType: v.WorkloadProfileType,
}

if v.Name != consumption {
r.MaximumCount = pointer.To(int64(v.MaximumCount))
r.MinimumCount = pointer.To(int64(v.MinimumCount))
}

result = append(result, r)
}

result = append(result, managedenvironments.WorkloadProfile{
Name: consumption,
WorkloadProfileType: consumption,
})

return &result
}

func FlattenWorkloadProfiles(input *[]managedenvironments.WorkloadProfile) []WorkloadProfileModel {
if input == nil || len(*input) == 0 {
return []WorkloadProfileModel{}
}
result := make([]WorkloadProfileModel, 0)

for _, v := range *input {
if strings.EqualFold(v.WorkloadProfileType, consumption) {
continue
}
result = append(result, WorkloadProfileModel{
Name: v.Name,
MaximumCount: int(pointer.From(v.MaximumCount)),
MinimumCount: int(pointer.From(v.MinimumCount)),
WorkloadProfileType: v.WorkloadProfileType,
})
}

return result
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func (d LocalRulestackDataSource) basic(data acceptance.TestData) string {
return fmt.Sprintf(`
%s
data "azurerm_palo_alto_local_rulestack" "test"{
data "azurerm_palo_alto_local_rulestack" "test" {
name = azurerm_palo_alto_local_rulestack.test.name
resource_group_name = azurerm_palo_alto_local_rulestack.test.resource_group_name
}
Expand Down
14 changes: 14 additions & 0 deletions website/docs/r/container_app_environment.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,22 @@ The following arguments are supported:

* `log_analytics_workspace_id` - (Optional) The ID for the Log Analytics Workspace to link this Container Apps Managed Environment to. Changing this forces a new resource to be created.

* `workload_profile` - (Optional) The profile of the workload to scope the container app execution. A `workload_profile` block as defined below.

* `tags` - (Optional) A mapping of tags to assign to the resource.

---

A `workload_profile` block supports the following:

* `name` - (Required) The name of the workload profile.

* `workload_profile_type` - (Required) Workload profile type for the workloads to run on. Possible values include `D4`, `D8`, `D16`, `D32`, `E4`, `E8`, `E16` and `E32`.

* `maximum_container_count` - (Optional) The maximum number of instances of workload profile that can be deployed in the Container App Environment.

* `minimum_container_count` - (Optional) The minimum number of instances of workload profile that can be deployed in the Container App Environment.

## Attributes Reference

In addition to the Arguments listed above - the following Attributes are exported:
Expand Down

0 comments on commit aa51826

Please sign in to comment.