diff --git a/azurerm/data_source_batch_pool.go b/azurerm/data_source_batch_pool.go index 1577b0e3d7a1..6f59df0fe306 100644 --- a/azurerm/data_source_batch_pool.go +++ b/azurerm/data_source_batch_pool.go @@ -110,6 +110,18 @@ func dataSourceArmBatchPool() *schema.Resource { Type: schema.TypeString, Computed: true, }, + "container_configuration": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, "certificate": { Type: schema.TypeList, Optional: true, @@ -274,14 +286,20 @@ func dataSourceArmBatchPoolRead(d *schema.ResourceData, meta interface{}) error } } - if props.DeploymentConfiguration != nil && - props.DeploymentConfiguration.VirtualMachineConfiguration != nil && - props.DeploymentConfiguration.VirtualMachineConfiguration.ImageReference != nil { + if dcfg := props.DeploymentConfiguration; dcfg != nil { + if vmcfg := dcfg.VirtualMachineConfiguration; vmcfg != nil { + if err := d.Set("container_configuration", azure.FlattenBatchPoolContainerConfiguration(vmcfg.ContainerConfiguration)); err != nil { + return fmt.Errorf("error setting `container_configuration`: %v", err) + } - imageReference := props.DeploymentConfiguration.VirtualMachineConfiguration.ImageReference + if err := d.Set("storage_image_reference", azure.FlattenBatchPoolImageReference(vmcfg.ImageReference)); err != nil { + return fmt.Errorf("error setting `storage_image_reference`: %v", err) + } - d.Set("storage_image_reference", azure.FlattenBatchPoolImageReference(imageReference)) - d.Set("node_agent_sku_id", props.DeploymentConfiguration.VirtualMachineConfiguration.NodeAgentSkuID) + if err := d.Set("node_agent_sku_id", vmcfg.NodeAgentSkuID); err != nil { + return fmt.Errorf("error setting `node_agent_sku_id`: %v", err) + } + } } if err := d.Set("certificate", azure.FlattenBatchPoolCertificateReferences(props.Certificates)); err != nil { diff --git a/azurerm/data_source_batch_pool_test.go b/azurerm/data_source_batch_pool_test.go index f1b6b8033d71..d21ee83d67af 100644 --- a/azurerm/data_source_batch_pool_test.go +++ b/azurerm/data_source_batch_pool_test.go @@ -29,9 +29,9 @@ func TestAccDataSourceAzureRMBatchPool_complete(t *testing.T) { resource.TestCheckResourceAttr(dataSourceName, "account_name", fmt.Sprintf("testaccbatch%s", rs)), resource.TestCheckResourceAttr(dataSourceName, "vm_size", "STANDARD_A1"), resource.TestCheckResourceAttr(dataSourceName, "storage_image_reference.#", "1"), - resource.TestCheckResourceAttr(dataSourceName, "storage_image_reference.0.publisher", "Canonical"), - resource.TestCheckResourceAttr(dataSourceName, "storage_image_reference.0.sku", "16.04.0-LTS"), - resource.TestCheckResourceAttr(dataSourceName, "storage_image_reference.0.offer", "UbuntuServer"), + resource.TestCheckResourceAttr(dataSourceName, "storage_image_reference.0.publisher", "microsoft-azure-batch"), + resource.TestCheckResourceAttr(dataSourceName, "storage_image_reference.0.sku", "16-04-lts"), + resource.TestCheckResourceAttr(dataSourceName, "storage_image_reference.0.offer", "ubuntu-server-container"), resource.TestCheckResourceAttr(dataSourceName, "fixed_scale.#", "1"), resource.TestCheckResourceAttr(dataSourceName, "fixed_scale.0.target_dedicated_nodes", "2"), resource.TestCheckResourceAttr(dataSourceName, "fixed_scale.0.resize_timeout", "PT15M"), @@ -53,6 +53,7 @@ func TestAccDataSourceAzureRMBatchPool_complete(t *testing.T) { resource.TestCheckResourceAttr(dataSourceName, "certificate.0.visibility.#", "2"), resource.TestCheckResourceAttr(dataSourceName, "certificate.0.visibility.3294600504", "StartTask"), resource.TestCheckResourceAttr(dataSourceName, "certificate.0.visibility.4077195354", "RemoteUser"), + resource.TestCheckResourceAttr(dataSourceName, "container_configuration.0.type", "DockerCompatible"), ), }, }, @@ -111,9 +112,9 @@ resource "azurerm_batch_pool" "test" { } storage_image_reference { - publisher = "Canonical" - offer = "UbuntuServer" - sku = "16.04.0-LTS" + publisher = "microsoft-azure-batch" + offer = "ubuntu-server-container" + sku = "16-04-lts" version = "latest" } @@ -122,6 +123,10 @@ resource "azurerm_batch_pool" "test" { store_location = "CurrentUser" visibility = [ "StartTask", "RemoteUser" ] } + + container_configuration { + type = "DockerCompatible" + } start_task { command_line = "echo 'Hello World from $env'" diff --git a/azurerm/helpers/azure/batch_pool.go b/azurerm/helpers/azure/batch_pool.go index 7bce4d14c7fa..967e88b3db01 100644 --- a/azurerm/helpers/azure/batch_pool.go +++ b/azurerm/helpers/azure/batch_pool.go @@ -191,6 +191,22 @@ func FlattenBatchPoolCertificateReferences(armCertificates *[]batch.CertificateR return output } +// FlattenBatchPoolContainerConfiguration flattens a Batch pool container configuration +func FlattenBatchPoolContainerConfiguration(armContainerConfiguration *batch.ContainerConfiguration) interface{} { + + result := make(map[string]interface{}) + + if armContainerConfiguration == nil { + return nil + } + + if armContainerConfiguration.Type != nil { + result["type"] = *armContainerConfiguration.Type + } + + return []interface{}{result} +} + // ExpandBatchPoolImageReference expands Batch pool image reference func ExpandBatchPoolImageReference(list []interface{}) (*batch.ImageReference, error) { if len(list) == 0 { @@ -214,6 +230,22 @@ func ExpandBatchPoolImageReference(list []interface{}) (*batch.ImageReference, e return imageRef, nil } +// ExpandBatchPoolContainerConfiguration expands the Batch pool container configuration +func ExpandBatchPoolContainerConfiguration(list []interface{}) (*batch.ContainerConfiguration, error) { + if len(list) == 0 { + return nil, nil + } + + containerConfiguration := list[0].(map[string]interface{}) + containerType := containerConfiguration["type"].(string) + + containerConf := &batch.ContainerConfiguration{ + Type: &containerType, + } + + return containerConf, nil +} + // ExpandBatchPoolCertificateReferences expands Batch pool certificate references func ExpandBatchPoolCertificateReferences(list []interface{}) (*[]batch.CertificateReference, error) { result := []batch.CertificateReference{} diff --git a/azurerm/resource_arm_batch_pool.go b/azurerm/resource_arm_batch_pool.go index ca5bf0107608..4fd5cad8f62f 100644 --- a/azurerm/resource_arm_batch_pool.go +++ b/azurerm/resource_arm_batch_pool.go @@ -113,6 +113,20 @@ func resourceArmBatchPool() *schema.Resource { }, }, }, + "container_configuration": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "type": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validate.NoEmptyStrings, + }, + }, + }, + }, "storage_image_reference": { Type: schema.TypeList, Required: true, @@ -385,10 +399,17 @@ func resourceArmBatchPoolCreate(d *schema.ResourceData, meta interface{}) error parameters.PoolProperties.StartTask = startTask } + containerConfigurationSet := d.Get("container_configuration").([]interface{}) + containerConfiguration, err := azure.ExpandBatchPoolContainerConfiguration(containerConfigurationSet) + if err != nil { + return fmt.Errorf("Error creating Batch pool %q (Resource Group %q): %+v", poolName, resourceGroup, err) + } + parameters.PoolProperties.DeploymentConfiguration = &batch.DeploymentConfiguration{ VirtualMachineConfiguration: &batch.VirtualMachineConfiguration{ - NodeAgentSkuID: &nodeAgentSkuID, - ImageReference: imageReference, + NodeAgentSkuID: &nodeAgentSkuID, + ImageReference: imageReference, + ContainerConfiguration: containerConfiguration, }, } @@ -567,6 +588,12 @@ func resourceArmBatchPoolRead(d *schema.ResourceData, meta interface{}) error { d.Set("node_agent_sku_id", props.DeploymentConfiguration.VirtualMachineConfiguration.NodeAgentSkuID) } + if dcfg := props.DeploymentConfiguration; dcfg != nil { + if vmcfg := dcfg.VirtualMachineConfiguration; vmcfg != nil { + d.Set("container_configuration", azure.FlattenBatchPoolContainerConfiguration(vmcfg.ContainerConfiguration)) + } + } + if err := d.Set("certificate", azure.FlattenBatchPoolCertificateReferences(props.Certificates)); err != nil { return fmt.Errorf("Error flattening `certificate`: %+v", err) } diff --git a/azurerm/resource_arm_batch_pool_test.go b/azurerm/resource_arm_batch_pool_test.go index 84a04849e4d3..6b7ed79fee92 100644 --- a/azurerm/resource_arm_batch_pool_test.go +++ b/azurerm/resource_arm_batch_pool_test.go @@ -296,6 +296,27 @@ func TestAccAzureRMBatchPool_validateResourceFileWithoutSource(t *testing.T) { }) } +func TestAccAzureRMBatchPool_container(t *testing.T) { + resourceName := "azurerm_batch_pool.test" + ri := tf.AccRandTimeInt() + rs := acctest.RandString(4) + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMBatchPoolDestroy, + Steps: []resource.TestStep{ + { + Config: testaccAzureRMBatchPoolContainerConfiguration(ri, rs, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMBatchPoolExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "container_configuration.0.type", "DockerCompatible"), + ), + }, + }, + }) +} + func TestAccAzureRMBatchPool_validateResourceFileWithMultipleSources(t *testing.T) { ri := tf.AccRandTimeInt() rs := acctest.RandString(4) @@ -919,3 +940,49 @@ resource "azurerm_batch_pool" "test" { `, rInt, location, rString, rString) } + +func testaccAzureRMBatchPoolContainerConfiguration(rInt int, rString string, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "testaccbatch%d" + location = "%s" +} + +resource "azurerm_container_registry" "test" { + name = "testregistry%s" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + sku = "Basic" +} + +resource "azurerm_batch_account" "test" { + name = "testaccbatch%s" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" +} + +resource "azurerm_batch_pool" "test" { + name = "testaccpool%s" + resource_group_name = "${azurerm_resource_group.test.name}" + account_name = "${azurerm_batch_account.test.name}" + node_agent_sku_id = "batch.node.ubuntu 16.04" + vm_size = "Standard_A1" + + fixed_scale { + target_dedicated_nodes = 1 + } + + storage_image_reference { + publisher = "microsoft-azure-batch" + offer = "ubuntu-server-container" + sku = "16-04-lts" + version = "latest" + } + + container_configuration { + type = "DockerCompatible" + } +} + +`, rInt, location, rString, rString, rString) +} diff --git a/website/docs/d/batch_pool.html.markdown b/website/docs/d/batch_pool.html.markdown index 6b3d0d4eaeb9..af89faaa7be2 100644 --- a/website/docs/d/batch_pool.html.markdown +++ b/website/docs/d/batch_pool.html.markdown @@ -47,6 +47,8 @@ The following attributes are exported: * `certificate` - One or more `certificate` blocks that describe the certificates installed on each compute node in the pool. +* `container_configuration` - The container configuration used in the pool's VMs. + --- A `fixed_scale` block exports the following: @@ -128,3 +130,9 @@ A `resource_file` block exports the following: * `http_url` - The URL of the file to download. If the URL is Azure Blob Storage, it must be readable using anonymous access. * `storage_container_url` - The URL of the blob container within Azure Blob Storage. + +--- + +A `container_configuration` block exports the following: + +* `type` - The type of container configuration. diff --git a/website/docs/r/batch_pool.html.markdown b/website/docs/r/batch_pool.html.markdown index 4753667c3cfa..5c2ccc095be5 100644 --- a/website/docs/r/batch_pool.html.markdown +++ b/website/docs/r/batch_pool.html.markdown @@ -68,12 +68,16 @@ EOF } storage_image_reference { - publisher = "Canonical" - offer = "UbuntuServer" - sku = "16.04.0-LTS" + publisher = "microsoft-azure-batch" + offer = "ubuntu-server-container" + sku = "16-04-lts" version = "latest" } + container_configuration { + type = "DockerCompatible" + } + start_task { command_line = "echo 'Hello World from $env'" max_task_retry_count = 1 @@ -128,6 +132,8 @@ The following arguments are supported: * `certificate` - (Optional) One or more `certificate` blocks that describe the certificates to be installed on each compute node in the pool. +* `container_configuration` - (Optional) The container configuration used in the pool's VMs. + -> **NOTE:** For Windows compute nodes, the Batch service installs the certificates to the specified certificate store and location. For Linux compute nodes, the certificates are stored in a directory inside the task working directory and an environment variable `AZ_BATCH_CERTIFICATES_DIR` is supplied to the task to query for this location. For certificates with visibility of `remoteUser`, a `certs` directory is created in the user's home directory (e.g., `/home/{user-name}/certs`) and certificates are placed in that directory. ~> **Please Note:** `fixed_scale` and `auto_scale` blocks cannot be used both at the same time. @@ -200,6 +206,12 @@ A `certificate` block supports the following: --- +A `container_configuration` block supports the following: + +* `type` - (Optional) The type of container configuration. Possible value is `DockerCompatible`. + +--- + A `resource_file` block supports the following: * `auto_storage_container_name` - (Optional) The storage container name in the auto storage account.