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

New Resource: azurerm_container_group #333

Merged
merged 27 commits into from
Sep 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2377474
Merge pull request #1 from terraform-providers/master
Jun 14, 2017
927b5b9
Merge pull request #2 from terraform-providers/master
Aug 22, 2017
a46aec9
Added outline for container group resource.
Aug 30, 2017
2226646
WIP: Container group resource
Sep 3, 2017
c5847c3
WIP: Container group resource
Sep 4, 2017
92ae417
WIP: Container groups resource
Sep 5, 2017
89fdeca
WIP Container Instance Resource: basic works.
Sep 5, 2017
b66ae9b
Merge pull request #3 from terraform-providers/master
Sep 5, 2017
1a91933
Merge branch 'aci-dev' into master
Sep 5, 2017
a1365c7
WIP Container groups resource - formatting changes.
Sep 5, 2017
51356a4
WIP Container Groups resource
Sep 6, 2017
b95a618
WIP Container groups resource
Sep 6, 2017
b9e3297
WIP Container Group Resource
Sep 6, 2017
215a9f2
Merge from upstream
Sep 6, 2017
3274477
Merge branch 'terraform-providers-master'
Sep 6, 2017
db826d9
Merge pull request #6 from abhijeetgaiha/aci-dev
Sep 6, 2017
ad6b4ec
WIP Container Groups Provider: Added Basic Tests
Sep 7, 2017
8ad469b
WIP Container Groups Resource : Added docs
Sep 7, 2017
c69bd1d
WIP: Container groups resource.
Sep 11, 2017
e27b424
Removing ability to update using create/recreate.
Sep 12, 2017
caf0765
Changes based on review feedback.
Sep 14, 2017
5f1688f
Fixed error in test.
Sep 14, 2017
d685d2a
Small updates to schema.
Sep 14, 2017
03d2678
Changes based on review feedback.
Sep 14, 2017
e07edaf
Allowing updates through ForceNew.
Sep 14, 2017
6ab2d97
Changes due to review feedback
Sep 14, 2017
ecd99fc
Adding an acceptance test covering updating containers
tombuildsstuff Sep 14, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions azurerm/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/Azure/azure-sdk-for-go/arm/appinsights"
"github.com/Azure/azure-sdk-for-go/arm/cdn"
"github.com/Azure/azure-sdk-for-go/arm/compute"
"github.com/Azure/azure-sdk-for-go/arm/containerinstance"
"github.com/Azure/azure-sdk-for-go/arm/containerregistry"
"github.com/Azure/azure-sdk-for-go/arm/containerservice"
"github.com/Azure/azure-sdk-for-go/arm/cosmos-db"
Expand Down Expand Up @@ -85,6 +86,7 @@ type ArmClient struct {

containerRegistryClient containerregistry.RegistriesClient
containerServicesClient containerservice.ContainerServicesClient
containerGroupsClient containerinstance.ContainerGroupsClient

eventGridTopicsClient eventgrid.TopicsClient
eventHubClient eventhub.EventHubsClient
Expand Down Expand Up @@ -293,6 +295,12 @@ func (c *Config) getArmClient() (*ArmClient, error) {
csc.Sender = autorest.CreateSender(withRequestLogging())
client.containerServicesClient = csc

cgc := containerinstance.NewContainerGroupsClientWithBaseURI(endpoint, c.SubscriptionID)
setUserAgent(&cgc.Client)
cgc.Authorizer = auth
cgc.Sender = autorest.CreateSender(withRequestLogging())
client.containerGroupsClient = cgc

cdb := cosmosdb.NewDatabaseAccountsClientWithBaseURI(endpoint, c.SubscriptionID)
setUserAgent(&cdb.Client)
cdb.Authorizer = auth
Expand Down
3 changes: 2 additions & 1 deletion azurerm/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func Provider() terraform.ResourceProvider {
"azurerm_cdn_profile": resourceArmCdnProfile(),
"azurerm_container_registry": resourceArmContainerRegistry(),
"azurerm_container_service": resourceArmContainerService(),
"azurerm_container_group": resourceArmContainerGroup(),
"azurerm_cosmosdb_account": resourceArmCosmosDBAccount(),
"azurerm_dns_a_record": resourceArmDnsARecord(),
"azurerm_dns_aaaa_record": resourceArmDnsAAAARecord(),
Expand Down Expand Up @@ -246,6 +247,7 @@ func determineAzureResourceProvidersToRegister(providerList []resources.Provider
"Microsoft.Cache": {},
"Microsoft.Cdn": {},
"Microsoft.Compute": {},
"Microsoft.ContainerInstance": {},
"Microsoft.ContainerRegistry": {},
"Microsoft.ContainerService": {},
"Microsoft.DBforPostgreSQL": {},
Expand Down Expand Up @@ -284,7 +286,6 @@ func determineAzureResourceProvidersToRegister(providerList []resources.Provider
func registerAzureResourceProvidersWithSubscription(providerList []resources.Provider, client resources.ProvidersClient) error {
var err error
providerRegistrationOnce.Do(func() {

providers := determineAzureResourceProvidersToRegister(providerList)

var wg sync.WaitGroup
Expand Down
328 changes: 328 additions & 0 deletions azurerm/resource_arm_container_group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,328 @@
package azurerm

import (
"fmt"
"strings"

"github.com/Azure/azure-sdk-for-go/arm/containerinstance"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
"github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils"
)

func resourceArmContainerGroup() *schema.Resource {
return &schema.Resource{
Create: resourceArmContainerGroupCreate,
Read: resourceArmContainerGroupRead,
Delete: resourceArmContainerGroupDelete,

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"location": locationSchema(),

"resource_group_name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"ip_address_type": {
Type: schema.TypeString,
Optional: true,
Default: "Public",
ForceNew: true,
DiffSuppressFunc: ignoreCaseDiffSuppressFunc,
ValidateFunc: validation.StringInSlice([]string{
"Public",
}, true),
},

"os_type": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
DiffSuppressFunc: ignoreCaseDiffSuppressFunc,
ValidateFunc: validation.StringInSlice([]string{
"windows",
"linux",
}, true),
},

"tags": tagsForceNewSchema(),

"ip_address": {
Type: schema.TypeString,
Computed: true,
},

"container": {
Type: schema.TypeList,
Required: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"image": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"cpu": {
Type: schema.TypeFloat,
Required: true,
ForceNew: true,
},

"memory": {
Type: schema.TypeFloat,
Required: true,
ForceNew: true,
},

"port": {
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
ValidateFunc: validation.IntBetween(1, 65535),
},

"protocol": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
DiffSuppressFunc: ignoreCaseDiffSuppressFunc,
ValidateFunc: validation.StringInSlice([]string{
"tcp",
"udp",
}, true),
},

"env_var": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"value": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
},
},
},
},
},
},
},
},
}
}

func resourceArmContainerGroupCreate(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
containerGroupsClient := client.containerGroupsClient

// container group properties
resGroup := d.Get("resource_group_name").(string)
name := d.Get("name").(string)
location := d.Get("location").(string)
OSType := d.Get("os_type").(string)
IPAddressType := d.Get("ip_address_type").(string)
tags := d.Get("tags").(map[string]interface{})

containers, containerGroupPorts := expandContainerGroupContainers(d)

containerGroup := containerinstance.ContainerGroup{
Name: &name,
Location: &location,
Tags: expandTags(tags),
ContainerGroupProperties: &containerinstance.ContainerGroupProperties{
Containers: containers,
IPAddress: &containerinstance.IPAddress{
Type: &IPAddressType,
Ports: containerGroupPorts,
},
OsType: containerinstance.OperatingSystemTypes(OSType),
},
}

_, err := containerGroupsClient.CreateOrUpdate(resGroup, name, containerGroup)
if err != nil {
return err
}

read, err := containerGroupsClient.Get(resGroup, name)
if err != nil {
return err
}

if read.ID == nil {
return fmt.Errorf("Cannot read container group %s (resource group %s) ID", name, resGroup)
}

d.SetId(*read.ID)

return resourceArmContainerGroupRead(d, meta)
}
func resourceArmContainerGroupRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
containterGroupsClient := client.containerGroupsClient

id, err := parseAzureResourceID(d.Id())

if err != nil {
return err
}

resGroup := id.ResourceGroup
name := id.Path["containerGroups"]

resp, err := containterGroupsClient.Get(resGroup, name)

if err != nil {
return err
}

d.Set("name", name)
d.Set("resource_group_name", resGroup)
d.Set("location", azureRMNormalizeLocation(*resp.Location))
flattenAndSetTags(d, resp.Tags)

d.Set("os_type", string(resp.OsType))
if address := resp.IPAddress; address != nil {
d.Set("ip_address_type", address.Type)
d.Set("ip_address", address.IP)
}

containerConfigs := flattenContainerGroupContainers(resp.Containers)
err = d.Set("container", containerConfigs)
if err != nil {
return fmt.Errorf("Error setting `container`: %+v", err)
}

return nil
}

func resourceArmContainerGroupDelete(d *schema.ResourceData, meta interface{}) error {
client := meta.(*ArmClient)
containterGroupsClient := client.containerGroupsClient

id, err := parseAzureResourceID(d.Id())

if err != nil {
return err
}

// container group properties
resGroup := id.ResourceGroup
name := id.Path["containerGroups"]

resp, err := containterGroupsClient.Delete(resGroup, name)
if err != nil {
if utils.ResponseWasNotFound(resp.Response) {
return nil
}
return err
}

return nil
}

func flattenContainerGroupContainers(containers *[]containerinstance.Container) []interface{} {

containerConfigs := make([]interface{}, 0, len(*containers))
for _, container := range *containers {
containerConfig := make(map[string]interface{})
containerConfig["name"] = *container.Name
containerConfig["image"] = *container.Image

if resources := container.Resources; resources != nil {
if resourceRequests := resources.Requests; resourceRequests != nil {
containerConfig["cpu"] = *resourceRequests.CPU
containerConfig["memory"] = *resourceRequests.MemoryInGB
}
}

if len(*container.Ports) > 0 {
containerConfig["port"] = *(*container.Ports)[0].Port
}
// protocol isn't returned in container config

containerConfigs = append(containerConfigs, containerConfig)
}

return containerConfigs
}

func expandContainerGroupContainers(d *schema.ResourceData) (*[]containerinstance.Container, *[]containerinstance.Port) {
containersConfig := d.Get("container").([]interface{})
containers := make([]containerinstance.Container, 0, len(containersConfig))
containerGroupPorts := make([]containerinstance.Port, 0, len(containersConfig))

for _, containerConfig := range containersConfig {
data := containerConfig.(map[string]interface{})

// required
name := data["name"].(string)
image := data["image"].(string)
cpu := data["cpu"].(float64)
memory := data["memory"].(float64)

container := containerinstance.Container{
Name: &name,
ContainerProperties: &containerinstance.ContainerProperties{
Image: &image,
Resources: &containerinstance.ResourceRequirements{
Requests: &containerinstance.ResourceRequests{
MemoryInGB: &memory,
CPU: &cpu,
},
},
},
}

if v, _ := data["port"]; v != 0 {
port := int32(v.(int))

// container port (port number)
containerPort := containerinstance.ContainerPort{
Port: &port,
}

container.Ports = &[]containerinstance.ContainerPort{containerPort}

// container group port (port number + protocol)
containerGroupPort := containerinstance.Port{
Port: &port,
}

if v, ok := data["protocol"]; ok {
protocol := v.(string)
containerGroupPort.Protocol = containerinstance.ContainerGroupNetworkProtocol(strings.ToUpper(protocol))
}

containerGroupPorts = append(containerGroupPorts, containerGroupPort)
}

containers = append(containers, container)
}

return &containers, &containerGroupPorts
}
Loading