From 1640d6733c65022fc6a4d22447987cf8383ca604 Mon Sep 17 00:00:00 2001 From: Tony Fortes Ramos Date: Mon, 6 May 2019 00:31:59 +0200 Subject: [PATCH 01/21] Add automation_job_schedule --- azurerm/config.go | 5 + azurerm/provider.go | 1 + .../resource_arm_automation_job_schedule.go | 198 ++++++++++++++++++ 3 files changed, 204 insertions(+) create mode 100644 azurerm/resource_arm_automation_job_schedule.go diff --git a/azurerm/config.go b/azurerm/config.go index 8b0a069070eb..59cbff1b3af1 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -102,6 +102,7 @@ type ArmClient struct { automationCredentialClient automation.CredentialClient automationDscConfigurationClient automation.DscConfigurationClient automationDscNodeConfigurationClient automation.DscNodeConfigurationClient + automationJobScheduleClient automation.JobScheduleClient automationModuleClient automation.ModuleClient automationRunbookClient automation.RunbookClient automationRunbookDraftClient automation.RunbookDraftClient @@ -645,6 +646,10 @@ func (c *ArmClient) registerAutomationClients(endpoint, subscriptionId string, a c.configureClient(&dscNodeConfigurationClient.Client, auth) c.automationDscNodeConfigurationClient = dscNodeConfigurationClient + jobScheduleClient := automation.NewJobScheduleClientWithBaseURI(endpoint, subscriptionId) + c.configureClient(&jobScheduleClient.Client, auth) + c.automationJobScheduleClient = jobScheduleClient + moduleClient := automation.NewModuleClientWithBaseURI(endpoint, subscriptionId) c.configureClient(&moduleClient.Client, auth) c.automationModuleClient = moduleClient diff --git a/azurerm/provider.go b/azurerm/provider.go index 60eeed2e8886..e249a18d0dc6 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -203,6 +203,7 @@ func Provider() terraform.ResourceProvider { "azurerm_automation_credential": resourceArmAutomationCredential(), "azurerm_automation_dsc_configuration": resourceArmAutomationDscConfiguration(), "azurerm_automation_dsc_nodeconfiguration": resourceArmAutomationDscNodeConfiguration(), + "azurerm_automation_job_schedule": resourceArmAutomationJobSchedule(), "azurerm_automation_module": resourceArmAutomationModule(), "azurerm_automation_runbook": resourceArmAutomationRunbook(), "azurerm_automation_schedule": resourceArmAutomationSchedule(), diff --git a/azurerm/resource_arm_automation_job_schedule.go b/azurerm/resource_arm_automation_job_schedule.go new file mode 100644 index 000000000000..9675ad387db9 --- /dev/null +++ b/azurerm/resource_arm_automation_job_schedule.go @@ -0,0 +1,198 @@ +package azurerm + +import ( + "fmt" + "log" + + "github.com/Azure/azure-sdk-for-go/services/automation/mgmt/2015-10-31/automation" + "github.com/hashicorp/terraform/helper/schema" + uuid "github.com/satori/go.uuid" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmAutomationJobSchedule() *schema.Resource { + return &schema.Resource{ + Create: resourceArmAutomationJobScheduleCreate, + Read: resourceArmAutomationJobScheduleRead, + Delete: resourceArmAutomationJobScheduleDelete, + + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Schema: map[string]*schema.Schema{ + + "resource_group_name": resourceGroupNameSchema(), + + "automation_account_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "runbook_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "schedule_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + "parameters": { + Type: schema.TypeMap, + Optional: true, + ForceNew: true, + }, + + "run_on": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + }, + }, + } +} + +func resourceArmAutomationJobScheduleCreate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).automationJobScheduleClient + ctx := meta.(*ArmClient).StopContext + + log.Printf("[INFO] preparing arguments for AzureRM Automation Job Schedule creation.") + + nameUUID := uuid.NewV4() + resGroup := d.Get("resource_group_name").(string) + accountName := d.Get("automation_account_name").(string) + + runbookName := d.Get("runbook_name").(string) + scheduleName := d.Get("schedule_name").(string) + + if requireResourcesToBeImported && d.IsNewResource() { + existing, err := client.Get(ctx, resGroup, accountName, nameUUID) + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Automation Job Schedule %q (Account %q / Resource Group %q): %s", nameUUID, accountName, resGroup, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_automation_job_schedule", *existing.ID) + } + } + + parameters := automation.JobScheduleCreateParameters{ + JobScheduleCreateProperties: &automation.JobScheduleCreateProperties{ + Schedule: &automation.ScheduleAssociationProperty{ + Name: &scheduleName, + }, + Runbook: &automation.RunbookAssociationProperty{ + Name: &runbookName, + }, + }, + } + properties := parameters.JobScheduleCreateProperties + + // parameters to be passed into the runbook + if v, ok := d.GetOk("parameters"); ok { + jsParameters := make(map[string]*string) + for k, v := range v.(map[string]interface{}) { + value := v.(string) + jsParameters[k] = &value + } + properties.Parameters = jsParameters + } + + if v, ok := d.GetOk("run_on"); ok { + value := v.(string) + properties.RunOn = &value + } + + if _, err := client.Create(ctx, resGroup, accountName, nameUUID, parameters); err != nil { + return err + } + + read, err := client.Get(ctx, resGroup, accountName, nameUUID) + if err != nil { + return err + } + + if read.ID == nil { + return fmt.Errorf("Cannot read Automation Job Schedule '%s' (Account %q / Resource Group %s) ID", nameUUID, accountName, resGroup) + } + + d.SetId(*read.ID) + + return resourceArmAutomationJobScheduleRead(d, meta) +} + +func resourceArmAutomationJobScheduleRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).automationJobScheduleClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + + name := id.Path["jobSchedules"] + nameUUID := uuid.FromStringOrNil(name) + resGroup := id.ResourceGroup + accountName := id.Path["automationAccounts"] + + resp, err := client.Get(ctx, resGroup, accountName, nameUUID) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + return nil + } + + return fmt.Errorf("Error making Read request on AzureRM Automation Job Schedule '%s': %+v", nameUUID, err) + } + + d.Set("resource_group_name", resGroup) + d.Set("automation_account_name", accountName) + d.Set("runbook_name", resp.JobScheduleProperties.Runbook.Name) + d.Set("schedule_name", resp.JobScheduleProperties.Schedule.Name) + + if v := resp.JobScheduleProperties.RunOn; v != nil { + d.Set("run_on", v) + } + + if v := resp.JobScheduleProperties.Parameters; v != nil { + jsParameters := make(map[string]interface{}) + for key, value := range v { + jsParameters[key] = value + } + d.Set("parameters", jsParameters) + } + + return nil +} + +func resourceArmAutomationJobScheduleDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).automationJobScheduleClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + + name := id.Path["jobSchedules"] + nameUUID := uuid.FromStringOrNil(name) + resGroup := id.ResourceGroup + accountName := id.Path["automationAccounts"] + + resp, err := client.Delete(ctx, resGroup, accountName, nameUUID) + if err != nil { + if !utils.ResponseWasNotFound(resp) { + return fmt.Errorf("Error issuing AzureRM delete request for Automation Job Schedule '%s': %+v", nameUUID, err) + } + } + + return nil +} From 290378ebef7b00b55bbe7503ffa9d0b4ef370465 Mon Sep 17 00:00:00 2001 From: Tony Fortes Ramos Date: Mon, 6 May 2019 00:32:39 +0200 Subject: [PATCH 02/21] Update docs --- website/azurerm.erb | 10 +- .../r/automation_job_schedule.html.markdown | 105 ++++++++++++++++++ 2 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 website/docs/r/automation_job_schedule.html.markdown diff --git a/website/azurerm.erb b/website/azurerm.erb index d1f74c33bfc8..e6ccc3310c01 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -158,7 +158,7 @@ > azurerm_express_route_circuit - + > azurerm_firewall @@ -365,7 +365,7 @@ > azurerm_api_management_api_operation - + > azurerm_api_management_version_set @@ -498,6 +498,10 @@ azurerm_automation_dsc_nodeconfiguration + > + azurerm_automation_job_schedule + + > azurerm_automation_module @@ -764,7 +768,7 @@ > azurerm_data_factory_linked_service_postgresql - + > azurerm_data_factory_linked_service_sql_server diff --git a/website/docs/r/automation_job_schedule.html.markdown b/website/docs/r/automation_job_schedule.html.markdown new file mode 100644 index 000000000000..5fe385ab3b55 --- /dev/null +++ b/website/docs/r/automation_job_schedule.html.markdown @@ -0,0 +1,105 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_automation_job_schedule" +sidebar_current: "docs-azurerm-resource-automation-job-schedule" +description: |- + Links an Automation Runbook and Schedule. +--- + +# azurerm_automation_job_schedule + +Links an Automation Runbook and Schedule. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "tfex-automation-account" + location = "West Europe" +} + +resource "azurerm_automation_account" "example" { + name = "tfex-automation-account" + location = "${azurerm_resource_group.example.location}" + resource_group_name = "${azurerm_resource_group.example.name}" + + sku { + name = "Basic" + } +} + +resource "azurerm_automation_runbook" "example" { + name = "Get-AzureVMTutorial" + location = "${azurerm_resource_group.example.location}" + resource_group_name = "${azurerm_resource_group.example.name}" + account_name = "${azurerm_automation_account.example.name}" + log_verbose = "true" + log_progress = "true" + description = "This is an example runbook" + runbook_type = "PowerShellWorkflow" + + publish_content_link { + uri = "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-automation-runbook-getvms/Runbooks/Get-AzureVMTutorial.ps1" + } +} + +resource "azurerm_automation_schedule" "example" { + name = "tfex-automation-schedule" + resource_group_name = "${azurerm_resource_group.example.name}" + automation_account_name = "${azurerm_automation_account.example.name}" + frequency = "Week" + interval = 1 + timezone = "Central Europe Standard Time" + start_time = "2014-04-15T18:00:15+02:00" + description = "This is an example schedule" + + advanced_schedule { + week_days = ["Friday"] + } +} + +resource "azurerm_automation_job_schedule" "example" { + resource_group_name = "${azurerm_resource_group.example.name}" + automation_account_name = "${azurerm_automation_account.example.name}" + schedule_name = "${azurerm_automation_schedule.example.name}" + runbook_name = "${azurerm_automation_runbook.example.name}" + + parameters = { + Connection = "AzureRunAsConnection" + VMCount = 10 + } +} + +``` + +## Argument Reference + +The following arguments are supported: + +* `resource_group_name` - (Required) The name of the resource group in which the Job Schedule is created. Changing this forces a new resource to be created. + +* `automation_account_name` - (Required) The name of the Automation Account in which the Job Schedule is created. Changing this forces a new resource to be created. + +* `runbook_name` - (Required) The name of a Runbook to link to a Schedule. It needs to be in the same Automation Account as the Schedule and Job Schedule. Changing this forces a new resource to be created. + +* `parameters` - (Optional) A map of key/value pairs corresponding to the arguments that can be passed to the Runbook. Changing this forces a new resource to be created. + +* `run_on` - (Optional) Name of a Hybrid Worker Group the Runbook will be executed on. Changing this forces a new resource to be created. + +* `start_time` - (Optional) Start time of the schedule. Must be at least five minutes in the future. Defaults to seven minutes in the future from the time the resource is created. + + + +## Attributes Reference + +The following attributes are exported: + +* `id` - The Automation Schedule ID. + +## Import + +Automation Schedule can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_automation_job_schedule.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Automation/automationAccounts/account1/jobSchedules/10000000-1001-1001-1001-000000000001 +``` From 136415ea5267944970ee422a68293d2a006b8f42 Mon Sep 17 00:00:00 2001 From: Tony Fortes Ramos Date: Mon, 6 May 2019 23:08:26 +0200 Subject: [PATCH 03/21] Add job_schedule tests --- ...source_arm_automation_job_schedule_test.go | 216 ++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 azurerm/resource_arm_automation_job_schedule_test.go diff --git a/azurerm/resource_arm_automation_job_schedule_test.go b/azurerm/resource_arm_automation_job_schedule_test.go new file mode 100644 index 000000000000..0d89e9b1c06b --- /dev/null +++ b/azurerm/resource_arm_automation_job_schedule_test.go @@ -0,0 +1,216 @@ +package azurerm + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" + uuid "github.com/satori/go.uuid" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func TestAccAzureRMAutomationJobScheduleCreate(t *testing.T) { + resourceName := "azurerm_automation_job_schedule.test" + ri := tf.AccRandTimeInt() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAutomationJobScheduleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationJobScheduleCreate(ri, testLocation()), + Check: checkAccAzureRMAutomationJobScheduleCreate(resourceName), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMAutomationJobScheduleRequiresImport(t *testing.T) { + if !requireResourcesToBeImported { + t.Skip("Skipping since resources aren't required to be imported") + return + } + + resourceName := "azurerm_automation_job_schedule.test" + ri := tf.AccRandTimeInt() + location := testLocation() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAutomationJobScheduleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationJobScheduleCreate(ri, location), + Check: checkAccAzureRMAutomationJobScheduleCreate(resourceName), + }, + { + Config: testAccAzureRMAutomationJobScheduleRequiresImport(ri, location), + ExpectError: testRequiresImportError("azurerm_automation_job_schedule"), + }, + }, + }) +} + +func testCheckAzureRMAutomationJobScheduleDestroy(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).automationJobScheduleClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_automation_job_schedule" { + continue + } + + id, err := parseAzureResourceID(rs.Primary.Attributes["id"]) + if err != nil { + return err + } + name := id.Path["jobSchedules"] + nameUUID := uuid.FromStringOrNil(name) + accName := rs.Primary.Attributes["account_name"] + + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Automation Job Schedule: '%s'", name) + } + + resp, err := conn.Get(ctx, resourceGroup, accName, nameUUID) + + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + + return err + } + + return fmt.Errorf("Automation Job Schedule still exists:\n%#v", resp) + } + + return nil +} + +func testCheckAzureRMAutomationJobScheduleExists(resourceName string) resource.TestCheckFunc { + return func(s *terraform.State) error { + conn := testAccProvider.Meta().(*ArmClient).automationJobScheduleClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[resourceName] + if !ok { + return fmt.Errorf("Not found: %s", resourceName) + } + + id, err := parseAzureResourceID(rs.Primary.Attributes["id"]) + if err != nil { + return err + } + name := id.Path["jobSchedules"] + nameUUID := uuid.FromStringOrNil(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 Job Schedule: '%s'", name) + } + + resp, err := conn.Get(ctx, resourceGroup, accName, nameUUID) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Automation Job Schedule '%s' (Account %q / Resource Group %q) does not exist", name, accName, resourceGroup) + } + + return fmt.Errorf("Bad: Get on automationJobScheduleClient: %+v", err) + } + + return nil + } +} + +func testAccAzureRMAutomationJobSchedulePrerequisites(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_automation_account" "test" { + name = "acctestAA-%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + sku { + name = "Basic" + } +} + +resource "azurerm_automation_runbook" "test" { + name = "Get-AzureVMTutorial" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" + + account_name = "${azurerm_automation_account.test.name}" + log_verbose = "true" + log_progress = "true" + description = "This is a test runbook for terraform acceptance test" + runbook_type = "PowerShellWorkflow" + + publish_content_link { + uri = "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-automation-runbook-getvms/Runbooks/Get-AzureVMTutorial.ps1" + } +} + +resource "azurerm_automation_schedule" "test" { + name = "acctestAS-%d" + resource_group_name = "${azurerm_resource_group.test.name}" + automation_account_name = "${azurerm_automation_account.test.name}" + frequency = "OneTime" +} +`, rInt, location, rInt, rInt) +} + +func testAccAzureRMAutomationJobScheduleCreate(rInt int, location string) string { + template := testAccAzureRMAutomationJobSchedulePrerequisites(rInt, location) + return fmt.Sprintf(` +%s + +resource "azurerm_automation_job_schedule" "test" { + resource_group_name = "${azurerm_resource_group.test.name}" + automation_account_name = "${azurerm_automation_account.test.name}" + schedule_name = "${azurerm_automation_schedule.test.name}" + runbook_name = "${azurerm_automation_runbook.test.name}" +} +`, template) +} + +func checkAccAzureRMAutomationJobScheduleCreate(resourceName string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMAutomationJobScheduleExists(resourceName), + resource.TestCheckResourceAttrSet(resourceName, "resource_group_name"), + resource.TestCheckResourceAttrSet(resourceName, "automation_account_name"), + resource.TestCheckResourceAttrSet(resourceName, "schedule_name"), + resource.TestCheckResourceAttrSet(resourceName, "runbook_name"), + ) +} + +func testAccAzureRMAutomationJobScheduleRequiresImport(rInt int, location string) string { + template := testAccAzureRMAutomationJobScheduleCreate(rInt, location) + return fmt.Sprintf(` +%s + +resource "azurerm_automation_job_schedule" "import" { + resource_group_name = "${azurerm_automation_job_schedule.test.resource_group_name}" + automation_account_name = "${azurerm_automation_job_schedule.test.automation_account_name}" + schedule_name = "${azurerm_automation_job_schedule.test.schedule_name}" + runbook_name = "${azurerm_automation_job_schedule.test.runbook_name}" +} +`, template) +} From 34f7a458eb8890e4d1eee674acf5ed13760aa088 Mon Sep 17 00:00:00 2001 From: Tony Fortes Ramos Date: Mon, 6 May 2019 23:10:58 +0200 Subject: [PATCH 04/21] Revert name of requiresImport tests --- azurerm/resource_arm_automation_job_schedule_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/azurerm/resource_arm_automation_job_schedule_test.go b/azurerm/resource_arm_automation_job_schedule_test.go index 0d89e9b1c06b..387ecd1c1825 100644 --- a/azurerm/resource_arm_automation_job_schedule_test.go +++ b/azurerm/resource_arm_automation_job_schedule_test.go @@ -33,7 +33,7 @@ func TestAccAzureRMAutomationJobScheduleCreate(t *testing.T) { }) } -func TestAccAzureRMAutomationJobScheduleRequiresImport(t *testing.T) { +func TestAccAzureRMAutomationJobSchedule_requiresImport(t *testing.T) { if !requireResourcesToBeImported { t.Skip("Skipping since resources aren't required to be imported") return @@ -53,7 +53,7 @@ func TestAccAzureRMAutomationJobScheduleRequiresImport(t *testing.T) { Check: checkAccAzureRMAutomationJobScheduleCreate(resourceName), }, { - Config: testAccAzureRMAutomationJobScheduleRequiresImport(ri, location), + Config: testAccAzureRMAutomationJobSchedule_requiresImport(ri, location), ExpectError: testRequiresImportError("azurerm_automation_job_schedule"), }, }, @@ -201,7 +201,7 @@ func checkAccAzureRMAutomationJobScheduleCreate(resourceName string) resource.Te ) } -func testAccAzureRMAutomationJobScheduleRequiresImport(rInt int, location string) string { +func testAccAzureRMAutomationJobSchedule_requiresImport(rInt int, location string) string { template := testAccAzureRMAutomationJobScheduleCreate(rInt, location) return fmt.Sprintf(` %s From 9eb0656e9233826b1011f0492253d79dc1363a91 Mon Sep 17 00:00:00 2001 From: Tony Fortes Ramos Date: Mon, 6 May 2019 23:29:13 +0200 Subject: [PATCH 05/21] Fix documentation error - removed start_time as a parameter --- website/docs/r/automation_job_schedule.html.markdown | 4 ---- 1 file changed, 4 deletions(-) diff --git a/website/docs/r/automation_job_schedule.html.markdown b/website/docs/r/automation_job_schedule.html.markdown index 5fe385ab3b55..4a1df01dc32e 100644 --- a/website/docs/r/automation_job_schedule.html.markdown +++ b/website/docs/r/automation_job_schedule.html.markdown @@ -86,10 +86,6 @@ The following arguments are supported: * `run_on` - (Optional) Name of a Hybrid Worker Group the Runbook will be executed on. Changing this forces a new resource to be created. -* `start_time` - (Optional) Start time of the schedule. Must be at least five minutes in the future. Defaults to seven minutes in the future from the time the resource is created. - - - ## Attributes Reference The following attributes are exported: From bacaec6cf38d4286bbb860e413b8137083120684 Mon Sep 17 00:00:00 2001 From: Tony Fortes Ramos Date: Mon, 6 May 2019 23:44:50 +0200 Subject: [PATCH 06/21] fix gofmt on job_schedule --- azurerm/resource_arm_automation_job_schedule.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/azurerm/resource_arm_automation_job_schedule.go b/azurerm/resource_arm_automation_job_schedule.go index 9675ad387db9..84c1f5643359 100644 --- a/azurerm/resource_arm_automation_job_schedule.go +++ b/azurerm/resource_arm_automation_job_schedule.go @@ -138,8 +138,8 @@ func resourceArmAutomationJobScheduleRead(d *schema.ResourceData, meta interface return err } - name := id.Path["jobSchedules"] - nameUUID := uuid.FromStringOrNil(name) + name := id.Path["jobSchedules"] + nameUUID := uuid.FromStringOrNil(name) resGroup := id.ResourceGroup accountName := id.Path["automationAccounts"] @@ -183,7 +183,7 @@ func resourceArmAutomationJobScheduleDelete(d *schema.ResourceData, meta interfa } name := id.Path["jobSchedules"] - nameUUID := uuid.FromStringOrNil(name) + nameUUID := uuid.FromStringOrNil(name) resGroup := id.ResourceGroup accountName := id.Path["automationAccounts"] From 9000c88523e13e697322d198d4497c0f00fd8003 Mon Sep 17 00:00:00 2001 From: Tony Fortes Ramos Date: Tue, 7 May 2019 13:35:11 +0200 Subject: [PATCH 07/21] Add job_schedule_id attribute - changed name/nameUUID to jobScheduleID and JobScheduleUUID - Fix some errors referring to Automation Schedule instead of Automation Job Schedule --- .../resource_arm_automation_job_schedule.go | 35 +++++++++++-------- ...source_arm_automation_job_schedule_test.go | 19 +++++----- .../r/automation_job_schedule.html.markdown | 6 ++-- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/azurerm/resource_arm_automation_job_schedule.go b/azurerm/resource_arm_automation_job_schedule.go index 84c1f5643359..bc681c153f91 100644 --- a/azurerm/resource_arm_automation_job_schedule.go +++ b/azurerm/resource_arm_automation_job_schedule.go @@ -54,6 +54,12 @@ func resourceArmAutomationJobSchedule() *schema.Resource { Optional: true, ForceNew: true, }, + + "job_schedule_id": { + Type: schema.TypeString, + Optional: true, + Computed: true, + }, }, } } @@ -64,7 +70,7 @@ func resourceArmAutomationJobScheduleCreate(d *schema.ResourceData, meta interfa log.Printf("[INFO] preparing arguments for AzureRM Automation Job Schedule creation.") - nameUUID := uuid.NewV4() + jobScheduleUUID := uuid.NewV4() resGroup := d.Get("resource_group_name").(string) accountName := d.Get("automation_account_name").(string) @@ -72,10 +78,10 @@ func resourceArmAutomationJobScheduleCreate(d *schema.ResourceData, meta interfa scheduleName := d.Get("schedule_name").(string) if requireResourcesToBeImported && d.IsNewResource() { - existing, err := client.Get(ctx, resGroup, accountName, nameUUID) + existing, err := client.Get(ctx, resGroup, accountName, jobScheduleUUID) if err != nil { if !utils.ResponseWasNotFound(existing.Response) { - return fmt.Errorf("Error checking for presence of existing Automation Job Schedule %q (Account %q / Resource Group %q): %s", nameUUID, accountName, resGroup, err) + return fmt.Errorf("Error checking for presence of existing Automation Job Schedule %q (Account %q / Resource Group %q): %s", jobScheduleUUID, accountName, resGroup, err) } } @@ -111,17 +117,17 @@ func resourceArmAutomationJobScheduleCreate(d *schema.ResourceData, meta interfa properties.RunOn = &value } - if _, err := client.Create(ctx, resGroup, accountName, nameUUID, parameters); err != nil { + if _, err := client.Create(ctx, resGroup, accountName, jobScheduleUUID, parameters); err != nil { return err } - read, err := client.Get(ctx, resGroup, accountName, nameUUID) + read, err := client.Get(ctx, resGroup, accountName, jobScheduleUUID) if err != nil { return err } if read.ID == nil { - return fmt.Errorf("Cannot read Automation Job Schedule '%s' (Account %q / Resource Group %s) ID", nameUUID, accountName, resGroup) + return fmt.Errorf("Cannot read Automation Job Schedule '%s' (Account %q / Resource Group %s) ID", jobScheduleUUID, accountName, resGroup) } d.SetId(*read.ID) @@ -138,21 +144,22 @@ func resourceArmAutomationJobScheduleRead(d *schema.ResourceData, meta interface return err } - name := id.Path["jobSchedules"] - nameUUID := uuid.FromStringOrNil(name) + jobScheduleID := id.Path["jobSchedules"] + jobScheduleUUID := uuid.FromStringOrNil(jobScheduleID) resGroup := id.ResourceGroup accountName := id.Path["automationAccounts"] - resp, err := client.Get(ctx, resGroup, accountName, nameUUID) + resp, err := client.Get(ctx, resGroup, accountName, jobScheduleUUID) if err != nil { if utils.ResponseWasNotFound(resp.Response) { d.SetId("") return nil } - return fmt.Errorf("Error making Read request on AzureRM Automation Job Schedule '%s': %+v", nameUUID, err) + return fmt.Errorf("Error making Read request on AzureRM Automation Job Schedule '%s': %+v", jobScheduleUUID, err) } + d.Set("job_schedule_id", resp.JobScheduleID) d.Set("resource_group_name", resGroup) d.Set("automation_account_name", accountName) d.Set("runbook_name", resp.JobScheduleProperties.Runbook.Name) @@ -182,15 +189,15 @@ func resourceArmAutomationJobScheduleDelete(d *schema.ResourceData, meta interfa return err } - name := id.Path["jobSchedules"] - nameUUID := uuid.FromStringOrNil(name) + jobScheduleID := id.Path["jobSchedules"] + jobScheduleUUID := uuid.FromStringOrNil(jobScheduleID) resGroup := id.ResourceGroup accountName := id.Path["automationAccounts"] - resp, err := client.Delete(ctx, resGroup, accountName, nameUUID) + resp, err := client.Delete(ctx, resGroup, accountName, jobScheduleUUID) if err != nil { if !utils.ResponseWasNotFound(resp) { - return fmt.Errorf("Error issuing AzureRM delete request for Automation Job Schedule '%s': %+v", nameUUID, err) + return fmt.Errorf("Error issuing AzureRM delete request for Automation Job Schedule '%s': %+v", jobScheduleUUID, err) } } diff --git a/azurerm/resource_arm_automation_job_schedule_test.go b/azurerm/resource_arm_automation_job_schedule_test.go index 387ecd1c1825..2f5e634ee1c1 100644 --- a/azurerm/resource_arm_automation_job_schedule_test.go +++ b/azurerm/resource_arm_automation_job_schedule_test.go @@ -73,16 +73,16 @@ func testCheckAzureRMAutomationJobScheduleDestroy(s *terraform.State) error { if err != nil { return err } - name := id.Path["jobSchedules"] - nameUUID := uuid.FromStringOrNil(name) + jobScheduleID := id.Path["jobSchedules"] + jobScheduleUUID := uuid.FromStringOrNil(jobScheduleID) accName := rs.Primary.Attributes["account_name"] resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] if !hasResourceGroup { - return fmt.Errorf("Bad: no resource group found in state for Automation Job Schedule: '%s'", name) + return fmt.Errorf("Bad: no resource group found in state for Automation Job Schedule: '%s'", jobScheduleUUID) } - resp, err := conn.Get(ctx, resourceGroup, accName, nameUUID) + resp, err := conn.Get(ctx, resourceGroup, accName, jobScheduleUUID) if err != nil { if utils.ResponseWasNotFound(resp.Response) { @@ -113,19 +113,19 @@ func testCheckAzureRMAutomationJobScheduleExists(resourceName string) resource.T if err != nil { return err } - name := id.Path["jobSchedules"] - nameUUID := uuid.FromStringOrNil(name) + jobScheduleID := id.Path["jobSchedules"] + jobScheduleUUID := uuid.FromStringOrNil(jobScheduleID) 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 Job Schedule: '%s'", name) + return fmt.Errorf("Bad: no resource group found in state for Automation Job Schedule: '%s'", jobScheduleUUID) } - resp, err := conn.Get(ctx, resourceGroup, accName, nameUUID) + resp, err := conn.Get(ctx, resourceGroup, accName, jobScheduleUUID) if err != nil { if utils.ResponseWasNotFound(resp.Response) { - return fmt.Errorf("Automation Job Schedule '%s' (Account %q / Resource Group %q) does not exist", name, accName, resourceGroup) + return fmt.Errorf("Automation Job Schedule '%s' (Account %q / Resource Group %q) does not exist", jobScheduleUUID, accName, resourceGroup) } return fmt.Errorf("Bad: Get on automationJobScheduleClient: %+v", err) @@ -194,6 +194,7 @@ resource "azurerm_automation_job_schedule" "test" { func checkAccAzureRMAutomationJobScheduleCreate(resourceName string) resource.TestCheckFunc { return resource.ComposeAggregateTestCheckFunc( testCheckAzureRMAutomationJobScheduleExists(resourceName), + resource.TestCheckResourceAttrSet(resourceName, "job_schedule_id"), resource.TestCheckResourceAttrSet(resourceName, "resource_group_name"), resource.TestCheckResourceAttrSet(resourceName, "automation_account_name"), resource.TestCheckResourceAttrSet(resourceName, "schedule_name"), diff --git a/website/docs/r/automation_job_schedule.html.markdown b/website/docs/r/automation_job_schedule.html.markdown index 4a1df01dc32e..940b75c41d80 100644 --- a/website/docs/r/automation_job_schedule.html.markdown +++ b/website/docs/r/automation_job_schedule.html.markdown @@ -90,11 +90,13 @@ The following arguments are supported: The following attributes are exported: -* `id` - The Automation Schedule ID. +* `id` - The Automation Job Schedule's full ID. + +* `job_schedule_id` - The UUID identifying the Automation Job Schedule. ## Import -Automation Schedule can be imported using the `resource id`, e.g. +Automation Job Schedule can be imported using the `resource id`, e.g. ```shell terraform import azurerm_automation_job_schedule.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/group1/providers/Microsoft.Automation/automationAccounts/account1/jobSchedules/10000000-1001-1001-1001-000000000001 From 4335da9b91b1c17f69766c565408d65e0fd05770 Mon Sep 17 00:00:00 2001 From: Tony Fortes Ramos Date: Thu, 9 May 2019 00:14:03 +0200 Subject: [PATCH 08/21] Add Automation input validation --- azurerm/helpers/azure/automation.go | 32 +++++++++++++++++++ .../resource_arm_automation_job_schedule.go | 4 +++ 2 files changed, 36 insertions(+) create mode 100644 azurerm/helpers/azure/automation.go diff --git a/azurerm/helpers/azure/automation.go b/azurerm/helpers/azure/automation.go new file mode 100644 index 000000000000..3f819b5140e9 --- /dev/null +++ b/azurerm/helpers/azure/automation.go @@ -0,0 +1,32 @@ +package azure + +import ( + "regexp" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" +) + +// ValidateAutomationAccountName validates Automation Account names +func ValidateAutomationAccountName() schema.SchemaValidateFunc { + return validation.StringMatch( + regexp.MustCompile(`^[0-9a-zA-Z][-0-9a-zA-Z]{4,48}[0-9a-zA-Z]$`), + `The account name must not be empty, and must not exceed 50 characters in length. The account name must start with a letter or number. The account name can contain letters, numbers, and dashes. The final character must be a letter or a number. The account name length must be from 6 to 50 characters.`, + ) +} + +// ValidateAutomationRunbookName validates Automation Account Runbook names +func ValidateAutomationRunbookName() schema.SchemaValidateFunc { + return validation.StringMatch( + regexp.MustCompile(`^[0-9a-zA-Z][-_0-9a-zA-Z]{0,62}$`), + `The name can contain only letters, numbers, underscores and dashes. The name must begin with a letter. The name must be less than 64 characters.`, + ) +} + +// ValidateAutomationScheduleName validates Automation Account Schedule names +func ValidateAutomationScheduleName() schema.SchemaValidateFunc { + return validation.StringMatch( + regexp.MustCompile(`^[^<>*%&:\\?.+\/]{0,127}[^<>*%&:\\?.+\/\s]$`), + `The name length must be from 1 to 128 characters. The name cannot contain special characters < > * % & : \ ? . + / and cannot end with a whitespace character.`, + ) +} diff --git a/azurerm/resource_arm_automation_job_schedule.go b/azurerm/resource_arm_automation_job_schedule.go index bc681c153f91..10991467f8b8 100644 --- a/azurerm/resource_arm_automation_job_schedule.go +++ b/azurerm/resource_arm_automation_job_schedule.go @@ -7,6 +7,7 @@ import ( "github.com/Azure/azure-sdk-for-go/services/automation/mgmt/2015-10-31/automation" "github.com/hashicorp/terraform/helper/schema" uuid "github.com/satori/go.uuid" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -29,18 +30,21 @@ func resourceArmAutomationJobSchedule() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, + ValidateFunc: azure.ValidateAutomationAccountName(), }, "runbook_name": { Type: schema.TypeString, Required: true, ForceNew: true, + ValidateFunc: azure.ValidateAutomationRunbookName(), }, "schedule_name": { Type: schema.TypeString, Required: true, ForceNew: true, + ValidateFunc: azure.ValidateAutomationScheduleName(), }, "parameters": { From 644c5f85bb92853b852d921635fdc02e6e2333b8 Mon Sep 17 00:00:00 2001 From: Tony Fortes Ramos Date: Thu, 9 May 2019 00:28:05 +0200 Subject: [PATCH 09/21] Update examples --- examples/automation-account/main.tf | 23 +++++++ .../r/automation_job_schedule.html.markdown | 60 +++---------------- 2 files changed, 31 insertions(+), 52 deletions(-) diff --git a/examples/automation-account/main.tf b/examples/automation-account/main.tf index 8c22df14629a..0b7726282403 100644 --- a/examples/automation-account/main.tf +++ b/examples/automation-account/main.tf @@ -13,6 +13,21 @@ resource "azurerm_automation_account" "example" { } } +resource "azurerm_automation_runbook" "example" { + name = "Get-AzureVMTutorial" + location = "${azurerm_resource_group.example.location}" + resource_group_name = "${azurerm_resource_group.example.name}" + account_name = "${azurerm_automation_account.example.name}" + log_verbose = "true" + log_progress = "true" + description = "This is an example runbook" + runbook_type = "PowerShellWorkflow" + + publish_content_link { + uri = "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-automation-runbook-getvms/Runbooks/Get-AzureVMTutorial.ps1" + } +} + resource "azurerm_automation_schedule" "one-time" { name = "${var.prefix}-one-time" resource_group_name = "${azurerm_resource_group.example.name}" @@ -31,3 +46,11 @@ resource "azurerm_automation_schedule" "hour" { // Timezone defaults to UTC } + + // Schedules the example runbook to run on the hour schedule +resource "azurerm_automation_job_schedule" "example" { + resource_group_name = "${azurerm_resource_group.example.name}" + automation_account_name = "${azurerm_automation_account.example.name}" + runbook_name = "${azurerm_automation_runbook.example.name}" + schedule_name = "${azurerm_automation_schedule.hour.name}" +} diff --git a/website/docs/r/automation_job_schedule.html.markdown b/website/docs/r/automation_job_schedule.html.markdown index 940b75c41d80..1888d26fb2ef 100644 --- a/website/docs/r/automation_job_schedule.html.markdown +++ b/website/docs/r/automation_job_schedule.html.markdown @@ -12,64 +12,20 @@ Links an Automation Runbook and Schedule. ## Example Usage -```hcl -resource "azurerm_resource_group" "example" { - name = "tfex-automation-account" - location = "West Europe" -} - -resource "azurerm_automation_account" "example" { - name = "tfex-automation-account" - location = "${azurerm_resource_group.example.location}" - resource_group_name = "${azurerm_resource_group.example.name}" - - sku { - name = "Basic" - } -} - -resource "azurerm_automation_runbook" "example" { - name = "Get-AzureVMTutorial" - location = "${azurerm_resource_group.example.location}" - resource_group_name = "${azurerm_resource_group.example.name}" - account_name = "${azurerm_automation_account.example.name}" - log_verbose = "true" - log_progress = "true" - description = "This is an example runbook" - runbook_type = "PowerShellWorkflow" - - publish_content_link { - uri = "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-automation-runbook-getvms/Runbooks/Get-AzureVMTutorial.ps1" - } -} - -resource "azurerm_automation_schedule" "example" { - name = "tfex-automation-schedule" - resource_group_name = "${azurerm_resource_group.example.name}" - automation_account_name = "${azurerm_automation_account.example.name}" - frequency = "Week" - interval = 1 - timezone = "Central Europe Standard Time" - start_time = "2014-04-15T18:00:15+02:00" - description = "This is an example schedule" - - advanced_schedule { - week_days = ["Friday"] - } -} +This is an example of just the Job Schedule. A full example of the `azurerm_automation_job_schedule` resource can be found in [the `./examples/automation-account` directory within the Github Repository](https://github.com/terraform-providers/terraform-provider-azurerm/tree/master/examples/automation-account) +```hcl resource "azurerm_automation_job_schedule" "example" { - resource_group_name = "${azurerm_resource_group.example.name}" - automation_account_name = "${azurerm_automation_account.example.name}" - schedule_name = "${azurerm_automation_schedule.example.name}" - runbook_name = "${azurerm_automation_runbook.example.name}" + resource_group_name = "tf-rgr-automation" + automation_account_name = "tf-automation-account" + schedule_name = "hour" + runbook_name = "Get-VirtualMachine" parameters = { - Connection = "AzureRunAsConnection" - VMCount = 10 + ResourceGroup = "tf-rgr-vm" + VMName = "tf-vm-01" } } - ``` ## Argument Reference From 5868c1ec81630a7e2acbef94817a50071591ee34 Mon Sep 17 00:00:00 2001 From: Tony Fortes Ramos Date: Thu, 9 May 2019 00:29:18 +0200 Subject: [PATCH 10/21] Fix validation description --- azurerm/helpers/azure/automation.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azurerm/helpers/azure/automation.go b/azurerm/helpers/azure/automation.go index 3f819b5140e9..354271fc1cff 100644 --- a/azurerm/helpers/azure/automation.go +++ b/azurerm/helpers/azure/automation.go @@ -11,7 +11,7 @@ import ( func ValidateAutomationAccountName() schema.SchemaValidateFunc { return validation.StringMatch( regexp.MustCompile(`^[0-9a-zA-Z][-0-9a-zA-Z]{4,48}[0-9a-zA-Z]$`), - `The account name must not be empty, and must not exceed 50 characters in length. The account name must start with a letter or number. The account name can contain letters, numbers, and dashes. The final character must be a letter or a number. The account name length must be from 6 to 50 characters.`, + `The account name must start with a letter or number. The account name can contain letters, numbers, and dashes. The final character must be a letter or a number. The account name length must be from 6 to 50 characters.`, ) } From 8e3e501ed46cb5806fef5a27dc5eba983bef1ba8 Mon Sep 17 00:00:00 2001 From: Tony Fortes Ramos Date: Thu, 9 May 2019 15:36:31 +0200 Subject: [PATCH 11/21] Add requested tests --- ...source_arm_automation_job_schedule_test.go | 113 ++++++++++++++++-- 1 file changed, 102 insertions(+), 11 deletions(-) diff --git a/azurerm/resource_arm_automation_job_schedule_test.go b/azurerm/resource_arm_automation_job_schedule_test.go index 2f5e634ee1c1..dc69488b4a88 100644 --- a/azurerm/resource_arm_automation_job_schedule_test.go +++ b/azurerm/resource_arm_automation_job_schedule_test.go @@ -3,6 +3,7 @@ package azurerm import ( "fmt" "testing" + "math/rand" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" @@ -11,9 +12,31 @@ import ( "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) -func TestAccAzureRMAutomationJobScheduleCreate(t *testing.T) { +func TestAccAzureRMAutomationJobSchedule_basic(t *testing.T) { resourceName := "azurerm_automation_job_schedule.test" - ri := tf.AccRandTimeInt() + ri := rand.Int() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAutomationJobScheduleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationJobSchedule_basic(ri, testLocation()), + Check: checkAccAzureRMAutomationJobSchedule_basic(resourceName), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMAutomationJobSchedule_complete(t *testing.T) { + resourceName := "azurerm_automation_job_schedule.test" + ri := rand.Int() resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -21,8 +44,38 @@ func TestAccAzureRMAutomationJobScheduleCreate(t *testing.T) { CheckDestroy: testCheckAzureRMAutomationJobScheduleDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMAutomationJobScheduleCreate(ri, testLocation()), - Check: checkAccAzureRMAutomationJobScheduleCreate(resourceName), + Config: testAccAzureRMAutomationJobSchedule_complete(ri, testLocation()), + Check: checkAccAzureRMAutomationJobSchedule_complete(resourceName), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMAutomationJobSchedule_update(t *testing.T) { + resourceName := "azurerm_automation_job_schedule.test" + ri := rand.Int() + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMAutomationJobScheduleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMAutomationJobSchedule_basic(ri, testLocation()), + Check: checkAccAzureRMAutomationJobSchedule_basic(resourceName), + }, + { + Config: testAccAzureRMAutomationJobSchedule_complete(ri, testLocation()), + Check: checkAccAzureRMAutomationJobSchedule_complete(resourceName), + }, + { + Config: testAccAzureRMAutomationJobSchedule_basic(ri, testLocation()), + Check: checkAccAzureRMAutomationJobSchedule_basic(resourceName), }, { ResourceName: resourceName, @@ -49,8 +102,8 @@ func TestAccAzureRMAutomationJobSchedule_requiresImport(t *testing.T) { CheckDestroy: testCheckAzureRMAutomationJobScheduleDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMAutomationJobScheduleCreate(ri, location), - Check: checkAccAzureRMAutomationJobScheduleCreate(resourceName), + Config: testAccAzureRMAutomationJobSchedule_basic(ri, location), + Check: checkAccAzureRMAutomationJobSchedule_basic(resourceName), }, { Config: testAccAzureRMAutomationJobSchedule_requiresImport(ri, location), @@ -153,7 +206,7 @@ resource "azurerm_automation_account" "test" { } resource "azurerm_automation_runbook" "test" { - name = "Get-AzureVMTutorial" + name = "Output-HelloWorld" location = "${azurerm_resource_group.test.location}" resource_group_name = "${azurerm_resource_group.test.name}" @@ -161,11 +214,18 @@ resource "azurerm_automation_runbook" "test" { log_verbose = "true" log_progress = "true" description = "This is a test runbook for terraform acceptance test" - runbook_type = "PowerShellWorkflow" + runbook_type = "PowerShell" publish_content_link { uri = "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-automation-runbook-getvms/Runbooks/Get-AzureVMTutorial.ps1" } + + content = < Date: Thu, 9 May 2019 15:46:32 +0200 Subject: [PATCH 12/21] run gofmt --- .../resource_arm_automation_job_schedule.go | 18 +++++++++--------- ...esource_arm_automation_job_schedule_test.go | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/azurerm/resource_arm_automation_job_schedule.go b/azurerm/resource_arm_automation_job_schedule.go index 10991467f8b8..c9f86b1ded9f 100644 --- a/azurerm/resource_arm_automation_job_schedule.go +++ b/azurerm/resource_arm_automation_job_schedule.go @@ -27,23 +27,23 @@ func resourceArmAutomationJobSchedule() *schema.Resource { "resource_group_name": resourceGroupNameSchema(), "automation_account_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, ValidateFunc: azure.ValidateAutomationAccountName(), }, "runbook_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, ValidateFunc: azure.ValidateAutomationRunbookName(), }, "schedule_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, ValidateFunc: azure.ValidateAutomationScheduleName(), }, diff --git a/azurerm/resource_arm_automation_job_schedule_test.go b/azurerm/resource_arm_automation_job_schedule_test.go index dc69488b4a88..077e1508ce6a 100644 --- a/azurerm/resource_arm_automation_job_schedule_test.go +++ b/azurerm/resource_arm_automation_job_schedule_test.go @@ -2,8 +2,8 @@ package azurerm import ( "fmt" - "testing" "math/rand" + "testing" "github.com/hashicorp/terraform/helper/resource" "github.com/hashicorp/terraform/terraform" From 347d7076dc98b27545ca63a1c3081143c1a781db Mon Sep 17 00:00:00 2001 From: Tony Fortes Ramos Date: Sat, 11 May 2019 01:04:31 +0200 Subject: [PATCH 13/21] Revert random int back to tf.AccRandTimeInt() --- azurerm/resource_arm_automation_job_schedule_test.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/azurerm/resource_arm_automation_job_schedule_test.go b/azurerm/resource_arm_automation_job_schedule_test.go index 077e1508ce6a..06c96de59aef 100644 --- a/azurerm/resource_arm_automation_job_schedule_test.go +++ b/azurerm/resource_arm_automation_job_schedule_test.go @@ -2,7 +2,6 @@ package azurerm import ( "fmt" - "math/rand" "testing" "github.com/hashicorp/terraform/helper/resource" @@ -14,7 +13,7 @@ import ( func TestAccAzureRMAutomationJobSchedule_basic(t *testing.T) { resourceName := "azurerm_automation_job_schedule.test" - ri := rand.Int() + ri := tf.AccRandTimeInt() resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -36,7 +35,7 @@ func TestAccAzureRMAutomationJobSchedule_basic(t *testing.T) { func TestAccAzureRMAutomationJobSchedule_complete(t *testing.T) { resourceName := "azurerm_automation_job_schedule.test" - ri := rand.Int() + ri := tf.AccRandTimeInt() resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -58,7 +57,7 @@ func TestAccAzureRMAutomationJobSchedule_complete(t *testing.T) { func TestAccAzureRMAutomationJobSchedule_update(t *testing.T) { resourceName := "azurerm_automation_job_schedule.test" - ri := rand.Int() + ri := tf.AccRandTimeInt() resource.ParallelTest(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, From e1f6e39d453d697296fa907ad429bbea98690915 Mon Sep 17 00:00:00 2001 From: kt Date: Thu, 16 May 2019 10:09:04 -0700 Subject: [PATCH 14/21] added more Cased parameters to test --- azurerm/resource_arm_automation_job_schedule_test.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/azurerm/resource_arm_automation_job_schedule_test.go b/azurerm/resource_arm_automation_job_schedule_test.go index 06c96de59aef..f8535096d71e 100644 --- a/azurerm/resource_arm_automation_job_schedule_test.go +++ b/azurerm/resource_arm_automation_job_schedule_test.go @@ -273,7 +273,11 @@ resource "azurerm_automation_job_schedule" "test" { runbook_name = "${azurerm_automation_runbook.test.name}" parameters = { - output = "Earth" + OutPut = "Earth" + Case = "MATTERS" + KeepCount = "20" + WebhookUri = "http://www.example.com/hook" + URL = "https://www.Example.com" } } `, template) @@ -287,8 +291,12 @@ func checkAccAzureRMAutomationJobSchedule_complete(resourceName string) resource resource.TestCheckResourceAttrSet(resourceName, "automation_account_name"), resource.TestCheckResourceAttrSet(resourceName, "schedule_name"), resource.TestCheckResourceAttrSet(resourceName, "runbook_name"), - resource.TestCheckResourceAttr(resourceName, "parameters.%", "1"), + resource.TestCheckResourceAttr(resourceName, "parameters.%", "5"), resource.TestCheckResourceAttr(resourceName, "parameters.output", "Earth"), + resource.TestCheckResourceAttr(resourceName, "parameters.Case", "MATTERS"), + resource.TestCheckResourceAttr(resourceName, "parameters.KeepCount", "20"), + resource.TestCheckResourceAttr(resourceName, "parameters.WebhookUri", "http://www.example.com/hook"), + resource.TestCheckResourceAttr(resourceName, "parameters.URL", "https://www.Example.com"), ) } From 74c1a2b701dd72e39d7996f3c9ef5237e7589dff Mon Sep 17 00:00:00 2001 From: Tony Fortes Ramos Date: Sun, 19 May 2019 23:22:10 +0200 Subject: [PATCH 15/21] Update test playbook --- .../resource_arm_automation_job_schedule_test.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/azurerm/resource_arm_automation_job_schedule_test.go b/azurerm/resource_arm_automation_job_schedule_test.go index f8535096d71e..7befa508448f 100644 --- a/azurerm/resource_arm_automation_job_schedule_test.go +++ b/azurerm/resource_arm_automation_job_schedule_test.go @@ -221,7 +221,15 @@ resource "azurerm_automation_runbook" "test" { content = < Date: Mon, 14 Oct 2019 02:02:17 +0200 Subject: [PATCH 16/21] Migrate stuff over to the new style --- azurerm/helpers/azure/automation.go | 4 +-- .../internal/services/automation/client.go | 1 + .../resource_arm_automation_job_schedule.go | 31 +++++++++++++------ 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/azurerm/helpers/azure/automation.go b/azurerm/helpers/azure/automation.go index 354271fc1cff..8b67d481c0d2 100644 --- a/azurerm/helpers/azure/automation.go +++ b/azurerm/helpers/azure/automation.go @@ -3,8 +3,8 @@ package azure import ( "regexp" - "github.com/hashicorp/terraform/helper/schema" - "github.com/hashicorp/terraform/helper/validation" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" ) // ValidateAutomationAccountName validates Automation Account names diff --git a/azurerm/internal/services/automation/client.go b/azurerm/internal/services/automation/client.go index 3722528f39bf..bf534361e3da 100644 --- a/azurerm/internal/services/automation/client.go +++ b/azurerm/internal/services/automation/client.go @@ -11,6 +11,7 @@ type Client struct { CredentialClient *automation.CredentialClient DscConfigurationClient *automation.DscConfigurationClient DscNodeConfigurationClient *automation.DscNodeConfigurationClient + JobScheduleClient *automation.JobScheduleClient ModuleClient *automation.ModuleClient RunbookClient *automation.RunbookClient RunbookDraftClient *automation.RunbookDraftClient diff --git a/azurerm/resource_arm_automation_job_schedule.go b/azurerm/resource_arm_automation_job_schedule.go index c9f86b1ded9f..8583a6acc42b 100644 --- a/azurerm/resource_arm_automation_job_schedule.go +++ b/azurerm/resource_arm_automation_job_schedule.go @@ -3,12 +3,15 @@ package azurerm import ( "fmt" "log" + "strings" + "time" "github.com/Azure/azure-sdk-for-go/services/automation/mgmt/2015-10-31/automation" - "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" uuid "github.com/satori/go.uuid" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -22,9 +25,16 @@ func resourceArmAutomationJobSchedule() *schema.Resource { State: schema.ImportStatePassthrough, }, + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + Schema: map[string]*schema.Schema{ - "resource_group_name": resourceGroupNameSchema(), + "resource_group_name": azure.SchemaResourceGroupName(), "automation_account_name": { Type: schema.TypeString, @@ -69,8 +79,9 @@ func resourceArmAutomationJobSchedule() *schema.Resource { } func resourceArmAutomationJobScheduleCreate(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient).automationJobScheduleClient - ctx := meta.(*ArmClient).StopContext + client := meta.(*ArmClient).Automation.JobScheduleClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*ArmClient).StopContext, d) + defer cancel() log.Printf("[INFO] preparing arguments for AzureRM Automation Job Schedule creation.") @@ -140,8 +151,9 @@ func resourceArmAutomationJobScheduleCreate(d *schema.ResourceData, meta interfa } func resourceArmAutomationJobScheduleRead(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient).automationJobScheduleClient - ctx := meta.(*ArmClient).StopContext + client := meta.(*ArmClient).Automation.JobScheduleClient + ctx, cancel := timeouts.ForRead(meta.(*ArmClient).StopContext, d) + defer cancel() id, err := parseAzureResourceID(d.Id()) if err != nil { @@ -176,7 +188,7 @@ func resourceArmAutomationJobScheduleRead(d *schema.ResourceData, meta interface if v := resp.JobScheduleProperties.Parameters; v != nil { jsParameters := make(map[string]interface{}) for key, value := range v { - jsParameters[key] = value + jsParameters[strings.ToLower(key)] = value } d.Set("parameters", jsParameters) } @@ -185,8 +197,9 @@ func resourceArmAutomationJobScheduleRead(d *schema.ResourceData, meta interface } func resourceArmAutomationJobScheduleDelete(d *schema.ResourceData, meta interface{}) error { - client := meta.(*ArmClient).automationJobScheduleClient - ctx := meta.(*ArmClient).StopContext + client := meta.(*ArmClient).Automation.JobScheduleClient + ctx, cancel := timeouts.ForDelete(meta.(*ArmClient).StopContext, d) + defer cancel() id, err := parseAzureResourceID(d.Id()) if err != nil { From ef659e3c8581404a8f605964dd0619fc85ffccd9 Mon Sep 17 00:00:00 2001 From: Tony Fortes Ramos Date: Mon, 14 Oct 2019 02:18:29 +0200 Subject: [PATCH 17/21] Add validation --- azurerm/resource_arm_automation_job_schedule.go | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/azurerm/resource_arm_automation_job_schedule.go b/azurerm/resource_arm_automation_job_schedule.go index 8583a6acc42b..88a42b03dc08 100644 --- a/azurerm/resource_arm_automation_job_schedule.go +++ b/azurerm/resource_arm_automation_job_schedule.go @@ -61,6 +61,17 @@ func resourceArmAutomationJobSchedule() *schema.Resource { Type: schema.TypeMap, Optional: true, ForceNew: true, + ValidateFunc: func(v interface{}, _ string) (warnings []string, errors []error) { + m := v.(map[string]interface{}) + + for k := range m { + if k != strings.ToLower(k) { + errors = append(errors, fmt.Errorf("Due to a bug in the implementation of Runbooks in Azure, the parameter names need to be specified in lowercase only. See: \"https://github.com/Azure/azure-sdk-for-go/issues/4780\" for more information.")) + } + } + + return warnings, errors + }, }, "run_on": { From c582607f5ffb860554e78af45bc4cc41d6e0b42c Mon Sep 17 00:00:00 2001 From: Tony Fortes Ramos Date: Mon, 14 Oct 2019 16:54:58 +0200 Subject: [PATCH 18/21] Fix tests --- azurerm/resource_arm_automation_job_schedule_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/azurerm/resource_arm_automation_job_schedule_test.go b/azurerm/resource_arm_automation_job_schedule_test.go index 7befa508448f..2a5851a2c4bb 100644 --- a/azurerm/resource_arm_automation_job_schedule_test.go +++ b/azurerm/resource_arm_automation_job_schedule_test.go @@ -4,8 +4,8 @@ import ( "fmt" "testing" - "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" uuid "github.com/satori/go.uuid" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" @@ -113,7 +113,7 @@ func TestAccAzureRMAutomationJobSchedule_requiresImport(t *testing.T) { } func testCheckAzureRMAutomationJobScheduleDestroy(s *terraform.State) error { - conn := testAccProvider.Meta().(*ArmClient).automationJobScheduleClient + conn := testAccProvider.Meta().(*ArmClient).Automation.JobScheduleClient ctx := testAccProvider.Meta().(*ArmClient).StopContext for _, rs := range s.RootModule().Resources { @@ -152,7 +152,7 @@ func testCheckAzureRMAutomationJobScheduleDestroy(s *terraform.State) error { func testCheckAzureRMAutomationJobScheduleExists(resourceName string) resource.TestCheckFunc { return func(s *terraform.State) error { - conn := testAccProvider.Meta().(*ArmClient).automationJobScheduleClient + conn := testAccProvider.Meta().(*ArmClient).Automation.JobScheduleClient ctx := testAccProvider.Meta().(*ArmClient).StopContext // Ensure we have enough information in state to look up in API From f068da5e566a12593da9aa5dab02ba69f89ed261 Mon Sep 17 00:00:00 2001 From: Tony Fortes Ramos Date: Tue, 15 Oct 2019 00:10:53 +0200 Subject: [PATCH 19/21] Update tests --- .../resource_arm_automation_job_schedule.go | 3 +++ ...source_arm_automation_job_schedule_test.go | 20 +++++++++---------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/azurerm/resource_arm_automation_job_schedule.go b/azurerm/resource_arm_automation_job_schedule.go index 88a42b03dc08..61f0799cd430 100644 --- a/azurerm/resource_arm_automation_job_schedule.go +++ b/azurerm/resource_arm_automation_job_schedule.go @@ -61,6 +61,9 @@ func resourceArmAutomationJobSchedule() *schema.Resource { Type: schema.TypeMap, Optional: true, ForceNew: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, ValidateFunc: func(v interface{}, _ string) (warnings []string, errors []error) { m := v.(map[string]interface{}) diff --git a/azurerm/resource_arm_automation_job_schedule_test.go b/azurerm/resource_arm_automation_job_schedule_test.go index 2a5851a2c4bb..4cf31122aab7 100644 --- a/azurerm/resource_arm_automation_job_schedule_test.go +++ b/azurerm/resource_arm_automation_job_schedule_test.go @@ -281,11 +281,11 @@ resource "azurerm_automation_job_schedule" "test" { runbook_name = "${azurerm_automation_runbook.test.name}" parameters = { - OutPut = "Earth" - Case = "MATTERS" - KeepCount = 20 - WebhookUri = "http://www.example.com/hook" - URL = "https://www.Example.com" + output = "Earth" + case = "MATTERS" + keepcount = 20 + webhookuri = "http://www.example.com/hook" + url = "https://www.Example.com" } } `, template) @@ -300,11 +300,11 @@ func checkAccAzureRMAutomationJobSchedule_complete(resourceName string) resource resource.TestCheckResourceAttrSet(resourceName, "schedule_name"), resource.TestCheckResourceAttrSet(resourceName, "runbook_name"), resource.TestCheckResourceAttr(resourceName, "parameters.%", "5"), - resource.TestCheckResourceAttr(resourceName, "parameters.Output", "Earth"), - resource.TestCheckResourceAttr(resourceName, "parameters.Case", "MATTERS"), - resource.TestCheckResourceAttr(resourceName, "parameters.KeepCount", "20"), - resource.TestCheckResourceAttr(resourceName, "parameters.WebhookUri", "http://www.example.com/hook"), - resource.TestCheckResourceAttr(resourceName, "parameters.URL", "https://www.Example.com"), + resource.TestCheckResourceAttr(resourceName, "parameters.output", "Earth"), + resource.TestCheckResourceAttr(resourceName, "parameters.case", "MATTERS"), + resource.TestCheckResourceAttr(resourceName, "parameters.keepcount", "20"), + resource.TestCheckResourceAttr(resourceName, "parameters.webhookuri", "http://www.example.com/hook"), + resource.TestCheckResourceAttr(resourceName, "parameters.url", "https://www.Example.com"), ) } From 50866ccdd9ea7a4687dd8456ca97f1e3c48ee2e1 Mon Sep 17 00:00:00 2001 From: Tony Fortes Ramos Date: Thu, 17 Oct 2019 00:17:02 +0200 Subject: [PATCH 20/21] Update docs --- website/docs/r/automation_job_schedule.html.markdown | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/website/docs/r/automation_job_schedule.html.markdown b/website/docs/r/automation_job_schedule.html.markdown index 1888d26fb2ef..14eb1b181300 100644 --- a/website/docs/r/automation_job_schedule.html.markdown +++ b/website/docs/r/automation_job_schedule.html.markdown @@ -22,8 +22,8 @@ resource "azurerm_automation_job_schedule" "example" { runbook_name = "Get-VirtualMachine" parameters = { - ResourceGroup = "tf-rgr-vm" - VMName = "tf-vm-01" + resourcegroup = "tf-rgr-vm" + vmname = "TF-VM-01" } } ``` @@ -40,6 +40,8 @@ The following arguments are supported: * `parameters` - (Optional) A map of key/value pairs corresponding to the arguments that can be passed to the Runbook. Changing this forces a new resource to be created. +-> **NOTE:** The parameter keys/names must strictly be in lowercase, even if this is not the case in the runbook. This is due to a limitation in Azure Automation where the parameter names are normalized. The values specified don't have this limitation. + * `run_on` - (Optional) Name of a Hybrid Worker Group the Runbook will be executed on. Changing this forces a new resource to be created. ## Attributes Reference From e7ee900eec0281e7853f8a351644cb48027f9f98 Mon Sep 17 00:00:00 2001 From: Tony Fortes Ramos Date: Fri, 18 Oct 2019 23:30:48 +0200 Subject: [PATCH 21/21] Fix job schedule publishing url --- azurerm/resource_arm_automation_job_schedule_test.go | 2 +- azurerm/resource_arm_automation_runbook_test.go | 8 ++++---- examples/automation-account/main.tf | 2 +- website/docs/r/automation_runbook.html.markdown | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/azurerm/resource_arm_automation_job_schedule_test.go b/azurerm/resource_arm_automation_job_schedule_test.go index 4cf31122aab7..cc516712f74f 100644 --- a/azurerm/resource_arm_automation_job_schedule_test.go +++ b/azurerm/resource_arm_automation_job_schedule_test.go @@ -216,7 +216,7 @@ resource "azurerm_automation_runbook" "test" { runbook_type = "PowerShell" publish_content_link { - uri = "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/master/101-automation-runbook-getvms/Runbooks/Get-AzureVMTutorial.ps1" + uri = "https://raw.githubusercontent.com/Azure/azure-quickstart-templates/c4935ffb69246a6058eb24f54640f53f69d3ac9f/101-automation-runbook-getvms/Runbooks/Get-AzureVMTutorial.ps1" } content = <