diff --git a/azurerm/resource_arm_container_registry.go b/azurerm/resource_arm_container_registry.go index 7e3596a7cd3d..eee61f3c3c53 100644 --- a/azurerm/resource_arm_container_registry.go +++ b/azurerm/resource_arm_container_registry.go @@ -155,6 +155,28 @@ func resourceArmContainerRegistry() *schema.Resource { }, }, }, + + "virtual_network": { + Type: schema.TypeSet, + Optional: true, + ConfigMode: schema.SchemaConfigModeAttr, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "action": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(containerregistry.Allow), + }, false), + }, + "subnet_id": { + Type: schema.TypeString, + Required: true, + ValidateFunc: azure.ValidateResourceID, + }, + }, + }, + }, }, }, }, @@ -574,16 +596,28 @@ func expandNetworkRuleSet(profiles []interface{}) *containerregistry.NetworkRule ipRules := make([]containerregistry.IPRule, 0) for _, ipRuleInterface := range ipRuleConfigs { config := ipRuleInterface.(map[string]interface{}) - ipRules = - append(ipRules, containerregistry.IPRule{ - Action: containerregistry.Action(config["action"].(string)), - IPAddressOrRange: utils.String(config["ip_range"].(string)), - }) + newIpRule := containerregistry.IPRule{ + Action: containerregistry.Action(config["action"].(string)), + IPAddressOrRange: utils.String(config["ip_range"].(string)), + } + ipRules = append(ipRules, newIpRule) + } + + networkRuleConfigs := profile["virtual_network"].(*schema.Set).List() + virtualNetworkRules := make([]containerregistry.VirtualNetworkRule, 0) + for _, networkRuleInterface := range networkRuleConfigs { + config := networkRuleInterface.(map[string]interface{}) + newVirtualNetworkRule := containerregistry.VirtualNetworkRule{ + Action: containerregistry.Action(config["action"].(string)), + VirtualNetworkResourceID: utils.String(config["subnet_id"].(string)), + } + virtualNetworkRules = append(virtualNetworkRules, newVirtualNetworkRule) } networkRuleSet := containerregistry.NetworkRuleSet{ - DefaultAction: containerregistry.DefaultAction(profile["default_action"].(string)), - IPRules: &ipRules, + DefaultAction: containerregistry.DefaultAction(profile["default_action"].(string)), + IPRules: &ipRules, + VirtualNetworkRules: &virtualNetworkRules, } return &networkRuleSet } @@ -613,5 +647,19 @@ func flattenNetworkRuleSet(networkRuleSet *containerregistry.NetworkRuleSet) []i values["ip_rule"] = ipRules + virtualNetworkRules := make([]interface{}, 0) + + if networkRuleSet.VirtualNetworkRules != nil { + for _, virtualNetworkRule := range *networkRuleSet.VirtualNetworkRules { + value := make(map[string]interface{}) + value["action"] = string(virtualNetworkRule.Action) + + value["subnet_id"] = virtualNetworkRule.VirtualNetworkResourceID + virtualNetworkRules = append(virtualNetworkRules, value) + } + } + + values["virtual_network"] = virtualNetworkRules + return []interface{}{values} } diff --git a/azurerm/resource_arm_container_registry_test.go b/azurerm/resource_arm_container_registry_test.go index 6cab70951069..8ee190b4623d 100644 --- a/azurerm/resource_arm_container_registry_test.go +++ b/azurerm/resource_arm_container_registry_test.go @@ -263,9 +263,6 @@ func TestAccAzureRMContainerRegistry_geoReplication(t *testing.T) { skuPremium := "Premium" skuBasic := "Basic" - containerRegistryName := fmt.Sprintf("testacccr%d", ri) - resourceGroupName := fmt.Sprintf("testAccRg-%d", ri) - resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, @@ -273,10 +270,9 @@ func TestAccAzureRMContainerRegistry_geoReplication(t *testing.T) { Steps: []resource.TestStep{ // first config creates an ACR with locations { + // TODO: fix this to use dynamic locations Config: testAccAzureRMContainerRegistry_geoReplication(ri, testLocation(), skuPremium, `eastus", "westus`), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(dsn, "name", containerRegistryName), - resource.TestCheckResourceAttr(dsn, "resource_group_name", resourceGroupName), resource.TestCheckResourceAttr(dsn, "sku", skuPremium), resource.TestCheckResourceAttr(dsn, "georeplication_locations.#", "2"), testCheckAzureRMContainerRegistryExists(dsn), @@ -287,8 +283,6 @@ func TestAccAzureRMContainerRegistry_geoReplication(t *testing.T) { { Config: testAccAzureRMContainerRegistry_geoReplication(ri, testLocation(), skuPremium, `centralus", "eastus`), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(dsn, "name", containerRegistryName), - resource.TestCheckResourceAttr(dsn, "resource_group_name", resourceGroupName), resource.TestCheckResourceAttr(dsn, "sku", skuPremium), resource.TestCheckResourceAttr(dsn, "georeplication_locations.#", "2"), testCheckAzureRMContainerRegistryExists(dsn), @@ -299,8 +293,6 @@ func TestAccAzureRMContainerRegistry_geoReplication(t *testing.T) { { Config: testAccAzureRMContainerRegistry_geoReplicationUpdateWithNoLocation(ri, testLocation(), skuPremium), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(dsn, "name", containerRegistryName), - resource.TestCheckResourceAttr(dsn, "resource_group_name", resourceGroupName), resource.TestCheckResourceAttr(dsn, "sku", skuPremium), testCheckAzureRMContainerRegistryExists(dsn), testCheckAzureRMContainerRegistryGeoreplications(dsn, skuPremium, nil), @@ -310,8 +302,6 @@ func TestAccAzureRMContainerRegistry_geoReplication(t *testing.T) { { Config: testAccAzureRMContainerRegistry_geoReplication(ri, testLocation(), skuPremium, `eastus", "westus`), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(dsn, "name", containerRegistryName), - resource.TestCheckResourceAttr(dsn, "resource_group_name", resourceGroupName), resource.TestCheckResourceAttr(dsn, "sku", skuPremium), resource.TestCheckResourceAttr(dsn, "georeplication_locations.#", "2"), testCheckAzureRMContainerRegistryExists(dsn), @@ -322,8 +312,6 @@ func TestAccAzureRMContainerRegistry_geoReplication(t *testing.T) { { Config: testAccAzureRMContainerRegistry_geoReplicationUpdateWithNoLocation_basic(ri, testLocation()), Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr(dsn, "name", containerRegistryName), - resource.TestCheckResourceAttr(dsn, "resource_group_name", resourceGroupName), resource.TestCheckResourceAttr(dsn, "sku", skuBasic), testCheckAzureRMContainerRegistryExists(dsn), testCheckAzureRMContainerRegistryGeoreplications(dsn, skuBasic, nil), @@ -333,7 +321,7 @@ func TestAccAzureRMContainerRegistry_geoReplication(t *testing.T) { }) } -func TestAccAzureRMContainerRegistry_networkAccessProfile_ip(t *testing.T) { +func TestAccAzureRMContainerRegistry_networkAccessProfileIp(t *testing.T) { rn := "azurerm_container_registry.test" ri := tf.AccRandTimeInt() l := testLocation() @@ -360,7 +348,7 @@ func TestAccAzureRMContainerRegistry_networkAccessProfile_ip(t *testing.T) { }) } -func TestAccAzureRMContainerRegistry_networkAccessProfile_update(t *testing.T) { +func TestAccAzureRMContainerRegistry_networkAccessProfileIp_update(t *testing.T) { rn := "azurerm_container_registry.test" ri := tf.AccRandTimeInt() l := testLocation() @@ -399,6 +387,33 @@ func TestAccAzureRMContainerRegistry_networkAccessProfile_update(t *testing.T) { }) } +func TestAccAzureRMContainerRegistry_networkAccessProfileVnet(t *testing.T) { + rn := "azurerm_container_registry.test" + ri := tf.AccRandTimeInt() + l := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMContainerRegistryDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMContainerRegistry_networkAccessProfile_vnet(ri, l), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMContainerRegistryExists(rn), + resource.TestCheckResourceAttr(rn, "network_rule_set.0.default_action", "Deny"), + resource.TestCheckResourceAttr(rn, "network_rule_set.0.virtual_network.#", "1"), + ), + }, + { + ResourceName: rn, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + func testCheckAzureRMContainerRegistryDestroy(s *terraform.State) error { conn := testAccProvider.Meta().(*ArmClient).containers.RegistriesClient ctx := testAccProvider.Meta().(*ArmClient).StopContext @@ -497,7 +512,7 @@ func testCheckAzureRMContainerRegistryGeoreplications(resourceName string, sku s func testAccAzureRMContainerRegistry_basic_basic(rInt int, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "acctestRg-%d" + name = "acctestrg-%d" location = "%s" } @@ -517,7 +532,7 @@ resource "azurerm_container_registry" "test" { func testAccAzureRMContainerRegistry_basicManaged(rInt int, location string, sku string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "acctestRg-%d" + name = "acctestrg-%d" location = "%s" } @@ -548,7 +563,7 @@ resource "azurerm_container_registry" "import" { func testAccAzureRMContainerRegistry_complete(rInt int, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "acctestRg-%d" + name = "acctestrg-%d" location = "%s" } @@ -569,7 +584,7 @@ resource "azurerm_container_registry" "test" { func testAccAzureRMContainerRegistry_completeUpdated(rInt int, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "acctestRg-%d" + name = "acctestrg-%d" location = "%s" } @@ -590,7 +605,7 @@ resource "azurerm_container_registry" "test" { func testAccAzureRMContainerRegistry_geoReplication(rInt int, location string, sku string, georeplicationLocations string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "testAccRg-%d" + name = "acctestrg-%d" location = "%s" } @@ -607,7 +622,7 @@ resource "azurerm_container_registry" "test" { func testAccAzureRMContainerRegistry_geoReplicationUpdateWithNoLocation(rInt int, location string, sku string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "testAccRg-%d" + name = "acctestrg-%d" location = "%s" } @@ -623,7 +638,7 @@ resource "azurerm_container_registry" "test" { func testAccAzureRMContainerRegistry_geoReplicationUpdateWithNoLocation_basic(rInt int, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "testAccRg-%d" + name = "acctestrg-%d" location = "%s" } @@ -643,7 +658,7 @@ resource "azurerm_container_registry" "test" { func testAccAzureRMContainerRegistry_networkAccessProfile_ip(rInt int, location string, sku string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { - name = "testAccRg-%[1]d" + name = "acctestrg-%[1]d" location = "%[2]s" } @@ -665,3 +680,45 @@ resource "azurerm_container_registry" "test" { } `, rInt, location, sku) } + +func testAccAzureRMContainerRegistry_networkAccessProfile_vnet(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestrg-%[1]d" + location = "%[2]s" +} + +resource "azurerm_virtual_network" "test" { + name = "virtualNetwork1" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + address_space = ["10.0.0.0/16"] +} + +resource "azurerm_subnet" "test" { + name = "testsubnet" + resource_group_name = "${azurerm_resource_group.test.name}" + virtual_network_name = "${azurerm_virtual_network.test.name}" + address_prefix = "10.0.1.0/24" + + service_endpoints = ["Microsoft.ContainerRegistry"] +} + +resource "azurerm_container_registry" "test" { + name = "testAccCr%[1]d" + resource_group_name = "${azurerm_resource_group.test.name}" + location = "${azurerm_resource_group.test.location}" + sku = "Premium" + admin_enabled = false + + network_rule_set { + default_action = "Deny" + + virtual_network { + action = "Allow" + subnet_id = "${azurerm_subnet.test.id}" + } + } +} +`, rInt, location) +} diff --git a/website/docs/r/container_registry.html.markdown b/website/docs/r/container_registry.html.markdown index 0027a0f71f0e..2e61e7fc0d5e 100644 --- a/website/docs/r/container_registry.html.markdown +++ b/website/docs/r/container_registry.html.markdown @@ -62,7 +62,9 @@ The following arguments are supported: * `ip_rule` - (Optional) One or more `ip_rule` blocks as defined below. -~> **NOTE:** `network_rule_set ` is only supported with the `Premium` SDK at this time. +* `virtual_network` - (Optional) One or more `virtual_network` blocks as defined below. + +~> **NOTE:** `network_rule_set ` is only supported with the `Premium` SKU at this time. `ip_rule` supports the following: @@ -70,6 +72,12 @@ The following arguments are supported: * `ip_range` - (Required) The CIDR block from which requests will match the rule. +`virtual_network` supports the following: + +* `action` - (Required) The behaviour for requests matching this rule. At this time the only supported value is `Allow` + +* `subnet_id` - (Required) The subnet id from which requests will match the rule. + --- ## Attributes Reference