-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implementation of Azure container groups #311
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @abhijeetgaiha
Thanks for this PR :)
I've taken a look through and left some comments in-line, but this is off to a good start :)
Thanks!
"ip_address_type": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
DiffSuppressFunc: ignoreCaseDiffSuppressFunc, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm assuming there's a limited set of options here? if so - could we add some validation to this, e.g.
ValidateFunc: validation.StringInSlice([]string{
"foo",
"bar",
}, true)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(as below) we should be able to make this Optional
and Default: "Public"
given `Public" is the only option at this time, which would mean users don't need to specify it :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Schema: map[string]*schema.Schema{ | ||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this also needs to be ForceNew
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
"resource_group_name": { | ||
Type: schema.TypeString, | ||
Required: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this also needs to be ForceNew
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
"os_type": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
DiffSuppressFunc: ignoreCaseDiffSuppressFunc, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm assuming there's a limited set of options here? if so - could we add some validation to this, e.g.
ValidateFunc: validation.StringInSlice([]string{
"foo",
"bar",
}, true)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
} | ||
|
||
_, error := containerGroupsClient.CreateOrUpdate(resGroup, name, containerGroup) | ||
if error != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor can we swap error
out for err
to match the other resources?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
} | ||
``` | ||
|
||
## Example Usage (Windows) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given the only difference between these two is the OS field - I think we can just use the Linux example (and just rename that to Example Usage
)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've updated the linux example to use two containers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we consolidate this into a single example, as they're fundamentally the same (compared to say Container Service in which some fields aren't valid for a non-Kubernetes cluster)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you mean two container groups in one file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was referring to picking either the Windows or the Linux example and removing the other (since they're virtually the same)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
* `location` - (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. Changing this forces a new resource to be created. | ||
|
||
* `ip_address_type` - (Required) Specifies the ip address type of the container. `public` is the only acceptable value at this time. Changing this forces a new resource to be created. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is the only acceptable value at this time, we can make this field Optional
and Default
it to Public
for the moment - so users don't have to specify it (in the schema)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
The following attributes are exported: | ||
|
||
* `ip_address` - The IP address allocated to the container group. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there's also the ID of the container group as id
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
"container": { | ||
Type: schema.TypeList, | ||
Required: true, | ||
Elem: &schema.Resource{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given only a single container's currently supported - can we add MaxItems: 1
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, more than 1 container is supported for Linux. Updated docs.
|
||
"name": { | ||
Type: schema.TypeString, | ||
Required: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these are marked as ForceNew
in the documentation below - if so, can we add ForceNew: true
to all of these fields in the container
group?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might have missed it, but I can't see these changes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I fixed the docs. This shouldn't force the whole group to be updated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
ValidateFunc: validation.StringInSlice([]string{ | ||
"tcp", | ||
"udp", | ||
}, true), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given the validation function allows for differences in case (the true
) can we add a DiffSuppressFunc
to this to ignore the case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
IPAddressType := d.Get("ip_address_type").(string) | ||
tags := d.Get("tags").(map[string]interface{}) | ||
|
||
containersConfig := d.Get("container").([]interface{}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we pull all of this out into a separate function expandContainerGroupContainers
which returns the deserialized object?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
}, | ||
} | ||
|
||
if port != 0 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given this is an Optional
field, we should be able to do this instead:
if v, ok := data["port"]; ok {
...
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Port: &port, | ||
} | ||
|
||
if protocol != "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(same as for port) for the Protocol field
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
// envVarsList = append(envVarsList, envVar) | ||
// } | ||
// container.EnvironmentVariables = &envVarsList | ||
// } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we remove this, since it's not being used?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
_, err = containterGroupsClient.Delete(resGroup, name) | ||
|
||
if err != nil { | ||
return err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we check for both a 404 and a dropped connection before throwing an error? we can do this via:
resp, err = containterGroupsClient.Delete(resGroup, name)
if err != nil && !utils.ResponseWasNotFound(resp) {
return nil
}
return nil
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
resource "azurerm_container_group" "test" { | ||
|
||
name = "acctestcontainergroup-%d" | ||
location = "%s" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rather than threading this through in multiple places, can we update this to "${azurerm_resource_group.test.location}"
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
resource "azurerm_container_group" "test" { | ||
|
||
name = "acctestcontainergroup-%d" | ||
location = "%s" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
rather than threading this through in multiple places, can we update this to "${azurerm_resource_group.test.location}"
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
examples/aci-linux-multi/main.tf
Outdated
|
||
resource "azurerm_container_group" "aci-test" { | ||
name = "mynginx" | ||
location = "west us" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor since Location is available on the Resource Group resource, could we update this to "${azurerm_resource_group.aci-rg.location}"
to keep it a little DRY-er?, rather than in each resource? (I'm slowly working through the documentation for each resource to show this)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
resource "azurerm_container_group" "winapp" { | ||
|
||
name = "mywinapp" | ||
location = "west us" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor can we update this to be "${azurerm_resource_group.aci-rg.location}"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed the windows example.
resource "azurerm_container_group" "aci-helloworld" { | ||
|
||
name = "aci-hw" | ||
location = "west us" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor can we update this to be "${azurerm_resource_group.aci-rg.location}"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
* `os_type` - (Required) The OS for the container group. Allowed values are `linux` and `windows` Changing this forces a new resource to be created. | ||
|
||
* `container` - (Required) The definition of a container that is part of the group. Currently, only single containers are supported for Windows OS and multiple containers are supported for Linux OS. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We'd tend to phrase this as:
A `container` block as defined below.
~> **Note:** if `os_type` is set to `Windows` currently only a single container block is supported
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
The `container` block supports: | ||
|
||
* `name` - (Required) Specifies the name of the Container. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we suffix this with "Changing this value forces a new resource to be created"?
|
||
* `name` - (Required) Specifies the name of the Container. | ||
|
||
* `image` - (Required) The container image name. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we suffix this with "Changing this value forces a new resource to be created"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
* `image` - (Required) The container image name. | ||
|
||
* `cpu` - (Required) The required number of CPU cores of the containers. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we suffix this with "Changing this value forces a new resource to be created"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
* `cpu` - (Required) The required number of CPU cores of the containers. | ||
|
||
* `memory` - (Required) The required memory of the containers in GB. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we suffix this with "Changing this value forces a new resource to be created"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
|
||
* `memory` - (Required) The required memory of the containers in GB. | ||
|
||
* `port` - (Optional) A public port for the container. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we suffix this with "Changing this value forces a new resource to be created"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few minor points - but this otherwise LGTM (I'm just running the tests now :)
"ip_address": { | ||
Type: schema.TypeString, | ||
Computed: true, | ||
ForceNew: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
given this is Computed, it doesn't need to be ForceNew - so we can remove this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
} | ||
|
||
containerConfigs := flattenContainerGroupContainers(resp.Containers) | ||
d.Set("container", containerConfigs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor given this is setting a complex object, could we update this too:
containerConfigs := flattenContainerGroupContainers(resp.Containers)
if err = d.Set("container", containerConfigs) {
return fmt.Errorf("Error setting `container`: %+v", err)
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
containerConfig["name"] = *container.Name | ||
containerConfig["image"] = *container.Image | ||
|
||
resourceRequests := *(*container.Resources).Requests |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could we add an if
check around this to avoid Swagger/API issues? i.e.
if resources := container.Resources; resources != nil {
if resourceRequests := resources.Requests; resourceRequests != nil {
# ...
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The API will always return these values. Changing just in case.
|
||
if v, ok := data["protocol"]; ok { | ||
protocol := v.(string) | ||
containerGroupPort.Protocol = containerinstance.ContainerGroupNetworkProtocol(strings.ToUpper(protocol)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this actually need to be strings.ToUpper
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's needed as the ContainerGroupNetworkProtocol enum is composed of only all uppercase strings.
6ab2d97
to
c357dcd
Compare
Hey @abhijeetgaiha Sorry, I've unintentionally closed this by force-pushing the changes we discussed (to add an update test).. :( I'll re-open this in a separate PT (which will keep your commits) |
I'm going to lock this issue because it has been closed for 30 days ⏳. This helps our maintainers find and focus on the active issues. If you feel this issue should be reopened, we encourage creating a new issue linking back to this one for added context. If you feel I made an error 🤖 🙉 , please reach out to my human friends 👉 hashibot-feedback@hashicorp.com. Thanks! |
This has a basic implementation for #287 .
The following features are TBD: