diff --git a/azurerm/config.go b/azurerm/config.go index 159a54726a8d..d17e403f99d8 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -160,6 +160,9 @@ type ArmClient struct { sqlElasticPoolsClient sql.ElasticPoolsClient sqlFirewallRulesClient sql.FirewallRulesClient sqlServersClient sql.ServersClient + + // Networking + watcherClient network.WatchersClient } func withRequestLogging() autorest.SendDecorator { @@ -655,11 +658,21 @@ func (c *Config) getArmClient() (*ArmClient, error) { client.registerDatabases(endpoint, c.SubscriptionID, auth, sender) client.registerDisks(endpoint, c.SubscriptionID, auth, sender) client.registerKeyVaultClients(endpoint, c.SubscriptionID, auth, keyVaultAuth, sender) + client.registerNetworkingClients(endpoint, c.SubscriptionID, auth, sender) client.registerRedisClients(endpoint, c.SubscriptionID, auth, sender) return &client, nil } +func (c *ArmClient) registerNetworkingClients(endpoint, subscriptionId string, auth autorest.Authorizer, sender autorest.Sender) { + // TODO: move the other networking stuff in here, gradually + watchersClient := network.NewWatchersClientWithBaseURI(endpoint, subscriptionId) + setUserAgent(&watchersClient.Client) + watchersClient.Authorizer = auth + watchersClient.Sender = sender + c.watcherClient = watchersClient +} + func (c *ArmClient) registerAuthentication(endpoint, graphEndpoint, subscriptionId, tenantId string, auth, graphAuth autorest.Authorizer, sender autorest.Sender) { spc := graphrbac.NewServicePrincipalsClientWithBaseURI(graphEndpoint, tenantId) setUserAgent(&spc.Client) diff --git a/azurerm/import_arm_network_watcher_test.go b/azurerm/import_arm_network_watcher_test.go new file mode 100644 index 000000000000..32e4868d7e31 --- /dev/null +++ b/azurerm/import_arm_network_watcher_test.go @@ -0,0 +1,50 @@ +package azurerm + +import ( + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" +) + +func TestAccAzureRMNetworkWatcher_importBasic(t *testing.T) { + rInt := acctest.RandInt() + resourceName := "azurerm_network_watcher.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMNetworkWatcherDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMNetworkWatcher_basic(rInt, testLocation()), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMNetworkWatcher_importComplete(t *testing.T) { + rInt := acctest.RandInt() + resourceName := "azurerm_network_watcher.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMNetworkWatcherDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMNetworkWatcher_complete(rInt, testLocation()), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} diff --git a/azurerm/provider.go b/azurerm/provider.go index 5f7dfea31866..c085d8709899 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -134,6 +134,7 @@ func Provider() terraform.ResourceProvider { "azurerm_network_interface": resourceArmNetworkInterface(), "azurerm_network_security_group": resourceArmNetworkSecurityGroup(), "azurerm_network_security_rule": resourceArmNetworkSecurityRule(), + "azurerm_network_watcher": resourceArmNetworkWatcher(), "azurerm_postgresql_configuration": resourceArmPostgreSQLConfiguration(), "azurerm_postgresql_database": resourceArmPostgreSQLDatabase(), "azurerm_postgresql_firewall_rule": resourceArmPostgreSQLFirewallRule(), diff --git a/azurerm/resource_arm_network_watcher.go b/azurerm/resource_arm_network_watcher.go new file mode 100644 index 000000000000..e81f49b1ae6f --- /dev/null +++ b/azurerm/resource_arm_network_watcher.go @@ -0,0 +1,116 @@ +package azurerm + +import ( + "fmt" + + "github.com/Azure/azure-sdk-for-go/arm/network" + "github.com/hashicorp/terraform/helper/schema" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmNetworkWatcher() *schema.Resource { + return &schema.Resource{ + Create: resourceArmNetworkWatcherCreateUpdate, + Read: resourceArmNetworkWatcherRead, + Update: resourceArmNetworkWatcherCreateUpdate, + Delete: resourceArmNetworkWatcherDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "resource_group_name": resourceGroupNameSchema(), + + "location": locationSchema(), + + "tags": tagsSchema(), + }, + } +} + +func resourceArmNetworkWatcherCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).watcherClient + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + location := d.Get("location").(string) + tags := d.Get("tags").(map[string]interface{}) + + watcher := network.Watcher{ + Location: utils.String(location), + Tags: expandTags(tags), + } + _, err := client.CreateOrUpdate(resourceGroup, name, watcher) + if err != nil { + return err + } + + read, err := client.Get(resourceGroup, name) + if err != nil { + return err + } + if read.ID == nil { + return fmt.Errorf("Cannot read Network Watcher %q (Resource Group %q) ID", name, resourceGroup) + } + + d.SetId(*read.ID) + + return resourceArmNetworkWatcherRead(d, meta) +} + +func resourceArmNetworkWatcherRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).watcherClient + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["networkWatchers"] + + resp, err := client.Get(resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + return fmt.Errorf("Error making Read request on Network Watcher %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + d.Set("name", resp.Name) + d.Set("resource_group_name", resourceGroup) + d.Set("location", azureRMNormalizeLocation(*resp.Location)) + + flattenAndSetTags(d, resp.Tags) + + return nil +} + +func resourceArmNetworkWatcherDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).watcherClient + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resourceGroup := id.ResourceGroup + name := id.Path["networkWatchers"] + + deleteResp, deleteErr := client.Delete(resourceGroup, name, make(chan struct{})) + resp := <-deleteResp + err = <-deleteErr + + if err != nil { + if !utils.ResponseWasNotFound(resp) { + return fmt.Errorf("Error deleting Network Watcher %q (Resource Group %q): %+v", name, resourceGroup, err) + } + } + + return nil +} diff --git a/azurerm/resource_arm_network_watcher_test.go b/azurerm/resource_arm_network_watcher_test.go new file mode 100644 index 000000000000..73d963550f65 --- /dev/null +++ b/azurerm/resource_arm_network_watcher_test.go @@ -0,0 +1,204 @@ +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 TestAccAzureRMNetworkWatcher_basic(t *testing.T) { + resourceGroup := "azurerm_network_watcher.test" + rInt := acctest.RandInt() + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMNetworkWatcherDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMNetworkWatcher_basic(rInt, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkWatcherExists(resourceGroup), + ), + }, + }, + }) +} + +func TestAccAzureRMNetworkWatcher_complete(t *testing.T) { + resourceGroup := "azurerm_network_watcher.test" + rInt := acctest.RandInt() + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMNetworkWatcherDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMNetworkWatcher_complete(rInt, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkWatcherExists(resourceGroup), + ), + }, + }, + }) +} + +func TestAccAzureRMNetworkWatcher_update(t *testing.T) { + resourceGroup := "azurerm_network_watcher.test" + rInt := acctest.RandInt() + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMNetworkWatcherDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMNetworkWatcher_basic(rInt, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkWatcherExists(resourceGroup), + ), + }, + { + Config: testAccAzureRMNetworkWatcher_complete(rInt, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkWatcherExists(resourceGroup), + ), + }, + }, + }) +} + +func TestAccAzureRMNetworkWatcher_disappears(t *testing.T) { + resourceGroup := "azurerm_network_watcher.test" + rInt := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMNetworkWatcherDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMNetworkWatcher_basic(rInt, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMNetworkWatcherExists(resourceGroup), + testCheckAzureRMNetworkWatcherDisappears(resourceGroup), + ), + ExpectNonEmptyPlan: true, + }, + }, + }) +} + +func testCheckAzureRMNetworkWatcherExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", 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 Network Watcher: %q", name) + } + + conn := testAccProvider.Meta().(*ArmClient).watcherClient + + resp, err := conn.Get(resourceGroup, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: Network Watcher %q (resource group: %q) does not exist", name, resourceGroup) + } + return fmt.Errorf("Bad: Get on watcherClient: %+v", err) + } + + return nil + } +} + +func testCheckAzureRMNetworkWatcherDisappears(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + + 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 Network Watcher: %q", name) + } + + client := testAccProvider.Meta().(*ArmClient).watcherClient + deleteResp, deleteErr := client.Delete(resourceGroup, name, make(chan struct{})) + resp := <-deleteResp + err := <-deleteErr + if err != nil { + if !utils.ResponseWasNotFound(resp) { + return fmt.Errorf("Bad: Delete on watcherClient: %+v", err) + } + } + + return nil + } +} + +func testCheckAzureRMNetworkWatcherDestroy(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + + if rs.Type != "azurerm_network_watcher" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + + client := testAccProvider.Meta().(*ArmClient).watcherClient + resp, err := client.Get(resourceGroup, name) + + if err != nil { + if !utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Network Watcher still exists:\n%#v", resp) + } + } + } + + return nil +} + +func testAccAzureRMNetworkWatcher_basic(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_network_watcher" "test" { + name = "acctestnw-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +`, rInt, location, rInt) +} + +func testAccAzureRMNetworkWatcher_complete(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_network_watcher" "test" { + name = "acctestnw-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + tags { + "Source" = "AccTests" + } +} +`, rInt, location, rInt) +} diff --git a/website/azurerm.erb b/website/azurerm.erb index c01de2a7752d..8436799e6489 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -439,6 +439,10 @@ azurerm_network_security_rule + > + azurerm_network_watcher + + > azurerm_public_ip diff --git a/website/docs/r/network_watcher.html.markdown b/website/docs/r/network_watcher.html.markdown new file mode 100644 index 000000000000..6bdf22bcbca5 --- /dev/null +++ b/website/docs/r/network_watcher.html.markdown @@ -0,0 +1,53 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_network_watcher" +sidebar_current: "docs-azurerm-resource-network-watcher" +description: |- + Manages a Network Watcher. + +--- + +# azurerm_network_watcher + +Manages a Network Watcher. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "test" { + name = "production-nwwatcher" + location = "West US" +} + +resource "azurerm_network_watcher" "test" { + name = "production-nwwatcher" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the Network Watcher. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) The name of the resource group in which to create the Network Watcher. Changing this forces a new resource to be created. + +* `location` - (Required) Specifies the supported Azure location where the resource exists. Changing this forces a new resource to be created. + +* `tags` - (Optional) A mapping of tags to assign to the resource. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The Network Watcher ID. + +## Import + +Network Watchers can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_network_watcher.watcher1 /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/mygroup1/providers/Microsoft.Network/networkWatchers/watcher1 +```