diff --git a/azurerm/config.go b/azurerm/config.go index c1297a9c2a48..b91c560cb077 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -133,23 +133,24 @@ type ArmClient struct { monitorAlertRulesClient insights.AlertRulesClient // Networking - applicationGatewayClient network.ApplicationGatewaysClient - expressRouteCircuitClient network.ExpressRouteCircuitsClient - ifaceClient network.InterfacesClient - loadBalancerClient network.LoadBalancersClient - localNetConnClient network.LocalNetworkGatewaysClient - publicIPClient network.PublicIPAddressesClient - routesClient network.RoutesClient - routeTablesClient network.RouteTablesClient - secGroupClient network.SecurityGroupsClient - secRuleClient network.SecurityRulesClient - subnetClient network.SubnetsClient - netUsageClient network.UsagesClient - vnetGatewayConnectionsClient network.VirtualNetworkGatewayConnectionsClient - vnetGatewayClient network.VirtualNetworkGatewaysClient - vnetClient network.VirtualNetworksClient - vnetPeeringsClient network.VirtualNetworkPeeringsClient - watcherClient network.WatchersClient + applicationGatewayClient network.ApplicationGatewaysClient + applicationSecurityGroupsClient network.ApplicationSecurityGroupsClient + expressRouteCircuitClient network.ExpressRouteCircuitsClient + ifaceClient network.InterfacesClient + loadBalancerClient network.LoadBalancersClient + localNetConnClient network.LocalNetworkGatewaysClient + publicIPClient network.PublicIPAddressesClient + routesClient network.RoutesClient + routeTablesClient network.RouteTablesClient + secGroupClient network.SecurityGroupsClient + secRuleClient network.SecurityRulesClient + subnetClient network.SubnetsClient + netUsageClient network.UsagesClient + vnetGatewayConnectionsClient network.VirtualNetworkGatewayConnectionsClient + vnetGatewayClient network.VirtualNetworkGatewaysClient + vnetClient network.VirtualNetworksClient + vnetPeeringsClient network.VirtualNetworkPeeringsClient + watcherClient network.WatchersClient // Resources managementLocksClient locks.ManagementLocksClient @@ -323,18 +324,63 @@ func getArmClient(c *authentication.Config) (*ArmClient, error) { return keyVaultSpt, nil }) - csc := containerservice.NewContainerServicesClientWithBaseURI(endpoint, c.SubscriptionID) - setUserAgent(&csc.Client) - csc.Authorizer = auth - csc.Sender = sender - csc.SkipResourceProviderRegistration = c.SkipProviderRegistration - client.containerServicesClient = csc + // NOTE: these declarations should be left separate for clarity should the + // clients be wished to be configured with custom Responders/PollingModes etc... + asc := compute.NewAvailabilitySetsClientWithBaseURI(endpoint, c.SubscriptionID) + setUserAgent(&asc.Client) + asc.Authorizer = auth + asc.Sender = sender + client.availSetClient = asc + + uoc := compute.NewUsageClientWithBaseURI(endpoint, c.SubscriptionID) + setUserAgent(&uoc.Client) + uoc.Authorizer = auth + uoc.Sender = sender + client.usageOpsClient = uoc + + vmeic := compute.NewVirtualMachineExtensionImagesClientWithBaseURI(endpoint, c.SubscriptionID) + setUserAgent(&vmeic.Client) + vmeic.Authorizer = auth + vmeic.Sender = sender + client.vmExtensionImageClient = vmeic + + vmec := compute.NewVirtualMachineExtensionsClientWithBaseURI(endpoint, c.SubscriptionID) + setUserAgent(&vmec.Client) + vmec.Authorizer = auth + vmec.Sender = sender + client.vmExtensionClient = vmec + + vmic := compute.NewVirtualMachineImagesClientWithBaseURI(endpoint, c.SubscriptionID) + setUserAgent(&vmic.Client) + vmic.Authorizer = auth + vmic.Sender = sender + client.vmImageClient = vmic + + vmssc := compute.NewVirtualMachineScaleSetsClientWithBaseURI(endpoint, c.SubscriptionID) + setUserAgent(&vmssc.Client) + vmssc.Authorizer = auth + vmssc.Sender = sender + client.vmScaleSetClient = vmssc + + vmc := compute.NewVirtualMachinesClientWithBaseURI(endpoint, c.SubscriptionID) + setUserAgent(&vmc.Client) + vmc.Authorizer = auth + vmc.Sender = sender + client.vmClient = vmc + + crc := containerregistry.NewRegistriesClientWithBaseURI(endpoint, c.SubscriptionID) + setUserAgent(&crc.Client) + crc.Authorizer = auth + crc.Sender = sender + client.containerRegistryClient = crc client.registerAppInsightsClients(endpoint, c.SubscriptionID, auth, sender) client.registerAutomationClients(endpoint, c.SubscriptionID, auth, sender) client.registerAuthentication(endpoint, graphEndpoint, c.SubscriptionID, c.TenantID, auth, graphAuth, sender) client.registerCDNClients(endpoint, c.SubscriptionID, auth, sender) client.registerComputeClients(endpoint, c.SubscriptionID, auth, sender) + client.registerContainerRegistryClients(endpoint, c.SubscriptionID, auth, sender) + client.registerContainerRegistryClients(endpoint, c.SubscriptionID, auth, sender) client.registerContainerServicesClients(endpoint, c.SubscriptionID, auth) client.registerCosmosDBClients(endpoint, c.SubscriptionID, auth, sender) client.registerContainerInstanceClients(endpoint, c.SubscriptionID, auth, sender) @@ -723,6 +769,104 @@ func (c *ArmClient) registerOperationalInsightsClients(endpoint, subscriptionId c.workspacesClient = opwc } +func (c *ArmClient) registerNetworkClients(endpoint, subscriptionId string, auth autorest.Authorizer, sender autorest.Sender) { + appGatewaysClient := network.NewApplicationGatewaysClientWithBaseURI(endpoint, subscriptionId) + setUserAgent(&appGatewaysClient.Client) + appGatewaysClient.Authorizer = auth + appGatewaysClient.Sender = sender + c.applicationGatewayClient = appGatewaysClient + + appSecurityGroupsClient := network.NewApplicationSecurityGroupsClientWithBaseURI(endpoint, subscriptionId) + setUserAgent(&appSecurityGroupsClient.Client) + appSecurityGroupsClient.Authorizer = auth + appSecurityGroupsClient.Sender = sender + c.applicationSecurityGroupsClient = appSecurityGroupsClient + + ercClient := network.NewExpressRouteCircuitsClientWithBaseURI(endpoint, subscriptionId) + setUserAgent(&ercClient.Client) + ercClient.Authorizer = auth + ercClient.Sender = sender + c.expressRouteCircuitClient = ercClient + + nicClient := network.NewInterfacesClientWithBaseURI(endpoint, subscriptionId) + setUserAgent(&nicClient.Client) + nicClient.Authorizer = auth + nicClient.Sender = sender + c.ifaceClient = nicClient + + lbClient := network.NewLoadBalancersClientWithBaseURI(endpoint, subscriptionId) + setUserAgent(&lbClient.Client) + lbClient.Authorizer = auth + lbClient.Sender = sender + c.loadBalancerClient = lbClient + + lngClient := network.NewLocalNetworkGatewaysClientWithBaseURI(endpoint, subscriptionId) + setUserAgent(&lngClient.Client) + lngClient.Authorizer = auth + lngClient.Sender = sender + c.localNetConnClient = lngClient + + pipClient := network.NewPublicIPAddressesClientWithBaseURI(endpoint, subscriptionId) + setUserAgent(&pipClient.Client) + pipClient.Authorizer = auth + pipClient.Sender = sender + c.publicIPClient = pipClient + + nsgClient := network.NewSecurityGroupsClientWithBaseURI(endpoint, subscriptionId) + setUserAgent(&nsgClient.Client) + nsgClient.Authorizer = auth + nsgClient.Sender = sender + c.secGroupClient = nsgClient + + src := network.NewSecurityRulesClientWithBaseURI(endpoint, subscriptionId) + setUserAgent(&src.Client) + src.Authorizer = auth + src.Sender = sender + c.secRuleClient = src + + subnetsClient := network.NewSubnetsClientWithBaseURI(endpoint, subscriptionId) + setUserAgent(&subnetsClient.Client) + subnetsClient.Authorizer = auth + subnetsClient.Sender = sender + c.subnetClient = subnetsClient + + vncCClient := network.NewVirtualNetworkGatewayConnectionsClientWithBaseURI(endpoint, subscriptionId) + setUserAgent(&vncCClient.Client) + vncCClient.Authorizer = auth + vncCClient.Sender = sender + c.vnetGatewayConnectionsClient = vncCClient + + vngClient := network.NewVirtualNetworkGatewaysClientWithBaseURI(endpoint, subscriptionId) + setUserAgent(&vngClient.Client) + vngClient.Authorizer = auth + vngClient.Sender = sender + c.vnetGatewayClient = vngClient + + virtualNetworksClient := network.NewVirtualNetworksClientWithBaseURI(endpoint, subscriptionId) + setUserAgent(&virtualNetworksClient.Client) + virtualNetworksClient.Authorizer = auth + virtualNetworksClient.Sender = sender + c.vnetClient = virtualNetworksClient + + vnetPeeringsClient := network.NewVirtualNetworkPeeringsClientWithBaseURI(endpoint, subscriptionId) + setUserAgent(&vnetPeeringsClient.Client) + vnetPeeringsClient.Authorizer = auth + vnetPeeringsClient.Sender = sender + c.vnetPeeringsClient = vnetPeeringsClient + + routeTablesClient := network.NewRouteTablesClientWithBaseURI(endpoint, subscriptionId) + setUserAgent(&routeTablesClient.Client) + routeTablesClient.Authorizer = auth + routeTablesClient.Sender = sender + c.routeTablesClient = routeTablesClient + + routesClient := network.NewRoutesClientWithBaseURI(endpoint, subscriptionId) + setUserAgent(&routesClient.Client) + routesClient.Authorizer = auth + routesClient.Sender = sender + c.routesClient = routesClient +} + func (c *ArmClient) registerRedisClients(endpoint, subscriptionId string, auth autorest.Authorizer, sender autorest.Sender) { redisClient := redis.NewClientWithBaseURI(endpoint, subscriptionId) c.configureClient(&redisClient.Client, auth) diff --git a/azurerm/provider.go b/azurerm/provider.go index ea3f8221bde8..db56caae4f7d 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -90,6 +90,7 @@ func Provider() terraform.ResourceProvider { ResourcesMap: map[string]*schema.Resource{ "azurerm_application_gateway": resourceArmApplicationGateway(), "azurerm_application_insights": resourceArmApplicationInsights(), + "azurerm_application_security_group": resourceArmApplicationSecurityGroup(), "azurerm_app_service": resourceArmAppService(), "azurerm_app_service_plan": resourceArmAppServicePlan(), "azurerm_app_service_active_slot": resourceArmAppServiceActiveSlot(), diff --git a/azurerm/resource_arm_application_security_group.go b/azurerm/resource_arm_application_security_group.go new file mode 100644 index 000000000000..ce3b8bf3352b --- /dev/null +++ b/azurerm/resource_arm_application_security_group.go @@ -0,0 +1,132 @@ +package azurerm + +import ( + "fmt" + "log" + + "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2017-09-01/network" + "github.com/hashicorp/terraform/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/response" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmApplicationSecurityGroup() *schema.Resource { + return &schema.Resource{ + Create: resourceArmApplicationSecurityGroupCreateUpdate, + Read: resourceArmApplicationSecurityGroupRead, + Update: resourceArmApplicationSecurityGroupCreateUpdate, + Delete: resourceArmApplicationSecurityGroupDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "location": locationSchema(), + + "resource_group_name": resourceGroupNameSchema(), + + "tags": tagsSchema(), + }, + } +} + +func resourceArmApplicationSecurityGroupCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).applicationSecurityGroupsClient + ctx := meta.(*ArmClient).StopContext + + resourceGroup := d.Get("resource_group_name").(string) + name := d.Get("name").(string) + location := d.Get("location").(string) + tags := d.Get("tags").(map[string]interface{}) + + securityGroup := network.ApplicationSecurityGroup{ + Location: utils.String(location), + Tags: expandTags(tags), + } + future, err := client.CreateOrUpdate(ctx, resourceGroup, name, securityGroup) + if err != nil { + return fmt.Errorf("Error creating Application Security Group %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + err = future.WaitForCompletion(ctx, client.Client) + if err != nil { + return fmt.Errorf("Error waiting for the Application Security Group %q (Resource Group %q) to finish creating: %+v", name, resourceGroup, err) + } + + read, err := client.Get(ctx, resourceGroup, name) + if err != nil { + return err + } + if read.ID == nil { + return fmt.Errorf("Cannot read Application Security Group %q (Resource Group %q) ID", name, resourceGroup) + } + + d.SetId(*read.ID) + + return resourceArmApplicationSecurityGroupRead(d, meta) +} + +func resourceArmApplicationSecurityGroupRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).applicationSecurityGroupsClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["applicationSecurityGroups"] + + resp, err := client.Get(ctx, resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + + return fmt.Errorf("Error making Read request on Application Security Group %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + d.Set("name", resp.Name) + d.Set("location", azureRMNormalizeLocation(*resp.Location)) + d.Set("resource_group_name", resourceGroup) + flattenAndSetTags(d, resp.Tags) + + return nil +} + +func resourceArmApplicationSecurityGroupDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).applicationSecurityGroupsClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["applicationSecurityGroups"] + + log.Printf("[DEBUG] Deleting Application Security Group %q (resource group %q)", name, resourceGroup) + + future, err := client.Delete(ctx, resourceGroup, name) + if err != nil { + if !response.WasNotFound(future.Response()) { + return fmt.Errorf("Error issuing delete request for Application Security Group %q (Resource Group %q): %+v", name, resourceGroup, err) + } + } + + err = future.WaitForCompletion(ctx, client.Client) + if err != nil { + if !response.WasNotFound(future.Response()) { + return fmt.Errorf("Error waiting for deletion of Application Security Group %q (Resource Group %q): %+v", name, resourceGroup, err) + } + } + + return nil +} diff --git a/azurerm/resource_arm_application_security_group_test.go b/azurerm/resource_arm_application_security_group_test.go new file mode 100644 index 000000000000..a4387826f730 --- /dev/null +++ b/azurerm/resource_arm_application_security_group_test.go @@ -0,0 +1,174 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func TestAccAzureRMApplicationSecurityGroup_basic(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_application_security_group.test" + config := testAccAzureRMApplicationSecurityGroup_basic(ri, testLocation()) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApplicationSecurityGroupDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApplicationSecurityGroupExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + ), + }, + }, + }) +} + +func TestAccAzureRMApplicationSecurityGroup_complete(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_application_security_group.test" + config := testAccAzureRMApplicationSecurityGroup_complete(ri, testLocation()) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApplicationSecurityGroupDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApplicationSecurityGroupExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.Hello", "World"), + ), + }, + }, + }) +} + +func TestAccAzureRMApplicationSecurityGroup_update(t *testing.T) { + ri := acctest.RandInt() + location := testLocation() + resourceName := "azurerm_application_security_group.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMApplicationSecurityGroupDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMApplicationSecurityGroup_basic(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApplicationSecurityGroupExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "0"), + ), + }, + { + Config: testAccAzureRMApplicationSecurityGroup_complete(ri, location), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMApplicationSecurityGroupExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "tags.%", "1"), + resource.TestCheckResourceAttr(resourceName, "tags.Hello", "World"), + ), + }, + }, + }) +} + +func testCheckAzureRMApplicationSecurityGroupDestroy(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_application_security_group" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + client := testAccProvider.Meta().(*ArmClient).applicationSecurityGroupsClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + resp, err := client.Get(ctx, resourceGroup, name) + + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + + return err + } + + return fmt.Errorf("Applicaton Security Group still exists:\n%#v", resp) + } + + return nil +} + +func testCheckAzureRMApplicationSecurityGroupExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %q", name) + } + + name := rs.Primary.Attributes["name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Application Security Group: %q", name) + } + + client := testAccProvider.Meta().(*ArmClient).applicationSecurityGroupsClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + resp, err := client.Get(ctx, resourceGroup, name) + + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Application Security Group %q (resource group: %q) was not found: %+v", name, resourceGroup, err) + } + + return fmt.Errorf("Bad: Get on applicationSecurityGroupsClient: %+v", err) + } + + return nil + } +} + +func testAccAzureRMApplicationSecurityGroup_basic(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_application_security_group" "test" { + name = "acctest-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, rInt, location, rInt) +} + +func testAccAzureRMApplicationSecurityGroup_complete(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_application_security_group" "test" { + name = "acctest-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + tags { + "Hello" = "World" + } +} +`, rInt, location, rInt) +}