Skip to content

Commit

Permalink
azurerm_container_app - suppot for the init_container block (#23955)
Browse files Browse the repository at this point in the history
Co-authored-by: jackofallops <11830746+jackofallops@users.noreply.github.com>
  • Loading branch information
sakazuki and jackofallops authored Dec 14, 2023
1 parent 84d4f38 commit 88c1055
Show file tree
Hide file tree
Showing 4 changed files with 306 additions and 5 deletions.
11 changes: 11 additions & 0 deletions internal/services/containerapps/container_app_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,17 @@ resource "azurerm_container_app" "test" {
}
}
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 = "/tmp/testdata"
}
}
volume {
name = azurerm_container_app_environment_storage.test.name
storage_type = "AzureFile"
Expand Down
246 changes: 241 additions & 5 deletions internal/services/containerapps/helpers/container_apps.go
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,7 @@ func ContainerAppEnvironmentDaprMetadataSchema() *pluginsdk.Schema {

type ContainerTemplate struct {
Containers []Container `tfschema:"container"`
InitContainers []BaseContainer `tfschema:"init_container"`
Suffix string `tfschema:"revision_suffix"`
MinReplicas int `tfschema:"min_replicas"`
MaxReplicas int `tfschema:"max_replicas"`
Expand All @@ -705,6 +706,8 @@ func ContainerTemplateSchema() *pluginsdk.Schema {
Schema: map[string]*pluginsdk.Schema{
"container": ContainerAppContainerSchema(),

"init_container": InitContainerAppContainerSchema(),

"min_replicas": {
Type: pluginsdk.TypeInt,
Optional: true,
Expand Down Expand Up @@ -750,6 +753,8 @@ func ContainerTemplateSchemaComputed() *pluginsdk.Schema {
Schema: map[string]*pluginsdk.Schema{
"container": ContainerAppContainerSchemaComputed(),

"init_container": InitContainerAppContainerSchemaComputed(),

"min_replicas": {
Type: pluginsdk.TypeInt,
Computed: true,
Expand Down Expand Up @@ -788,8 +793,9 @@ func ExpandContainerAppTemplate(input []ContainerTemplate, metadata sdk.Resource

config := input[0]
template := &containerapps.Template{
Containers: expandContainerAppContainers(config.Containers),
Volumes: expandContainerAppVolumes(config.Volumes),
Containers: expandContainerAppContainers(config.Containers),
InitContainers: expandInitContainerAppContainers(config.InitContainers),
Volumes: expandContainerAppVolumes(config.Volumes),
}

if config.MaxReplicas != 0 {
Expand Down Expand Up @@ -828,9 +834,10 @@ func FlattenContainerAppTemplate(input *containerapps.Template) []ContainerTempl
return []ContainerTemplate{}
}
result := ContainerTemplate{
Containers: flattenContainerAppContainers(input.Containers),
Suffix: pointer.From(input.RevisionSuffix),
Volumes: flattenContainerAppVolumes(input.Volumes),
Containers: flattenContainerAppContainers(input.Containers),
InitContainers: flattenInitContainerAppContainers(input.InitContainers),
Suffix: pointer.From(input.RevisionSuffix),
Volumes: flattenContainerAppVolumes(input.Volumes),
}

if scale := input.Scale; scale != nil {
Expand Down Expand Up @@ -1007,6 +1014,213 @@ func ContainerAppContainerSchemaComputed() *pluginsdk.Schema {
}
}

type BaseContainer struct {
Name string `tfschema:"name"`
Image string `tfschema:"image"`
CPU float64 `tfschema:"cpu"`
Memory string `tfschema:"memory"`
EphemeralStorage string `tfschema:"ephemeral_storage"`
Env []ContainerEnvVar `tfschema:"env"`
Args []string `tfschema:"args"`
Command []string `tfschema:"command"`
VolumeMounts []ContainerVolumeMount `tfschema:"volume_mounts"`
}

func InitContainerAppContainerSchema() *pluginsdk.Schema {
return &pluginsdk.Schema{
Type: pluginsdk.TypeList,
Optional: true,
MinItems: 1,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validate.ContainerAppContainerName,
Description: "The name of the container.",
},

"image": {
Type: pluginsdk.TypeString,
Required: true,
ValidateFunc: validation.StringIsNotEmpty,
Description: "The image to use to create the container.",
},

"cpu": {
Type: pluginsdk.TypeFloat,
Optional: true,
ValidateFunc: validate.ContainerCpu,
Description: "The amount of vCPU to allocate to the container. Possible values include `0.25`, `0.5`, `0.75`, `1.0`, `1.25`, `1.5`, `1.75`, and `2.0`. **NOTE:** `cpu` and `memory` must be specified in `0.25'/'0.5Gi` combination increments. e.g. `1.0` / `2.0` or `0.5` / `1.0`",
},

"memory": {
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: validation.StringInSlice([]string{
"0.5Gi",
"1Gi",
"1.5Gi",
"2Gi",
"2.5Gi",
"3Gi",
"3.5Gi",
"4Gi",
}, false),
Description: "The amount of memory to allocate to the container. Possible values include `0.5Gi`, `1.0Gi`, `1.5Gi`, `2.0Gi`, `2.5Gi`, `3.0Gi`, `3.5Gi`, and `4.0Gi`. **NOTE:** `cpu` and `memory` must be specified in `0.25'/'0.5Gi` combination increments. e.g. `1.25` / `2.5Gi` or `0.75` / `1.5Gi`",
},

"ephemeral_storage": {
Type: pluginsdk.TypeString,
Computed: true,
Description: "The amount of ephemeral storage available to the Container App.",
},

"env": ContainerEnvVarSchema(),

"args": {
Type: pluginsdk.TypeList,
Optional: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
Description: "A list of args to pass to the container.",
},

"command": {
Type: pluginsdk.TypeList,
Optional: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
Description: "A command to pass to the container to override the default. This is provided as a list of command line elements without spaces.",
},

"volume_mounts": ContainerVolumeMountSchema(),
},
},
}
}

func InitContainerAppContainerSchemaComputed() *pluginsdk.Schema {
return &pluginsdk.Schema{
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Resource{
Schema: map[string]*pluginsdk.Schema{
"name": {
Type: pluginsdk.TypeString,
Computed: true,
Description: "The name of the container.",
},

"image": {
Type: pluginsdk.TypeString,
Computed: true,
Description: "The image to use to create the container.",
},

"cpu": {
Type: pluginsdk.TypeFloat,
Computed: true,
Description: "The amount of vCPU to allocate to the container. Possible values include `0.25`, `0.5`, `0.75`, `1.0`, `1.25`, `1.5`, `1.75`, and `2.0`. **NOTE:** `cpu` and `memory` must be specified in `0.25'/'0.5Gi` combination increments. e.g. `1.0` / `2.0` or `0.5` / `1.0`",
},

"memory": {
Type: pluginsdk.TypeString,
Computed: true,
Description: "The amount of memory to allocate to the container. Possible values include `0.5Gi`, `1.0Gi`, `1.5Gi`, `2.0Gi`, `2.5Gi`, `3.0Gi`, `3.5Gi`, and `4.0Gi`. **NOTE:** `cpu` and `memory` must be specified in `0.25'/'0.5Gi` combination increments. e.g. `1.25` / `2.5Gi` or `0.75` / `1.5Gi`",
},

"ephemeral_storage": {
Type: pluginsdk.TypeString,
Computed: true,
Description: "The amount of ephemeral storage available to the Container App.",
},

"env": ContainerEnvVarSchemaComputed(),

"args": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
Description: "A list of args to pass to the container.",
},

"command": {
Type: pluginsdk.TypeList,
Computed: true,
Elem: &pluginsdk.Schema{
Type: pluginsdk.TypeString,
},
Description: "A command to pass to the container to override the default. This is provided as a list of command line elements without spaces.",
},

"volume_mounts": ContainerVolumeMountSchemaComputed(),
},
},
}
}

func expandInitContainerAppContainers(input []BaseContainer) *[]containerapps.BaseContainer {
if input == nil {
return nil
}

result := make([]containerapps.BaseContainer, 0)
for _, v := range input {
container := containerapps.BaseContainer{
Env: expandInitContainerEnvVar(v),
Image: pointer.To(v.Image),
Name: pointer.To(v.Name),
Resources: &containerapps.ContainerResources{
Cpu: pointer.To(v.CPU),
EphemeralStorage: pointer.To(v.EphemeralStorage),
Memory: pointer.To(v.Memory),
},
VolumeMounts: expandContainerVolumeMounts(v.VolumeMounts),
}
if len(v.Args) != 0 {
container.Args = pointer.To(v.Args)
}
if len(v.Command) != 0 {
container.Command = pointer.To(v.Command)
}

result = append(result, container)
}

return &result
}

func flattenInitContainerAppContainers(input *[]containerapps.BaseContainer) []BaseContainer {
if input == nil || len(*input) == 0 {
return []BaseContainer{}
}
result := make([]BaseContainer, 0)
for _, v := range *input {
container := BaseContainer{
Name: pointer.From(v.Name),
Image: pointer.From(v.Image),
Args: pointer.From(v.Args),
Command: pointer.From(v.Command),
Env: flattenContainerEnvVar(v.Env),
VolumeMounts: flattenContainerVolumeMounts(v.VolumeMounts),
}

if resources := v.Resources; resources != nil {
container.CPU = pointer.From(resources.Cpu)
container.Memory = pointer.From(resources.Memory)
container.EphemeralStorage = pointer.From(resources.EphemeralStorage)
}

result = append(result, container)
}
return result
}

func expandContainerAppContainers(input []Container) *[]containerapps.Container {
if input == nil {
return nil
Expand Down Expand Up @@ -1335,6 +1549,28 @@ func ContainerEnvVarSchemaComputed() *pluginsdk.Schema {
}
}

func expandInitContainerEnvVar(input BaseContainer) *[]containerapps.EnvironmentVar {
envs := make([]containerapps.EnvironmentVar, 0)
if input.Env == nil || len(input.Env) == 0 {
return &envs
}

for _, v := range input.Env {
env := containerapps.EnvironmentVar{
Name: pointer.To(v.Name),
}
if v.SecretReference != "" {
env.SecretRef = pointer.To(v.SecretReference)
} else {
env.Value = pointer.To(v.Value)
}

envs = append(envs, env)
}

return &envs
}

func expandContainerEnvVar(input Container) *[]containerapps.EnvironmentVar {
envs := make([]containerapps.EnvironmentVar, 0)
if input.Env == nil || len(input.Env) == 0 {
Expand Down
24 changes: 24 additions & 0 deletions website/docs/d/container_app.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ A `secret` block supports the following:

A `template` block supports the following:

* `init_container` - One or more `init_container` blocks as detailed below.

* `container` - One or more `container` blocks as detailed below.

* `max_replicas` - The maximum number of replicas for this container.
Expand All @@ -85,6 +87,28 @@ A `volume` block supports the following:

---

A `init_container` block supports the following:

* `args` - A list of extra arguments to pass to the container.

* `command` - A command to pass to the container to override the default. This is provided as a list of command line elements without spaces.

* `cpu` - The amount of vCPU to allocate to the container. Possible values include `0.25`, `0.5`, `0.75`, `1.0`, `1.25`, `1.5`, `1.75`, and `2.0`.

* `env` - One or more `env` blocks as detailed below.

* `ephemeral_storage` - The amount of ephemeral storage available to the Container App.

* `image` - The image to use to create the container.

* `memory` - The amount of memory to allocate to the container. Possible values include `0.5Gi`, `1Gi`, `1.5Gi`, `2Gi`, `2.5Gi`, `3Gi`, `3.5Gi`, and `4Gi`.

* `name` - The name of the container

* `volume_mounts` - A `volume_mounts` block as detailed below.

---

A `container` block supports the following:

* `args` - A list of extra arguments to pass to the container.
Expand Down
30 changes: 30 additions & 0 deletions website/docs/r/container_app.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ A `secret` block supports the following:

A `template` block supports the following:

* `init_container` - (Optional) The definition of an init container that is part of the group as documented in the `init_container` block below.

* `container` - (Required) One or more `container` blocks as detailed below.

* `max_replicas` - (Optional) The maximum number of replicas for this container.
Expand Down Expand Up @@ -177,6 +179,34 @@ A `volume` block supports the following:

---

An `init_container` block supports:

* `args` - (Optional) A list of extra arguments to pass to the container.

* `command` - (Optional) A command to pass to the container to override the default. This is provided as a list of command line elements without spaces.

* `cpu` - (Required) The amount of vCPU to allocate to the container. Possible values include `0.25`, `0.5`, `0.75`, `1.0`, `1.25`, `1.5`, `1.75`, and `2.0`.

~> **NOTE:** `cpu` and `memory` must be specified in `0.25'/'0.5Gi` combination increments. e.g. `1.0` / `2.0` or `0.5` / `1.0`

* `env` - (Optional) One or more `env` blocks as detailed below.

* `ephemeral_storage` - The amount of ephemeral storage available to the Container App.

~> **NOTE:** `ephemeral_storage` is currently in preview and not configurable at this time.

* `image` - (Required) The image to use to create the container.

* `memory` - (Required) The amount of memory to allocate to the container. Possible values are `0.5Gi`, `1Gi`, `1.5Gi`, `2Gi`, `2.5Gi`, `3Gi`, `3.5Gi` and `4Gi`.

~> **NOTE:** `cpu` and `memory` must be specified in `0.25'/'0.5Gi` combination increments. e.g. `1.25` / `2.5Gi` or `0.75` / `1.5Gi`

* `name` - (Required) The name of the container

* `volume_mounts` - (Optional) A `volume_mounts` block as detailed below.

---

A `container` block supports the following:

* `args` - (Optional) A list of extra arguments to pass to the container.
Expand Down

0 comments on commit 88c1055

Please sign in to comment.