diff --git a/azurerm/config.go b/azurerm/config.go index b250516e2c47..e47322f657bc 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -85,11 +85,14 @@ type ArmClient struct { cosmosDBClient documentdb.DatabaseAccountsClient - automationAccountClient automation.AccountClient - automationRunbookClient automation.RunbookClient - automationCredentialClient automation.CredentialClient - automationScheduleClient automation.ScheduleClient - automationRunbookDraftClient automation.RunbookDraftClient + automationAccountClient automation.AccountClient + automationCredentialClient automation.CredentialClient + automationDscConfigurationClient automation.DscConfigurationClient + automationDscNodeConfigurationClient automation.DscNodeConfigurationClient + automationModuleClient automation.ModuleClient + automationRunbookClient automation.RunbookClient + automationRunbookDraftClient automation.RunbookDraftClient + automationScheduleClient automation.ScheduleClient dnsClient dns.RecordSetsClient zonesClient dns.ZonesClient @@ -534,6 +537,18 @@ func (c *ArmClient) registerAutomationClients(endpoint, subscriptionId string, a c.configureClient(&credentialClient.Client, auth) c.automationCredentialClient = credentialClient + dscConfigurationClient := automation.NewDscConfigurationClientWithBaseURI(endpoint, subscriptionId) + c.configureClient(&dscConfigurationClient.Client, auth) + c.automationDscConfigurationClient = dscConfigurationClient + + dscNodeConfigurationClient := automation.NewDscNodeConfigurationClientWithBaseURI(endpoint, subscriptionId) + c.configureClient(&dscNodeConfigurationClient.Client, auth) + c.automationDscNodeConfigurationClient = dscNodeConfigurationClient + + moduleClient := automation.NewModuleClientWithBaseURI(endpoint, subscriptionId) + c.configureClient(&moduleClient.Client, auth) + c.automationModuleClient = moduleClient + runbookClient := automation.NewRunbookClientWithBaseURI(endpoint, subscriptionId) c.configureClient(&runbookClient.Client, auth) c.automationRunbookClient = runbookClient diff --git a/azurerm/provider.go b/azurerm/provider.go index 0c80937485c3..a2b581c56ddc 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -143,6 +143,9 @@ func Provider() terraform.ResourceProvider { "azurerm_app_service_slot": resourceArmAppServiceSlot(), "azurerm_automation_account": resourceArmAutomationAccount(), "azurerm_automation_credential": resourceArmAutomationCredential(), + "azurerm_automation_dsc_configuration": resourceArmAutomationDscConfiguration(), + "azurerm_automation_dsc_nodeconfiguration": resourceArmAutomationDscNodeConfiguration(), + "azurerm_automation_module": resourceArmAutomationModule(), "azurerm_automation_runbook": resourceArmAutomationRunbook(), "azurerm_automation_schedule": resourceArmAutomationSchedule(), "azurerm_autoscale_setting": resourceArmAutoScaleSetting(), diff --git a/azurerm/resource_arm_automation_dsc_configuration.go b/azurerm/resource_arm_automation_dsc_configuration.go new file mode 100644 index 000000000000..f6355ed8d6fb --- /dev/null +++ b/azurerm/resource_arm_automation_dsc_configuration.go @@ -0,0 +1,190 @@ +package azurerm + +import ( + "bytes" + "fmt" + "log" + "regexp" + + "github.com/Azure/azure-sdk-for-go/services/automation/mgmt/2015-10-31/automation" + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmAutomationDscConfiguration() *schema.Resource { + return &schema.Resource{ + Create: resourceArmAutomationDscConfigurationCreateUpdate, + Read: resourceArmAutomationDscConfigurationRead, + Update: resourceArmAutomationDscConfigurationCreateUpdate, + Delete: resourceArmAutomationDscConfigurationDelete, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.StringMatch( + regexp.MustCompile(`^[a-zA-Z0-9_]{1,64}$`), + `The name length must be from 1 to 64 characters. The name can only contain letters, numbers and underscores.`, + ), + }, + + "automation_account_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.NoZeroValues, + }, + + "content_embedded": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.NoZeroValues, + }, + + "resource_group_name": resourceGroupNameSchema(), + + "location": locationSchema(), + + "log_verbose": { + Type: schema.TypeBool, + Optional: true, + Default: false, + }, + + "description": { + Type: schema.TypeString, + Optional: true, + }, + + "state": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceArmAutomationDscConfigurationCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).automationDscConfigurationClient + ctx := meta.(*ArmClient).StopContext + + log.Printf("[INFO] preparing arguments for AzureRM Automation Dsc Configuration creation.") + + name := d.Get("name").(string) + resGroup := d.Get("resource_group_name").(string) + accName := d.Get("automation_account_name").(string) + contentEmbedded := d.Get("content_embedded").(string) + location := azureRMNormalizeLocation(d.Get("location").(string)) + logVerbose := d.Get("log_verbose").(bool) + description := d.Get("description").(string) + + parameters := automation.DscConfigurationCreateOrUpdateParameters{ + DscConfigurationCreateOrUpdateProperties: &automation.DscConfigurationCreateOrUpdateProperties{ + LogVerbose: utils.Bool(logVerbose), + Description: utils.String(description), + Source: &automation.ContentSource{ + Type: automation.EmbeddedContent, + Value: utils.String(contentEmbedded), + }, + }, + Location: utils.String(location), + } + + _, err := client.CreateOrUpdate(ctx, resGroup, accName, name, parameters) + if err != nil { + return err + } + + read, err := client.Get(ctx, resGroup, accName, name) + if err != nil { + return err + } + + if read.ID == nil { + return fmt.Errorf("Cannot read Automation Dsc Configuration %q (resource group %q) ID", name, resGroup) + } + + d.SetId(*read.ID) + + return resourceArmAutomationDscConfigurationRead(d, meta) +} + +func resourceArmAutomationDscConfigurationRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).automationDscConfigurationClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resGroup := id.ResourceGroup + accName := id.Path["automationAccounts"] + name := id.Path["configurations"] + + resp, err := client.Get(ctx, resGroup, accName, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + + return fmt.Errorf("Error making Read request on AzureRM Automation Dsc Configuration %q: %+v", name, err) + } + + d.Set("name", resp.Name) + d.Set("resource_group_name", resGroup) + d.Set("automation_account_name", accName) + + if location := resp.Location; location != nil { + d.Set("location", azureRMNormalizeLocation(*location)) + } + + if props := resp.DscConfigurationProperties; props != nil { + d.Set("log_verbose", props.LogVerbose) + d.Set("description", props.Description) + d.Set("state", resp.State) + } + + contentresp, err := client.GetContent(ctx, resGroup, accName, name) + if err != nil { + return fmt.Errorf("Error making Read request on AzureRM Automation Dsc Configuration content %q: %+v", name, err) + } + + buf := new(bytes.Buffer) + buf.ReadFrom(contentresp.Body) + content := buf.String() + + d.Set("content_embedded", content) + + return nil +} + +func resourceArmAutomationDscConfigurationDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).automationDscConfigurationClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resGroup := id.ResourceGroup + accName := id.Path["automationAccounts"] + name := id.Path["configurations"] + + resp, err := client.Delete(ctx, resGroup, accName, name) + if err != nil { + if utils.ResponseWasNotFound(resp) { + return nil + } + + return fmt.Errorf("Error issuing AzureRM delete request for Automation Dsc Configuration %q: %+v", name, err) + } + + return nil +} diff --git a/azurerm/resource_arm_automation_dsc_configuration_test.go b/azurerm/resource_arm_automation_dsc_configuration_test.go new file mode 100644 index 000000000000..31d186d6205c --- /dev/null +++ b/azurerm/resource_arm_automation_dsc_configuration_test.go @@ -0,0 +1,135 @@ +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 TestAccAzureRMAutomationDscConfiguration_basic(t *testing.T) { + resourceName := "azurerm_automation_dsc_configuration.test" + ri := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAutomationDscConfigurationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationDscConfiguration_basic(ri, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationDscConfigurationExists(resourceName), + resource.TestCheckResourceAttrSet(resourceName, "location"), + resource.TestCheckResourceAttr(resourceName, "description", "test"), + resource.TestCheckResourceAttrSet(resourceName, "log_verbose"), + resource.TestCheckResourceAttrSet(resourceName, "state"), + resource.TestCheckResourceAttr(resourceName, "content_embedded", "configuration acctest {}"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testCheckAzureRMAutomationDscConfigurationDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).automationDscConfigurationClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_automation_dsc_configuration" { + continue + } + + name := rs.Primary.Attributes["name"] + accName := rs.Primary.Attributes["automation_account_name"] + + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Automation Dsc Configuration: '%s'", name) + } + + resp, err := conn.Get(ctx, resourceGroup, accName, name) + + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + + return err + } + + return fmt.Errorf("Automation Dsc Configuration still exists:\n%#v", resp) + + } + + return nil +} + +func testCheckAzureRMAutomationDscConfigurationExists(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: %s", name) + } + + name := rs.Primary.Attributes["name"] + accName := rs.Primary.Attributes["automation_account_name"] + + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Automation Dsc Configuration: '%s'", name) + } + + conn := testAccProvider.Meta().(*ArmClient).automationDscConfigurationClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + resp, err := conn.Get(ctx, resourceGroup, accName, name) + + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Automation Dsc Configuration '%s' (resource group: '%s') does not exist", name, resourceGroup) + } + + return fmt.Errorf("Bad: Get on automationDscConfigurationClient: %s\nName: %s, Account name: %s, Resource group: %s OBJECT: %+v", err, name, accName, resourceGroup, rs.Primary) + } + + return nil + } +} + +func testAccAzureRMAutomationDscConfiguration_basic(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_automation_account" "test" { + name = "acctest-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + sku { + name = "Basic" + } +} + +resource "azurerm_automation_dsc_configuration" "test" { + name = "acctest" + resource_group_name = "${azurerm_resource_group.test.name}" + automation_account_name = "${azurerm_automation_account.test.name}" + location = "${azurerm_resource_group.test.location}" + content_embedded = "configuration acctest {}" + description = "test" +} +`, rInt, location, rInt) +} diff --git a/azurerm/resource_arm_automation_dsc_nodeconfiguration.go b/azurerm/resource_arm_automation_dsc_nodeconfiguration.go new file mode 100644 index 000000000000..ce539d818f93 --- /dev/null +++ b/azurerm/resource_arm_automation_dsc_nodeconfiguration.go @@ -0,0 +1,156 @@ +package azurerm + +import ( + "fmt" + "log" + "strings" + + "github.com/Azure/azure-sdk-for-go/services/automation/mgmt/2015-10-31/automation" + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmAutomationDscNodeConfiguration() *schema.Resource { + return &schema.Resource{ + Create: resourceArmAutomationDscNodeConfigurationCreateUpdate, + Read: resourceArmAutomationDscNodeConfigurationRead, + Update: resourceArmAutomationDscNodeConfigurationCreateUpdate, + Delete: resourceArmAutomationDscNodeConfigurationDelete, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.NoZeroValues, + }, + + "automation_account_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.NoZeroValues, + }, + + "resource_group_name": resourceGroupNameSchema(), + + "content_embedded": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.NoZeroValues, + }, + + "configuration_name": { + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func resourceArmAutomationDscNodeConfigurationCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).automationDscNodeConfigurationClient + ctx := meta.(*ArmClient).StopContext + + log.Printf("[INFO] preparing arguments for AzureRM Automation Dsc Node Configuration creation.") + + name := d.Get("name").(string) + resGroup := d.Get("resource_group_name").(string) + accName := d.Get("automation_account_name").(string) + content := d.Get("content_embedded").(string) + + // configuration name is always the first part of the dsc node configuration + // e.g. webserver.prod or webserver.local will be associated to the dsc configuration webserver + + configurationName := strings.Split(name, ".")[0] + + parameters := automation.DscNodeConfigurationCreateOrUpdateParameters{ + Source: &automation.ContentSource{ + Type: automation.EmbeddedContent, + Value: utils.String(content), + }, + Configuration: &automation.DscConfigurationAssociationProperty{ + Name: utils.String(configurationName), + }, + Name: utils.String(name), + } + + _, err := client.CreateOrUpdate(ctx, resGroup, accName, name, parameters) + if err != nil { + return err + } + + read, err := client.Get(ctx, resGroup, accName, name) + if err != nil { + return err + } + + if read.ID == nil { + return fmt.Errorf("Cannot read Automation Dsc Node Configuration %q (resource group %q) ID", name, resGroup) + } + + d.SetId(*read.ID) + + return resourceArmAutomationDscNodeConfigurationRead(d, meta) +} + +func resourceArmAutomationDscNodeConfigurationRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).automationDscNodeConfigurationClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resGroup := id.ResourceGroup + accName := id.Path["automationAccounts"] + name := id.Path["nodeConfigurations"] + + resp, err := client.Get(ctx, resGroup, accName, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + + return fmt.Errorf("Error making Read request on AzureRM Automation Dsc Node Configuration %q: %+v", name, err) + } + + d.Set("name", resp.Name) + d.Set("resource_group_name", resGroup) + d.Set("automation_account_name", accName) + d.Set("configuration_name", resp.Configuration.Name) + + // cannot read back content_embedded as not part of body nor exposed through method + + return nil +} + +func resourceArmAutomationDscNodeConfigurationDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).automationDscNodeConfigurationClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + resGroup := id.ResourceGroup + accName := id.Path["automationAccounts"] + name := id.Path["nodeConfigurations"] + + resp, err := client.Delete(ctx, resGroup, accName, name) + if err != nil { + if utils.ResponseWasNotFound(resp) { + return nil + } + + return fmt.Errorf("Error issuing AzureRM delete request for Automation Dsc Node Configuration %q: %+v", name, err) + } + + return nil +} diff --git a/azurerm/resource_arm_automation_dsc_nodeconfiguration_test.go b/azurerm/resource_arm_automation_dsc_nodeconfiguration_test.go new file mode 100644 index 000000000000..2394e5eaf2cf --- /dev/null +++ b/azurerm/resource_arm_automation_dsc_nodeconfiguration_test.go @@ -0,0 +1,162 @@ +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 TestAccAzureRMAutomationDscNodeConfiguration_basic(t *testing.T) { + resourceName := "azurerm_automation_dsc_nodeconfiguration.test" + ri := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAutomationDscNodeConfigurationDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationDscNodeConfiguration_basic(ri, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationDscNodeConfigurationExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "configuration_name", "acctest"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + // Cannot check content_embedded at this time as it is not exposed via REST API / Azure SDK + ImportStateVerifyIgnore: []string{"content_embedded"}, + }, + }, + }) +} + +func testCheckAzureRMAutomationDscNodeConfigurationDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).automationDscNodeConfigurationClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_automation_dsc_nodeconfiguration" { + continue + } + + name := rs.Primary.Attributes["name"] + accName := rs.Primary.Attributes["automation_account_name"] + + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Automation Dsc Node Configuration: '%s'", name) + } + + resp, err := conn.Get(ctx, resourceGroup, accName, name) + + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + + return err + } + + return fmt.Errorf("Automation Dsc Node Configuration still exists:\n%#v", resp) + + } + + return nil +} + +func testCheckAzureRMAutomationDscNodeConfigurationExists(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: %s", name) + } + + name := rs.Primary.Attributes["name"] + accName := rs.Primary.Attributes["automation_account_name"] + + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Automation Dsc Node Configuration: '%s'", name) + } + + conn := testAccProvider.Meta().(*ArmClient).automationDscNodeConfigurationClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + resp, err := conn.Get(ctx, resourceGroup, accName, name) + + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Automation Dsc Node Configuration '%s' (resource group: '%s') does not exist", name, resourceGroup) + } + + return fmt.Errorf("Bad: Get on automationDscNodeConfigurationClient: %s\nName: %s, Account name: %s, Resource group: %s OBJECT: %+v", err, name, accName, resourceGroup, rs.Primary) + } + + return nil + } +} + +func testAccAzureRMAutomationDscNodeConfiguration_basic(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_automation_account" "test" { + name = "acctest-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + sku { + name = "Basic" + } +} + +resource "azurerm_automation_dsc_configuration" "test" { + name = "acctest" + resource_group_name = "${azurerm_resource_group.test.name}" + automation_account_name = "${azurerm_automation_account.test.name}" + location = "${azurerm_resource_group.test.location}" + content_embedded = "configuration acctest {}" +} + +resource "azurerm_automation_dsc_nodeconfiguration" "test" { + name = "acctest.localhost" + resource_group_name = "${azurerm_resource_group.test.name}" + automation_account_name = "${azurerm_automation_account.test.name}" + depends_on = ["azurerm_automation_dsc_configuration.test"] + content_embedded = < 0 { + hash := hashes[0].(map[string]interface{}) + hashValue := hash["value"].(string) + hashAlgorithm := hash["algorithm"].(string) + + return automation.ContentLink{ + URI: &uri, + ContentHash: &automation.ContentHash{ + Algorithm: &hashAlgorithm, + Value: &hashValue, + }, + } + } + + return automation.ContentLink{ + URI: &uri, + } +} diff --git a/azurerm/resource_arm_automation_module_test.go b/azurerm/resource_arm_automation_module_test.go new file mode 100644 index 000000000000..ddee87a218fc --- /dev/null +++ b/azurerm/resource_arm_automation_module_test.go @@ -0,0 +1,133 @@ +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 TestAccAzureRMAutomationModule_basic(t *testing.T) { + resourceName := "azurerm_automation_module.test" + ri := acctest.RandInt() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAutomationModuleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationModule_basic(ri, testLocation()), + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMAutomationModuleExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + // Module link is not returned by api in Get operation + ImportStateVerifyIgnore: []string{"module_link"}, + }, + }, + }) +} + +func testCheckAzureRMAutomationModuleDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).automationModuleClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_automation_module" { + continue + } + + name := rs.Primary.Attributes["name"] + accName := rs.Primary.Attributes["automation_account_name"] + + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Automation Module: '%s'", name) + } + + resp, err := conn.Get(ctx, resourceGroup, accName, name) + + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + + return err + } + + return fmt.Errorf("Automation Module still exists:\n%#v", resp) + + } + + return nil +} + +func testCheckAzureRMAutomationModuleExists(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: %s", name) + } + + name := rs.Primary.Attributes["name"] + accName := rs.Primary.Attributes["automation_account_name"] + + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Automation Module: '%s'", name) + } + + conn := testAccProvider.Meta().(*ArmClient).automationModuleClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + resp, err := conn.Get(ctx, resourceGroup, accName, name) + + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Automation Module '%s' (resource group: '%s') does not exist", name, resourceGroup) + } + + return fmt.Errorf("Bad: Get on automationModuleClient: %s\nName: %s, Account name: %s, Resource group: %s OBJECT: %+v", err, name, accName, resourceGroup, rs.Primary) + } + + return nil + } +} + +func testAccAzureRMAutomationModule_basic(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_automation_account" "test" { + name = "acctest-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + sku { + name = "Basic" + } +} + +resource "azurerm_automation_module" "test" { + name = "xActiveDirectory" + resource_group_name = "${azurerm_resource_group.test.name}" + automation_account_name = "${azurerm_automation_account.test.name}" + + module_link = { + uri = "https://devopsgallerystorage.blob.core.windows.net/packages/xactivedirectory.2.19.0.nupkg" + } +} +`, rInt, location, rInt) +} diff --git a/website/azurerm.erb b/website/azurerm.erb index f09d7e862f09..1529ecbc9750 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -320,6 +320,18 @@ azurerm_automation_credential + > + azurerm_automation_dsc_configuration + + + > + azurerm_automation_dsc_nodeconfiguration + + + > + azurerm_automation_module + + > azurerm_automation_runbook diff --git a/website/docs/r/automation_dsc_configuration.html.markdown b/website/docs/r/automation_dsc_configuration.html.markdown new file mode 100644 index 000000000000..efae7903fea3 --- /dev/null +++ b/website/docs/r/automation_dsc_configuration.html.markdown @@ -0,0 +1,61 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_automation_dsc_configuration" +sidebar_current: "docs-azurerm-resource-automation-dsc-configuration" +description: |- + Manages a Automation DSC Configuration. +--- + +# azurerm_automation_dsc_configuration + +Manages a Automation DSC Configuration. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "resourceGroup1" + location = "West Europe" +} + +resource "azurerm_automation_account" "example" { + name = "account1" + location = "${azurerm_resource_group.example.location}" + resource_group_name = "${azurerm_resource_group.example.name}" + sku { + name = "Basic" + } +} + +resource "azurerm_automation_dsc_configuration" "example" { + name = "test" + resource_group_name = "${azurerm_resource_group.example.name}" + automation_account_name = "${azurerm_automation_account.example.name}" + location = "${azurerm_resource_group.example.location}" + content_embedded = "configuration test {}" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Specifies the name of the DSC Configuration. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) The name of the resource group in which the DSC Configuration is created. Changing this forces a new resource to be created. + +* `automation_account_name` - (Required) The name of the automation account in which the DSC Configuration is created. Changing this forces a new resource to be created. + +* `content_embedded` - (Required) The PowerShell DSC Configuration script. + +* `location` - (Required) Must be the same location as the Automation Account. + +* `log_verbose` - (Optional) Verbose log option. + +* `description` - (Optional) Description to go with DSC Configuration. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The DSC Configuration ID. diff --git a/website/docs/r/automation_dsc_nodeconfiguration.html.markdown b/website/docs/r/automation_dsc_nodeconfiguration.html.markdown new file mode 100644 index 000000000000..0355cb5340f4 --- /dev/null +++ b/website/docs/r/automation_dsc_nodeconfiguration.html.markdown @@ -0,0 +1,85 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_automation_dsc_nodeconfiguration" +sidebar_current: "docs-azurerm-resource-automation-dsc-nodeconfiguration" +description: |- + Manages a Automation DSC Node Configuration. +--- + +# azurerm_automation_dsc_nodeconfiguration + +Manages a Automation DSC Node Configuration. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "resourceGroup1" + location = "West Europe" +} + +resource "azurerm_automation_account" "example" { + name = "account1" + location = "${azurerm_resource_group.example.location}" + resource_group_name = "${azurerm_resource_group.example.name}" + sku { + name = "Basic" + } +} + +resource "azurerm_automation_dsc_configuration" "example" { + name = "test" + resource_group_name = "${azurerm_resource_group.example.name}" + automation_account_name = "${azurerm_automation_account.example.name}" + location = "${azurerm_resource_group.example.location}" + content_embedded = "configuration test {}" +} + +resource "azurerm_automation_dsc_nodeconfiguration" "example" { + name = "test.localhost" + resource_group_name = "${azurerm_resource_group.example.name}" + automation_account_name = "${azurerm_automation_account.example.name}" + depends_on = ["azurerm_automation_dsc_configuration.example"] + content_embedded = <