Skip to content
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

resource/container_group: add registry credential #1529

Merged
merged 7 commits into from Jul 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
91 changes: 89 additions & 2 deletions azurerm/resource_arm_container_group.go
Expand Up @@ -49,6 +49,37 @@ func resourceArmContainerGroup() *schema.Resource {
}, true),
},

"image_registry_credential": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"server": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.NoZeroValues,
ForceNew: true,
},

"username": {
Type: schema.TypeString,
Required: true,
ValidateFunc: validation.NoZeroValues,
ForceNew: true,
},

"password": {
Type: schema.TypeString,
Required: true,
Sensitive: true,
ValidateFunc: validation.NoZeroValues,
ForceNew: true,
},
},
},
},

"tags": tagsForceNewSchema(),

"restart_policy": {
Expand Down Expand Up @@ -218,8 +249,9 @@ func resourceArmContainerGroupCreate(d *schema.ResourceData, meta interface{}) e
Type: &IPAddressType,
Ports: containerGroupPorts,
},
OsType: containerinstance.OperatingSystemTypes(OSType),
Volumes: containerGroupVolumes,
OsType: containerinstance.OperatingSystemTypes(OSType),
Volumes: containerGroupVolumes,
ImageRegistryCredentials: expandContainerImageRegistryCredentials(d),
},
}

Expand Down Expand Up @@ -277,6 +309,10 @@ func resourceArmContainerGroupRead(d *schema.ResourceData, meta interface{}) err
}
flattenAndSetTags(d, resp.Tags)

if err := d.Set("image_registry_credential", flattenContainerImageRegistryCredentials(d, resp.ImageRegistryCredentials)); err != nil {
return fmt.Errorf("Error setting `capabilities`: %+v", err)
}

d.Set("os_type", string(resp.OsType))
if address := resp.IPAddress; address != nil {
d.Set("ip_address_type", address.Type)
Expand Down Expand Up @@ -531,6 +567,57 @@ func expandContainerEnvironmentVariables(input interface{}) *[]containerinstance
return &output
}

func expandContainerImageRegistryCredentials(d *schema.ResourceData) *[]containerinstance.ImageRegistryCredential {
credsRaw := d.Get("image_registry_credential").([]interface{})
if len(credsRaw) == 0 {
return nil
}

output := make([]containerinstance.ImageRegistryCredential, 0, len(credsRaw))

for _, c := range credsRaw {
credConfig := c.(map[string]interface{})

output = append(output, containerinstance.ImageRegistryCredential{
Server: utils.String(credConfig["server"].(string)),
Password: utils.String(credConfig["password"].(string)),
Username: utils.String(credConfig["username"].(string)),
})
}

return &output
}

func flattenContainerImageRegistryCredentials(d *schema.ResourceData, credsPtr *[]containerinstance.ImageRegistryCredential) []interface{} {
if credsPtr == nil {
return nil
}
configsOld := d.Get("image_registry_credential").([]interface{})

creds := *credsPtr
output := make([]interface{}, 0, len(creds))
for i, cred := range creds {
credConfig := make(map[string]interface{})
if cred.Server != nil {
credConfig["server"] = *cred.Server
}
if cred.Username != nil {
credConfig["username"] = *cred.Username
}

data := configsOld[i].(map[string]interface{})
oldServer := data["server"].(string)
if cred.Server != nil && *cred.Server == oldServer {
if v, ok := d.GetOk(fmt.Sprintf("image_registry_credential.%d.password", i)); ok {
credConfig["password"] = v.(string)
}
}

output = append(output, credConfig)
}
return output
}

func expandContainerVolumes(input interface{}) (*[]containerinstance.VolumeMount, *[]containerinstance.Volume) {
volumesRaw := input.([]interface{})

Expand Down
157 changes: 157 additions & 0 deletions azurerm/resource_arm_container_group_test.go
Expand Up @@ -11,6 +11,73 @@ import (
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func TestAccAzureRMContainerGroup_imageRegistryCredentials(t *testing.T) {
resourceName := "azurerm_container_group.test"
ri := acctest.RandInt()

config := testAccAzureRMContainerGroup_imageRegistryCredentials(ri, testLocation())

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMContainerGroupDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMContainerGroupExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "image_registry_credential.#", "2"),
resource.TestCheckResourceAttr(resourceName, "image_registry_credential.0.server", "hub.docker.com"),
resource.TestCheckResourceAttr(resourceName, "image_registry_credential.0.username", "yourusername"),
resource.TestCheckResourceAttr(resourceName, "image_registry_credential.0.password", "yourpassword"),
resource.TestCheckResourceAttr(resourceName, "image_registry_credential.1.server", "mine.acr.io"),
resource.TestCheckResourceAttr(resourceName, "image_registry_credential.1.username", "acrusername"),
resource.TestCheckResourceAttr(resourceName, "image_registry_credential.1.password", "acrpassword"),
),
},
},
})
}

func TestAccAzureRMContainerGroup_imageRegistryCredentialsUpdate(t *testing.T) {
resourceName := "azurerm_container_group.test"
ri := acctest.RandInt()

config := testAccAzureRMContainerGroup_imageRegistryCredentials(ri, testLocation())
updated := testAccAzureRMContainerGroup_imageRegistryCredentialsUpdated(ri, testLocation())

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testCheckAzureRMContainerGroupDestroy,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMContainerGroupExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "image_registry_credential.#", "2"),
resource.TestCheckResourceAttr(resourceName, "image_registry_credential.0.server", "hub.docker.com"),
resource.TestCheckResourceAttr(resourceName, "image_registry_credential.0.username", "yourusername"),
resource.TestCheckResourceAttr(resourceName, "image_registry_credential.0.password", "yourpassword"),
resource.TestCheckResourceAttr(resourceName, "image_registry_credential.1.server", "mine.acr.io"),
resource.TestCheckResourceAttr(resourceName, "image_registry_credential.1.username", "acrusername"),
resource.TestCheckResourceAttr(resourceName, "image_registry_credential.1.password", "acrpassword"),
),
},
{
Config: updated,
Check: resource.ComposeTestCheckFunc(
testCheckAzureRMContainerGroupExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "image_registry_credential.#", "1"),
resource.TestCheckResourceAttr(resourceName, "image_registry_credential.0.server", "hub.docker.com"),
resource.TestCheckResourceAttr(resourceName, "image_registry_credential.0.username", "updatedusername"),
resource.TestCheckResourceAttr(resourceName, "image_registry_credential.0.password", "updatedpassword"),
),
},
},
})
}

func TestAccAzureRMContainerGroup_linuxBasic(t *testing.T) {
resourceName := "azurerm_container_group.test"
ri := acctest.RandInt()
Expand Down Expand Up @@ -176,6 +243,96 @@ resource "azurerm_container_group" "test" {
`, ri, location, ri)
}

func testAccAzureRMContainerGroup_imageRegistryCredentials(ri int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}

resource "azurerm_container_group" "test" {
name = "acctestcontainergroup-%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
ip_address_type = "public"
os_type = "linux"

container {
name = "hw"
image = "microsoft/aci-helloworld:latest"
cpu = "0.5"
memory = "0.5"
port = "80"
}

image_registry_credential {
server = "hub.docker.com"
username = "yourusername"
password = "yourpassword"
}

image_registry_credential {
server = "mine.acr.io"
username = "acrusername"
password = "acrpassword"
}

container {
name = "sidecar"
image = "microsoft/aci-tutorial-sidecar"
cpu = "0.5"
memory = "0.5"
}

tags {
environment = "Testing"
}
}
`, ri, location, ri)
}

func testAccAzureRMContainerGroup_imageRegistryCredentialsUpdated(ri int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
name = "acctestRG-%d"
location = "%s"
}

resource "azurerm_container_group" "test" {
name = "acctestcontainergroup-%d"
location = "${azurerm_resource_group.test.location}"
resource_group_name = "${azurerm_resource_group.test.name}"
ip_address_type = "public"
os_type = "linux"

container {
name = "hw"
image = "microsoft/aci-helloworld:latest"
cpu = "0.5"
memory = "0.5"
port = "80"
}

image_registry_credential {
server = "hub.docker.com"
username = "updatedusername"
password = "updatedpassword"
}

container {
name = "sidecar"
image = "microsoft/aci-tutorial-sidecar"
cpu = "0.5"
memory = "0.5"
}

tags {
environment = "Testing"
}
}
`, ri, location, ri)
}

func testAccAzureRMContainerGroup_linuxBasicUpdated(ri int, location string) string {
return fmt.Sprintf(`
resource "azurerm_resource_group" "test" {
Expand Down
43 changes: 43 additions & 0 deletions examples/aci-image-registry-credentials/main.tf
@@ -0,0 +1,43 @@
resource "azurerm_resource_group" "aci-rg" {
name = "aci-test-creds"
location = "west us"
}

resource "azurerm_container_group" "aci-test" {
name = "my-aci-hw"
location = "${azurerm_resource_group.aci-rg.location}"
resource_group_name = "${azurerm_resource_group.aci-rg.name}"
ip_address_type = "public"
os_type = "linux"

image_registry_credential {
server = "hub.docker.com"
username = "yourusername1"
password = "yourpassword"
}

image_registry_credential {
server = "2hub.docker.com"
username = "2yourusername1"
password = "2yourpassword"
}

container {
name = "hw"
image = "microsoft/aci-helloworld:latest"
cpu = "0.5"
memory = "1.5"
port = "80"
}

container {
name = "sidecar"
image = "microsoft/aci-tutorial-sidecar"
cpu = "0.5"
memory = "1.5"
}

tags {
environment = "testing"
}
}
10 changes: 10 additions & 0 deletions website/docs/r/container_group.html.markdown
Expand Up @@ -99,6 +99,8 @@ The following arguments are supported:

* `restart_policy` - (Optional) Restart policy for the container group. Allowed values are `Always`, `Never`, `OnFailure`. Defaults to `Always`.

* `image_registry_credential` - (Optional) Set image registry credentials for the group as documented in the `image_registry_credential` block below

* `container` - (Required) The definition of a container that is part of the group as documented in the `container` block below. Changing this forces a new resource to be created.

~> **Note:** if `os_type` is set to `Windows` currently only a single `container` block is supported.
Expand Down Expand Up @@ -135,6 +137,14 @@ The `volume` block supports:

* `share_name` - (Required) The Azure storage share that is to be mounted as a volume. This must be created on the storage account specified as above. Changing this forces a new resource to be created.

The `image_registry_credential` block supports:

* `username` - (Required) The username with which to connect to the registry.

* `password` - (Required) The password with which to connect to the registry.

* `server` - (Required) The address to use to connect to the registry without protocol ("https"/"http"). For example: "myacr.acr.io"

## Attributes Reference

The following attributes are exported:
Expand Down