From f1c9ef60455cc849a6c32d72f5524a41f94fee7f Mon Sep 17 00:00:00 2001 From: kt Date: Fri, 16 Mar 2018 11:33:28 -0700 Subject: [PATCH 01/18] Intial commit of scheduler_job --- GNUmakefile | 3 + azurerm/config.go | 23 +- azurerm/helpers/set/set.go | 16 + azurerm/helpers/supress/suppress.go | 23 + azurerm/helpers/supress/suppress_test.go | 88 ++ azurerm/helpers/validate/validator.go | 31 + azurerm/helpers/validate/validator_test.go | 43 + azurerm/provider.go | 2 + azurerm/resource_arm_scheduler_job.go | 995 +++++++++++++++++ .../resource_arm_scheduler_job_collection.go | 27 +- azurerm/resource_arm_scheduler_job_test.go | 999 ++++++++++++++++++ azurerm/validators.go | 5 + examples/scheduler-jobs/main.tf | 164 ++- examples/scheduler-jobs/outputs.tf | 21 +- website/azurerm.erb | 5 + website/docs/r/scheduler_job.html.markdown | 226 ++++ .../r/scheduler_job_collection.html.markdown | 4 +- 17 files changed, 2650 insertions(+), 25 deletions(-) create mode 100644 azurerm/helpers/set/set.go create mode 100644 azurerm/helpers/supress/suppress.go create mode 100644 azurerm/helpers/supress/suppress_test.go create mode 100644 azurerm/helpers/validate/validator.go create mode 100644 azurerm/helpers/validate/validator_test.go create mode 100644 azurerm/resource_arm_scheduler_job.go create mode 100644 azurerm/resource_arm_scheduler_job_test.go create mode 100644 website/docs/r/scheduler_job.html.markdown diff --git a/GNUmakefile b/GNUmakefile index 20581cad41e5..bfc6884e4acf 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -14,6 +14,9 @@ test: fmtcheck testacc: fmtcheck TF_ACC=1 go test $(TEST) -v $(TESTARGS) -timeout 180m +debugacc: fmtcheck + TF_ACC=1 dlv test $(TEST) --headless --listen=:2345 --api-version=2 -- -test.v $(TESTARGS) + vet: @echo "go vet ." @go vet $$(go list ./... | grep -v vendor/) ; if [ $$? -eq 1 ]; then \ diff --git a/azurerm/config.go b/azurerm/config.go index f8b15910ad20..c20463a19e53 100644 --- a/azurerm/config.go +++ b/azurerm/config.go @@ -173,6 +173,10 @@ type ArmClient struct { resourceGroupsClient resources.GroupsClient subscriptionsClient subscriptions.Client + //Scheduler + schedulerJobCollectionsClient scheduler.JobCollectionsClient + schedulerJobsClient scheduler.JobsClient + // Search searchServicesClient search.ServicesClient @@ -182,9 +186,6 @@ type ArmClient struct { serviceBusTopicsClient servicebus.TopicsClient serviceBusSubscriptionsClient servicebus.SubscriptionsClient - //Scheduler - schedulerJobCollectionsClient scheduler.JobCollectionsClient - // Storage storageServiceClient storage.AccountsClient storageUsageClient storage.UsageClient @@ -821,6 +822,16 @@ func (c *ArmClient) registerResourcesClients(endpoint, subscriptionId string, au c.subscriptionsClient = subscriptionsClient } +func (c *ArmClient) registerSchedulerClients(endpoint, subscriptionId string, auth autorest.Authorizer) { + jobCollectionsClient := scheduler.NewJobCollectionsClientWithBaseURI(endpoint, subscriptionId) + c.configureClient(&jobCollectionsClient.Client, auth) + c.schedulerJobCollectionsClient = jobCollectionsClient + + jobsClient := scheduler.NewJobsClientWithBaseURI(endpoint, subscriptionId) + c.configureClient(&jobsClient.Client, auth) + c.schedulerJobsClient = jobsClient +} + func (c *ArmClient) registerSearchClients(endpoint, subscriptionId string, auth autorest.Authorizer) { searchClient := search.NewServicesClientWithBaseURI(endpoint, subscriptionId) c.configureClient(&searchClient.Client, auth) @@ -845,12 +856,6 @@ func (c *ArmClient) registerServiceBusClients(endpoint, subscriptionId string, a c.serviceBusSubscriptionsClient = subscriptionsClient } -func (c *ArmClient) registerSchedulerClients(endpoint, subscriptionId string, auth autorest.Authorizer) { - jobsClient := scheduler.NewJobCollectionsClientWithBaseURI(endpoint, subscriptionId) - c.configureClient(&jobsClient.Client, auth) - c.schedulerJobCollectionsClient = jobsClient -} - func (c *ArmClient) registerStorageClients(endpoint, subscriptionId string, auth autorest.Authorizer) { accountsClient := storage.NewAccountsClientWithBaseURI(endpoint, subscriptionId) c.configureClient(&accountsClient.Client, auth) diff --git a/azurerm/helpers/set/set.go b/azurerm/helpers/set/set.go new file mode 100644 index 000000000000..a8cc3daf138c --- /dev/null +++ b/azurerm/helpers/set/set.go @@ -0,0 +1,16 @@ +package set + +import ( + "strconv" + "strings" + + "github.com/hashicorp/terraform/helper/hashcode" +) + +func HashInt(v interface{}) int { + return hashcode.String(strconv.Itoa(v.(int))) +} + +func HashStringIgnoreCase(v interface{}) int { + return hashcode.String(strings.ToLower(v.(string))) +} diff --git a/azurerm/helpers/supress/suppress.go b/azurerm/helpers/supress/suppress.go new file mode 100644 index 000000000000..3b2c63e1e6f9 --- /dev/null +++ b/azurerm/helpers/supress/suppress.go @@ -0,0 +1,23 @@ +package supress + +import ( + "time" + + "github.com/hashicorp/terraform/helper/schema" + "strings" +) + +func CaseDifference(k, old, new string, d *schema.ResourceData) bool { + return strings.ToLower(old) == strings.ToLower(new) +} + +func Rfc3339Time(k, old, new string, d *schema.ResourceData) bool { + ot, oerr := time.Parse(time.RFC3339, old) + nt, nerr := time.Parse(time.RFC3339, new) + + if oerr != nil || nerr != nil { + return false + } + + return nt.Equal(ot) +} diff --git a/azurerm/helpers/supress/suppress_test.go b/azurerm/helpers/supress/suppress_test.go new file mode 100644 index 000000000000..b66600938222 --- /dev/null +++ b/azurerm/helpers/supress/suppress_test.go @@ -0,0 +1,88 @@ +package supress + +import "testing" + +func TestInternal_Suppress_CaseDifference(t *testing.T) { + cases := []struct { + StringA string + StringB string + Suppress bool + }{ + { + StringA: "", + StringB: "", + Suppress: true, + }, + { + StringA: "ye old text", + StringB: "", + Suppress: false, + }, + { + StringA: "ye old text?", + StringB: "ye different text", + Suppress: false, + }, + { + StringA: "ye same text!", + StringB: "ye same text!", + Suppress: true, + }, + { + StringA: "ye old text?", + StringB: "Ye OLD texT?", + Suppress: true, + }, + } + + for _, tc := range cases { + if CaseDifference("test", tc.StringA, tc.StringB, nil) != tc.Suppress { + t.Fatalf("Expected CaseDifference to return %t for '%s' == '%s'", tc.Suppress, tc.StringA, tc.StringB) + } + } +} + +func TestInternal_Supress_Rfc3339Time(t *testing.T) { + cases := []struct { + TimeA string + TimeB string + Suppress bool + }{ + { + TimeA: "", + TimeB: "", + Suppress: false, + }, + { + TimeA: "this is not a time", + TimeB: "neither is this", + Suppress: false, + }, + { + TimeA: "2000-01-01T01:23:45+00:00", + TimeB: "that is a valid time", + Suppress: false, + }, + { + TimeA: "2000-01-01T01:23:45+00:00", + TimeB: "1984-07-07T01:23:45+00:00", + Suppress: false, + }, + { + TimeA: "2000-01-01T01:23:45+00:00", + TimeB: "2000-01-01T01:23:45Z", + Suppress: true, + }, + { + TimeA: "2000-01-01T01:23:45+7:00", + TimeB: "2010-01-01T08:23:45Z", + Suppress: true, + }, + } + + for _, tc := range cases { + if Rfc3339Time("test", tc.TimeA, tc.TimeB, nil) != tc.Suppress { + t.Fatalf("Expected Rfc3339Time to return %t for '%s' == '%s'", tc.Suppress, tc.TimeA, tc.TimeB) + } + } +} diff --git a/azurerm/helpers/validate/validator.go b/azurerm/helpers/validate/validator.go new file mode 100644 index 000000000000..d7f482f1280e --- /dev/null +++ b/azurerm/helpers/validate/validator.go @@ -0,0 +1,31 @@ +package validate + +import ( + "fmt" + "time" + + "github.com/Azure/go-autorest/autorest/date" + "net/url" +) + +//todo, now in terraform helper, switch over once vended, +func Rfc3339Time(v interface{}, k string) (ws []string, errors []error) { + if _, err := date.ParseTime(time.RFC3339, v.(string)); err != nil { + errors = append(errors, fmt.Errorf("%q has the invalid RFC3339 date format %q: %+v", k, v, err)) + } + + return +} + +func Url(v interface{}, k string) (ws []string, errors []error) { + url, err := url.Parse(v.(string)) + if err != nil { + errors = append(errors, fmt.Errorf("%q url is in an invalid format: %q (%+v)", k, v, err)) + } else if url.Scheme != "http" && url.Scheme != "https" { + errors = append(errors, fmt.Errorf("%q url is neither an http or https uri: %q", k, url.Scheme)) + } else if url.Host == "" { + errors = append(errors, fmt.Errorf("%q url has no host: %q", k, url)) + } + + return +} diff --git a/azurerm/helpers/validate/validator_test.go b/azurerm/helpers/validate/validator_test.go new file mode 100644 index 000000000000..cc69adc86f70 --- /dev/null +++ b/azurerm/helpers/validate/validator_test.go @@ -0,0 +1,43 @@ +package validate + +import "testing" + +func TestInternal_ValidateRFC3339Time(t *testing.T) { + cases := []struct { + Time string + Errors int + }{ + { + Time: "", + Errors: 1, + }, + { + Time: "this is not a date", + Errors: 1, + }, + { + Time: "2000-01-01", + Errors: 1, + }, + { + Time: "2000-01-01T01:23:45", + Errors: 1, + }, + { + Time: "2000-01-01T01:23:45Z", + Errors: 0, + }, + { + Time: "2000-01-01T01:23:45+00:00", + Errors: 0, + }, + } + + for _, tc := range cases { + _, errors := Rfc3339Time(tc.Time, "test") + + if len(errors) != tc.Errors { + t.Fatalf("Expected Rfc3339Time to have an error for '%s'", tc.Time) + } + } +} diff --git a/azurerm/provider.go b/azurerm/provider.go index ab9138e3b598..8fa9b41efaea 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -191,6 +191,7 @@ func Provider() terraform.ResourceProvider { "azurerm_servicebus_topic_authorization_rule": resourceArmServiceBusTopicAuthorizationRule(), "azurerm_snapshot": resourceArmSnapshot(), "azurerm_scheduler_job_collection": resourceArmSchedulerJobCollection(), + "azurerm_scheduler_job": resourceArmSchedulerJob(), "azurerm_sql_database": resourceArmSqlDatabase(), "azurerm_sql_elasticpool": resourceArmSqlElasticPool(), "azurerm_sql_firewall_rule": resourceArmSqlFirewallRule(), @@ -384,6 +385,7 @@ var armMutexKV = mutexkv.NewMutexKV() // Resource group names can be capitalised, but we store them in lowercase. // Use a custom diff function to avoid creation of new resources. +// todo move to the file its used in (the only one) func resourceAzurermResourceGroupNameDiffSuppress(k, old, new string, d *schema.ResourceData) bool { return strings.ToLower(old) == strings.ToLower(new) } diff --git a/azurerm/resource_arm_scheduler_job.go b/azurerm/resource_arm_scheduler_job.go new file mode 100644 index 000000000000..fb17bed22021 --- /dev/null +++ b/azurerm/resource_arm_scheduler_job.go @@ -0,0 +1,995 @@ +package azurerm + +import ( + "bytes" + "fmt" + "log" + "regexp" + "strings" + "time" + + "github.com/Azure/azure-sdk-for-go/services/scheduler/mgmt/2016-03-01/scheduler" + "github.com/Azure/go-autorest/autorest/date" + + "github.com/hashicorp/terraform/helper/hashcode" + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" + + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/set" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/supress" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmSchedulerJob() *schema.Resource { + return &schema.Resource{ + Create: resourceArmSchedulerJobCreateUpdate, + Read: resourceArmSchedulerJobRead, + Update: resourceArmSchedulerJobCreateUpdate, + Delete: resourceArmSchedulerJobDelete, + + 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-Z][-_a-zA-Z0-9].*$"), + "Job Collection Name name must start with a letter and contain only letters, numbers, hyphens and underscores.", + ), + }, + + "resource_group_name": resourceGroupNameSchema(), + + "job_collection_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + + //actions + "action_web": resourceArmSchedulerJobActionWebSchema("action_web"), + //"action_servicebus": resourceArmSchedulerJobActionServicebusSchema("action_servicebus", []string{"action_web", "action_storagequeue"}), + + //each action can also be an error action + "error_action_web": resourceArmSchedulerJobActionWebSchema("error_action_web"), + //"error_action_servicebus": resourceArmSchedulerJobActionServicebusSchema("action_servicebus", []string{"action_web", "action_servicebus"}), + + //retry policy + "retry": { + Type: schema.TypeList, + MinItems: 1, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + //none cannot be used with either of these values todo keep? + /*"type": { + Type: schema.TypeString, + Optional: true, + Default: string(scheduler.Fixed), + DiffSuppressFunc: internal.CaseDifference, + ValidateFunc: validation.StringInSlice([]string{ + string(scheduler.Fixed), + string(scheduler.None), + }, true), + },*/ + + //silently fails if the duration is not in the correct format + "interval": { + Type: schema.TypeString, + Optional: true, + Default: "00:00:30", + }, + + "count": { + Type: schema.TypeInt, + Optional: true, + Default: 4, + ValidateFunc: validation.IntBetween(1, 20), + }, + }, + }, + }, + + //recurrences (schedule in portal, recurrence in API) + "recurrence": { + Type: schema.TypeList, + MinItems: 1, + MaxItems: 1, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + "frequency": { + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: supress.CaseDifference, + ValidateFunc: validation.StringInSlice([]string{ + string(scheduler.Minute), + string(scheduler.Hour), + string(scheduler.Day), + string(scheduler.Week), + string(scheduler.Month), + }, true), + }, + + "interval": { + Type: schema.TypeInt, + Optional: true, + Default: 1, //defaults to 1 in the portal + + //maximum is dynamic: 1 min <= interval * frequency <= 500 days (bounded by JobCollection quotas) + ValidateFunc: validation.IntAtLeast(1), + }, + + "count": { + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntBetween(1, 2147483647), //silently fails/produces odd results at >2147483647 + }, + + "end_time": { + Type: schema.TypeString, + Optional: true, + Computed: true, + DiffSuppressFunc: supress.Rfc3339Time, + ValidateFunc: validate.Rfc3339Time, + }, + + "minutes": { + Type: schema.TypeSet, + Optional: true, + MinItems: 1, + Elem: &schema.Schema{Type: schema.TypeInt}, + Set: set.HashInt, + }, + + "hours": { + Type: schema.TypeSet, + Optional: true, + MinItems: 1, + Elem: &schema.Schema{Type: schema.TypeInt}, + Set: set.HashInt, + }, + + "week_days": { //used with weekly + Type: schema.TypeSet, + Optional: true, + ConflictsWith: []string{"recurrence.0.month_days", "recurrence.0.monthly_occurrences"}, + MinItems: 1, + Elem: &schema.Schema{Type: schema.TypeString}, + //the constants are title cased but the API returns all lowercase + //so lets ignore the case + Set: set.HashStringIgnoreCase, + }, + + "month_days": { //used with monthly, -1, 1- must be between 1/31 + Type: schema.TypeSet, + Optional: true, + ConflictsWith: []string{"recurrence.0.week_days", "recurrence.0.monthly_occurrences"}, + MinItems: 1, + Elem: &schema.Schema{Type: schema.TypeInt}, + Set: set.HashInt, + }, + + "monthly_occurrences": { + Type: schema.TypeSet, + Optional: true, + ConflictsWith: []string{"recurrence.0.week_days", "recurrence.0.month_days"}, + MinItems: 1, + Set: resourceAzureRMSchedulerJobMonthlyOccurrenceHash, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "day": { // DatOfWeek (sunday monday) + Type: schema.TypeString, + Required: true, + }, + "occurrence": { //-5 - 5, not 0 + Type: schema.TypeInt, + Required: true, + }, + }, + }, + }, + }, + }, + }, + + "start_time": { + Type: schema.TypeString, + Optional: true, + Default: time.Now().Format(time.RFC3339), //default to now + DiffSuppressFunc: supress.Rfc3339Time, + ValidateFunc: validate.Rfc3339Time, //times in the past just start immediately + }, + + "state": { + Type: schema.TypeString, + Optional: true, + Computed: true, + DiffSuppressFunc: supress.CaseDifference, + ValidateFunc: validation.StringInSlice([]string{ + string(scheduler.JobStateEnabled), + string(scheduler.JobStateDisabled), + // JobStateFaulted & JobStateCompleted are also possible, but silly + }, true), + }, + + //status + "execution_count": { + Type: schema.TypeInt, + Computed: true, + }, + "failure_count": { + Type: schema.TypeInt, + Computed: true, + }, + "faulted_count": { + Type: schema.TypeInt, + Computed: true, + }, + "last_execution_time": { + Type: schema.TypeString, + Computed: true, + }, + "next_execution_time": { + Type: schema.TypeString, + Computed: true, + }, + }, + + CustomizeDiff: resourceArmSchedulerJobCustomizeDiff, + } +} + +func resourceArmSchedulerJobActionWebSchema(propertyName string) *schema.Schema { + return &schema.Schema{ + Type: schema.TypeList, + MinItems: 1, + MaxItems: 1, + Optional: true, + //ConflictsWith: conflictsWith, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + + // we can determine the type (HTTP/HTTPS) from the url + // but we need to make sure the url starts with http/https + // both so we can determine the type and as azure requires it + "url": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: supress.CaseDifference, + ValidateFunc: validate.Url, + }, + + "method": { + Type: schema.TypeString, + Optional: true, + //DiffSuppressFunc: ignoreCaseDiffSuppressFunc, + Default: "Get", //todo have a default or force user to pick? + ValidateFunc: validation.StringInSlice([]string{ + "Get", "Put", "Post", "Delete", + }, true), + }, + + //only valid/used when action type is put + "body": { + Type: schema.TypeString, + Optional: true, + }, + + "headers": { + Type: schema.TypeMap, + Optional: true, + }, + + //authentication requires HTTPS + "authentication_basic": { + Type: schema.TypeList, + MinItems: 1, + MaxItems: 1, + Optional: true, + ConflictsWith: []string{ + fmt.Sprintf("%s.0.authentication_certificate", propertyName), + fmt.Sprintf("%s.0.authentication_active_directory", propertyName), + }, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "username": { + Type: schema.TypeString, + Required: true, + }, + + "password": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, + }, + }, + }, + + "authentication_certificate": { + Type: schema.TypeList, + Optional: true, + MinItems: 1, + MaxItems: 1, + ConflictsWith: []string{ + fmt.Sprintf("%s.0.authentication_basic", propertyName), + fmt.Sprintf("%s.0.authentication_active_directory", propertyName), + }, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "pfx": { + Type: schema.TypeString, + Required: true, + Sensitive: true, //sensitive & shortens diff + }, + + "password": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, + + "thumbprint": { + Type: schema.TypeString, + Computed: true, + }, + + "expiration": { + Type: schema.TypeString, + Computed: true, + }, + + "subject_name": { + Type: schema.TypeString, + Computed: true, + }, + }, + }, + }, + + "authentication_active_directory": { + Type: schema.TypeList, + Optional: true, + MinItems: 1, + MaxItems: 1, + ConflictsWith: []string{ + fmt.Sprintf("%s.0.authentication_basic", propertyName), + fmt.Sprintf("%s.0.authentication_certificate", propertyName), + }, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "tenant_id": { + Type: schema.TypeString, + Required: true, + }, + + "client_id": { + Type: schema.TypeString, + Required: true, + }, + + "secret": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, + + "audience": { + Type: schema.TypeString, + Optional: true, + Default: "https://management.core.windows.net/", + }, + }, + }, + }, + }, + }, + } +} + +func resourceArmSchedulerJobCustomizeDiff(diff *schema.ResourceDiff, v interface{}) error { + + _, hasWeb := diff.GetOk("action_web") + //_, hasService := diff.GetOk("action_servicebus") + //_, hasStorage := diff.GetOk("action_storagequeue") + if !hasWeb { //&& !hasService && !hasStorage + return fmt.Errorf("One of `action_web`, `action_servicebus` or `action_storagequeue` must be set") + } + + if b, ok := diff.GetOk("recurrence"); ok { + if recurrence, ok := b.([]interface{})[0].(map[string]interface{}); ok { + + //if neither count nor end time is set the API will silently fail + _, hasCount := recurrence["count"] + _, hasEnd := recurrence["end_time"] + if !hasCount && !hasEnd { //&& !hasService && !hasStorage + return fmt.Errorf("One of `count` or `end_time` must be set for the 'recurrence' block.") + } + + if v, ok := recurrence["minutes"].(*schema.Set); ok { + for _, e := range v.List() { + //leverage existing function, validates type and value + if _, errors := validation.IntBetween(0, 59)(e, "minutes"); len(errors) > 0 { + return errors[0] + } + } + } + + if v, ok := recurrence["hours"].(*schema.Set); ok { + for _, e := range v.List() { + //leverage existing function, validates type and value + if _, errors := validation.IntBetween(0, 23)(e, "hours"); len(errors) > 0 { + return errors[0] + } + } + } + + if v, ok := recurrence["week_days"].(*schema.Set); ok { + for _, e := range v.List() { + //leverage existing function, validates type and value + if _, errors := validation.StringInSlice([]string{ + string(scheduler.Monday), + string(scheduler.Tuesday), + string(scheduler.Wednesday), + string(scheduler.Thursday), + string(scheduler.Friday), + string(scheduler.Saturday), + string(scheduler.Sunday), + }, true)(e, "week_days"); len(errors) > 0 { + return errors[0] //string in slice can only return one + } + } + } + + if v, ok := recurrence["month_days"].(*schema.Set); ok { + for _, e := range v.List() { + v := e.(int) + if (-31 < v && v > 31) && v != 0 { + return fmt.Errorf("expected 'month_days' to be in the range (-31 - 31) excluding 0, got %d", v) + } + } + } + } + } + + return nil +} + +func resourceArmSchedulerJobCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).schedulerJobsClient + ctx := meta.(*ArmClient).StopContext + + name := d.Get("name").(string) + resourceGroup := d.Get("resource_group_name").(string) + jobCollection := d.Get("job_collection_name").(string) + + job := scheduler.JobDefinition{ + Properties: &scheduler.JobProperties{ + Action: &scheduler.JobAction{}, + }, + } + + log.Printf("[DEBUG] Creating/updating Scheduler Job %q (resource group %q)", name, resourceGroup) + + //action + if b, ok := d.GetOk("action_web"); ok { + job.Properties.Action.Request, job.Properties.Action.Type = expandAzureArmSchedulerJobActionRequest(b) + } else { + //todo should never get here because of the customize diff, so is this required? + return fmt.Errorf("One of `action_web`, `action_servicebus` or `action_storagequeue` must be set for scheduler job %q (Resource Group %q)", name, resourceGroup) + } + + //error action + if b, ok := d.GetOk("error_action_web"); ok { + job.Properties.Action.ErrorAction = &scheduler.JobErrorAction{} + job.Properties.Action.ErrorAction.Request, job.Properties.Action.ErrorAction.Type = expandAzureArmSchedulerJobActionRequest(b) + } + + //retry policy + if b, ok := d.GetOk("retry"); ok { + job.Properties.Action.RetryPolicy = expandAzureArmSchedulerJobActionRetry(b) + } else { + job.Properties.Action.RetryPolicy = &scheduler.RetryPolicy{ + RetryType: scheduler.None, + } + } + + //schedule (recurrence) + if b, ok := d.GetOk("recurrence"); ok { + job.Properties.Recurrence = expandAzureArmSchedulerJobRecurrence(b) + } + + //start time + startTime, err := time.Parse(time.RFC3339, d.Get("start_time").(string)) + if err != nil { + return fmt.Errorf("Error parsing start time (%s) for job %q (Resource Group %q): %+v", d.Get("start_time"), name, resourceGroup, err) + } + job.Properties.StartTime = &date.Time{startTime} + + //state + if state, ok := d.GetOk("state"); ok { + job.Properties.State = scheduler.JobState(state.(string)) + } + + resp, err := client.CreateOrUpdate(ctx, resourceGroup, jobCollection, name, job) + if err != nil { + return fmt.Errorf("Error creating/updating Scheduler Job %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + d.SetId(*resp.ID) + + return resourceArmSchedulerJobPopulate(d, resourceGroup, jobCollection, &resp) +} + +func resourceArmSchedulerJobRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).schedulerJobsClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + + name := id.Path["jobs"] + resourceGroup := id.ResourceGroup + jobCollection := id.Path["jobCollections"] + + log.Printf("[DEBUG] Reading Scheduler Job %q (resource group %q)", name, resourceGroup) + + job, err := client.Get(ctx, resourceGroup, jobCollection, name) + if err != nil { + if utils.ResponseWasNotFound(job.Response) { + d.SetId("") + return nil + } + + return fmt.Errorf("Error making Read request on Scheduler Job %q (Resource Group %q): %+v", name, resourceGroup, err) + } + + return resourceArmSchedulerJobPopulate(d, resourceGroup, jobCollection, &job) +} + +func resourceArmSchedulerJobPopulate(d *schema.ResourceData, resourceGroup string, jobCollection string, job *scheduler.JobDefinition) error { + + //standard properties + name := strings.Split(*job.Name, "/")[1] //job.Name is actually "{job_collection_name}/{job_name} + d.Set("name", name) + d.Set("resource_group_name", resourceGroup) + d.Set("job_collection_name", jobCollection) + + //check & get properties + properties := job.Properties + if properties == nil { + return fmt.Errorf("job properties is nil") + } + + //action + action := properties.Action + if action == nil { + return fmt.Errorf("job action is nil") + } + actionType := strings.ToLower(string(action.Type)) + if strings.EqualFold(actionType, string(scheduler.HTTP)) || strings.EqualFold(actionType, string(scheduler.HTTPS)) { + d.Set("action_web", flattenAzureArmSchedulerJobActionRequest(action.Request, d.Get("action_web"))) + } else { + return fmt.Errorf("Unknown job type %q for scheduler job %q action (Resource Group %q)", action.Type, name, resourceGroup) + } + + //error action + if errorAction := action.ErrorAction; errorAction != nil { + if strings.EqualFold(actionType, string(scheduler.HTTP)) || strings.EqualFold(actionType, string(scheduler.HTTPS)) { + d.Set("error_action_web", flattenAzureArmSchedulerJobActionRequest(errorAction.Request, d.Get("error_action_web"))) + } else { + return fmt.Errorf("Unknown job type %q for scheduler job %q error action (Resource Group %q)", errorAction.Type, name, resourceGroup) + } + } + + //retry + if retry := properties.Action.RetryPolicy; retry != nil { + //if its not fixed we should not have a retry block + if retry.RetryType == scheduler.Fixed { + d.Set("retry", flattenAzureArmSchedulerJobActionRetry(retry)) + } + } + + //schedule + if recurrence := properties.Recurrence; recurrence != nil { + d.Set("recurrence", flattenAzureArmSchedulerJobSchedule(recurrence)) + } + + d.Set("start_time", properties.StartTime.Format(time.RFC3339)) + d.Set("state", properties.State) + + //status + status := properties.Status + if status != nil { + if v := status.ExecutionCount; v != nil { + d.Set("execution_count", *v) + } + if v := status.FailureCount; v != nil { + d.Set("failure_count", *v) + } + if v := status.FaultedCount; v != nil { + d.Set("faulted_count", *v) + } + + //these can be nil, if so set to empty so any outputs referencing them won't explode + if v := status.LastExecutionTime; v != nil { + d.Set("last_execution_time", (*v).Format(time.RFC3339)) + } else { + d.Set("last_execution_time", "") + } + if v := status.NextExecutionTime; v != nil { + d.Set("next_execution_time", (*v).Format(time.RFC3339)) + } else { + d.Set("next_execution_time", "") + } + } + + return nil +} + +func resourceArmSchedulerJobDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).schedulerJobsClient + ctx := meta.(*ArmClient).StopContext + + id, err := parseAzureResourceID(d.Id()) + if err != nil { + return err + } + + name := id.Path["jobs"] + resourceGroup := id.ResourceGroup + jobCollection := id.Path["jobCollections"] + + log.Printf("[DEBUG] Deleting Scheduler Job %q (resource group %q)", name, resourceGroup) + + resp, err := client.Delete(ctx, resourceGroup, jobCollection, name) + if err != nil { + if !utils.ResponseWasNotFound(resp) { + return fmt.Errorf("Error issuing delete request for Scheduler Job %q (Resource Group %q): %+v", name, resourceGroup, err) + } + } + + return nil +} + +//expand (terraform -> API) + +func expandAzureArmSchedulerJobActionRequest(b interface{}) (*scheduler.HTTPRequest, scheduler.JobActionType) { + + block := b.([]interface{})[0].(map[string]interface{}) + + url := block["url"].(string) + + request := scheduler.HTTPRequest{ + URI: &url, + Method: utils.String(block["method"].(string)), + Headers: &map[string]*string{}, + } + + // determine type from the url, the property validation must ensure this + // otherwise we need to worry about what happens if neither is true + var jobType scheduler.JobActionType + if strings.HasPrefix(strings.ToLower(url), "https://") { + jobType = scheduler.HTTPS + //} else if strings.HasPrefix(strings.ToLower(url), "http://") { + } else { + jobType = scheduler.HTTP + } + + //load headers + //if v, ok := block["headers"].(map[string]interface{}); ok { //check doesn't seem to be needed + for k, v := range block["headers"].(map[string]interface{}) { + (*request.Headers)[k] = utils.String(v.(string)) + } + + //only valid for a set + if v, ok := block["body"].(string); ok && v != "" { + request.Body = utils.String(block["body"].(string)) + } + + //authentications + if v, ok := block["authentication_basic"].([]interface{}); ok && len(v) > 0 { + b := v[0].(map[string]interface{}) + request.Authentication = &scheduler.BasicAuthentication{ + Type: scheduler.TypeBasic, + Username: utils.String(b["username"].(string)), + Password: utils.String(b["password"].(string)), + } + } + + if v, ok := block["authentication_certificate"].([]interface{}); ok && len(v) > 0 { + b := v[0].(map[string]interface{}) + request.Authentication = &scheduler.ClientCertAuthentication{ + Type: scheduler.TypeClientCertificate, + Pfx: utils.String(b["pfx"].(string)), + Password: utils.String(b["password"].(string)), + } + } + + if v, ok := block["authentication_active_directory"].([]interface{}); ok && len(v) > 0 { + b := v[0].(map[string]interface{}) + request.Authentication = &scheduler.OAuthAuthentication{ + Type: scheduler.TypeActiveDirectoryOAuth, + Tenant: utils.String(b["tenant_id"].(string)), + ClientID: utils.String(b["client_id"].(string)), + Audience: utils.String(b["audience"].(string)), + Secret: utils.String(b["secret"].(string)), + } + } + + return &request, jobType +} + +func expandAzureArmSchedulerJobActionRetry(b interface{}) *scheduler.RetryPolicy { + block := b.([]interface{})[0].(map[string]interface{}) + retry := scheduler.RetryPolicy{ + RetryType: scheduler.Fixed, + } + + if v, ok := block["interval"].(string); ok && v != "" { + retry.RetryInterval = utils.String(v) + } + if v, ok := block["count"].(int); ok { + retry.RetryCount = utils.Int32(int32(v)) + } + + return &retry +} + +func expandAzureArmSchedulerJobRecurrence(b interface{}) *scheduler.JobRecurrence { + block := b.([]interface{})[0].(map[string]interface{}) + recurrence := scheduler.JobRecurrence{} + schedule := scheduler.JobRecurrenceSchedule{} + + if v, ok := block["frequency"].(string); ok && v != "" { + recurrence.Frequency = scheduler.RecurrenceFrequency(v) + } + if v, ok := block["interval"].(int); ok { + recurrence.Interval = utils.Int32(int32(v)) + } + if v, ok := block["count"].(int); ok { + recurrence.Count = utils.Int32(int32(v)) + } + if v, ok := block["end_time"].(string); ok && v != "" { + endTime, _ := time.Parse(time.RFC3339, v) + recurrence.EndTime = &date.Time{Time: endTime} + } + + if s, ok := block["minutes"].(*schema.Set); ok && s.Len() > 0 { + schedule.Minutes = setToSliceInt32P(s) + } + if s, ok := block["hours"].(*schema.Set); ok && s.Len() > 0 { + schedule.Hours = setToSliceInt32P(s) + } + + if s, ok := block["week_days"].(*schema.Set); ok && s.Len() > 0 { + var slice []scheduler.DayOfWeek + for _, m := range s.List() { + slice = append(slice, scheduler.DayOfWeek(m.(string))) + } + schedule.WeekDays = &slice + } + + if s, ok := block["month_days"].(*schema.Set); ok && s.Len() > 0 { + schedule.MonthDays = setToSliceInt32P(s) + } + if s, ok := block["monthly_occurrences"].(*schema.Set); ok && s.Len() > 0 { + var slice []scheduler.JobRecurrenceScheduleMonthlyOccurrence + for _, e := range s.List() { + b := e.(map[string]interface{}) + slice = append(slice, scheduler.JobRecurrenceScheduleMonthlyOccurrence{ + Day: scheduler.JobScheduleDay(b["day"].(string)), + Occurrence: utils.Int32(int32(b["occurrence"].(int))), + }) + } + schedule.MonthlyOccurrences = &slice + } + + if schedule.Minutes != nil || + schedule.Hours != nil || + schedule.WeekDays != nil || + schedule.MonthDays != nil || + schedule.MonthlyOccurrences != nil { + recurrence.Schedule = &schedule + } + return &recurrence +} + +// flatten (API --> terraform) + +func flattenAzureArmSchedulerJobActionRequest(request *scheduler.HTTPRequest, ob interface{}) []interface{} { + oldBlock := map[string]interface{}{} + + if v, ok := ob.([]interface{}); ok && len(v) > 0 { + oldBlock = v[0].(map[string]interface{}) + } + + block := map[string]interface{}{} + + if v := request.URI; v != nil { + block["url"] = *v + } + if v := request.Method; v != nil { + block["method"] = *v + } + if v := request.Body; v != nil { + block["body"] = *v + } + + if v := request.Headers; v != nil { + headers := map[string]interface{}{} + for k, v := range *v { + headers[k] = *v + } + + block["headers"] = headers + } + + if auth := request.Authentication; auth != nil { + + authBlock := map[string]interface{}{} + + if basic, ok := auth.AsBasicAuthentication(); ok { + block["authentication_basic"] = []interface{}{authBlock} + + if v := basic.Username; v != nil { + authBlock["username"] = *v + } + + //password is always blank, so preserve state + if v, ok := oldBlock["authentication_basic"].([]interface{}); ok && len(v) > 0 { + oab := v[0].(map[string]interface{}) + authBlock["password"] = oab["password"] + } + + } else if cert, ok := auth.AsClientCertAuthentication(); ok { + block["authentication_certificate"] = []interface{}{authBlock} + + //pfx and password are always empty, so preserve state + if v, ok := oldBlock["authentication_certificate"].([]interface{}); ok && len(v) > 0 { + oab := v[0].(map[string]interface{}) + authBlock["pfx"] = oab["pfx"] + authBlock["password"] = oab["password"] + } + + if v := cert.CertificateThumbprint; v != nil { + authBlock["thumbprint"] = *v + } + if v := cert.CertificateExpirationDate; v != nil { + authBlock["expiration"] = (*v).Format(time.RFC3339) + } + if v := cert.CertificateSubjectName; v != nil { + authBlock["subject_name"] = *v + } + + } else if oauth, ok := auth.AsOAuthAuthentication(); ok { + block["authentication_active_directory"] = []interface{}{authBlock} + + if v := oauth.Audience; v != nil { + authBlock["audience"] = *v + } + if v := oauth.ClientID; v != nil { + authBlock["client_id"] = *v + } + if v := oauth.Tenant; v != nil { + authBlock["tenant_id"] = *v + } + + //secret is always empty, so preserve state + if v, ok := oldBlock["authentication_active_directory"].([]interface{}); ok && len(v) > 0 { + oab := v[0].(map[string]interface{}) + authBlock["secret"] = oab["secret"] + } + } + } + + return []interface{}{block} +} + +func flattenAzureArmSchedulerJobActionRetry(retry *scheduler.RetryPolicy) []interface{} { + block := map[string]interface{}{} + + block["type"] = string(retry.RetryType) + if v := retry.RetryInterval; v != nil { + block["interval"] = *v + } + if v := retry.RetryCount; v != nil { + block["count"] = *v + } + + return []interface{}{block} +} + +func flattenAzureArmSchedulerJobSchedule(recurrence *scheduler.JobRecurrence) []interface{} { + block := map[string]interface{}{} + + block["frequency"] = string(recurrence.Frequency) + + if v := recurrence.Interval; v != nil { + block["interval"] = *v + } + if v := recurrence.Count; v != nil { + block["count"] = *v + } + if v := recurrence.EndTime; v != nil { + block["end_time"] = (*v).Format(time.RFC3339) + } + + if schedule := recurrence.Schedule; schedule != nil { + + if v := schedule.Minutes; v != nil { + block["minutes"] = sliceToSetInt32(*v) + } + if v := schedule.Hours; v != nil { + block["hours"] = sliceToSetInt32(*v) + } + + if v := schedule.WeekDays; v != nil { + set := &schema.Set{F: schema.HashString} + for _, v := range *v { + set.Add(string(v)) + } + block["week_days"] = set + } + if v := schedule.MonthDays; v != nil { + block["month_days"] = sliceToSetInt32(*v) + } + + if monthly := schedule.MonthlyOccurrences; monthly != nil { + set := &schema.Set{F: resourceAzureRMSchedulerJobMonthlyOccurrenceHash} + for _, e := range *monthly { + + m := map[string]interface{}{ + "day": string(e.Day), + } + + if v := e.Occurrence; v != nil { + m["occurrence"] = int(*v) + } + + set.Add(m) + } + block["monthly_occurrences"] = set + } + } + + return []interface{}{block} +} + +func resourceAzureRMSchedulerJobMonthlyOccurrenceHash(v interface{}) int { + var buf bytes.Buffer + m := v.(map[string]interface{}) + + //day returned by azure is in a different case then the API constants + buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["day"].(string)))) + buf.WriteString(fmt.Sprintf("%d-", m["occurrence"].(int))) + + return hashcode.String(buf.String()) +} + +//todo move these somewhere? +func sliceToSetInt32(slice []int32) *schema.Set { + set := &schema.Set{F: set.HashInt} + for _, v := range slice { + set.Add(int(v)) + } + return set +} + +func setToSliceInt32P(set *schema.Set) *[]int32 { + var slice []int32 + for _, m := range set.List() { + slice = append(slice, int32(m.(int))) + } + return &slice +} diff --git a/azurerm/resource_arm_scheduler_job_collection.go b/azurerm/resource_arm_scheduler_job_collection.go index bdcd61a103c1..ecaa2ddab2b5 100644 --- a/azurerm/resource_arm_scheduler_job_collection.go +++ b/azurerm/resource_arm_scheduler_job_collection.go @@ -69,6 +69,7 @@ func resourceArmSchedulerJobCollection() *schema.Resource { "quota": { Type: schema.TypeList, Optional: true, + MinItems: 1, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -94,12 +95,21 @@ func resourceArmSchedulerJobCollection() *schema.Resource { }, true), }, - //this is MaxRecurrance.Interval, property is named this as the documentation in the api states: - // Gets or sets the interval between retries. + //while in the documentation the MaxRecurrance.Interval is stated to "Gets or sets the interval between retries." + //it does appear it is the max interval allowed for a recurrence "max_retry_interval": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntAtLeast(1), //changes depending on the frequency, unknown maximums + Type: schema.TypeInt, + Optional: true, + Deprecated: "Renamed to match azure", + ConflictsWith: []string{"quota.0.max_recurrence_interval"}, + ValidateFunc: validation.IntAtLeast(1), //changes depending on the frequency, unknown maximums + }, + + "max_recurrence_interval": { + Type: schema.TypeInt, + Optional: true, + ConflictsWith: []string{"quota.0.max_retry_interval"}, + ValidateFunc: validation.IntAtLeast(1), //changes depending on the frequency, unknown maximums }, }, }, @@ -245,8 +255,10 @@ func expandAzureArmSchedulerJobCollectionQuota(d *schema.ResourceData) *schedule } if v, ok := quotaBlock["max_recurrence_frequency"].(string); ok { quota.MaxRecurrence.Frequency = scheduler.RecurrenceFrequency(v) + } else if v, ok := quotaBlock["max_retry_interval"].(int); ok { + quota.MaxRecurrence.Interval = utils.Int32(int32(v)) } - if v, ok := quotaBlock["max_retry_interval"].(int); ok { + if v, ok := quotaBlock["max_recurrence_interval"].(int); ok { quota.MaxRecurrence.Interval = utils.Int32(int32(v)) } @@ -269,7 +281,8 @@ func flattenAzureArmSchedulerJobCollectionQuota(quota *scheduler.JobCollectionQu } if recurrence := quota.MaxRecurrence; recurrence != nil { if v := recurrence.Interval; v != nil { - quotaBlock["max_retry_interval"] = *v + //quotaBlock["max_retry_interval"] = *v //todo fix + quotaBlock["max_recurrence_interval"] = *v } quotaBlock["max_recurrence_frequency"] = string(recurrence.Frequency) diff --git a/azurerm/resource_arm_scheduler_job_test.go b/azurerm/resource_arm_scheduler_job_test.go new file mode 100644 index 000000000000..2c0c6a49d77a --- /dev/null +++ b/azurerm/resource_arm_scheduler_job_test.go @@ -0,0 +1,999 @@ +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" + "os" +) + +// check recurring basic -> recurring each type? +// check: basic everything -> complete everything? +// check : base + web + error action + +func TestAccAzureRMSchedulerJob_web_basic(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_scheduler_job.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSchedulerJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + "", "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMSchedulerJob_startTime(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_scheduler_job.test" + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSchedulerJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + "", "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + ), + }, + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + testAccAzureRMSchedulerJob_block_startTime("2019-07-07T07:07:07-07:00"), + "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_startTime(resourceName, "2019-07-07T14:07:07Z"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMSchedulerJob_web_retry(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_scheduler_job.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSchedulerJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + testAccAzureRMSchedulerJob_block_retry_empty(), + "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + checkAccAzureRMSchedulerJob_retry_empty(resourceName), + ), + }, + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + testAccAzureRMSchedulerJob_block_retry_complete(), + "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + checkAccAzureRMSchedulerJob_retry_complete(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMSchedulerJob_web_recurring(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_scheduler_job.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSchedulerJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + testAccAzureRMSchedulerJob_block_recurrence_basic(), + "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + checkAccAzureRMSchedulerJob_recurrence_basic(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMSchedulerJob_web_recurringDaily(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_scheduler_job.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSchedulerJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + testAccAzureRMSchedulerJob_block_recurrence_daily(), + "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + checkAccAzureRMSchedulerJob_recurrence_daily(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMSchedulerJob_web_recurringWeekly(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_scheduler_job.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSchedulerJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + testAccAzureRMSchedulerJob_block_recurrence_weekly(), + "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + checkAccAzureRMSchedulerJob_recurrence_weekly(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMSchedulerJob_web_recurringMonthly(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_scheduler_job.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSchedulerJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + testAccAzureRMSchedulerJob_block_recurrence_monthly(), + "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + checkAccAzureRMSchedulerJob_recurrence_monthly(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMSchedulerJob_web_recurringMonthlyOccurrences(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_scheduler_job.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSchedulerJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + testAccAzureRMSchedulerJob_block_recurrence_monthlyOccurrences(), + "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + checkAccAzureRMSchedulerJob_recurrence_monthlyOccurrences(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMSchedulerJob_web_recurringAll(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_scheduler_job.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSchedulerJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + testAccAzureRMSchedulerJob_block_recurrence_basic(), + "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + checkAccAzureRMSchedulerJob_recurrence_basic(resourceName), + ), + }, + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + testAccAzureRMSchedulerJob_block_recurrence_daily(), + "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + checkAccAzureRMSchedulerJob_recurrence_daily(resourceName), + ), + }, + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + testAccAzureRMSchedulerJob_block_recurrence_weekly(), + "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + checkAccAzureRMSchedulerJob_recurrence_weekly(resourceName), + ), + }, + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + testAccAzureRMSchedulerJob_block_recurrence_monthly(), + "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + checkAccAzureRMSchedulerJob_recurrence_monthly(resourceName), + ), + }, + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + testAccAzureRMSchedulerJob_block_recurrence_monthlyOccurrences(), + "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + checkAccAzureRMSchedulerJob_recurrence_monthlyOccurrences(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMSchedulerJob_web_put(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_scheduler_job.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSchedulerJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + "", "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + ), + }, + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_put("action_web"), + "", "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_put(resourceName, "action_web"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMSchedulerJob_web_authBasic(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_scheduler_job.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSchedulerJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_authBasic("action_web"), + "", "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_authBasic(resourceName, "action_web"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"action_web.0.authentication_basic.0.password"}, + }, + }, + }) +} + +func TestAccAzureRMSchedulerJob_web_authCert(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_scheduler_job.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSchedulerJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_authCert(), + "", "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_authCert(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "action_web.0.authentication_certificate.0.pfx", + "action_web.0.authentication_certificate.0.password", + }, + }, + }, + }) +} + +func TestAccAzureRMSchedulerJob_web_authAd(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_scheduler_job.test" + + clientId := os.Getenv("ARM_CLIENT_ID") + tenantId := os.Getenv("ARM_TENANT_ID") + secret := os.Getenv("ARM_CLIENT_SECRET") + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSchedulerJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_authAd(tenantId, clientId, secret), + "", "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_authAd(resourceName, tenantId, clientId, secret), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "action_web.0.authentication_active_directory.0.secret", + }, + }, + }, + }) +} + +func TestAccAzureRMSchedulerJob_web_basic_onceToRecurring(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_scheduler_job.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSchedulerJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + "", "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + ), + }, + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + "", "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMSchedulerJob_errrActionWeb_basic(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_scheduler_job.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSchedulerJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + "", "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + ), + }, + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), + testAccAzureRMSchedulerJob_block_actionWeb_basic("error_action_web"), + "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), + checkAccAzureRMSchedulerJob_web_basic(resourceName, "error_action_web"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMSchedulerJob_errorActionWeb_put(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_scheduler_job.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSchedulerJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_put("action_web"), + testAccAzureRMSchedulerJob_block_actionWeb_put("error_action_web"), + "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_put(resourceName, "action_web"), + checkAccAzureRMSchedulerJob_web_put(resourceName, "error_action_web"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMSchedulerJob_errorActionWeb_authBasic(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_scheduler_job.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSchedulerJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_authBasic("action_web"), + testAccAzureRMSchedulerJob_block_actionWeb_authBasic("error_action_web"), + "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_authBasic(resourceName, "action_web"), + checkAccAzureRMSchedulerJob_web_authBasic(resourceName, "error_action_web"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "action_web.0.authentication_basic.0.password", + "error_action_web.0.authentication_basic.0.password", + }, + }, + }, + }) +} + +func TestAccAzureRMSchedulerJob_errorAndActionWebAuth(t *testing.T) { + ri := acctest.RandInt() + resourceName := "azurerm_scheduler_job.test" + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMSchedulerJobDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), + testAccAzureRMSchedulerJob_block_actionWeb_authCert(), + testAccAzureRMSchedulerJob_block_actionWeb_authBasic("error_action_web"), + "", ""), + Check: resource.ComposeAggregateTestCheckFunc( + checkAccAzureRMSchedulerJob_base(resourceName), + checkAccAzureRMSchedulerJob_web_authCert(resourceName), + checkAccAzureRMSchedulerJob_web_authBasic(resourceName, "error_action_web"), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, ImportStateVerifyIgnore: []string{ + "action_web.0.authentication_certificate.0.pfx", + "action_web.0.authentication_certificate.0.password", + "error_action_web.0.authentication_basic.0.password", + }, + }, + }, + }) +} + +func testCheckAzureRMSchedulerJobDestroy(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_scheduler_job.test" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + jobCollection := rs.Primary.Attributes["job_collection_name"] + + client := testAccProvider.Meta().(*ArmClient).schedulerJobsClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + resp, err := client.Get(ctx, resourceGroup, jobCollection, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return nil + } + + return err + } + + return fmt.Errorf("Scheduler Job Collection still exists:\n%#v", resp) + } + + return nil +} + +func testCheckAzureRMSchedulerJobExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %q", name) + } + + name := rs.Primary.Attributes["name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + jobCollection := rs.Primary.Attributes["job_collection_name"] + + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Scheduler Job: %q", name) + } + + client := testAccProvider.Meta().(*ArmClient).schedulerJobsClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + resp, err := client.Get(ctx, resourceGroup, jobCollection, name) + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Scheduler Job %q (resource group: %q) was not found: %+v", name, resourceGroup, err) + } + + return fmt.Errorf("Bad: Get on schedulerJobsClient: %+v", err) + } + + return nil + } +} + +func testAccAzureRMSchedulerJob_base(rInt int, location, block1, block2, block3, block4 string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "rg" { + name = "acctestRG-%[1]d" + location = "%[2]s" +} + +resource "azurerm_scheduler_job_collection" "jc" { + name = "acctestRG-%[1]d-job_collection" + location = "${azurerm_resource_group.rg.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + sku = "standard" +} + +resource "azurerm_scheduler_job" "test" { + name = "acctestRG-%[1]d-job" + resource_group_name = "${azurerm_resource_group.rg.name}" + job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" + + %[3]s + + %[4]s + + %[5]s + + %[6]s +} +`, rInt, location, block1, block2, block3, block4) +} +func checkAccAzureRMSchedulerJob_base(resourceName string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttrSet(resourceName, "name"), + resource.TestCheckResourceAttrSet(resourceName, "resource_group_name"), + resource.TestCheckResourceAttrSet(resourceName, "job_collection_name"), + resource.TestCheckResourceAttr(resourceName, "state", "enabled"), + ) +} + +func testAccAzureRMSchedulerJob_block_startTime(time string) string { + return fmt.Sprintf(` + start_time = "%s" +`, time) +} + +func checkAccAzureRMSchedulerJob_startTime(resourceName, time string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "start_time", time), + ) +} + +func testAccAzureRMSchedulerJob_block_recurrence_basic() string { + return ` + recurrence { + frequency = "minute" + interval = 5 + count = 10 + //end_time = "2019-07-17T07:07:07-07:00" + } +` +} + +func checkAccAzureRMSchedulerJob_recurrence_basic(resourceName string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "minute"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.interval", "5"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "10"), + ) +} + +func testAccAzureRMSchedulerJob_block_recurrence_daily() string { + return ` + recurrence { + frequency = "day" + count = 100 + hours = [0,12] + minutes = [0,15,30,45] + } +` +} + +func checkAccAzureRMSchedulerJob_recurrence_daily(resourceName string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "day"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.hours.#", "2"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.minutes.#", "4"), + ) +} + +func testAccAzureRMSchedulerJob_block_recurrence_weekly() string { + return ` + recurrence { + frequency = "week" + count = 100 + week_days = ["Sunday", "Saturday"] + } +` +} + +func checkAccAzureRMSchedulerJob_recurrence_weekly(resourceName string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "week"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.week_days.#", "2"), + ) +} + +func testAccAzureRMSchedulerJob_block_recurrence_monthly() string { + return ` + recurrence { + frequency = "month" + count = 100 + month_days = [-11,-1,1,11] + } +` +} + +func checkAccAzureRMSchedulerJob_recurrence_monthly(resourceName string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "month"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.month_days.#", "4"), + ) +} + +func testAccAzureRMSchedulerJob_block_recurrence_monthlyOccurrences() string { + return ` + recurrence { + frequency = "month" + count = 100 + monthly_occurrences = [ + { + day = "sunday" + occurrence = 1 + }, + { + day = "sunday" + occurrence = 3 + }, + { + day = "sunday" + occurrence = -1 + } + ] + } +` +} + +func checkAccAzureRMSchedulerJob_recurrence_monthlyOccurrences(resourceName string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "month"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.#", "3"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.2181640481.day", "sunday"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.2181640481.occurrence", "1"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.2956940195.day", "sunday"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.2956940195.occurrence", "3"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.679325150.day", "sunday"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.679325150.occurrence", "-1"), + ) +} + +func testAccAzureRMSchedulerJob_block_retry_empty() string { + return ` + retry { + } +` +} + +func checkAccAzureRMSchedulerJob_retry_empty(resourceName string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "retry.0.interval", "00:00:30"), + resource.TestCheckResourceAttr(resourceName, "retry.0.count", "4"), + ) +} + +func testAccAzureRMSchedulerJob_block_retry_complete() string { + return ` + retry { + interval = "00:05:00" //5 min + count = 10 + } +` +} + +func checkAccAzureRMSchedulerJob_retry_complete(resourceName string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "retry.0.interval", "00:05:00"), + resource.TestCheckResourceAttr(resourceName, "retry.0.count", "10"), + ) +} + +func testAccAzureRMSchedulerJob_block_actionWeb_basic(blockName string) string { + return fmt.Sprintf(` + %s { + url = "http://this.get.url.fails" + } +`, blockName) +} + +func checkAccAzureRMSchedulerJob_web_basic(resourceName, blockName string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.url", blockName), "http://this.get.url.fails"), + ) +} + +func testAccAzureRMSchedulerJob_block_actionWeb_put(blockName string) string { + return fmt.Sprintf(` + %s { + url = "http://this.put.url.fails" + method = "put" + body = "this is some text" + headers = { + Content-Type = "text" + } + } +`, blockName) +} + +func checkAccAzureRMSchedulerJob_web_put(resourceName, blockName string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.url", blockName), "http://this.put.url.fails"), + resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.method", blockName), "put"), + resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.body", blockName), "this is some text"), + resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.headers.%%", blockName), "1"), + ) +} + +func testAccAzureRMSchedulerJob_block_actionWeb_authBasic(blockName string) string { + return fmt.Sprintf(` + %s { + url = "https://this.url.fails" + method = "get" + + authentication_basic { + username = "login" + password = "apassword" + } + } +`, blockName) +} + +func checkAccAzureRMSchedulerJob_web_authBasic(resourceName string, blockName string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.url", blockName), "https://this.url.fails"), + resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.method", blockName), "get"), + resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.authentication_basic.0.username", blockName), "login"), + resource.TestCheckResourceAttrSet(resourceName, fmt.Sprintf("%s.0.authentication_basic.0.password", blockName)), + ) +} + +func testAccAzureRMSchedulerJob_block_actionWeb_authCert() string { + return ` + action_web { + url = "https://this.url.fails" + method = "get" + + authentication_certificate { + pfx = "${base64encode(file("testdata/application_gateway_test.pfx"))}" + password = "terraform" + } + } +` +} + +func checkAccAzureRMSchedulerJob_web_authCert(resourceName string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://this.url.fails"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + resource.TestCheckResourceAttrSet(resourceName, "action_web.0.authentication_certificate.0.pfx"), + resource.TestCheckResourceAttrSet(resourceName, "action_web.0.authentication_certificate.0.password"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_certificate.0.thumbprint", "42C107874FD0E4A9583292A2F1098E8FE4B2EDDA"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_certificate.0.subject_name", "CN=Terraform App Gateway, OU=Azure, O=Terraform Tests, S=Some-State, C=US"), + ) +} + +func testAccAzureRMSchedulerJob_block_actionWeb_authAd(tenantId, clientId, secret string) string { + return fmt.Sprintf(` + action_web { + url = "https://this.url.fails" + method = "get" + + authentication_active_directory { + tenant_id = "%s" + client_id = "%s" + secret = "%s" + audience = "https://management.core.windows.net/" + } + } +`, tenantId, clientId, secret) +} + +func checkAccAzureRMSchedulerJob_web_authAd(resourceName, tenantId, clientId, secret string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://this.url.fails"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_active_directory.0.tenant_id", tenantId), + resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_active_directory.0.client_id", clientId), + resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_active_directory.0.secret", secret), + resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_active_directory.0.audience", "https://management.core.windows.net/"), + ) +} diff --git a/azurerm/validators.go b/azurerm/validators.go index c54d632b8f06..82e2c91b7617 100644 --- a/azurerm/validators.go +++ b/azurerm/validators.go @@ -10,6 +10,8 @@ import ( "github.com/satori/uuid" ) +//move to package! + func validateRFC3339Date(v interface{}, k string) (ws []string, errors []error) { dateString := v.(string) @@ -48,6 +50,7 @@ func validateUUID(v interface{}, k string) (ws []string, errors []error) { return } +//todo move to where it is used, simplify to basic regex func validateDBAccountName(v interface{}, k string) (ws []string, errors []error) { value := v.(string) @@ -64,6 +67,7 @@ func validateDBAccountName(v interface{}, k string) (ws []string, errors []error return } +//what is? func evaluateSchemaValidateFunc(i interface{}, k string, validateFunc schema.SchemaValidateFunc) (bool, error) { _, es := validateFunc(i, k) @@ -74,6 +78,7 @@ func evaluateSchemaValidateFunc(i interface{}, k string, validateFunc schema.Sch return true, nil } +//replace with built in TODO func validateStringLength(maxLength int) schema.SchemaValidateFunc { return func(v interface{}, k string) (ws []string, errors []error) { value := v.(string) diff --git a/examples/scheduler-jobs/main.tf b/examples/scheduler-jobs/main.tf index 483cacc85129..a03876e7f23b 100644 --- a/examples/scheduler-jobs/main.tf +++ b/examples/scheduler-jobs/main.tf @@ -4,16 +4,168 @@ resource "azurerm_resource_group" "rg" { location = "${var.resource_group_location}" } -resource "azurerm_scheduler_job_collection" "jobs" { - name = "example_job_collection" +resource "azurerm_scheduler_job_collection" "jc" { + name = "tfex-scheduler-job-collection" location = "${azurerm_resource_group.rg.location}" resource_group_name = "${azurerm_resource_group.rg.name}" - sku = "free" + sku = "standard" state = "enabled" quota { - max_job_count = 5 - max_retry_interval = 24 - max_recurrence_frequency = "hour" + max_job_count = 15 + max_recurrence_interval = 1 + max_recurrence_frequency = "minute" } } + +resource "azurerm_scheduler_job" "web-once-now" { + name = "tfex-web-once-now" + resource_group_name = "${azurerm_resource_group.rg.name}" + job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" + + state = "enabled" + + action_web { + url = "http://this.url.fails" + } + + retry { + interval = "00:05:00" //5 min + count = 4 + } + + //times in the past start imediatly and run once, + start_time = "1987-07-07T07:07:07-07:00" +} + +resource "azurerm_scheduler_job" "web-recurring" { + name = "tfex-web-recurring" + resource_group_name = "${azurerm_resource_group.rg.name}" + job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" + + action_web { + url = "http://this.url.fails" + method = "put" + body = "this is some text" + headers = { + Content-Type = "text" + } + } + + retry { + interval = "00:05:00" //5 min + count = 4 + } + + recurrence { + frequency = "minute" + interval = 5 + count = 10 //recurring counts start in past + } + + start_time = "2019-07-07T07:07:07-07:00" +} + +resource "azurerm_scheduler_job" "web-recurring_daily-auth_basic" { + name = "tfex-web-recurring_daily-auth_basic" + resource_group_name = "${azurerm_resource_group.rg.name}" + job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" + + state = "enabled" + + action_web { + url = "https://this.url.fails" + method = "get" + + authentication_basic { + username = "login" + password = "apassword" + } + } + + recurrence { + frequency = "day" + count = 1000 + hours = [0,12] + minutes = [0,15,30,45] + } + + start_time = "2019-07-07T07:07:07-07:00" +} + + +resource "azurerm_scheduler_job" "web-recurring_weekly-auth_cert" { + name = "tfex-web-recurring_weekly-auth_cert" + resource_group_name = "${azurerm_resource_group.rg.name}" + job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" + + state = "enabled" + + action_web { + url = "https://this.url.fails" + method = "get" + + authentication_certificate { + pfx = "${base64encode(file("../../azurerm/testdata/application_gateway_test.pfx"))}" + password = "terraform" + } + } + + recurrence { + frequency = "week" + count = 1000 + week_days = ["Sunday", "Saturday"] + } + + start_time = "2019-07-07T07:07:07-07:00" +} + + +resource "azurerm_scheduler_job" "web-recurring_monthly-error_actioin" { + name = "tfex-web-recurring_monthly-auth_ad" + resource_group_name = "${azurerm_resource_group.rg.name}" + job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" + + state = "enabled" + + action_web { + url = "http://this.url.fails" + method = "get" + } + + error_action_web { + url = "https://this.url.fails" + method = "put" + body = "The job failed" + + headers = { + Content-Type = "text" + } + + authentication_basic { + username = "login" + password = "apassword" + } + } + + recurrence { + frequency = "month" + count = 1000 + monthly_occurrences = [ + { + day = "Sunday" + occurrence = 1 + }, + { + day = "Sunday" + occurrence = 3 + }, + { + day = "Sunday" + occurrence = -1 + } + ] + } + + start_time = "2019-07-07T07:07:07-07:00" +} \ No newline at end of file diff --git a/examples/scheduler-jobs/outputs.tf b/examples/scheduler-jobs/outputs.tf index feb8f4d27f83..fd5248c866c7 100644 --- a/examples/scheduler-jobs/outputs.tf +++ b/examples/scheduler-jobs/outputs.tf @@ -1,4 +1,23 @@ output "job_collection-id" { - value = "${azurerm_scheduler_job_collection.jobs.id}" + value = "${azurerm_scheduler_job_collection.jc.id}" +} + +output "job-web-once-url" { + value = "${azurerm_scheduler_job.web-once-now.action_web.0.url}" +} + +output "job-web-once-count" { + value = "${azurerm_scheduler_job.web-once-now.execution_count}" +} + +output "job-web-recurring_weekly-authCert_thumb" { + value = "${azurerm_scheduler_job.web-recurring_weekly-auth_cert.action_web.0.authentication_certificate.0.thumbprint}" +} +output "job-web-recurring_weekly-authCert_expire" { + value = "${azurerm_scheduler_job.web-recurring_weekly-auth_cert.action_web.0.authentication_certificate.0.expiration}" +} + +output "job-web-recurring_weekly-authCert_san" { + value = "${azurerm_scheduler_job.web-recurring_weekly-auth_cert.action_web.0.authentication_certificate.0.subject_name}" } \ No newline at end of file diff --git a/website/azurerm.erb b/website/azurerm.erb index 9f4529b4285c..c0453a27a9ef 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -663,6 +663,11 @@ azurerm_scheduler_job_collection + > diff --git a/website/docs/r/scheduler_job.html.markdown b/website/docs/r/scheduler_job.html.markdown new file mode 100644 index 000000000000..3c25f9e18270 --- /dev/null +++ b/website/docs/r/scheduler_job.html.markdown @@ -0,0 +1,226 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_scheduler_job" +sidebar_current: "docs-azurerm-resource-scheduler_job +description: |- + Create or modify a Scheduler Job. +--- + +# azurerm_scheduler_job + +Create or modify a Scheduler Job. + +## Example Usage (single web get now) + +```hcl +resource "azurerm_scheduler_job" "web-once-now" { + name = "tfex-web-once-now" + resource_group_name = "${azurerm_resource_group.rg.name}" + job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" + + state = "enabled" //re-enable it each run + + action_web { + url = "http://this.url.fails" //defaults to get + } + + //default start time is now +} +``` + +## Example Usage (recurring daily with retry and basic authentication) + +```hcl +resource "azurerm_scheduler_job" "web-recurring-daily" { + name = "tfex-web-recurring-daily" + resource_group_name = "${azurerm_resource_group.rg.name}" + job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" + + action_web { + url = "https://this.url.fails" + method = "put" + body = "this is some text" + + headers = { + Content-Type = "text" + } + + authentication_basic { + username = "login" + password = "apassword" + } + } + + retry { + interval = "00:05:00" //retry every 5 min + count = 10 //a maximum or 10 times + } + + recurrence { + frequency = "day" + count = 1000 + hours = [0,12] //run every 12 hours + minutes = [0,15,30,45] //4 times an hour + } + + start_time = "2018-07-07T07:07:07-07:00" +} +``` + +## Example Usage (recurring monthly with an error action and client certificate authentication) + +```hcl +resource "azurerm_scheduler_job" "web-recurring-daily" { + name = "tfex-web-recurring-daily" + resource_group_name = "${azurerm_resource_group.rg.name}" + job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" + + action_web { + url = "https://this.url.fails" + authentication_certificate { + pfx = "${base64encode(file("your_cert.pfx"))}" + password = "cert_password" + } + } + + error_action_web { + url = "https://this.url.fails" + method = "put" + body = "The job failed" + + headers = { + Content-Type = "text" + } + + authentication_basic { + username = "login" + password = "apassword" + } + } + + recurrence { + frequency = "monthly" + count = 1000 + monthly_occurrences = [ + { //first sunday + day = "Sunday" + occurrence = 1 + }, + { //third sunday + day = "Sunday" + occurrence = 3 + }, + { //last sunday + day = "Sunday" + occurrence = -1 + } + ] + } + + start_time = "2018-07-07T07:07:07-07:00" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) The name of the Scheduler Job. Changing this forces a new resource to be created. + +* `resource_group_name` - (Required) The name of the resource group in which to create the Scheduler Job. Changing this forces a new resource to be created. + +* `job_collection_name` - (Required) Specifies the Scheduler Job Collection to add the job to. Changing this forces a new resource to be created. + +* `action_web` - (Required) A `action_web` block defining the job action as described below. Note this is identical to an `error_action_web` block. + +* `error_action_web` - (Optional) A `error_action_web` block defining the action to take on an error as described below. Note this is identical to an `action_web` block. + +* `retry` - (Optional) A `retry` block defining how to retry as described below. Omitting this block defaults to no retry. + +* `recurrence` - (Optional) A `recurrence` block defining a job occurrence schedule. Omitting this block causes the job to run just once. + +* `start_time` - (Optional) The time the first instance of the job is to start running at. Omitting this causes the job to start now. + +* `state` - (Optional) The sets or gets the current state of the job. Could be one of: `Enabled`, `Completed`, `Disabled`, `Faulted` + + +`web_action` & `error_web_action` block supports the following: + +* `url` - (Required) Specifies the URL of the web request. Must be HTTPS for authenticated requests. +* `method` - (Optional) Specifies the method of the request. Defaults to `Get` and must be one of `Get`, `Put`, `Post`, `Delete`. +* `body` - (Optional) Specifies the request body. +* `headers` - (Optional) A map specifying the headers sent with the request. +* `authentication_basic` - (Optional) A `authentication_basic` block allowing HTTP basic authentication to be used. +* `authentication_certificate` - (Optional) A `authentication_certificate` block allowing a client certificate information to be used for authentication. +* `authentication_active_directory` - (Optional) A `authentication_active_directory` block to configure OAUTH Active Directory authentication. + + +`authentication_basic` block supports the following: + +* `username` - (Required) Specifies the username to use. +* `password` - (Required) Specifies the password t use. Cannot be imported. + + +`authentication_certificate` block supports the following: + +* `pfx` - (Required) Specifies the pfx certificate. Cannot be imported. +* `password` - (Required) Specifies the certificate password. Cannot be imported. +* `thumbprint` - (Computed) The certificate thumbprint. +* `expiration` - (Computed) The certificate expiration date. +* `subject_name` - (Computed) The certificate's certificate subject name. + + +`authentication_active_directory` block supports the following: + +* `client_id` - (Required) Specifies the client ID to use. +* `tenant_id` - (Required) Specifies the tenant ID to use. +* `secret` - (Required) Specifies the secret to use. Cannot be imported. +* `audience` - (Optional) Specifies the audience. + + +`retry` block supports the following: + +* `interval` - (Required) Specifies the duration between retries. +* `count` - (Required) Specifies the number of times a retry should be attempted. + +`recurrence` block supports the following: + +* `frequency` - (Required) Specifies the frequency of recurrence. Must be one of `Minute`, `Hour`, `Day`, `Week`, `Month`. +* `interval` - (Optional) Specifies the interval between executions. Defaults to `1`. +* `count` - (Optional) Specifies the maximum number of times that the job should run. +* `end_time` - (Optional) Specifies the time at which the job will cease running. Must be less then 500 days into the future. +* `minutes` - (Optional) Specifies the minutes of the hour that the job should execute at. Must be between `0` and `59` +* `hours` - (Optional) Specifies the hours of the day that the job should execute at. Must be between `0` and `23` +* `week_days` - (Optional) Specifies the days of the week that the job should execute on. Must be one of `Monday`, `Tuesday`, `Wednesday`, `Thursday`, `Friday`, `Saturday`, `Sunday`. Only applies when `Week` is used for frequency. +* `month_days` - (Optional) Specifies the days of the month that the job should execute on. Must be non zero and between ``-1` and `31`. Only applies when `Month` is used for frequency. +* `monthly_occurrences` - (Optional) Specifies specific monthly occurrences like "last sunday of the month" with `monthly_occurrences` blocks. Only applies when `Month` is used for frequency. + +`monthly_occurrences` block supports the following: + +* `day` - (Optional) Specifies the day of the week that the job should execute on. Must be one of one of `Monday`, `Tuesday`, `Wednesday`, `Thursday`, `Friday`, `Saturday`, `Sunday`. +* `occurrence` - (Optional) Specifies the week the job should run on. For example 1 for the first week, -1 for the last week of the month. Must be between -5 and 5. + + +## Attributes Reference + +The following attributes are exported: + +* `id` - The Scheduler Job ID. + +* `execution_count` - The number of times this job has executed. + +* `failure_count` - The number of times this job has failed. + +* `faulted_count` - The number of faulted occurrences (occurrences that were retried and failed as many times as the retry policy states). + +* `last_execution_time` - The time the last occurrence executed in ISO-8601 format. Could be empty if job has not run yet. + +* `next_execution_time` - The time of the next occurrence. Could be empty if the job is completed.. + +## Import + +Scheduler Job can be imported using a `resource id`, e.g. + +```shell +terraform import azurerm_search_service.service1 /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resourceGroup1/providers/Microsoft.Scheduler/jobCollections/jobCollection1/jobs/job1 +``` diff --git a/website/docs/r/scheduler_job_collection.html.markdown b/website/docs/r/scheduler_job_collection.html.markdown index 3a760f0f547a..96704fa1e5df 100644 --- a/website/docs/r/scheduler_job_collection.html.markdown +++ b/website/docs/r/scheduler_job_collection.html.markdown @@ -3,12 +3,12 @@ layout: "azurerm" page_title: "Azure Resource Manager: azurerm_scheduler_job_collection" sidebar_current: "docs-azurerm-resource-scheduler_job_collection" description: |- - Create an Scheduler Job Collection. + Create a Scheduler Job Collection. --- # azurerm_scheduler_job_collection -Create an Scheduler Job Collection. +Create a Scheduler Job Collection. ## Example Usage From beb79b871b5f6fc2b45f41dcd8989efef842db40 Mon Sep 17 00:00:00 2001 From: kt Date: Thu, 26 Apr 2018 19:08:31 -0700 Subject: [PATCH 02/18] azurerm_scheduler_job todo & misc cleanup --- azurerm/helpers/supress/suppress_test.go | 2 +- azurerm/resource_arm_scheduler_job.go | 38 +++++-------------- .../resource_arm_scheduler_job_collection.go | 27 ++++--------- azurerm/validators.go | 2 - examples/scheduler-jobs/main.tf | 2 +- 5 files changed, 19 insertions(+), 52 deletions(-) diff --git a/azurerm/helpers/supress/suppress_test.go b/azurerm/helpers/supress/suppress_test.go index b66600938222..4ed1647da373 100644 --- a/azurerm/helpers/supress/suppress_test.go +++ b/azurerm/helpers/supress/suppress_test.go @@ -75,7 +75,7 @@ func TestInternal_Supress_Rfc3339Time(t *testing.T) { }, { TimeA: "2000-01-01T01:23:45+7:00", - TimeB: "2010-01-01T08:23:45Z", + TimeB: "2000-01-01T08:23:45Z", Suppress: true, }, } diff --git a/azurerm/resource_arm_scheduler_job.go b/azurerm/resource_arm_scheduler_job.go index fb17bed22021..9cff11e79636 100644 --- a/azurerm/resource_arm_scheduler_job.go +++ b/azurerm/resource_arm_scheduler_job.go @@ -53,11 +53,9 @@ func resourceArmSchedulerJob() *schema.Resource { //actions "action_web": resourceArmSchedulerJobActionWebSchema("action_web"), - //"action_servicebus": resourceArmSchedulerJobActionServicebusSchema("action_servicebus", []string{"action_web", "action_storagequeue"}), //each action can also be an error action "error_action_web": resourceArmSchedulerJobActionWebSchema("error_action_web"), - //"error_action_servicebus": resourceArmSchedulerJobActionServicebusSchema("action_servicebus", []string{"action_web", "action_servicebus"}), //retry policy "retry": { @@ -67,19 +65,9 @@ func resourceArmSchedulerJob() *schema.Resource { Optional: true, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - //none cannot be used with either of these values todo keep? - /*"type": { - Type: schema.TypeString, - Optional: true, - Default: string(scheduler.Fixed), - DiffSuppressFunc: internal.CaseDifference, - ValidateFunc: validation.StringInSlice([]string{ - string(scheduler.Fixed), - string(scheduler.None), - }, true), - },*/ //silently fails if the duration is not in the correct format + //todo validation "interval": { Type: schema.TypeString, Optional: true, @@ -128,9 +116,10 @@ func resourceArmSchedulerJob() *schema.Resource { }, "count": { - Type: schema.TypeInt, - Optional: true, - ValidateFunc: validation.IntBetween(1, 2147483647), //silently fails/produces odd results at >2147483647 + Type: schema.TypeInt, + Optional: true, + //silently fails/produces odd results at >2147483647 + ValidateFunc: validation.IntBetween(1, 2147483647), }, "end_time": { @@ -398,9 +387,7 @@ func resourceArmSchedulerJobActionWebSchema(propertyName string) *schema.Schema func resourceArmSchedulerJobCustomizeDiff(diff *schema.ResourceDiff, v interface{}) error { _, hasWeb := diff.GetOk("action_web") - //_, hasService := diff.GetOk("action_servicebus") - //_, hasStorage := diff.GetOk("action_storagequeue") - if !hasWeb { //&& !hasService && !hasStorage + if !hasWeb { return fmt.Errorf("One of `action_web`, `action_servicebus` or `action_storagequeue` must be set") } @@ -410,7 +397,7 @@ func resourceArmSchedulerJobCustomizeDiff(diff *schema.ResourceDiff, v interface //if neither count nor end time is set the API will silently fail _, hasCount := recurrence["count"] _, hasEnd := recurrence["end_time"] - if !hasCount && !hasEnd { //&& !hasService && !hasStorage + if !hasCount && !hasEnd { return fmt.Errorf("One of `count` or `end_time` must be set for the 'recurrence' block.") } @@ -482,9 +469,6 @@ func resourceArmSchedulerJobCreateUpdate(d *schema.ResourceData, meta interface{ //action if b, ok := d.GetOk("action_web"); ok { job.Properties.Action.Request, job.Properties.Action.Type = expandAzureArmSchedulerJobActionRequest(b) - } else { - //todo should never get here because of the customize diff, so is this required? - return fmt.Errorf("One of `action_web`, `action_servicebus` or `action_storagequeue` must be set for scheduler job %q (Resource Group %q)", name, resourceGroup) } //error action @@ -663,7 +647,6 @@ func resourceArmSchedulerJobDelete(d *schema.ResourceData, meta interface{}) err } //expand (terraform -> API) - func expandAzureArmSchedulerJobActionRequest(b interface{}) (*scheduler.HTTPRequest, scheduler.JobActionType) { block := b.([]interface{})[0].(map[string]interface{}) @@ -673,7 +656,7 @@ func expandAzureArmSchedulerJobActionRequest(b interface{}) (*scheduler.HTTPRequ request := scheduler.HTTPRequest{ URI: &url, Method: utils.String(block["method"].(string)), - Headers: &map[string]*string{}, + Headers: map[string]*string{}, } // determine type from the url, the property validation must ensure this @@ -689,7 +672,7 @@ func expandAzureArmSchedulerJobActionRequest(b interface{}) (*scheduler.HTTPRequ //load headers //if v, ok := block["headers"].(map[string]interface{}); ok { //check doesn't seem to be needed for k, v := range block["headers"].(map[string]interface{}) { - (*request.Headers)[k] = utils.String(v.(string)) + (request.Headers)[k] = utils.String(v.(string)) } //only valid for a set @@ -828,7 +811,7 @@ func flattenAzureArmSchedulerJobActionRequest(request *scheduler.HTTPRequest, ob if v := request.Headers; v != nil { headers := map[string]interface{}{} - for k, v := range *v { + for k, v := range v { headers[k] = *v } @@ -977,7 +960,6 @@ func resourceAzureRMSchedulerJobMonthlyOccurrenceHash(v interface{}) int { return hashcode.String(buf.String()) } -//todo move these somewhere? func sliceToSetInt32(slice []int32) *schema.Set { set := &schema.Set{F: set.HashInt} for _, v := range slice { diff --git a/azurerm/resource_arm_scheduler_job_collection.go b/azurerm/resource_arm_scheduler_job_collection.go index fec1b097f4f5..b052f3c0f3f6 100644 --- a/azurerm/resource_arm_scheduler_job_collection.go +++ b/azurerm/resource_arm_scheduler_job_collection.go @@ -69,7 +69,6 @@ func resourceArmSchedulerJobCollection() *schema.Resource { "quota": { Type: schema.TypeList, Optional: true, - MinItems: 1, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ @@ -95,21 +94,12 @@ func resourceArmSchedulerJobCollection() *schema.Resource { }, true), }, - //while in the documentation the MaxRecurrance.Interval is stated to "Gets or sets the interval between retries." - //it does appear it is the max interval allowed for a recurrence + //this is MaxRecurrance.Interval, property is named this as the documentation in the api states: + // Gets or sets the interval between retries. "max_retry_interval": { - Type: schema.TypeInt, - Optional: true, - Deprecated: "Renamed to match azure", - ConflictsWith: []string{"quota.0.max_recurrence_interval"}, - ValidateFunc: validation.IntAtLeast(1), //changes depending on the frequency, unknown maximums - }, - - "max_recurrence_interval": { - Type: schema.TypeInt, - Optional: true, - ConflictsWith: []string{"quota.0.max_retry_interval"}, - ValidateFunc: validation.IntAtLeast(1), //changes depending on the frequency, unknown maximums + Type: schema.TypeInt, + Optional: true, + ValidateFunc: validation.IntAtLeast(1), //changes depending on the frequency, unknown maximums }, }, }, @@ -257,10 +247,8 @@ func expandAzureArmSchedulerJobCollectionQuota(d *schema.ResourceData) *schedule } if v, ok := quotaBlock["max_recurrence_frequency"].(string); ok { quota.MaxRecurrence.Frequency = scheduler.RecurrenceFrequency(v) - } else if v, ok := quotaBlock["max_retry_interval"].(int); ok { - quota.MaxRecurrence.Interval = utils.Int32(int32(v)) } - if v, ok := quotaBlock["max_recurrence_interval"].(int); ok { + if v, ok := quotaBlock["max_retry_interval"].(int); ok { quota.MaxRecurrence.Interval = utils.Int32(int32(v)) } @@ -283,8 +271,7 @@ func flattenAzureArmSchedulerJobCollectionQuota(quota *scheduler.JobCollectionQu } if recurrence := quota.MaxRecurrence; recurrence != nil { if v := recurrence.Interval; v != nil { - //quotaBlock["max_retry_interval"] = *v //todo fix - quotaBlock["max_recurrence_interval"] = *v + quotaBlock["max_retry_interval"] = *v } quotaBlock["max_recurrence_frequency"] = string(recurrence.Frequency) diff --git a/azurerm/validators.go b/azurerm/validators.go index ed8bb6b7c5e3..94df9dfa3519 100644 --- a/azurerm/validators.go +++ b/azurerm/validators.go @@ -10,8 +10,6 @@ import ( "github.com/satori/uuid" ) -//move to package! - func validateRFC3339Date(v interface{}, k string) (ws []string, errors []error) { dateString := v.(string) diff --git a/examples/scheduler-jobs/main.tf b/examples/scheduler-jobs/main.tf index a03876e7f23b..617865475731 100644 --- a/examples/scheduler-jobs/main.tf +++ b/examples/scheduler-jobs/main.tf @@ -121,7 +121,7 @@ resource "azurerm_scheduler_job" "web-recurring_weekly-auth_cert" { } -resource "azurerm_scheduler_job" "web-recurring_monthly-error_actioin" { +resource "azurerm_scheduler_job" "web-recurring_monthly-error_action" { name = "tfex-web-recurring_monthly-auth_ad" resource_group_name = "${azurerm_resource_group.rg.name}" job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" From 2c9a46aa414d4683dcf00f070fe3d8f4a21ef963 Mon Sep 17 00:00:00 2001 From: kt Date: Sat, 28 Apr 2018 13:58:17 -0700 Subject: [PATCH 03/18] travis CI fixes travis CI fixes --- azurerm/helpers/supress/suppress_test.go | 8 +++++--- azurerm/resource_arm_scheduler_job.go | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/azurerm/helpers/supress/suppress_test.go b/azurerm/helpers/supress/suppress_test.go index 4ed1647da373..4638caa2867e 100644 --- a/azurerm/helpers/supress/suppress_test.go +++ b/azurerm/helpers/supress/suppress_test.go @@ -1,6 +1,8 @@ package supress -import "testing" +import ( + "testing" +) func TestInternal_Suppress_CaseDifference(t *testing.T) { cases := []struct { @@ -74,8 +76,8 @@ func TestInternal_Supress_Rfc3339Time(t *testing.T) { Suppress: true, }, { - TimeA: "2000-01-01T01:23:45+7:00", - TimeB: "2000-01-01T08:23:45Z", + TimeA: "2000-01-01T01:23:45-08:00", + TimeB: "2000-01-01T09:23:45Z", Suppress: true, }, } diff --git a/azurerm/resource_arm_scheduler_job.go b/azurerm/resource_arm_scheduler_job.go index 9cff11e79636..16a3fdc53526 100644 --- a/azurerm/resource_arm_scheduler_job.go +++ b/azurerm/resource_arm_scheduler_job.go @@ -496,7 +496,7 @@ func resourceArmSchedulerJobCreateUpdate(d *schema.ResourceData, meta interface{ if err != nil { return fmt.Errorf("Error parsing start time (%s) for job %q (Resource Group %q): %+v", d.Get("start_time"), name, resourceGroup, err) } - job.Properties.StartTime = &date.Time{startTime} + job.Properties.StartTime = &date.Time{Time: startTime} //state if state, ok := d.GetOk("state"); ok { From 720eabccd23066ac598acab9982b8f8a6f737a92 Mon Sep 17 00:00:00 2001 From: kt Date: Sat, 12 May 2018 18:54:19 -0700 Subject: [PATCH 04/18] azurerm_scheduler_job: removed populate function & other small changes --- azurerm/helpers/supress/suppress.go | 4 +-- .../validate/{validator.go => validate.go} | 12 ++++----- .../{validator_test.go => validate_test.go} | 0 azurerm/resource_arm_scheduler_job.go | 27 +++++++++---------- azurerm/resource_arm_scheduler_job_test.go | 5 ++-- 5 files changed, 23 insertions(+), 25 deletions(-) rename azurerm/helpers/validate/{validator.go => validate.go} (67%) rename azurerm/helpers/validate/{validator_test.go => validate_test.go} (100%) diff --git a/azurerm/helpers/supress/suppress.go b/azurerm/helpers/supress/suppress.go index 3b2c63e1e6f9..14ea92fba1cf 100644 --- a/azurerm/helpers/supress/suppress.go +++ b/azurerm/helpers/supress/suppress.go @@ -7,11 +7,11 @@ import ( "strings" ) -func CaseDifference(k, old, new string, d *schema.ResourceData) bool { +func CaseDifference(_, old, new string, _ *schema.ResourceData) bool { return strings.ToLower(old) == strings.ToLower(new) } -func Rfc3339Time(k, old, new string, d *schema.ResourceData) bool { +func Rfc3339Time(_, old, new string, _ *schema.ResourceData) bool { ot, oerr := time.Parse(time.RFC3339, old) nt, nerr := time.Parse(time.RFC3339, new) diff --git a/azurerm/helpers/validate/validator.go b/azurerm/helpers/validate/validate.go similarity index 67% rename from azurerm/helpers/validate/validator.go rename to azurerm/helpers/validate/validate.go index d7f482f1280e..1b4cbe714886 100644 --- a/azurerm/helpers/validate/validator.go +++ b/azurerm/helpers/validate/validate.go @@ -9,18 +9,18 @@ import ( ) //todo, now in terraform helper, switch over once vended, -func Rfc3339Time(v interface{}, k string) (ws []string, errors []error) { - if _, err := date.ParseTime(time.RFC3339, v.(string)); err != nil { - errors = append(errors, fmt.Errorf("%q has the invalid RFC3339 date format %q: %+v", k, v, err)) +func Rfc3339Time(i interface{}, k string) (ws []string, errors []error) { + if _, err := date.ParseTime(time.RFC3339, i.(string)); err != nil { + errors = append(errors, fmt.Errorf("%q has the invalid RFC3339 date format %q: %+v", k, i, err)) } return } -func Url(v interface{}, k string) (ws []string, errors []error) { - url, err := url.Parse(v.(string)) +func Url(i interface{}, k string) (ws []string, errors []error) { + url, err := url.Parse(i.(string)) if err != nil { - errors = append(errors, fmt.Errorf("%q url is in an invalid format: %q (%+v)", k, v, err)) + errors = append(errors, fmt.Errorf("%q url is in an invalid format: %q (%+v)", k, i, err)) } else if url.Scheme != "http" && url.Scheme != "https" { errors = append(errors, fmt.Errorf("%q url is neither an http or https uri: %q", k, url.Scheme)) } else if url.Host == "" { diff --git a/azurerm/helpers/validate/validator_test.go b/azurerm/helpers/validate/validate_test.go similarity index 100% rename from azurerm/helpers/validate/validator_test.go rename to azurerm/helpers/validate/validate_test.go diff --git a/azurerm/resource_arm_scheduler_job.go b/azurerm/resource_arm_scheduler_job.go index 16a3fdc53526..087f65f7cb43 100644 --- a/azurerm/resource_arm_scheduler_job.go +++ b/azurerm/resource_arm_scheduler_job.go @@ -491,11 +491,8 @@ func resourceArmSchedulerJobCreateUpdate(d *schema.ResourceData, meta interface{ job.Properties.Recurrence = expandAzureArmSchedulerJobRecurrence(b) } - //start time - startTime, err := time.Parse(time.RFC3339, d.Get("start_time").(string)) - if err != nil { - return fmt.Errorf("Error parsing start time (%s) for job %q (Resource Group %q): %+v", d.Get("start_time"), name, resourceGroup, err) - } + //start time, should be validated by schema + startTime, _ := time.Parse(time.RFC3339, d.Get("start_time").(string)) job.Properties.StartTime = &date.Time{Time: startTime} //state @@ -510,7 +507,7 @@ func resourceArmSchedulerJobCreateUpdate(d *schema.ResourceData, meta interface{ d.SetId(*resp.ID) - return resourceArmSchedulerJobPopulate(d, resourceGroup, jobCollection, &resp) + return resourceArmSchedulerJobRead(d, meta) } func resourceArmSchedulerJobRead(d *schema.ResourceData, meta interface{}) error { @@ -538,13 +535,7 @@ func resourceArmSchedulerJobRead(d *schema.ResourceData, meta interface{}) error return fmt.Errorf("Error making Read request on Scheduler Job %q (Resource Group %q): %+v", name, resourceGroup, err) } - return resourceArmSchedulerJobPopulate(d, resourceGroup, jobCollection, &job) -} - -func resourceArmSchedulerJobPopulate(d *schema.ResourceData, resourceGroup string, jobCollection string, job *scheduler.JobDefinition) error { - //standard properties - name := strings.Split(*job.Name, "/")[1] //job.Name is actually "{job_collection_name}/{job_name} d.Set("name", name) d.Set("resource_group_name", resourceGroup) d.Set("job_collection_name", jobCollection) @@ -589,10 +580,13 @@ func resourceArmSchedulerJobPopulate(d *schema.ResourceData, resourceGroup strin d.Set("recurrence", flattenAzureArmSchedulerJobSchedule(recurrence)) } - d.Set("start_time", properties.StartTime.Format(time.RFC3339)) + if v := properties.StartTime; v != nil { + d.Set("start_time", (*v).Format(time.RFC3339)) + } + + //status && state d.Set("state", properties.State) - //status status := properties.Status if status != nil { if v := status.ExecutionCount; v != nil { @@ -744,7 +738,7 @@ func expandAzureArmSchedulerJobRecurrence(b interface{}) *scheduler.JobRecurrenc recurrence.Count = utils.Int32(int32(v)) } if v, ok := block["end_time"].(string); ok && v != "" { - endTime, _ := time.Parse(time.RFC3339, v) + endTime, _ := time.Parse(time.RFC3339, v) //validated by schema recurrence.EndTime = &date.Time{Time: endTime} } @@ -778,6 +772,8 @@ func expandAzureArmSchedulerJobRecurrence(b interface{}) *scheduler.JobRecurrenc schedule.MonthlyOccurrences = &slice } + // if non of these are set and we try and send out a empty JobRecurrenceSchedule block + // the API will not respond so kindly if schedule.Minutes != nil || schedule.Hours != nil || schedule.WeekDays != nil || @@ -960,6 +956,7 @@ func resourceAzureRMSchedulerJobMonthlyOccurrenceHash(v interface{}) int { return hashcode.String(buf.String()) } +//todo where to put these? func sliceToSetInt32(slice []int32) *schema.Set { set := &schema.Set{F: set.HashInt} for _, v := range slice { diff --git a/azurerm/resource_arm_scheduler_job_test.go b/azurerm/resource_arm_scheduler_job_test.go index 2c0c6a49d77a..0d3eca10baca 100644 --- a/azurerm/resource_arm_scheduler_job_test.go +++ b/azurerm/resource_arm_scheduler_job_test.go @@ -888,16 +888,17 @@ func checkAccAzureRMSchedulerJob_retry_complete(resourceName string) resource.Te } func testAccAzureRMSchedulerJob_block_actionWeb_basic(blockName string) string { + //need a valid URL here otherwise on a slow connection job might fault before the test check return fmt.Sprintf(` %s { - url = "http://this.get.url.fails" + url = "http://terraform.io" } `, blockName) } func checkAccAzureRMSchedulerJob_web_basic(resourceName, blockName string) resource.TestCheckFunc { return resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.url", blockName), "http://this.get.url.fails"), + resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.url", blockName), "http://www.google.com"), ) } From 6b7b92486d7c078435a1c1f8730f86d3222cd8bf Mon Sep 17 00:00:00 2001 From: kt Date: Wed, 16 May 2018 16:23:34 -0700 Subject: [PATCH 05/18] aszurerm_schduler_job: update tests & validation --- azurerm/helpers/validate/validate.go | 41 +++++++- azurerm/resource_arm_scheduler_job.go | 114 ++++++++++----------- azurerm/resource_arm_scheduler_job_test.go | 20 ++-- 3 files changed, 100 insertions(+), 75 deletions(-) diff --git a/azurerm/helpers/validate/validate.go b/azurerm/helpers/validate/validate.go index 1b4cbe714886..137b46deb7ab 100644 --- a/azurerm/helpers/validate/validate.go +++ b/azurerm/helpers/validate/validate.go @@ -3,22 +3,57 @@ package validate import ( "fmt" "time" + "net/url" "github.com/Azure/go-autorest/autorest/date" - "net/url" + "github.com/hashicorp/terraform/helper/schema" ) //todo, now in terraform helper, switch over once vended, func Rfc3339Time(i interface{}, k string) (ws []string, errors []error) { - if _, err := date.ParseTime(time.RFC3339, i.(string)); err != nil { + v, ok := i.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected type of %s to be string", k)) + return + } + + if _, err := date.ParseTime(time.RFC3339, v); err != nil { errors = append(errors, fmt.Errorf("%q has the invalid RFC3339 date format %q: %+v", k, i, err)) } return } +func IntBetweenAndNot(min, max, not int) schema.SchemaValidateFunc { + return func(i interface{}, k string) (s []string, es []error) { + v, ok := i.(int) + if !ok { + es = append(es, fmt.Errorf("expected type of %s to be int", k)) + return + } + + if v < min || v > max { + es = append(es, fmt.Errorf("expected %s to be in the range (%d - %d), got %d", k, min, max, v)) + return + } + + if v == not { + es = append(es, fmt.Errorf("expected %s to not be %d, got %d", k, not, v)) + return + } + + return + } +} + func Url(i interface{}, k string) (ws []string, errors []error) { - url, err := url.Parse(i.(string)) + v, ok := i.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected type of %s to be string", k)) + return + } + + url, err := url.Parse(v) if err != nil { errors = append(errors, fmt.Errorf("%q url is in an invalid format: %q (%+v)", k, i, err)) } else if url.Scheme != "http" && url.Scheme != "https" { diff --git a/azurerm/resource_arm_scheduler_job.go b/azurerm/resource_arm_scheduler_job.go index 087f65f7cb43..c2e3712e7a8d 100644 --- a/azurerm/resource_arm_scheduler_job.go +++ b/azurerm/resource_arm_scheduler_job.go @@ -134,16 +134,22 @@ func resourceArmSchedulerJob() *schema.Resource { Type: schema.TypeSet, Optional: true, MinItems: 1, - Elem: &schema.Schema{Type: schema.TypeInt}, - Set: set.HashInt, + Elem: &schema.Schema{ + Type: schema.TypeInt, + ValidateFunc: validation.IntBetween(0, 59), + }, + Set: set.HashInt, }, "hours": { Type: schema.TypeSet, Optional: true, MinItems: 1, - Elem: &schema.Schema{Type: schema.TypeInt}, - Set: set.HashInt, + Elem: &schema.Schema{ + Type: schema.TypeInt, + ValidateFunc: validation.IntBetween(0, 23), + }, + Set: set.HashInt, }, "week_days": { //used with weekly @@ -151,19 +157,33 @@ func resourceArmSchedulerJob() *schema.Resource { Optional: true, ConflictsWith: []string{"recurrence.0.month_days", "recurrence.0.monthly_occurrences"}, MinItems: 1, - Elem: &schema.Schema{Type: schema.TypeString}, - //the constants are title cased but the API returns all lowercase - //so lets ignore the case + // the constants are title cased but the API returns all lowercase + // so lets ignore the case Set: set.HashStringIgnoreCase, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validation.StringInSlice([]string{ + string(scheduler.Sunday), + string(scheduler.Monday), + string(scheduler.Tuesday), + string(scheduler.Wednesday), + string(scheduler.Thursday), + string(scheduler.Friday), + string(scheduler.Saturday), + }, true), + }, }, - "month_days": { //used with monthly, -1, 1- must be between 1/31 + "month_days": { //used with monthly, Type: schema.TypeSet, Optional: true, ConflictsWith: []string{"recurrence.0.week_days", "recurrence.0.monthly_occurrences"}, MinItems: 1, - Elem: &schema.Schema{Type: schema.TypeInt}, - Set: set.HashInt, + Elem: &schema.Schema{ + Type: schema.TypeInt, + ValidateFunc: validate.IntBetweenAndNot(-31, 31, 0), + }, + Set: set.HashInt, }, "monthly_occurrences": { @@ -174,13 +194,23 @@ func resourceArmSchedulerJob() *schema.Resource { Set: resourceAzureRMSchedulerJobMonthlyOccurrenceHash, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ - "day": { // DatOfWeek (sunday monday) + "day": { Type: schema.TypeString, Required: true, + ValidateFunc: validation.StringInSlice([]string{ + string(scheduler.Sunday), + string(scheduler.Monday), + string(scheduler.Tuesday), + string(scheduler.Wednesday), + string(scheduler.Thursday), + string(scheduler.Friday), + string(scheduler.Saturday), + }, true), }, - "occurrence": { //-5 - 5, not 0 - Type: schema.TypeInt, - Required: true, + "occurrence": { + Type: schema.TypeInt, + Required: true, + ValidateFunc: validate.IntBetweenAndNot(-5, 5, 0), }, }, }, @@ -192,7 +222,7 @@ func resourceArmSchedulerJob() *schema.Resource { "start_time": { Type: schema.TypeString, Optional: true, - Default: time.Now().Format(time.RFC3339), //default to now + Computed: true, //defaults to now in create function DiffSuppressFunc: supress.Rfc3339Time, ValidateFunc: validate.Rfc3339Time, //times in the past just start immediately }, @@ -400,50 +430,6 @@ func resourceArmSchedulerJobCustomizeDiff(diff *schema.ResourceDiff, v interface if !hasCount && !hasEnd { return fmt.Errorf("One of `count` or `end_time` must be set for the 'recurrence' block.") } - - if v, ok := recurrence["minutes"].(*schema.Set); ok { - for _, e := range v.List() { - //leverage existing function, validates type and value - if _, errors := validation.IntBetween(0, 59)(e, "minutes"); len(errors) > 0 { - return errors[0] - } - } - } - - if v, ok := recurrence["hours"].(*schema.Set); ok { - for _, e := range v.List() { - //leverage existing function, validates type and value - if _, errors := validation.IntBetween(0, 23)(e, "hours"); len(errors) > 0 { - return errors[0] - } - } - } - - if v, ok := recurrence["week_days"].(*schema.Set); ok { - for _, e := range v.List() { - //leverage existing function, validates type and value - if _, errors := validation.StringInSlice([]string{ - string(scheduler.Monday), - string(scheduler.Tuesday), - string(scheduler.Wednesday), - string(scheduler.Thursday), - string(scheduler.Friday), - string(scheduler.Saturday), - string(scheduler.Sunday), - }, true)(e, "week_days"); len(errors) > 0 { - return errors[0] //string in slice can only return one - } - } - } - - if v, ok := recurrence["month_days"].(*schema.Set); ok { - for _, e := range v.List() { - v := e.(int) - if (-31 < v && v > 31) && v != 0 { - return fmt.Errorf("expected 'month_days' to be in the range (-31 - 31) excluding 0, got %d", v) - } - } - } } } @@ -491,9 +477,13 @@ func resourceArmSchedulerJobCreateUpdate(d *schema.ResourceData, meta interface{ job.Properties.Recurrence = expandAzureArmSchedulerJobRecurrence(b) } - //start time, should be validated by schema - startTime, _ := time.Parse(time.RFC3339, d.Get("start_time").(string)) - job.Properties.StartTime = &date.Time{Time: startTime} + //start time, should be validated by schema, also defaults to now if not set + if v, ok := d.GetOk("start_time"); ok { + startTime, _ := time.Parse(time.RFC3339, v.(string)) + job.Properties.StartTime = &date.Time{Time: startTime} + } else { + job.Properties.StartTime = &date.Time{Time: time.Now()} + } //state if state, ok := d.GetOk("state"); ok { diff --git a/azurerm/resource_arm_scheduler_job_test.go b/azurerm/resource_arm_scheduler_job_test.go index 0d3eca10baca..3b9ebdca75a4 100644 --- a/azurerm/resource_arm_scheduler_job_test.go +++ b/azurerm/resource_arm_scheduler_job_test.go @@ -891,21 +891,21 @@ func testAccAzureRMSchedulerJob_block_actionWeb_basic(blockName string) string { //need a valid URL here otherwise on a slow connection job might fault before the test check return fmt.Sprintf(` %s { - url = "http://terraform.io" + url = "http://example.com" } `, blockName) } func checkAccAzureRMSchedulerJob_web_basic(resourceName, blockName string) resource.TestCheckFunc { return resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.url", blockName), "http://www.google.com"), + resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.url", blockName), "http://example.com"), ) } func testAccAzureRMSchedulerJob_block_actionWeb_put(blockName string) string { return fmt.Sprintf(` %s { - url = "http://this.put.url.fails" + url = "http://example.com" method = "put" body = "this is some text" headers = { @@ -917,7 +917,7 @@ func testAccAzureRMSchedulerJob_block_actionWeb_put(blockName string) string { func checkAccAzureRMSchedulerJob_web_put(resourceName, blockName string) resource.TestCheckFunc { return resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.url", blockName), "http://this.put.url.fails"), + resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.url", blockName), "http://example.com"), resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.method", blockName), "put"), resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.body", blockName), "this is some text"), resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.headers.%%", blockName), "1"), @@ -927,7 +927,7 @@ func checkAccAzureRMSchedulerJob_web_put(resourceName, blockName string) resourc func testAccAzureRMSchedulerJob_block_actionWeb_authBasic(blockName string) string { return fmt.Sprintf(` %s { - url = "https://this.url.fails" + url = "https://example.com" method = "get" authentication_basic { @@ -940,7 +940,7 @@ func testAccAzureRMSchedulerJob_block_actionWeb_authBasic(blockName string) stri func checkAccAzureRMSchedulerJob_web_authBasic(resourceName string, blockName string) resource.TestCheckFunc { return resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.url", blockName), "https://this.url.fails"), + resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.url", blockName), "https://example.com"), resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.method", blockName), "get"), resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.authentication_basic.0.username", blockName), "login"), resource.TestCheckResourceAttrSet(resourceName, fmt.Sprintf("%s.0.authentication_basic.0.password", blockName)), @@ -950,7 +950,7 @@ func checkAccAzureRMSchedulerJob_web_authBasic(resourceName string, blockName st func testAccAzureRMSchedulerJob_block_actionWeb_authCert() string { return ` action_web { - url = "https://this.url.fails" + url = "https://example.com" method = "get" authentication_certificate { @@ -963,7 +963,7 @@ func testAccAzureRMSchedulerJob_block_actionWeb_authCert() string { func checkAccAzureRMSchedulerJob_web_authCert(resourceName string) resource.TestCheckFunc { return resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://this.url.fails"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), resource.TestCheckResourceAttrSet(resourceName, "action_web.0.authentication_certificate.0.pfx"), resource.TestCheckResourceAttrSet(resourceName, "action_web.0.authentication_certificate.0.password"), @@ -975,7 +975,7 @@ func checkAccAzureRMSchedulerJob_web_authCert(resourceName string) resource.Test func testAccAzureRMSchedulerJob_block_actionWeb_authAd(tenantId, clientId, secret string) string { return fmt.Sprintf(` action_web { - url = "https://this.url.fails" + url = "https://example.com" method = "get" authentication_active_directory { @@ -990,7 +990,7 @@ func testAccAzureRMSchedulerJob_block_actionWeb_authAd(tenantId, clientId, secre func checkAccAzureRMSchedulerJob_web_authAd(resourceName, tenantId, clientId, secret string) resource.TestCheckFunc { return resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://this.url.fails"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_active_directory.0.tenant_id", tenantId), resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_active_directory.0.client_id", clientId), From 61ea61289a1c13311470f4fd538d4de9173c057e Mon Sep 17 00:00:00 2001 From: kt Date: Thu, 17 May 2018 01:03:40 -0700 Subject: [PATCH 06/18] Updated example URLs --- azurerm/helpers/validate/validate.go | 2 +- examples/scheduler-jobs/main.tf | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/azurerm/helpers/validate/validate.go b/azurerm/helpers/validate/validate.go index 137b46deb7ab..0461039d6a8c 100644 --- a/azurerm/helpers/validate/validate.go +++ b/azurerm/helpers/validate/validate.go @@ -2,8 +2,8 @@ package validate import ( "fmt" - "time" "net/url" + "time" "github.com/Azure/go-autorest/autorest/date" "github.com/hashicorp/terraform/helper/schema" diff --git a/examples/scheduler-jobs/main.tf b/examples/scheduler-jobs/main.tf index 617865475731..f416034a13aa 100644 --- a/examples/scheduler-jobs/main.tf +++ b/examples/scheduler-jobs/main.tf @@ -26,7 +26,7 @@ resource "azurerm_scheduler_job" "web-once-now" { state = "enabled" action_web { - url = "http://this.url.fails" + url = "http://example.com" } retry { @@ -44,7 +44,7 @@ resource "azurerm_scheduler_job" "web-recurring" { job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" action_web { - url = "http://this.url.fails" + url = "http://example.com" method = "put" body = "this is some text" headers = { @@ -74,7 +74,7 @@ resource "azurerm_scheduler_job" "web-recurring_daily-auth_basic" { state = "enabled" action_web { - url = "https://this.url.fails" + url = "https://example.com" method = "get" authentication_basic { @@ -102,7 +102,7 @@ resource "azurerm_scheduler_job" "web-recurring_weekly-auth_cert" { state = "enabled" action_web { - url = "https://this.url.fails" + url = "https://example.com" method = "get" authentication_certificate { @@ -129,12 +129,12 @@ resource "azurerm_scheduler_job" "web-recurring_monthly-error_action" { state = "enabled" action_web { - url = "http://this.url.fails" + url = "http://example.com" method = "get" } error_action_web { - url = "https://this.url.fails" + url = "https://example.com" method = "put" body = "The job failed" From ee60252beab69b5f729e99198d09581ede8a93d7 Mon Sep 17 00:00:00 2001 From: kt Date: Thu, 17 May 2018 15:56:53 -0700 Subject: [PATCH 07/18] schduler jobs & collection: formatted examples --- examples/scheduler-jobs/main.tf | 249 ++++++++++++++--------------- examples/scheduler-jobs/outputs.tf | 4 +- 2 files changed, 126 insertions(+), 127 deletions(-) diff --git a/examples/scheduler-jobs/main.tf b/examples/scheduler-jobs/main.tf index 65eff6c16dc8..791a99110f1d 100644 --- a/examples/scheduler-jobs/main.tf +++ b/examples/scheduler-jobs/main.tf @@ -1,171 +1,170 @@ - resource "azurerm_resource_group" "rg" { - name = "${var.resource_group_name}" - location = "${var.resource_group_location}" + name = "${var.resource_group_name}" + location = "${var.resource_group_location}" } resource "azurerm_scheduler_job_collection" "jc" { - name = "tfex-scheduler-job-collection" - location = "${azurerm_resource_group.rg.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" - sku = "standard" - state = "enabled" - - quota { - max_job_count = 5 - max_recurrence_interval = 5 - max_recurrence_frequency = "minute" - } + name = "tfex-scheduler-job-collection" + location = "${azurerm_resource_group.rg.location}" + resource_group_name = "${azurerm_resource_group.rg.name}" + sku = "standard" + state = "enabled" + + quota { + max_job_count = 5 + max_recurrence_interval = 5 + max_recurrence_frequency = "minute" + } } resource "azurerm_scheduler_job" "web-once-now" { - name = "tfex-web-once-now" - resource_group_name = "${azurerm_resource_group.rg.name}" - job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" + name = "tfex-web-once-now" + resource_group_name = "${azurerm_resource_group.rg.name}" + job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" - state = "enabled" + state = "enabled" - action_web { - url = "http://example.com" - } + action_web { + url = "http://example.com" + } - retry { - interval = "00:05:00" //5 min - count = 4 - } + retry { + interval = "00:05:00" //5 min + count = 4 + } - //times in the past start imediatly and run once, - start_time = "1987-07-07T07:07:07-07:00" + //times in the past start imediatly and run once, + start_time = "1987-07-07T07:07:07-07:00" } resource "azurerm_scheduler_job" "web-recurring" { - name = "tfex-web-recurring" - resource_group_name = "${azurerm_resource_group.rg.name}" - job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" - - action_web { - url = "http://example.com" - method = "put" - body = "this is some text" - headers = { - Content-Type = "text" - } - } + name = "tfex-web-recurring" + resource_group_name = "${azurerm_resource_group.rg.name}" + job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" - retry { - interval = "00:05:00" //5 min - count = 4 - } + action_web { + url = "http://example.com" + method = "put" + body = "this is some text" - recurrence { - frequency = "minute" - interval = 10 - count = 10 //recurring counts start in past + headers = { + Content-Type = "text" } + } + + retry { + interval = "00:05:00" //5 min + count = 4 + } + + recurrence { + frequency = "minute" + interval = 10 + count = 10 //recurring counts start in past + } - start_time = "2019-07-07T07:07:07-07:00" + start_time = "2019-07-07T07:07:07-07:00" } resource "azurerm_scheduler_job" "web-recurring_daily-auth_basic" { - name = "tfex-web-recurring_daily-auth_basic" - resource_group_name = "${azurerm_resource_group.rg.name}" - job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" + name = "tfex-web-recurring_daily-auth_basic" + resource_group_name = "${azurerm_resource_group.rg.name}" + job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" - state = "enabled" + state = "enabled" - action_web { - url = "https://example.com" - method = "get" + action_web { + url = "https://example.com" + method = "get" - authentication_basic { - username = "login" - password = "apassword" - } + authentication_basic { + username = "login" + password = "apassword" } + } - recurrence { - frequency = "day" - count = 1000 - hours = [0,12] - minutes = [0,15,30,45] - } + recurrence { + frequency = "day" + count = 1000 + hours = [0, 12] + minutes = [0, 15, 30, 45] + } - start_time = "2019-07-07T07:07:07-07:00" + start_time = "2019-07-07T07:07:07-07:00" } - resource "azurerm_scheduler_job" "web-recurring_weekly-auth_cert" { - name = "tfex-web-recurring_weekly-auth_cert" - resource_group_name = "${azurerm_resource_group.rg.name}" - job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" + name = "tfex-web-recurring_weekly-auth_cert" + resource_group_name = "${azurerm_resource_group.rg.name}" + job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" - state = "enabled" + state = "enabled" - action_web { - url = "https://example.com" - method = "get" + action_web { + url = "https://example.com" + method = "get" - authentication_certificate { - pfx = "${base64encode(file("../../azurerm/testdata/application_gateway_test.pfx"))}" - password = "terraform" - } + authentication_certificate { + pfx = "${base64encode(file("../../azurerm/testdata/application_gateway_test.pfx"))}" + password = "terraform" } + } - recurrence { - frequency = "week" - count = 1000 - week_days = ["Sunday", "Saturday"] - } + recurrence { + frequency = "week" + count = 1000 + week_days = ["Sunday", "Saturday"] + } - start_time = "2019-07-07T07:07:07-07:00" + start_time = "2019-07-07T07:07:07-07:00" } - resource "azurerm_scheduler_job" "web-recurring_monthly-error_action" { - name = "tfex-web-recurring_monthly-auth_ad" - resource_group_name = "${azurerm_resource_group.rg.name}" - job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" + name = "tfex-web-recurring_monthly-auth_ad" + resource_group_name = "${azurerm_resource_group.rg.name}" + job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" - state = "enabled" + state = "enabled" - action_web { - url = "http://example.com" - method = "get" - } - - error_action_web { - url = "https://example.com" - method = "put" - body = "The job failed" + action_web { + url = "http://example.com" + method = "get" + } - headers = { - Content-Type = "text" - } + error_action_web { + url = "https://example.com" + method = "put" + body = "The job failed" - authentication_basic { - username = "login" - password = "apassword" - } + headers = { + Content-Type = "text" } - recurrence { - frequency = "month" - count = 1000 - monthly_occurrences = [ - { - day = "Sunday" - occurrence = 1 - }, - { - day = "Sunday" - occurrence = 3 - }, - { - day = "Sunday" - occurrence = -1 - } - ] + authentication_basic { + username = "login" + password = "apassword" } - - start_time = "2019-07-07T07:07:07-07:00" -} \ No newline at end of file + } + + recurrence { + frequency = "month" + count = 1000 + + monthly_occurrences = [ + { + day = "Sunday" + occurrence = 1 + }, + { + day = "Sunday" + occurrence = 3 + }, + { + day = "Sunday" + occurrence = -1 + }, + ] + } + + start_time = "2019-07-07T07:07:07-07:00" +} diff --git a/examples/scheduler-jobs/outputs.tf b/examples/scheduler-jobs/outputs.tf index fd5248c866c7..c09ef605928d 100644 --- a/examples/scheduler-jobs/outputs.tf +++ b/examples/scheduler-jobs/outputs.tf @@ -1,4 +1,3 @@ - output "job_collection-id" { value = "${azurerm_scheduler_job_collection.jc.id}" } @@ -14,10 +13,11 @@ output "job-web-once-count" { output "job-web-recurring_weekly-authCert_thumb" { value = "${azurerm_scheduler_job.web-recurring_weekly-auth_cert.action_web.0.authentication_certificate.0.thumbprint}" } + output "job-web-recurring_weekly-authCert_expire" { value = "${azurerm_scheduler_job.web-recurring_weekly-auth_cert.action_web.0.authentication_certificate.0.expiration}" } output "job-web-recurring_weekly-authCert_san" { value = "${azurerm_scheduler_job.web-recurring_weekly-auth_cert.action_web.0.authentication_certificate.0.subject_name}" -} \ No newline at end of file +} From 218376a85741544d59ec19bbe9b5d657bc1a41a1 Mon Sep 17 00:00:00 2001 From: kt Date: Mon, 21 May 2018 00:03:29 -0700 Subject: [PATCH 08/18] azurerm_scheduler_job: schema adjustments --- azurerm/resource_arm_scheduler_job.go | 250 +++++++++++++------------- 1 file changed, 122 insertions(+), 128 deletions(-) diff --git a/azurerm/resource_arm_scheduler_job.go b/azurerm/resource_arm_scheduler_job.go index c2e3712e7a8d..37921acb7136 100644 --- a/azurerm/resource_arm_scheduler_job.go +++ b/azurerm/resource_arm_scheduler_job.go @@ -52,15 +52,24 @@ func resourceArmSchedulerJob() *schema.Resource { }, //actions - "action_web": resourceArmSchedulerJobActionWebSchema("action_web"), + "action_web": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: resourceArmSchedulerJobActionWebSchema("action_web"), + }, - //each action can also be an error action - "error_action_web": resourceArmSchedulerJobActionWebSchema("error_action_web"), + //actions + "error_action_web": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + Elem: resourceArmSchedulerJobActionWebSchema("error_action_web"), + }, //retry policy "retry": { Type: schema.TypeList, - MinItems: 1, MaxItems: 1, Optional: true, Elem: &schema.Resource{ @@ -133,7 +142,6 @@ func resourceArmSchedulerJob() *schema.Resource { "minutes": { Type: schema.TypeSet, Optional: true, - MinItems: 1, Elem: &schema.Schema{ Type: schema.TypeInt, ValidateFunc: validation.IntBetween(0, 59), @@ -144,7 +152,6 @@ func resourceArmSchedulerJob() *schema.Resource { "hours": { Type: schema.TypeSet, Optional: true, - MinItems: 1, Elem: &schema.Schema{ Type: schema.TypeInt, ValidateFunc: validation.IntBetween(0, 23), @@ -156,7 +163,6 @@ func resourceArmSchedulerJob() *schema.Resource { Type: schema.TypeSet, Optional: true, ConflictsWith: []string{"recurrence.0.month_days", "recurrence.0.monthly_occurrences"}, - MinItems: 1, // the constants are title cased but the API returns all lowercase // so lets ignore the case Set: set.HashStringIgnoreCase, @@ -266,146 +272,134 @@ func resourceArmSchedulerJob() *schema.Resource { } } -func resourceArmSchedulerJobActionWebSchema(propertyName string) *schema.Schema { - return &schema.Schema{ - Type: schema.TypeList, - MinItems: 1, - MaxItems: 1, - Optional: true, - //ConflictsWith: conflictsWith, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - - // we can determine the type (HTTP/HTTPS) from the url - // but we need to make sure the url starts with http/https - // both so we can determine the type and as azure requires it - "url": { - Type: schema.TypeString, - Optional: true, - DiffSuppressFunc: supress.CaseDifference, - ValidateFunc: validate.Url, - }, +func resourceArmSchedulerJobActionWebSchema(propertyName string) *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + // we can determine the type (HTTP/HTTPS) from the url + // but we need to make sure the url starts with http/https + // both so we can determine the type and as azure requires it + "url": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: supress.CaseDifference, + ValidateFunc: validate.Url, + }, - "method": { - Type: schema.TypeString, - Optional: true, - //DiffSuppressFunc: ignoreCaseDiffSuppressFunc, - Default: "Get", //todo have a default or force user to pick? - ValidateFunc: validation.StringInSlice([]string{ - "Get", "Put", "Post", "Delete", - }, true), - }, + "method": { + Type: schema.TypeString, + Optional: true, + //DiffSuppressFunc: ignoreCaseDiffSuppressFunc, + Default: "Get", //todo have a default or force user to pick? + ValidateFunc: validation.StringInSlice([]string{ + "Get", "Put", "Post", "Delete", + }, true), + }, - //only valid/used when action type is put - "body": { - Type: schema.TypeString, - Optional: true, - }, + //only valid/used when action type is put + "body": { + Type: schema.TypeString, + Optional: true, + }, - "headers": { - Type: schema.TypeMap, - Optional: true, - }, + "headers": { + Type: schema.TypeMap, + Optional: true, + }, - //authentication requires HTTPS - "authentication_basic": { - Type: schema.TypeList, - MinItems: 1, - MaxItems: 1, - Optional: true, - ConflictsWith: []string{ - fmt.Sprintf("%s.0.authentication_certificate", propertyName), - fmt.Sprintf("%s.0.authentication_active_directory", propertyName), - }, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "username": { - Type: schema.TypeString, - Required: true, - }, + //authentication requires HTTPS + "authentication_basic": { + Type: schema.TypeList, + MaxItems: 1, + Optional: true, + ConflictsWith: []string{ + fmt.Sprintf("%s.0.authentication_certificate", propertyName), + fmt.Sprintf("%s.0.authentication_active_directory", propertyName), + }, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "username": { + Type: schema.TypeString, + Required: true, + }, - "password": { - Type: schema.TypeString, - Required: true, - Sensitive: true, - }, + "password": { + Type: schema.TypeString, + Required: true, + Sensitive: true, }, }, }, + }, - "authentication_certificate": { - Type: schema.TypeList, - Optional: true, - MinItems: 1, - MaxItems: 1, - ConflictsWith: []string{ - fmt.Sprintf("%s.0.authentication_basic", propertyName), - fmt.Sprintf("%s.0.authentication_active_directory", propertyName), - }, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "pfx": { - Type: schema.TypeString, - Required: true, - Sensitive: true, //sensitive & shortens diff - }, + "authentication_certificate": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + ConflictsWith: []string{ + fmt.Sprintf("%s.0.authentication_basic", propertyName), + fmt.Sprintf("%s.0.authentication_active_directory", propertyName), + }, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "pfx": { + Type: schema.TypeString, + Required: true, + Sensitive: true, //sensitive & shortens diff + }, - "password": { - Type: schema.TypeString, - Required: true, - Sensitive: true, - }, + "password": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, - "thumbprint": { - Type: schema.TypeString, - Computed: true, - }, + "thumbprint": { + Type: schema.TypeString, + Computed: true, + }, - "expiration": { - Type: schema.TypeString, - Computed: true, - }, + "expiration": { + Type: schema.TypeString, + Computed: true, + }, - "subject_name": { - Type: schema.TypeString, - Computed: true, - }, + "subject_name": { + Type: schema.TypeString, + Computed: true, }, }, }, + }, - "authentication_active_directory": { - Type: schema.TypeList, - Optional: true, - MinItems: 1, - MaxItems: 1, - ConflictsWith: []string{ - fmt.Sprintf("%s.0.authentication_basic", propertyName), - fmt.Sprintf("%s.0.authentication_certificate", propertyName), - }, - Elem: &schema.Resource{ - Schema: map[string]*schema.Schema{ - "tenant_id": { - Type: schema.TypeString, - Required: true, - }, - - "client_id": { - Type: schema.TypeString, - Required: true, - }, + "authentication_active_directory": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + ConflictsWith: []string{ + fmt.Sprintf("%s.0.authentication_basic", propertyName), + fmt.Sprintf("%s.0.authentication_certificate", propertyName), + }, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "tenant_id": { + Type: schema.TypeString, + Required: true, + }, - "secret": { - Type: schema.TypeString, - Required: true, - Sensitive: true, - }, + "client_id": { + Type: schema.TypeString, + Required: true, + }, + "secret": { + Type: schema.TypeString, + Required: true, + Sensitive: true, + }, - "audience": { - Type: schema.TypeString, - Optional: true, - Default: "https://management.core.windows.net/", - }, + "audience": { + Type: schema.TypeString, + Optional: true, + Default: "https://management.core.windows.net/", }, }, }, From 5a505222f90135f5856f20b0503f344aa8864c9b Mon Sep 17 00:00:00 2001 From: kt Date: Fri, 25 May 2018 11:56:17 -0700 Subject: [PATCH 09/18] azurerm_scheduler_job: resolving PR comments --- .../helpers/{supress => suppress}/suppress.go | 4 +- .../{supress => suppress}/suppress_test.go | 6 +-- azurerm/helpers/validate/validate.go | 10 +++-- azurerm/helpers/validate/validate_test.go | 2 +- azurerm/resource_arm_scheduler_job.go | 44 +++++-------------- 5 files changed, 23 insertions(+), 43 deletions(-) rename azurerm/helpers/{supress => suppress}/suppress.go (96%) rename azurerm/helpers/{supress => suppress}/suppress_test.go (89%) diff --git a/azurerm/helpers/supress/suppress.go b/azurerm/helpers/suppress/suppress.go similarity index 96% rename from azurerm/helpers/supress/suppress.go rename to azurerm/helpers/suppress/suppress.go index 14ea92fba1cf..22555f5d29e6 100644 --- a/azurerm/helpers/supress/suppress.go +++ b/azurerm/helpers/suppress/suppress.go @@ -1,10 +1,10 @@ -package supress +package suppress import ( + "strings" "time" "github.com/hashicorp/terraform/helper/schema" - "strings" ) func CaseDifference(_, old, new string, _ *schema.ResourceData) bool { diff --git a/azurerm/helpers/supress/suppress_test.go b/azurerm/helpers/suppress/suppress_test.go similarity index 89% rename from azurerm/helpers/supress/suppress_test.go rename to azurerm/helpers/suppress/suppress_test.go index 4638caa2867e..f532c40c2551 100644 --- a/azurerm/helpers/supress/suppress_test.go +++ b/azurerm/helpers/suppress/suppress_test.go @@ -1,4 +1,4 @@ -package supress +package suppress import ( "testing" @@ -39,7 +39,7 @@ func TestInternal_Suppress_CaseDifference(t *testing.T) { for _, tc := range cases { if CaseDifference("test", tc.StringA, tc.StringB, nil) != tc.Suppress { - t.Fatalf("Expected CaseDifference to return %t for '%s' == '%s'", tc.Suppress, tc.StringA, tc.StringB) + t.Fatalf("Expected CaseDifference to return %t for '%q' == '%q'", tc.Suppress, tc.StringA, tc.StringB) } } } @@ -84,7 +84,7 @@ func TestInternal_Supress_Rfc3339Time(t *testing.T) { for _, tc := range cases { if Rfc3339Time("test", tc.TimeA, tc.TimeB, nil) != tc.Suppress { - t.Fatalf("Expected Rfc3339Time to return %t for '%s' == '%s'", tc.Suppress, tc.TimeA, tc.TimeB) + t.Fatalf("Expected Rfc3339Time to return %t for '%q' == '%q'", tc.Suppress, tc.TimeA, tc.TimeB) } } } diff --git a/azurerm/helpers/validate/validate.go b/azurerm/helpers/validate/validate.go index 0461039d6a8c..71c8fd742c61 100644 --- a/azurerm/helpers/validate/validate.go +++ b/azurerm/helpers/validate/validate.go @@ -13,7 +13,7 @@ import ( func Rfc3339Time(i interface{}, k string) (ws []string, errors []error) { v, ok := i.(string) if !ok { - errors = append(errors, fmt.Errorf("expected type of %s to be string", k)) + errors = append(errors, fmt.Errorf("expected type of %q to be string", k)) return } @@ -28,7 +28,7 @@ func IntBetweenAndNot(min, max, not int) schema.SchemaValidateFunc { return func(i interface{}, k string) (s []string, es []error) { v, ok := i.(int) if !ok { - es = append(es, fmt.Errorf("expected type of %s to be int", k)) + es = append(es, fmt.Errorf("expected type of %q to be int", k)) return } @@ -46,10 +46,14 @@ func IntBetweenAndNot(min, max, not int) schema.SchemaValidateFunc { } } +func UrlIsHttp(i interface{}, k string) (ws []string, errors []error) { + +} + func Url(i interface{}, k string) (ws []string, errors []error) { v, ok := i.(string) if !ok { - errors = append(errors, fmt.Errorf("expected type of %s to be string", k)) + errors = append(errors, fmt.Errorf("expected type of %q to be string", k)) return } diff --git a/azurerm/helpers/validate/validate_test.go b/azurerm/helpers/validate/validate_test.go index cc69adc86f70..c1bf2b5c43a0 100644 --- a/azurerm/helpers/validate/validate_test.go +++ b/azurerm/helpers/validate/validate_test.go @@ -37,7 +37,7 @@ func TestInternal_ValidateRFC3339Time(t *testing.T) { _, errors := Rfc3339Time(tc.Time, "test") if len(errors) != tc.Errors { - t.Fatalf("Expected Rfc3339Time to have an error for '%s'", tc.Time) + t.Fatalf("Expected Rfc3339Time to have an error for '%q'", tc.Time) } } } diff --git a/azurerm/resource_arm_scheduler_job.go b/azurerm/resource_arm_scheduler_job.go index 37921acb7136..9708cd2a4871 100644 --- a/azurerm/resource_arm_scheduler_job.go +++ b/azurerm/resource_arm_scheduler_job.go @@ -16,7 +16,7 @@ import ( "github.com/hashicorp/terraform/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/set" - "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/supress" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" ) @@ -32,6 +32,8 @@ func resourceArmSchedulerJob() *schema.Resource { State: schema.ImportStatePassthrough, }, + CustomizeDiff: resourceArmSchedulerJobCustomizeDiff, + Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, @@ -105,7 +107,7 @@ func resourceArmSchedulerJob() *schema.Resource { "frequency": { Type: schema.TypeString, Required: true, - DiffSuppressFunc: supress.CaseDifference, + DiffSuppressFunc: suppress.CaseDifference, ValidateFunc: validation.StringInSlice([]string{ string(scheduler.Minute), string(scheduler.Hour), @@ -135,7 +137,7 @@ func resourceArmSchedulerJob() *schema.Resource { Type: schema.TypeString, Optional: true, Computed: true, - DiffSuppressFunc: supress.Rfc3339Time, + DiffSuppressFunc: suppress.Rfc3339Time, ValidateFunc: validate.Rfc3339Time, }, @@ -229,7 +231,7 @@ func resourceArmSchedulerJob() *schema.Resource { Type: schema.TypeString, Optional: true, Computed: true, //defaults to now in create function - DiffSuppressFunc: supress.Rfc3339Time, + DiffSuppressFunc: suppress.Rfc3339Time, ValidateFunc: validate.Rfc3339Time, //times in the past just start immediately }, @@ -237,38 +239,14 @@ func resourceArmSchedulerJob() *schema.Resource { Type: schema.TypeString, Optional: true, Computed: true, - DiffSuppressFunc: supress.CaseDifference, + DiffSuppressFunc: suppress.CaseDifference, ValidateFunc: validation.StringInSlice([]string{ string(scheduler.JobStateEnabled), string(scheduler.JobStateDisabled), // JobStateFaulted & JobStateCompleted are also possible, but silly }, true), }, - - //status - "execution_count": { - Type: schema.TypeInt, - Computed: true, - }, - "failure_count": { - Type: schema.TypeInt, - Computed: true, - }, - "faulted_count": { - Type: schema.TypeInt, - Computed: true, - }, - "last_execution_time": { - Type: schema.TypeString, - Computed: true, - }, - "next_execution_time": { - Type: schema.TypeString, - Computed: true, - }, }, - - CustomizeDiff: resourceArmSchedulerJobCustomizeDiff, } } @@ -280,16 +258,14 @@ func resourceArmSchedulerJobActionWebSchema(propertyName string) *schema.Resourc // both so we can determine the type and as azure requires it "url": { Type: schema.TypeString, - Optional: true, - DiffSuppressFunc: supress.CaseDifference, + Required: true, + DiffSuppressFunc: suppress.CaseDifference, ValidateFunc: validate.Url, }, "method": { Type: schema.TypeString, - Optional: true, - //DiffSuppressFunc: ignoreCaseDiffSuppressFunc, - Default: "Get", //todo have a default or force user to pick? + Required: true, ValidateFunc: validation.StringInSlice([]string{ "Get", "Put", "Post", "Delete", }, true), From 878707c8bbc9c1fe906410148af27b6bf940aa8a Mon Sep 17 00:00:00 2001 From: kt Date: Thu, 31 May 2018 19:34:02 -0700 Subject: [PATCH 10/18] azurerm_scheduler_job: First round of PR fixes --- azurerm/helpers/validate/validate.go | 53 +++++---- azurerm/resource_arm_scheduler_job.go | 151 +++++++++++--------------- 2 files changed, 92 insertions(+), 112 deletions(-) diff --git a/azurerm/helpers/validate/validate.go b/azurerm/helpers/validate/validate.go index 71c8fd742c61..60272bd1f7a3 100644 --- a/azurerm/helpers/validate/validate.go +++ b/azurerm/helpers/validate/validate.go @@ -10,7 +10,7 @@ import ( ) //todo, now in terraform helper, switch over once vended, -func Rfc3339Time(i interface{}, k string) (ws []string, errors []error) { +func Rfc3339Time(i interface{}, k string) (_ []string, errors []error) { v, ok := i.(string) if !ok { errors = append(errors, fmt.Errorf("expected type of %q to be string", k)) @@ -25,20 +25,20 @@ func Rfc3339Time(i interface{}, k string) (ws []string, errors []error) { } func IntBetweenAndNot(min, max, not int) schema.SchemaValidateFunc { - return func(i interface{}, k string) (s []string, es []error) { + return func(i interface{}, k string) (_ []string, errors []error) { v, ok := i.(int) if !ok { - es = append(es, fmt.Errorf("expected type of %q to be int", k)) + errors = append(errors, fmt.Errorf("expected type of %q to be int", k)) return } if v < min || v > max { - es = append(es, fmt.Errorf("expected %s to be in the range (%d - %d), got %d", k, min, max, v)) + errors = append(errors, fmt.Errorf("expected %s to be in the range (%d - %d), got %d", k, min, max, v)) return } if v == not { - es = append(es, fmt.Errorf("expected %s to not be %d, got %d", k, not, v)) + errors = append(errors, fmt.Errorf("expected %s to not be %d, got %d", k, not, v)) return } @@ -46,25 +46,34 @@ func IntBetweenAndNot(min, max, not int) schema.SchemaValidateFunc { } } -func UrlIsHttp(i interface{}, k string) (ws []string, errors []error) { - +func UrlIsHttpOrHttps() schema.SchemaValidateFunc { + return UrlWithScheme([]string{"http", "https"}) } -func Url(i interface{}, k string) (ws []string, errors []error) { - v, ok := i.(string) - if !ok { - errors = append(errors, fmt.Errorf("expected type of %q to be string", k)) - return - } +func UrlWithScheme(validSchemes []string) schema.SchemaValidateFunc { + return func(i interface{}, k string) (_ []string, errors []error) { + v, ok := i.(string) + if !ok { + errors = append(errors, fmt.Errorf("expected type of %q to be string", k)) + return + } - url, err := url.Parse(v) - if err != nil { - errors = append(errors, fmt.Errorf("%q url is in an invalid format: %q (%+v)", k, i, err)) - } else if url.Scheme != "http" && url.Scheme != "https" { - errors = append(errors, fmt.Errorf("%q url is neither an http or https uri: %q", k, url.Scheme)) - } else if url.Host == "" { - errors = append(errors, fmt.Errorf("%q url has no host: %q", k, url)) - } + url, err := url.Parse(v) + if err != nil { + errors = append(errors, fmt.Errorf("%q url is in an invalid format: %q (%+v)", k, i, err)) + return + } - return + if url.Host == "" { + errors = append(errors, fmt.Errorf("%q url has no host: %q", k, url)) + } + + for _, s := range validSchemes { + if url.Scheme == s { + return //last check so just return + } + } + + return + } } diff --git a/azurerm/resource_arm_scheduler_job.go b/azurerm/resource_arm_scheduler_job.go index 9708cd2a4871..7499a01cd2a3 100644 --- a/azurerm/resource_arm_scheduler_job.go +++ b/azurerm/resource_arm_scheduler_job.go @@ -260,7 +260,7 @@ func resourceArmSchedulerJobActionWebSchema(propertyName string) *schema.Resourc Type: schema.TypeString, Required: true, DiffSuppressFunc: suppress.CaseDifference, - ValidateFunc: validate.Url, + ValidateFunc: validate.UrlIsHttpOrHttps(), }, "method": { @@ -375,7 +375,7 @@ func resourceArmSchedulerJobActionWebSchema(propertyName string) *schema.Resourc "audience": { Type: schema.TypeString, Optional: true, - Default: "https://management.core.windows.net/", + Computed: true, //is defaulted to the ServiceManagementEndpoint in create }, }, }, @@ -424,13 +424,13 @@ func resourceArmSchedulerJobCreateUpdate(d *schema.ResourceData, meta interface{ //action if b, ok := d.GetOk("action_web"); ok { - job.Properties.Action.Request, job.Properties.Action.Type = expandAzureArmSchedulerJobActionRequest(b) + job.Properties.Action.Request, job.Properties.Action.Type = expandAzureArmSchedulerJobActionRequest(meta, b) } //error action if b, ok := d.GetOk("error_action_web"); ok { job.Properties.Action.ErrorAction = &scheduler.JobErrorAction{} - job.Properties.Action.ErrorAction.Request, job.Properties.Action.ErrorAction.Type = expandAzureArmSchedulerJobActionRequest(b) + job.Properties.Action.ErrorAction.Request, job.Properties.Action.ErrorAction.Type = expandAzureArmSchedulerJobActionRequest(meta, b) } //retry policy @@ -502,74 +502,51 @@ func resourceArmSchedulerJobRead(d *schema.ResourceData, meta interface{}) error //check & get properties properties := job.Properties - if properties == nil { - return fmt.Errorf("job properties is nil") - } + if properties != nil { + + //action + action := properties.Action + if action != nil { + actionType := strings.ToLower(string(action.Type)) + if strings.EqualFold(actionType, string(scheduler.HTTP)) || strings.EqualFold(actionType, string(scheduler.HTTPS)) { + if err := d.Set("action_web", flattenAzureArmSchedulerJobActionRequest(action.Request)); err != nil { + return err + } + } - //action - action := properties.Action - if action == nil { - return fmt.Errorf("job action is nil") - } - actionType := strings.ToLower(string(action.Type)) - if strings.EqualFold(actionType, string(scheduler.HTTP)) || strings.EqualFold(actionType, string(scheduler.HTTPS)) { - d.Set("action_web", flattenAzureArmSchedulerJobActionRequest(action.Request, d.Get("action_web"))) - } else { - return fmt.Errorf("Unknown job type %q for scheduler job %q action (Resource Group %q)", action.Type, name, resourceGroup) - } + //error action + if errorAction := action.ErrorAction; errorAction != nil { + if strings.EqualFold(actionType, string(scheduler.HTTP)) || strings.EqualFold(actionType, string(scheduler.HTTPS)) { + if err := d.Set("error_action_web", flattenAzureArmSchedulerJobActionRequest(errorAction.Request)); err != nil { + return err + } + } + } - //error action - if errorAction := action.ErrorAction; errorAction != nil { - if strings.EqualFold(actionType, string(scheduler.HTTP)) || strings.EqualFold(actionType, string(scheduler.HTTPS)) { - d.Set("error_action_web", flattenAzureArmSchedulerJobActionRequest(errorAction.Request, d.Get("error_action_web"))) - } else { - return fmt.Errorf("Unknown job type %q for scheduler job %q error action (Resource Group %q)", errorAction.Type, name, resourceGroup) + //retry + if retry := action.RetryPolicy; retry != nil { + //if its not fixed we should not have a retry block + if retry.RetryType == scheduler.Fixed { + if err := d.Set("retry", flattenAzureArmSchedulerJobActionRetry(retry)); err != nil { + return err + } + } + } } - } - //retry - if retry := properties.Action.RetryPolicy; retry != nil { - //if its not fixed we should not have a retry block - if retry.RetryType == scheduler.Fixed { - d.Set("retry", flattenAzureArmSchedulerJobActionRetry(retry)) + //schedule + if recurrence := properties.Recurrence; recurrence != nil { + if err := d.Set("recurrence", flattenAzureArmSchedulerJobSchedule(recurrence)); err != nil { + return err + } } - } - - //schedule - if recurrence := properties.Recurrence; recurrence != nil { - d.Set("recurrence", flattenAzureArmSchedulerJobSchedule(recurrence)) - } - - if v := properties.StartTime; v != nil { - d.Set("start_time", (*v).Format(time.RFC3339)) - } - - //status && state - d.Set("state", properties.State) - status := properties.Status - if status != nil { - if v := status.ExecutionCount; v != nil { - d.Set("execution_count", *v) - } - if v := status.FailureCount; v != nil { - d.Set("failure_count", *v) - } - if v := status.FaultedCount; v != nil { - d.Set("faulted_count", *v) + if v := properties.StartTime; v != nil { + d.Set("start_time", (*v).Format(time.RFC3339)) } - //these can be nil, if so set to empty so any outputs referencing them won't explode - if v := status.LastExecutionTime; v != nil { - d.Set("last_execution_time", (*v).Format(time.RFC3339)) - } else { - d.Set("last_execution_time", "") - } - if v := status.NextExecutionTime; v != nil { - d.Set("next_execution_time", (*v).Format(time.RFC3339)) - } else { - d.Set("next_execution_time", "") - } + //status && state + d.Set("state", properties.State) } return nil @@ -601,7 +578,7 @@ func resourceArmSchedulerJobDelete(d *schema.ResourceData, meta interface{}) err } //expand (terraform -> API) -func expandAzureArmSchedulerJobActionRequest(b interface{}) (*scheduler.HTTPRequest, scheduler.JobActionType) { +func expandAzureArmSchedulerJobActionRequest(meta interface{}, b interface{}) (*scheduler.HTTPRequest, scheduler.JobActionType) { block := b.([]interface{})[0].(map[string]interface{}) @@ -655,13 +632,21 @@ func expandAzureArmSchedulerJobActionRequest(b interface{}) (*scheduler.HTTPRequ if v, ok := block["authentication_active_directory"].([]interface{}); ok && len(v) > 0 { b := v[0].(map[string]interface{}) - request.Authentication = &scheduler.OAuthAuthentication{ + oauth := &scheduler.OAuthAuthentication{ Type: scheduler.TypeActiveDirectoryOAuth, Tenant: utils.String(b["tenant_id"].(string)), ClientID: utils.String(b["client_id"].(string)), - Audience: utils.String(b["audience"].(string)), Secret: utils.String(b["secret"].(string)), } + + //default to the service Management Endpoint + if v, ok := b["audience"].(string); ok { + oauth.Audience = utils.String(v) + } else { + oauth.Audience = utils.String(meta.(*ArmClient).environment.ServiceManagementEndpoint) + } + + request.Authentication = oauth } return &request, jobType @@ -746,12 +731,7 @@ func expandAzureArmSchedulerJobRecurrence(b interface{}) *scheduler.JobRecurrenc // flatten (API --> terraform) -func flattenAzureArmSchedulerJobActionRequest(request *scheduler.HTTPRequest, ob interface{}) []interface{} { - oldBlock := map[string]interface{}{} - - if v, ok := ob.([]interface{}); ok && len(v) > 0 { - oldBlock = v[0].(map[string]interface{}) - } +func flattenAzureArmSchedulerJobActionRequest(request *scheduler.HTTPRequest) []interface{} { block := map[string]interface{}{} @@ -785,22 +765,12 @@ func flattenAzureArmSchedulerJobActionRequest(request *scheduler.HTTPRequest, ob authBlock["username"] = *v } - //password is always blank, so preserve state - if v, ok := oldBlock["authentication_basic"].([]interface{}); ok && len(v) > 0 { - oab := v[0].(map[string]interface{}) - authBlock["password"] = oab["password"] - } + //password is always blank, so blank it + authBlock["password"] = "" } else if cert, ok := auth.AsClientCertAuthentication(); ok { block["authentication_certificate"] = []interface{}{authBlock} - //pfx and password are always empty, so preserve state - if v, ok := oldBlock["authentication_certificate"].([]interface{}); ok && len(v) > 0 { - oab := v[0].(map[string]interface{}) - authBlock["pfx"] = oab["pfx"] - authBlock["password"] = oab["password"] - } - if v := cert.CertificateThumbprint; v != nil { authBlock["thumbprint"] = *v } @@ -811,6 +781,10 @@ func flattenAzureArmSchedulerJobActionRequest(request *scheduler.HTTPRequest, ob authBlock["subject_name"] = *v } + //always empty so blank it + authBlock["pfx"] = "" + authBlock["password"] = "" + } else if oauth, ok := auth.AsOAuthAuthentication(); ok { block["authentication_active_directory"] = []interface{}{authBlock} @@ -824,11 +798,8 @@ func flattenAzureArmSchedulerJobActionRequest(request *scheduler.HTTPRequest, ob authBlock["tenant_id"] = *v } - //secret is always empty, so preserve state - if v, ok := oldBlock["authentication_active_directory"].([]interface{}); ok && len(v) > 0 { - oab := v[0].(map[string]interface{}) - authBlock["secret"] = oab["secret"] - } + //secret is always empty, so blank it + authBlock["secret"] = "" } } From e404a9269e19d055490a94a0e100c38997f3b3d0 Mon Sep 17 00:00:00 2001 From: kt Date: Mon, 4 Jun 2018 14:05:55 -0700 Subject: [PATCH 11/18] azurerm_scheduler_job: Futher PR fixes --- azurerm/helpers/set/set.go | 19 +++++++ azurerm/resource_arm_scheduler_job.go | 51 +++++-------------- azurerm/resource_arm_scheduler_job_test.go | 23 +++++---- website/docs/r/scheduler_job.html.markdown | 35 +++++-------- .../r/scheduler_job_collection.html.markdown | 4 +- 5 files changed, 61 insertions(+), 71 deletions(-) diff --git a/azurerm/helpers/set/set.go b/azurerm/helpers/set/set.go index a8cc3daf138c..0968ad23de28 100644 --- a/azurerm/helpers/set/set.go +++ b/azurerm/helpers/set/set.go @@ -5,6 +5,7 @@ import ( "strings" "github.com/hashicorp/terraform/helper/hashcode" + "github.com/hashicorp/terraform/helper/schema" ) func HashInt(v interface{}) int { @@ -14,3 +15,21 @@ func HashInt(v interface{}) int { func HashStringIgnoreCase(v interface{}) int { return hashcode.String(strings.ToLower(v.(string))) } + +func FromInt32Slice(slice []int32) *schema.Set { + set := &schema.Set{F: HashInt} + for _, v := range slice { + set.Add(int(v)) + } + + return set +} + +func ToSliceInt32P(set *schema.Set) *[]int32 { + var slice []int32 + for _, m := range set.List() { + slice = append(slice, int32(m.(int))) + } + + return &slice +} diff --git a/azurerm/resource_arm_scheduler_job.go b/azurerm/resource_arm_scheduler_job.go index 7499a01cd2a3..e90368fd326f 100644 --- a/azurerm/resource_arm_scheduler_job.go +++ b/azurerm/resource_arm_scheduler_job.go @@ -577,7 +577,6 @@ func resourceArmSchedulerJobDelete(d *schema.ResourceData, meta interface{}) err return nil } -//expand (terraform -> API) func expandAzureArmSchedulerJobActionRequest(meta interface{}, b interface{}) (*scheduler.HTTPRequest, scheduler.JobActionType) { block := b.([]interface{})[0].(map[string]interface{}) @@ -595,15 +594,13 @@ func expandAzureArmSchedulerJobActionRequest(meta interface{}, b interface{}) (* var jobType scheduler.JobActionType if strings.HasPrefix(strings.ToLower(url), "https://") { jobType = scheduler.HTTPS - //} else if strings.HasPrefix(strings.ToLower(url), "http://") { } else { jobType = scheduler.HTTP } //load headers - //if v, ok := block["headers"].(map[string]interface{}); ok { //check doesn't seem to be needed for k, v := range block["headers"].(map[string]interface{}) { - (request.Headers)[k] = utils.String(v.(string)) + request.Headers[k] = utils.String(v.(string)) } //only valid for a set @@ -670,14 +667,10 @@ func expandAzureArmSchedulerJobActionRetry(b interface{}) *scheduler.RetryPolicy func expandAzureArmSchedulerJobRecurrence(b interface{}) *scheduler.JobRecurrence { block := b.([]interface{})[0].(map[string]interface{}) - recurrence := scheduler.JobRecurrence{} - schedule := scheduler.JobRecurrenceSchedule{} - if v, ok := block["frequency"].(string); ok && v != "" { - recurrence.Frequency = scheduler.RecurrenceFrequency(v) - } - if v, ok := block["interval"].(int); ok { - recurrence.Interval = utils.Int32(int32(v)) + recurrence := scheduler.JobRecurrence{ + Frequency: scheduler.RecurrenceFrequency(block["frequency"].(string)), + Interval: utils.Int32(int32(block["interval"].(int))), } if v, ok := block["count"].(int); ok { recurrence.Count = utils.Int32(int32(v)) @@ -687,11 +680,12 @@ func expandAzureArmSchedulerJobRecurrence(b interface{}) *scheduler.JobRecurrenc recurrence.EndTime = &date.Time{Time: endTime} } + schedule := scheduler.JobRecurrenceSchedule{} if s, ok := block["minutes"].(*schema.Set); ok && s.Len() > 0 { - schedule.Minutes = setToSliceInt32P(s) + schedule.Minutes = set.ToSliceInt32P(s) } if s, ok := block["hours"].(*schema.Set); ok && s.Len() > 0 { - schedule.Hours = setToSliceInt32P(s) + schedule.Hours = set.ToSliceInt32P(s) } if s, ok := block["week_days"].(*schema.Set); ok && s.Len() > 0 { @@ -703,7 +697,7 @@ func expandAzureArmSchedulerJobRecurrence(b interface{}) *scheduler.JobRecurrenc } if s, ok := block["month_days"].(*schema.Set); ok && s.Len() > 0 { - schedule.MonthDays = setToSliceInt32P(s) + schedule.MonthDays = set.ToSliceInt32P(s) } if s, ok := block["monthly_occurrences"].(*schema.Set); ok && s.Len() > 0 { var slice []scheduler.JobRecurrenceScheduleMonthlyOccurrence @@ -765,7 +759,7 @@ func flattenAzureArmSchedulerJobActionRequest(request *scheduler.HTTPRequest) [] authBlock["username"] = *v } - //password is always blank, so blank it + //password is not returned authBlock["password"] = "" } else if cert, ok := auth.AsClientCertAuthentication(); ok { @@ -781,7 +775,7 @@ func flattenAzureArmSchedulerJobActionRequest(request *scheduler.HTTPRequest) [] authBlock["subject_name"] = *v } - //always empty so blank it + //properties not returned authBlock["pfx"] = "" authBlock["password"] = "" @@ -798,7 +792,7 @@ func flattenAzureArmSchedulerJobActionRequest(request *scheduler.HTTPRequest) [] authBlock["tenant_id"] = *v } - //secret is always empty, so blank it + //properties not returned authBlock["secret"] = "" } } @@ -838,10 +832,10 @@ func flattenAzureArmSchedulerJobSchedule(recurrence *scheduler.JobRecurrence) [] if schedule := recurrence.Schedule; schedule != nil { if v := schedule.Minutes; v != nil { - block["minutes"] = sliceToSetInt32(*v) + block["minutes"] = set.FromInt32Slice(*v) } if v := schedule.Hours; v != nil { - block["hours"] = sliceToSetInt32(*v) + block["hours"] = set.FromInt32Slice(*v) } if v := schedule.WeekDays; v != nil { @@ -852,7 +846,7 @@ func flattenAzureArmSchedulerJobSchedule(recurrence *scheduler.JobRecurrence) [] block["week_days"] = set } if v := schedule.MonthDays; v != nil { - block["month_days"] = sliceToSetInt32(*v) + block["month_days"] = set.FromInt32Slice(*v) } if monthly := schedule.MonthlyOccurrences; monthly != nil { @@ -886,20 +880,3 @@ func resourceAzureRMSchedulerJobMonthlyOccurrenceHash(v interface{}) int { return hashcode.String(buf.String()) } - -//todo where to put these? -func sliceToSetInt32(slice []int32) *schema.Set { - set := &schema.Set{F: set.HashInt} - for _, v := range slice { - set.Add(int(v)) - } - return set -} - -func setToSliceInt32P(set *schema.Set) *[]int32 { - var slice []int32 - for _, m := range set.List() { - slice = append(slice, int32(m.(int))) - } - return &slice -} diff --git a/azurerm/resource_arm_scheduler_job_test.go b/azurerm/resource_arm_scheduler_job_test.go index 3b9ebdca75a4..b5b5ed997cba 100644 --- a/azurerm/resource_arm_scheduler_job_test.go +++ b/azurerm/resource_arm_scheduler_job_test.go @@ -450,7 +450,7 @@ func TestAccAzureRMSchedulerJob_web_authAd(t *testing.T) { "", "", ""), Check: resource.ComposeAggregateTestCheckFunc( checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_authAd(resourceName, tenantId, clientId, secret), + checkAccAzureRMSchedulerJob_web_authAd(resourceName, tenantId, clientId), ), }, { @@ -696,22 +696,22 @@ func testCheckAzureRMSchedulerJobExists(name string) resource.TestCheckFunc { func testAccAzureRMSchedulerJob_base(rInt int, location, block1, block2, block3, block4 string) string { return fmt.Sprintf(` -resource "azurerm_resource_group" "rg" { +resource "azurerm_resource_group" "test" { name = "acctestRG-%[1]d" location = "%[2]s" } -resource "azurerm_scheduler_job_collection" "jc" { +resource "azurerm_scheduler_job_collection" "test" { name = "acctestRG-%[1]d-job_collection" - location = "${azurerm_resource_group.rg.location}" - resource_group_name = "${azurerm_resource_group.rg.name}" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" sku = "standard" } resource "azurerm_scheduler_job" "test" { name = "acctestRG-%[1]d-job" - resource_group_name = "${azurerm_resource_group.rg.name}" - job_collection_name = "${azurerm_scheduler_job_collection.jc.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + job_collection_name = "${azurerm_scheduler_job_collection.test.name}" %[3]s @@ -891,7 +891,8 @@ func testAccAzureRMSchedulerJob_block_actionWeb_basic(blockName string) string { //need a valid URL here otherwise on a slow connection job might fault before the test check return fmt.Sprintf(` %s { - url = "http://example.com" + url = "http://example.com" + method = "get" } `, blockName) } @@ -988,13 +989,13 @@ func testAccAzureRMSchedulerJob_block_actionWeb_authAd(tenantId, clientId, secre `, tenantId, clientId, secret) } -func checkAccAzureRMSchedulerJob_web_authAd(resourceName, tenantId, clientId, secret string) resource.TestCheckFunc { +func checkAccAzureRMSchedulerJob_web_authAd(resourceName, tenantId, clientId string) resource.TestCheckFunc { return resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_active_directory.0.tenant_id", tenantId), resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_active_directory.0.client_id", clientId), - resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_active_directory.0.secret", secret), - resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_active_directory.0.audience", "https://management.core.windows.net/"), + resource.TestCheckResourceAttrSet(resourceName, "action_web.0.authentication_active_directory.0.secret"), + resource.TestCheckResourceAttrSet(resourceName, "action_web.0.authentication_active_directory.0.audience"), ) } diff --git a/website/docs/r/scheduler_job.html.markdown b/website/docs/r/scheduler_job.html.markdown index 3c25f9e18270..17245d180175 100644 --- a/website/docs/r/scheduler_job.html.markdown +++ b/website/docs/r/scheduler_job.html.markdown @@ -3,12 +3,12 @@ layout: "azurerm" page_title: "Azure Resource Manager: azurerm_scheduler_job" sidebar_current: "docs-azurerm-resource-scheduler_job description: |- - Create or modify a Scheduler Job. + Manages a Scheduler Job. --- # azurerm_scheduler_job -Create or modify a Scheduler Job. +Manages a Scheduler Job. ## Example Usage (single web get now) @@ -129,7 +129,7 @@ The following arguments are supported: * `resource_group_name` - (Required) The name of the resource group in which to create the Scheduler Job. Changing this forces a new resource to be created. -* `job_collection_name` - (Required) Specifies the Scheduler Job Collection to add the job to. Changing this forces a new resource to be created. +* `job_collection_name` - (Required) Specifies the name of the Scheduler Job Collection in which the Job should exist. Changing this forces a new resource to be created. * `action_web` - (Required) A `action_web` block defining the job action as described below. Note this is identical to an `error_action_web` block. @@ -141,7 +141,7 @@ The following arguments are supported: * `start_time` - (Optional) The time the first instance of the job is to start running at. Omitting this causes the job to start now. -* `state` - (Optional) The sets or gets the current state of the job. Could be one of: `Enabled`, `Completed`, `Disabled`, `Faulted` +* `state` - (Optional) The sets or gets the current state of the job. Can be set to either `Enabled` or `Completed` `web_action` & `error_web_action` block supports the following: @@ -158,23 +158,20 @@ The following arguments are supported: `authentication_basic` block supports the following: * `username` - (Required) Specifies the username to use. -* `password` - (Required) Specifies the password t use. Cannot be imported. +* `password` - (Required) Specifies the password to use. `authentication_certificate` block supports the following: -* `pfx` - (Required) Specifies the pfx certificate. Cannot be imported. -* `password` - (Required) Specifies the certificate password. Cannot be imported. -* `thumbprint` - (Computed) The certificate thumbprint. -* `expiration` - (Computed) The certificate expiration date. -* `subject_name` - (Computed) The certificate's certificate subject name. +* `pfx` - (Required) Specifies the pfx certificate in base-64 format. +* `password` - (Required) Specifies the certificate password. `authentication_active_directory` block supports the following: * `client_id` - (Required) Specifies the client ID to use. * `tenant_id` - (Required) Specifies the tenant ID to use. -* `secret` - (Required) Specifies the secret to use. Cannot be imported. +* `client_secret` - (Required) Specifies the secret to use. * `audience` - (Optional) Specifies the audience. @@ -192,13 +189,13 @@ The following arguments are supported: * `minutes` - (Optional) Specifies the minutes of the hour that the job should execute at. Must be between `0` and `59` * `hours` - (Optional) Specifies the hours of the day that the job should execute at. Must be between `0` and `23` * `week_days` - (Optional) Specifies the days of the week that the job should execute on. Must be one of `Monday`, `Tuesday`, `Wednesday`, `Thursday`, `Friday`, `Saturday`, `Sunday`. Only applies when `Week` is used for frequency. -* `month_days` - (Optional) Specifies the days of the month that the job should execute on. Must be non zero and between ``-1` and `31`. Only applies when `Month` is used for frequency. +* `month_days` - (Optional) Specifies the days of the month that the job should execute on. Must be non zero and between `-1` and `31`. Only applies when `Month` is used for frequency. * `monthly_occurrences` - (Optional) Specifies specific monthly occurrences like "last sunday of the month" with `monthly_occurrences` blocks. Only applies when `Month` is used for frequency. `monthly_occurrences` block supports the following: * `day` - (Optional) Specifies the day of the week that the job should execute on. Must be one of one of `Monday`, `Tuesday`, `Wednesday`, `Thursday`, `Friday`, `Saturday`, `Sunday`. -* `occurrence` - (Optional) Specifies the week the job should run on. For example 1 for the first week, -1 for the last week of the month. Must be between -5 and 5. +* `occurrence` - (Optional) Specifies the week the job should run on. For example `1` for the first week, `-1` for the last week of the month. Must be between `-5` and `5`. ## Attributes Reference @@ -207,15 +204,11 @@ The following attributes are exported: * `id` - The Scheduler Job ID. -* `execution_count` - The number of times this job has executed. - -* `failure_count` - The number of times this job has failed. - -* `faulted_count` - The number of faulted occurrences (occurrences that were retried and failed as many times as the retry policy states). +`authentication_certificate` block exports the following: -* `last_execution_time` - The time the last occurrence executed in ISO-8601 format. Could be empty if job has not run yet. - -* `next_execution_time` - The time of the next occurrence. Could be empty if the job is completed.. +* `thumbprint` - (Computed) The certificate thumbprint. +* `expiration` - (Computed) The certificate expiration date. +* `subject_name` - (Computed) The certificate's certificate subject name. ## Import diff --git a/website/docs/r/scheduler_job_collection.html.markdown b/website/docs/r/scheduler_job_collection.html.markdown index b5c994dc3f16..330b75c8800a 100644 --- a/website/docs/r/scheduler_job_collection.html.markdown +++ b/website/docs/r/scheduler_job_collection.html.markdown @@ -3,12 +3,12 @@ layout: "azurerm" page_title: "Azure Resource Manager: azurerm_scheduler_job_collection" sidebar_current: "docs-azurerm-resource-scheduler_job_collection" description: |- - Create a Scheduler Job Collection. + Manages a Scheduler Job Collection. --- # azurerm_scheduler_job_collection -Create a Scheduler Job Collection. +Manages a Scheduler Job Collection. ## Example Usage From c18fbfe36679afeb05a727b3291414d28369914b Mon Sep 17 00:00:00 2001 From: kt Date: Fri, 22 Jun 2018 08:57:39 -0700 Subject: [PATCH 12/18] scheduler job: address PR comments --- azurerm/helpers/suppress/suppress.go | 23 - azurerm/helpers/suppress/suppress_test.go | 90 -- azurerm/helpers/validate/validate.go | 17 - azurerm/helpers/validate/validate_test.go | 42 - azurerm/resource_arm_scheduler_job.go | 163 ++-- azurerm/resource_arm_scheduler_job_test.go | 933 +++++++++------------ examples/scheduler-jobs/main.tf | 3 +- examples/scheduler-jobs/outputs.tf | 15 - website/docs/r/scheduler_job.html.markdown | 14 +- 9 files changed, 485 insertions(+), 815 deletions(-) delete mode 100644 azurerm/helpers/suppress/suppress.go delete mode 100644 azurerm/helpers/suppress/suppress_test.go diff --git a/azurerm/helpers/suppress/suppress.go b/azurerm/helpers/suppress/suppress.go deleted file mode 100644 index 22555f5d29e6..000000000000 --- a/azurerm/helpers/suppress/suppress.go +++ /dev/null @@ -1,23 +0,0 @@ -package suppress - -import ( - "strings" - "time" - - "github.com/hashicorp/terraform/helper/schema" -) - -func CaseDifference(_, old, new string, _ *schema.ResourceData) bool { - return strings.ToLower(old) == strings.ToLower(new) -} - -func Rfc3339Time(_, old, new string, _ *schema.ResourceData) bool { - ot, oerr := time.Parse(time.RFC3339, old) - nt, nerr := time.Parse(time.RFC3339, new) - - if oerr != nil || nerr != nil { - return false - } - - return nt.Equal(ot) -} diff --git a/azurerm/helpers/suppress/suppress_test.go b/azurerm/helpers/suppress/suppress_test.go deleted file mode 100644 index f532c40c2551..000000000000 --- a/azurerm/helpers/suppress/suppress_test.go +++ /dev/null @@ -1,90 +0,0 @@ -package suppress - -import ( - "testing" -) - -func TestInternal_Suppress_CaseDifference(t *testing.T) { - cases := []struct { - StringA string - StringB string - Suppress bool - }{ - { - StringA: "", - StringB: "", - Suppress: true, - }, - { - StringA: "ye old text", - StringB: "", - Suppress: false, - }, - { - StringA: "ye old text?", - StringB: "ye different text", - Suppress: false, - }, - { - StringA: "ye same text!", - StringB: "ye same text!", - Suppress: true, - }, - { - StringA: "ye old text?", - StringB: "Ye OLD texT?", - Suppress: true, - }, - } - - for _, tc := range cases { - if CaseDifference("test", tc.StringA, tc.StringB, nil) != tc.Suppress { - t.Fatalf("Expected CaseDifference to return %t for '%q' == '%q'", tc.Suppress, tc.StringA, tc.StringB) - } - } -} - -func TestInternal_Supress_Rfc3339Time(t *testing.T) { - cases := []struct { - TimeA string - TimeB string - Suppress bool - }{ - { - TimeA: "", - TimeB: "", - Suppress: false, - }, - { - TimeA: "this is not a time", - TimeB: "neither is this", - Suppress: false, - }, - { - TimeA: "2000-01-01T01:23:45+00:00", - TimeB: "that is a valid time", - Suppress: false, - }, - { - TimeA: "2000-01-01T01:23:45+00:00", - TimeB: "1984-07-07T01:23:45+00:00", - Suppress: false, - }, - { - TimeA: "2000-01-01T01:23:45+00:00", - TimeB: "2000-01-01T01:23:45Z", - Suppress: true, - }, - { - TimeA: "2000-01-01T01:23:45-08:00", - TimeB: "2000-01-01T09:23:45Z", - Suppress: true, - }, - } - - for _, tc := range cases { - if Rfc3339Time("test", tc.TimeA, tc.TimeB, nil) != tc.Suppress { - t.Fatalf("Expected Rfc3339Time to return %t for '%q' == '%q'", tc.Suppress, tc.TimeA, tc.TimeB) - } - } -} diff --git a/azurerm/helpers/validate/validate.go b/azurerm/helpers/validate/validate.go index 60272bd1f7a3..1faad3ad7754 100644 --- a/azurerm/helpers/validate/validate.go +++ b/azurerm/helpers/validate/validate.go @@ -3,27 +3,10 @@ package validate import ( "fmt" "net/url" - "time" - "github.com/Azure/go-autorest/autorest/date" "github.com/hashicorp/terraform/helper/schema" ) -//todo, now in terraform helper, switch over once vended, -func Rfc3339Time(i interface{}, k string) (_ []string, errors []error) { - v, ok := i.(string) - if !ok { - errors = append(errors, fmt.Errorf("expected type of %q to be string", k)) - return - } - - if _, err := date.ParseTime(time.RFC3339, v); err != nil { - errors = append(errors, fmt.Errorf("%q has the invalid RFC3339 date format %q: %+v", k, i, err)) - } - - return -} - func IntBetweenAndNot(min, max, not int) schema.SchemaValidateFunc { return func(i interface{}, k string) (_ []string, errors []error) { v, ok := i.(int) diff --git a/azurerm/helpers/validate/validate_test.go b/azurerm/helpers/validate/validate_test.go index c1bf2b5c43a0..77fb273799a5 100644 --- a/azurerm/helpers/validate/validate_test.go +++ b/azurerm/helpers/validate/validate_test.go @@ -1,43 +1 @@ package validate - -import "testing" - -func TestInternal_ValidateRFC3339Time(t *testing.T) { - cases := []struct { - Time string - Errors int - }{ - { - Time: "", - Errors: 1, - }, - { - Time: "this is not a date", - Errors: 1, - }, - { - Time: "2000-01-01", - Errors: 1, - }, - { - Time: "2000-01-01T01:23:45", - Errors: 1, - }, - { - Time: "2000-01-01T01:23:45Z", - Errors: 0, - }, - { - Time: "2000-01-01T01:23:45+00:00", - Errors: 0, - }, - } - - for _, tc := range cases { - _, errors := Rfc3339Time(tc.Time, "test") - - if len(errors) != tc.Errors { - t.Fatalf("Expected Rfc3339Time to have an error for '%q'", tc.Time) - } - } -} diff --git a/azurerm/resource_arm_scheduler_job.go b/azurerm/resource_arm_scheduler_job.go index e90368fd326f..29f8d871a677 100644 --- a/azurerm/resource_arm_scheduler_job.go +++ b/azurerm/resource_arm_scheduler_job.go @@ -48,9 +48,10 @@ func resourceArmSchedulerJob() *schema.Resource { "resource_group_name": resourceGroupNameSchema(), "job_collection_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validation.NoZeroValues, }, //actions @@ -80,9 +81,10 @@ func resourceArmSchedulerJob() *schema.Resource { //silently fails if the duration is not in the correct format //todo validation "interval": { - Type: schema.TypeString, - Optional: true, - Default: "00:00:30", + Type: schema.TypeString, + Optional: true, + Default: "00:00:30", + ValidateFunc: validation.NoZeroValues, }, "count": { @@ -169,7 +171,8 @@ func resourceArmSchedulerJob() *schema.Resource { // so lets ignore the case Set: set.HashStringIgnoreCase, Elem: &schema.Schema{ - Type: schema.TypeString, + Type: schema.TypeString, + DiffSuppressFunc: suppress.CaseDifference, ValidateFunc: validation.StringInSlice([]string{ string(scheduler.Sunday), string(scheduler.Monday), @@ -203,8 +206,9 @@ func resourceArmSchedulerJob() *schema.Resource { Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "day": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + DiffSuppressFunc: suppress.CaseDifference, ValidateFunc: validation.StringInSlice([]string{ string(scheduler.Sunday), string(scheduler.Monday), @@ -215,6 +219,7 @@ func resourceArmSchedulerJob() *schema.Resource { string(scheduler.Saturday), }, true), }, + "occurrence": { Type: schema.TypeInt, Required: true, @@ -273,8 +278,9 @@ func resourceArmSchedulerJobActionWebSchema(propertyName string) *schema.Resourc //only valid/used when action type is put "body": { - Type: schema.TypeString, - Optional: true, + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.NoZeroValues, }, "headers": { @@ -294,14 +300,16 @@ func resourceArmSchedulerJobActionWebSchema(propertyName string) *schema.Resourc Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "username": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.NoZeroValues, }, "password": { - Type: schema.TypeString, - Required: true, - Sensitive: true, + Type: schema.TypeString, + Required: true, + Sensitive: true, + ValidateFunc: validation.NoZeroValues, }, }, }, @@ -318,15 +326,17 @@ func resourceArmSchedulerJobActionWebSchema(propertyName string) *schema.Resourc Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "pfx": { - Type: schema.TypeString, - Required: true, - Sensitive: true, //sensitive & shortens diff + Type: schema.TypeString, + Required: true, + Sensitive: true, //sensitive & shortens diff + ValidateFunc: validation.NoZeroValues, }, "password": { - Type: schema.TypeString, - Required: true, - Sensitive: true, + Type: schema.TypeString, + Required: true, + Sensitive: true, + ValidateFunc: validation.NoZeroValues, }, "thumbprint": { @@ -358,18 +368,21 @@ func resourceArmSchedulerJobActionWebSchema(propertyName string) *schema.Resourc Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "tenant_id": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.NoZeroValues, }, "client_id": { - Type: schema.TypeString, - Required: true, + Type: schema.TypeString, + Required: true, + ValidateFunc: validation.NoZeroValues, }, "secret": { - Type: schema.TypeString, - Required: true, - Sensitive: true, + Type: schema.TypeString, + Required: true, + Sensitive: true, + ValidateFunc: validation.NoZeroValues, }, "audience": { @@ -416,32 +429,12 @@ func resourceArmSchedulerJobCreateUpdate(d *schema.ResourceData, meta interface{ job := scheduler.JobDefinition{ Properties: &scheduler.JobProperties{ - Action: &scheduler.JobAction{}, + Action: expandAzureArmSchedulerJobAction(d, meta), }, } log.Printf("[DEBUG] Creating/updating Scheduler Job %q (resource group %q)", name, resourceGroup) - //action - if b, ok := d.GetOk("action_web"); ok { - job.Properties.Action.Request, job.Properties.Action.Type = expandAzureArmSchedulerJobActionRequest(meta, b) - } - - //error action - if b, ok := d.GetOk("error_action_web"); ok { - job.Properties.Action.ErrorAction = &scheduler.JobErrorAction{} - job.Properties.Action.ErrorAction.Request, job.Properties.Action.ErrorAction.Type = expandAzureArmSchedulerJobActionRequest(meta, b) - } - - //retry policy - if b, ok := d.GetOk("retry"); ok { - job.Properties.Action.RetryPolicy = expandAzureArmSchedulerJobActionRetry(b) - } else { - job.Properties.Action.RetryPolicy = &scheduler.RetryPolicy{ - RetryType: scheduler.None, - } - } - //schedule (recurrence) if b, ok := d.GetOk("recurrence"); ok { job.Properties.Recurrence = expandAzureArmSchedulerJobRecurrence(b) @@ -509,7 +502,7 @@ func resourceArmSchedulerJobRead(d *schema.ResourceData, meta interface{}) error if action != nil { actionType := strings.ToLower(string(action.Type)) if strings.EqualFold(actionType, string(scheduler.HTTP)) || strings.EqualFold(actionType, string(scheduler.HTTPS)) { - if err := d.Set("action_web", flattenAzureArmSchedulerJobActionRequest(action.Request)); err != nil { + if err := d.Set("action_web", flattenAzureArmSchedulerJobActionRequest(d, "action_web", action.Request)); err != nil { return err } } @@ -517,7 +510,7 @@ func resourceArmSchedulerJobRead(d *schema.ResourceData, meta interface{}) error //error action if errorAction := action.ErrorAction; errorAction != nil { if strings.EqualFold(actionType, string(scheduler.HTTP)) || strings.EqualFold(actionType, string(scheduler.HTTPS)) { - if err := d.Set("error_action_web", flattenAzureArmSchedulerJobActionRequest(errorAction.Request)); err != nil { + if err := d.Set("error_action_web", flattenAzureArmSchedulerJobActionRequest(d, "error_action_web", errorAction.Request)); err != nil { return err } } @@ -526,7 +519,8 @@ func resourceArmSchedulerJobRead(d *schema.ResourceData, meta interface{}) error //retry if retry := action.RetryPolicy; retry != nil { //if its not fixed we should not have a retry block - if retry.RetryType == scheduler.Fixed { + //api returns whatever casing it gets so do a case insensitive comparison + if strings.EqualFold(string(retry.RetryType), string(scheduler.Fixed)) { if err := d.Set("retry", flattenAzureArmSchedulerJobActionRetry(retry)); err != nil { return err } @@ -577,7 +571,34 @@ func resourceArmSchedulerJobDelete(d *schema.ResourceData, meta interface{}) err return nil } -func expandAzureArmSchedulerJobActionRequest(meta interface{}, b interface{}) (*scheduler.HTTPRequest, scheduler.JobActionType) { +func expandAzureArmSchedulerJobAction(d *schema.ResourceData, meta interface{}) *scheduler.JobAction { + + action := scheduler.JobAction{} + + //action + if b, ok := d.GetOk("action_web"); ok { + action.Request, action.Type = expandAzureArmSchedulerJobActionRequest(b, meta) + } + + //error action + if b, ok := d.GetOk("error_action_web"); ok { + action.ErrorAction = &scheduler.JobErrorAction{} + action.ErrorAction.Request, action.ErrorAction.Type = expandAzureArmSchedulerJobActionRequest(b, meta) + } + + //retry policy + if b, ok := d.GetOk("retry"); ok { + action.RetryPolicy = expandAzureArmSchedulerJobActionRetry(b) + } else { + action.RetryPolicy = &scheduler.RetryPolicy{ + RetryType: scheduler.None, + } + } + + return &action +} + +func expandAzureArmSchedulerJobActionRequest(b interface{}, meta interface{}) (*scheduler.HTTPRequest, scheduler.JobActionType) { block := b.([]interface{})[0].(map[string]interface{}) @@ -725,7 +746,7 @@ func expandAzureArmSchedulerJobRecurrence(b interface{}) *scheduler.JobRecurrenc // flatten (API --> terraform) -func flattenAzureArmSchedulerJobActionRequest(request *scheduler.HTTPRequest) []interface{} { +func flattenAzureArmSchedulerJobActionRequest(d *schema.ResourceData, blockName string, request *scheduler.HTTPRequest) []interface{} { block := map[string]interface{}{} @@ -759,8 +780,10 @@ func flattenAzureArmSchedulerJobActionRequest(request *scheduler.HTTPRequest) [] authBlock["username"] = *v } - //password is not returned - authBlock["password"] = "" + //password is not returned so lets fetch it + if v, ok := d.GetOk(fmt.Sprintf("%s.0.authentication_basic.0.password", blockName)); ok { + authBlock["password"] = v.(string) + } } else if cert, ok := auth.AsClientCertAuthentication(); ok { block["authentication_certificate"] = []interface{}{authBlock} @@ -775,9 +798,13 @@ func flattenAzureArmSchedulerJobActionRequest(request *scheduler.HTTPRequest) [] authBlock["subject_name"] = *v } - //properties not returned - authBlock["pfx"] = "" - authBlock["password"] = "" + //these properties not returned, so lets grab them + if v, ok := d.GetOk(fmt.Sprintf("%s.0.authentication_certificate.0.pfx", blockName)); ok { + authBlock["pfx"] = v.(string) + } + if v, ok := d.GetOk(fmt.Sprintf("%s.0.authentication_certificate.0.password", blockName)); ok { + authBlock["password"] = v.(string) + } } else if oauth, ok := auth.AsOAuthAuthentication(); ok { block["authentication_active_directory"] = []interface{}{authBlock} @@ -792,8 +819,10 @@ func flattenAzureArmSchedulerJobActionRequest(request *scheduler.HTTPRequest) [] authBlock["tenant_id"] = *v } - //properties not returned - authBlock["secret"] = "" + //secret is not returned + if v, ok := d.GetOk(fmt.Sprintf("%s.0.authentication_active_directory.0.secret", blockName)); ok { + authBlock["secret"] = v.(string) + } } } @@ -803,7 +832,6 @@ func flattenAzureArmSchedulerJobActionRequest(request *scheduler.HTTPRequest) [] func flattenAzureArmSchedulerJobActionRetry(retry *scheduler.RetryPolicy) []interface{} { block := map[string]interface{}{} - block["type"] = string(retry.RetryType) if v := retry.RetryInterval; v != nil { block["interval"] = *v } @@ -872,11 +900,12 @@ func flattenAzureArmSchedulerJobSchedule(recurrence *scheduler.JobRecurrence) [] func resourceAzureRMSchedulerJobMonthlyOccurrenceHash(v interface{}) int { var buf bytes.Buffer - m := v.(map[string]interface{}) - //day returned by azure is in a different case then the API constants - buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["day"].(string)))) - buf.WriteString(fmt.Sprintf("%d-", m["occurrence"].(int))) + if m, ok := v.(map[string]interface{}); ok { + //day returned by azure is in a different case then the API constants + buf.WriteString(fmt.Sprintf("%s-", strings.ToLower(m["day"].(string)))) + buf.WriteString(fmt.Sprintf("%d-", m["occurrence"].(int))) + } return hashcode.String(buf.String()) } diff --git a/azurerm/resource_arm_scheduler_job_test.go b/azurerm/resource_arm_scheduler_job_test.go index b5b5ed997cba..1f2d0d83443d 100644 --- a/azurerm/resource_arm_scheduler_job_test.go +++ b/azurerm/resource_arm_scheduler_job_test.go @@ -2,19 +2,15 @@ package azurerm import ( "fmt" + "os" "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" - "os" ) -// check recurring basic -> recurring each type? -// check: basic everything -> complete everything? -// check : base + web + error action - func TestAccAzureRMSchedulerJob_web_basic(t *testing.T) { ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" @@ -25,13 +21,8 @@ func TestAccAzureRMSchedulerJob_web_basic(t *testing.T) { CheckDestroy: testCheckAzureRMSchedulerJobDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - "", "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - ), + Config: testAccAzureRMSchedulerJob_web_basic(ri, testLocation()), + Check: checkAccAzureRMSchedulerJob_web_basic(resourceName), }, { ResourceName: resourceName, @@ -42,83 +33,7 @@ func TestAccAzureRMSchedulerJob_web_basic(t *testing.T) { }) } -func TestAccAzureRMSchedulerJob_startTime(t *testing.T) { - ri := acctest.RandInt() - resourceName := "azurerm_scheduler_job.test" - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testCheckAzureRMSchedulerJobDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - "", "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - ), - }, - { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - testAccAzureRMSchedulerJob_block_startTime("2019-07-07T07:07:07-07:00"), - "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_startTime(resourceName, "2019-07-07T14:07:07Z"), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func TestAccAzureRMSchedulerJob_web_retry(t *testing.T) { - ri := acctest.RandInt() - resourceName := "azurerm_scheduler_job.test" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testCheckAzureRMSchedulerJobDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - testAccAzureRMSchedulerJob_block_retry_empty(), - "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - checkAccAzureRMSchedulerJob_retry_empty(resourceName), - ), - }, - { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - testAccAzureRMSchedulerJob_block_retry_complete(), - "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - checkAccAzureRMSchedulerJob_retry_complete(resourceName), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} - -func TestAccAzureRMSchedulerJob_web_recurring(t *testing.T) { +func TestAccAzureRMSchedulerJob_web_put(t *testing.T) { ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" @@ -128,15 +43,8 @@ func TestAccAzureRMSchedulerJob_web_recurring(t *testing.T) { CheckDestroy: testCheckAzureRMSchedulerJobDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - testAccAzureRMSchedulerJob_block_recurrence_basic(), - "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - checkAccAzureRMSchedulerJob_recurrence_basic(resourceName), - ), + Config: testAccAzureRMSchedulerJob_web_put(ri, testLocation()), + Check: checkAccAzureRMSchedulerJob_web_put(resourceName), }, { ResourceName: resourceName, @@ -147,7 +55,7 @@ func TestAccAzureRMSchedulerJob_web_recurring(t *testing.T) { }) } -func TestAccAzureRMSchedulerJob_web_recurringDaily(t *testing.T) { +func TestAccAzureRMSchedulerJob_web_authBasic(t *testing.T) { ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" @@ -157,26 +65,20 @@ func TestAccAzureRMSchedulerJob_web_recurringDaily(t *testing.T) { CheckDestroy: testCheckAzureRMSchedulerJobDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - testAccAzureRMSchedulerJob_block_recurrence_daily(), - "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - checkAccAzureRMSchedulerJob_recurrence_daily(resourceName), - ), + Config: testAccAzureRMSchedulerJob_web_authBasic(ri, testLocation()), + Check: checkAccAzureRMSchedulerJob_web_authBasic(resourceName), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"action_web.0.authentication_basic.0.password"}, }, }, }) } -func TestAccAzureRMSchedulerJob_web_recurringWeekly(t *testing.T) { +func TestAccAzureRMSchedulerJob_web_authCert(t *testing.T) { ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" @@ -186,57 +88,31 @@ func TestAccAzureRMSchedulerJob_web_recurringWeekly(t *testing.T) { CheckDestroy: testCheckAzureRMSchedulerJobDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - testAccAzureRMSchedulerJob_block_recurrence_weekly(), - "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - checkAccAzureRMSchedulerJob_recurrence_weekly(resourceName), - ), + Config: testAccAzureRMSchedulerJob_web_authCert(ri, testLocation()), + Check: checkAccAzureRMSchedulerJob_web_authCert(resourceName), }, { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, + ImportStateVerifyIgnore: []string{ + "action_web.0.authentication_certificate.0.pfx", + "action_web.0.authentication_certificate.0.password", + }, }, }, }) } -func TestAccAzureRMSchedulerJob_web_recurringMonthly(t *testing.T) { +func TestAccAzureRMSchedulerJob_web_authAd(t *testing.T) { ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testCheckAzureRMSchedulerJobDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - testAccAzureRMSchedulerJob_block_recurrence_monthly(), - "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - checkAccAzureRMSchedulerJob_recurrence_monthly(resourceName), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} + clientId := os.Getenv("ARM_CLIENT_ID") + tenantId := os.Getenv("ARM_TENANT_ID") + secret := os.Getenv("ARM_CLIENT_SECRET") -func TestAccAzureRMSchedulerJob_web_recurringMonthlyOccurrences(t *testing.T) { - ri := acctest.RandInt() - resourceName := "azurerm_scheduler_job.test" + audiance := testAccProvider.Meta().(*ArmClient).environment.ServiceManagementEndpoint resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -244,26 +120,20 @@ func TestAccAzureRMSchedulerJob_web_recurringMonthlyOccurrences(t *testing.T) { CheckDestroy: testCheckAzureRMSchedulerJobDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - testAccAzureRMSchedulerJob_block_recurrence_monthlyOccurrences(), - "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - checkAccAzureRMSchedulerJob_recurrence_monthlyOccurrences(resourceName), - ), + Config: testAccAzureRMSchedulerJob_web_authAd(ri, testLocation(), tenantId, clientId, secret, audiance), + Check: checkAccAzureRMSchedulerJob_web_authAd(resourceName, tenantId, clientId), }, { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"action_web.0.authentication_active_directory.0.secret"}, }, }, }) } -func TestAccAzureRMSchedulerJob_web_recurringAll(t *testing.T) { +func TestAccAzureRMSchedulerJob_web_retry(t *testing.T) { ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" @@ -273,59 +143,8 @@ func TestAccAzureRMSchedulerJob_web_recurringAll(t *testing.T) { CheckDestroy: testCheckAzureRMSchedulerJobDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - testAccAzureRMSchedulerJob_block_recurrence_basic(), - "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - checkAccAzureRMSchedulerJob_recurrence_basic(resourceName), - ), - }, - { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - testAccAzureRMSchedulerJob_block_recurrence_daily(), - "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - checkAccAzureRMSchedulerJob_recurrence_daily(resourceName), - ), - }, - { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - testAccAzureRMSchedulerJob_block_recurrence_weekly(), - "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - checkAccAzureRMSchedulerJob_recurrence_weekly(resourceName), - ), - }, - { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - testAccAzureRMSchedulerJob_block_recurrence_monthly(), - "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - checkAccAzureRMSchedulerJob_recurrence_monthly(resourceName), - ), - }, - { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - testAccAzureRMSchedulerJob_block_recurrence_monthlyOccurrences(), - "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - checkAccAzureRMSchedulerJob_recurrence_monthlyOccurrences(resourceName), - ), + Config: testAccAzureRMSchedulerJob_web_retry(ri, testLocation()), + Check: checkAccAzureRMSchedulerJob_web_retry(resourceName), }, { ResourceName: resourceName, @@ -336,7 +155,7 @@ func TestAccAzureRMSchedulerJob_web_recurringAll(t *testing.T) { }) } -func TestAccAzureRMSchedulerJob_web_put(t *testing.T) { +func TestAccAzureRMSchedulerJob_web_recurring(t *testing.T) { ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" @@ -346,22 +165,8 @@ func TestAccAzureRMSchedulerJob_web_put(t *testing.T) { CheckDestroy: testCheckAzureRMSchedulerJobDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - "", "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - ), - }, - { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_put("action_web"), - "", "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_put(resourceName, "action_web"), - ), + Config: testAccAzureRMSchedulerJob_web_recurring(ri, testLocation()), + Check: checkAccAzureRMSchedulerJob_web_recurring(resourceName), }, { ResourceName: resourceName, @@ -372,35 +177,7 @@ func TestAccAzureRMSchedulerJob_web_put(t *testing.T) { }) } -func TestAccAzureRMSchedulerJob_web_authBasic(t *testing.T) { - ri := acctest.RandInt() - resourceName := "azurerm_scheduler_job.test" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testCheckAzureRMSchedulerJobDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_authBasic("action_web"), - "", "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_authBasic(resourceName, "action_web"), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, - ImportStateVerifyIgnore: []string{"action_web.0.authentication_basic.0.password"}, - }, - }, - }) -} - -func TestAccAzureRMSchedulerJob_web_authCert(t *testing.T) { +func TestAccAzureRMSchedulerJob_web_recurringDaily(t *testing.T) { ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" @@ -410,62 +187,41 @@ func TestAccAzureRMSchedulerJob_web_authCert(t *testing.T) { CheckDestroy: testCheckAzureRMSchedulerJobDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_authCert(), - "", "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_authCert(resourceName), - ), + Config: testAccAzureRMSchedulerJob_web_recurringDaily(ri, testLocation()), + Check: checkAccAzureRMSchedulerJob_web_recurringDaily(resourceName), }, { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "action_web.0.authentication_certificate.0.pfx", - "action_web.0.authentication_certificate.0.password", - }, }, }, }) } -func TestAccAzureRMSchedulerJob_web_authAd(t *testing.T) { +func TestAccAzureRMSchedulerJob_web_recurringWeekly(t *testing.T) { ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" - clientId := os.Getenv("ARM_CLIENT_ID") - tenantId := os.Getenv("ARM_TENANT_ID") - secret := os.Getenv("ARM_CLIENT_SECRET") - resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testCheckAzureRMSchedulerJobDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_authAd(tenantId, clientId, secret), - "", "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_authAd(resourceName, tenantId, clientId), - ), + Config: testAccAzureRMSchedulerJob_web_recurringWeekly(ri, testLocation()), + Check: checkAccAzureRMSchedulerJob_web_recurringWeekly(resourceName), }, { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "action_web.0.authentication_active_directory.0.secret", - }, }, }, }) } -func TestAccAzureRMSchedulerJob_web_basic_onceToRecurring(t *testing.T) { +func TestAccAzureRMSchedulerJob_web_recurringMonthly(t *testing.T) { ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" @@ -475,22 +231,8 @@ func TestAccAzureRMSchedulerJob_web_basic_onceToRecurring(t *testing.T) { CheckDestroy: testCheckAzureRMSchedulerJobDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - "", "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - ), - }, - { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - "", "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - ), + Config: testAccAzureRMSchedulerJob_web_recurringMonthly(ri, testLocation()), + Check: checkAccAzureRMSchedulerJob_web_recurringMonthly(resourceName), }, { ResourceName: resourceName, @@ -501,7 +243,7 @@ func TestAccAzureRMSchedulerJob_web_basic_onceToRecurring(t *testing.T) { }) } -func TestAccAzureRMSchedulerJob_errrActionWeb_basic(t *testing.T) { +func TestAccAzureRMSchedulerJob_web_recurringMonthlyOccurrences(t *testing.T) { ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" @@ -511,24 +253,8 @@ func TestAccAzureRMSchedulerJob_errrActionWeb_basic(t *testing.T) { CheckDestroy: testCheckAzureRMSchedulerJobDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - "", "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - ), - }, - { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_basic("action_web"), - testAccAzureRMSchedulerJob_block_actionWeb_basic("error_action_web"), - "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "action_web"), - checkAccAzureRMSchedulerJob_web_basic(resourceName, "error_action_web"), - ), + Config: testAccAzureRMSchedulerJob_web_recurringMonthlyOccurrences(ri, testLocation()), + Check: checkAccAzureRMSchedulerJob_web_recurringMonthlyOccurrences(resourceName), }, { ResourceName: resourceName, @@ -539,7 +265,7 @@ func TestAccAzureRMSchedulerJob_errrActionWeb_basic(t *testing.T) { }) } -func TestAccAzureRMSchedulerJob_errorActionWeb_put(t *testing.T) { +func TestAccAzureRMSchedulerJob_web_errorAction(t *testing.T) { ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" @@ -549,15 +275,8 @@ func TestAccAzureRMSchedulerJob_errorActionWeb_put(t *testing.T) { CheckDestroy: testCheckAzureRMSchedulerJobDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_put("action_web"), - testAccAzureRMSchedulerJob_block_actionWeb_put("error_action_web"), - "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_put(resourceName, "action_web"), - checkAccAzureRMSchedulerJob_web_put(resourceName, "error_action_web"), - ), + Config: testAccAzureRMSchedulerJob_web_errorAction(ri, testLocation()), + Check: checkAccAzureRMSchedulerJob_web_errorAction(resourceName), }, { ResourceName: resourceName, @@ -568,7 +287,7 @@ func TestAccAzureRMSchedulerJob_errorActionWeb_put(t *testing.T) { }) } -func TestAccAzureRMSchedulerJob_errorActionWeb_authBasic(t *testing.T) { +func TestAccAzureRMSchedulerJob_web_complete(t *testing.T) { ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" @@ -578,57 +297,13 @@ func TestAccAzureRMSchedulerJob_errorActionWeb_authBasic(t *testing.T) { CheckDestroy: testCheckAzureRMSchedulerJobDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_authBasic("action_web"), - testAccAzureRMSchedulerJob_block_actionWeb_authBasic("error_action_web"), - "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_authBasic(resourceName, "action_web"), - checkAccAzureRMSchedulerJob_web_authBasic(resourceName, "error_action_web"), - ), + Config: testAccAzureRMSchedulerJob_web_complete(ri, testLocation(), "2019-07-07T07:07:07-07:00"), + Check: checkAccAzureRMSchedulerJob_web_complete(resourceName, "2019-07-07T14:07:07Z"), }, { ResourceName: resourceName, ImportState: true, ImportStateVerify: true, - ImportStateVerifyIgnore: []string{ - "action_web.0.authentication_basic.0.password", - "error_action_web.0.authentication_basic.0.password", - }, - }, - }, - }) -} - -func TestAccAzureRMSchedulerJob_errorAndActionWebAuth(t *testing.T) { - ri := acctest.RandInt() - resourceName := "azurerm_scheduler_job.test" - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testCheckAzureRMSchedulerJobDestroy, - Steps: []resource.TestStep{ - { - Config: testAccAzureRMSchedulerJob_base(ri, testLocation(), - testAccAzureRMSchedulerJob_block_actionWeb_authCert(), - testAccAzureRMSchedulerJob_block_actionWeb_authBasic("error_action_web"), - "", ""), - Check: resource.ComposeAggregateTestCheckFunc( - checkAccAzureRMSchedulerJob_base(resourceName), - checkAccAzureRMSchedulerJob_web_authCert(resourceName), - checkAccAzureRMSchedulerJob_web_authBasic(resourceName, "error_action_web"), - ), - }, - { - ResourceName: resourceName, - ImportState: true, - ImportStateVerify: true, ImportStateVerifyIgnore: []string{ - "action_web.0.authentication_certificate.0.pfx", - "action_web.0.authentication_certificate.0.password", - "error_action_web.0.authentication_basic.0.password", - }, }, }, }) @@ -694,7 +369,7 @@ func testCheckAzureRMSchedulerJobExists(name string) resource.TestCheckFunc { } } -func testAccAzureRMSchedulerJob_base(rInt int, location, block1, block2, block3, block4 string) string { +func testAccAzureRMSchedulerJob_template(rInt int, location string) string { return fmt.Sprintf(` resource "azurerm_resource_group" "test" { name = "acctestRG-%[1]d" @@ -708,75 +383,245 @@ resource "azurerm_scheduler_job_collection" "test" { sku = "standard" } +`, rInt, location) +} + +func testAccAzureRMSchedulerJob_web_basic(rInt int, location string) string { + //need a valid URL here otherwise on a slow connection job might fault before the test check + return fmt.Sprintf(`%s resource "azurerm_scheduler_job" "test" { - name = "acctestRG-%[1]d-job" - resource_group_name = "${azurerm_resource_group.test.name}" - job_collection_name = "${azurerm_scheduler_job_collection.test.name}" + name = "acctestRG-%d-job" + resource_group_name = "${azurerm_resource_group.test.name}" + job_collection_name = "${azurerm_scheduler_job_collection.test.name}" + + action_web { + url = "http://example.com" + method = "get" + } +}`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) +} - %[3]s +func checkAccAzureRMSchedulerJob_web_basic(resourceName string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "http://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + ) +} - %[4]s +func testAccAzureRMSchedulerJob_web_put(rInt int, location string) string { + return fmt.Sprintf(`%s +resource "azurerm_scheduler_job" "test" { + name = "acctestRG-%d-job" + resource_group_name = "${azurerm_resource_group.test.name}" + job_collection_name = "${azurerm_scheduler_job_collection.test.name}" - %[5]s - %[6]s -} -`, rInt, location, block1, block2, block3, block4) + action_web { + url = "http://example.com" + method = "put" + body = "this is some text" + + headers = { + "Content-Type" = "text" + } + } +}`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_base(resourceName string) resource.TestCheckFunc { + +func checkAccAzureRMSchedulerJob_web_put(resourceName string) resource.TestCheckFunc { return resource.ComposeAggregateTestCheckFunc( testCheckAzureRMSchedulerJobExists(resourceName), - resource.TestCheckResourceAttrSet(resourceName, "name"), - resource.TestCheckResourceAttrSet(resourceName, "resource_group_name"), - resource.TestCheckResourceAttrSet(resourceName, "job_collection_name"), - resource.TestCheckResourceAttr(resourceName, "state", "enabled"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "http://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "put"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.body", "this is some text"), ) } -func testAccAzureRMSchedulerJob_block_startTime(time string) string { - return fmt.Sprintf(` - start_time = "%s" -`, time) +func testAccAzureRMSchedulerJob_web_authBasic(rInt int, location string) string { + return fmt.Sprintf(`%s +resource "azurerm_scheduler_job" "test" { + name = "acctestRG-%d-job" + resource_group_name = "${azurerm_resource_group.test.name}" + job_collection_name = "${azurerm_scheduler_job_collection.test.name}" + + + action_web { + url = "https://example.com" + method = "get" + + authentication_basic { + username = "login" + password = "apassword" + } + } +}`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_startTime(resourceName, time string) resource.TestCheckFunc { +func checkAccAzureRMSchedulerJob_web_authBasic(resourceName string) resource.TestCheckFunc { return resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "start_time", time), + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_basic.0.username", "login"), ) } -func testAccAzureRMSchedulerJob_block_recurrence_basic() string { - return ` +func testAccAzureRMSchedulerJob_web_authCert(rInt int, location string) string { + return fmt.Sprintf(`%s +resource "azurerm_scheduler_job" "test" { + name = "acctestRG-%d-job" + resource_group_name = "${azurerm_resource_group.test.name}" + job_collection_name = "${azurerm_scheduler_job_collection.test.name}" + + + action_web { + url = "https://example.com" + method = "get" + + authentication_certificate { + pfx = "${base64encode(file("testdata/application_gateway_test.pfx"))}" + password = "terraform" + } + } +}`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) +} + +func checkAccAzureRMSchedulerJob_web_authCert(resourceName string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_certificate.0.thumbprint", "42C107874FD0E4A9583292A2F1098E8FE4B2EDDA"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_certificate.0.subject_name", "CN=Terraform App Gateway, OU=Azure, O=Terraform Tests, S=Some-State, C=US"), + ) +} + +func testAccAzureRMSchedulerJob_web_authAd(rInt int, location, tenantId, clientId, secret, audience string) string { + return fmt.Sprintf(`%s +resource "azurerm_scheduler_job" "test" { + name = "acctestRG-%d-job" + resource_group_name = "${azurerm_resource_group.test.name}" + job_collection_name = "${azurerm_scheduler_job_collection.test.name}" + + + action_web { + url = "https://example.com" + method = "get" + + authentication_active_directory { + tenant_id = "%s" + client_id = "%s" + secret = "%s" + audience = "%s" + } + } +}`, testAccAzureRMSchedulerJob_template(rInt, location), rInt, tenantId, clientId, secret, audience) +} + +func checkAccAzureRMSchedulerJob_web_authAd(resourceName, tenantId, clientId string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_active_directory.0.tenant_id", tenantId), + resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_active_directory.0.client_id", clientId), + resource.TestCheckResourceAttrSet(resourceName, "action_web.0.authentication_active_directory.0.audience"), + ) +} + +func testAccAzureRMSchedulerJob_web_retry(rInt int, location string) string { + return fmt.Sprintf(`%s +resource "azurerm_scheduler_job" "test" { + name = "acctestRG-%d-job" + resource_group_name = "${azurerm_resource_group.test.name}" + job_collection_name = "${azurerm_scheduler_job_collection.test.name}" + + + action_web { + url = "https://example.com" + method = "get" + } + + retry { + interval = "00:05:00" //5 min + count = 10 + } + +}`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) +} + +func checkAccAzureRMSchedulerJob_web_retry(resourceName string) resource.TestCheckFunc { + return resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + resource.TestCheckResourceAttr(resourceName, "retry.0.interval", "00:05:00"), + resource.TestCheckResourceAttr(resourceName, "retry.0.count", "10"), + ) +} + +func testAccAzureRMSchedulerJob_web_recurring(rInt int, location string) string { + return fmt.Sprintf(`%s +resource "azurerm_scheduler_job" "test" { + name = "acctestRG-%d-job" + resource_group_name = "${azurerm_resource_group.test.name}" + job_collection_name = "${azurerm_scheduler_job_collection.test.name}" + + + action_web { + url = "https://example.com" + method = "get" + } + recurrence { frequency = "minute" interval = 5 count = 10 - //end_time = "2019-07-17T07:07:07-07:00" } -` + +}`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_recurrence_basic(resourceName string) resource.TestCheckFunc { +func checkAccAzureRMSchedulerJob_web_recurring(resourceName string) resource.TestCheckFunc { return resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "minute"), resource.TestCheckResourceAttr(resourceName, "recurrence.0.interval", "5"), resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "10"), ) } -func testAccAzureRMSchedulerJob_block_recurrence_daily() string { - return ` +func testAccAzureRMSchedulerJob_web_recurringDaily(rInt int, location string) string { + return fmt.Sprintf(`%s +resource "azurerm_scheduler_job" "test" { + name = "acctestRG-%d-job" + resource_group_name = "${azurerm_resource_group.test.name}" + job_collection_name = "${azurerm_scheduler_job_collection.test.name}" + + + action_web { + url = "https://example.com" + method = "get" + } + recurrence { frequency = "day" count = 100 hours = [0,12] minutes = [0,15,30,45] - } -` + } + +}`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_recurrence_daily(resourceName string) resource.TestCheckFunc { +func checkAccAzureRMSchedulerJob_web_recurringDaily(resourceName string) resource.TestCheckFunc { return resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "day"), resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), resource.TestCheckResourceAttr(resourceName, "recurrence.0.hours.#", "2"), @@ -784,67 +629,112 @@ func checkAccAzureRMSchedulerJob_recurrence_daily(resourceName string) resource. ) } -func testAccAzureRMSchedulerJob_block_recurrence_weekly() string { - return ` +func testAccAzureRMSchedulerJob_web_recurringWeekly(rInt int, location string) string { + return fmt.Sprintf(`%s +resource "azurerm_scheduler_job" "test" { + name = "acctestRG-%d-job" + resource_group_name = "${azurerm_resource_group.test.name}" + job_collection_name = "${azurerm_scheduler_job_collection.test.name}" + + + action_web { + url = "https://example.com" + method = "get" + } + recurrence { frequency = "week" count = 100 week_days = ["Sunday", "Saturday"] } -` + +}`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_recurrence_weekly(resourceName string) resource.TestCheckFunc { +func checkAccAzureRMSchedulerJob_web_recurringWeekly(resourceName string) resource.TestCheckFunc { return resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "week"), resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), resource.TestCheckResourceAttr(resourceName, "recurrence.0.week_days.#", "2"), ) } -func testAccAzureRMSchedulerJob_block_recurrence_monthly() string { - return ` +func testAccAzureRMSchedulerJob_web_recurringMonthly(rInt int, location string) string { + return fmt.Sprintf(`%s +resource "azurerm_scheduler_job" "test" { + name = "acctestRG-%d-job" + resource_group_name = "${azurerm_resource_group.test.name}" + job_collection_name = "${azurerm_scheduler_job_collection.test.name}" + + + action_web { + url = "https://example.com" + method = "get" + } + recurrence { frequency = "month" count = 100 month_days = [-11,-1,1,11] } -` + +}`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_recurrence_monthly(resourceName string) resource.TestCheckFunc { +func checkAccAzureRMSchedulerJob_web_recurringMonthly(resourceName string) resource.TestCheckFunc { return resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "month"), resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), resource.TestCheckResourceAttr(resourceName, "recurrence.0.month_days.#", "4"), ) } -func testAccAzureRMSchedulerJob_block_recurrence_monthlyOccurrences() string { - return ` +func testAccAzureRMSchedulerJob_web_recurringMonthlyOccurrences(rInt int, location string) string { + return fmt.Sprintf(`%s +resource "azurerm_scheduler_job" "test" { + name = "acctestRG-%d-job" + resource_group_name = "${azurerm_resource_group.test.name}" + job_collection_name = "${azurerm_scheduler_job_collection.test.name}" + + + action_web { + url = "https://example.com" + method = "get" + } + recurrence { frequency = "month" count = 100 monthly_occurrences = [ - { - day = "sunday" - occurrence = 1 - }, - { - day = "sunday" - occurrence = 3 - }, - { - day = "sunday" - occurrence = -1 - } - ] + { + day = "sunday" + occurrence = 1 + }, + { + day = "sunday" + occurrence = 3 + }, + { + day = "sunday" + occurrence = -1 + } + ] } -` + +}`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_recurrence_monthlyOccurrences(resourceName string) resource.TestCheckFunc { +func checkAccAzureRMSchedulerJob_web_recurringMonthlyOccurrences(resourceName string) resource.TestCheckFunc { return resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "month"), resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.#", "3"), @@ -857,145 +747,82 @@ func checkAccAzureRMSchedulerJob_recurrence_monthlyOccurrences(resourceName stri ) } -func testAccAzureRMSchedulerJob_block_retry_empty() string { - return ` - retry { - } -` -} - -func checkAccAzureRMSchedulerJob_retry_empty(resourceName string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "retry.0.interval", "00:00:30"), - resource.TestCheckResourceAttr(resourceName, "retry.0.count", "4"), - ) -} +func testAccAzureRMSchedulerJob_web_errorAction(rInt int, location string) string { + return fmt.Sprintf(`%s +resource "azurerm_scheduler_job" "test" { + name = "acctestRG-%d-job" + resource_group_name = "${azurerm_resource_group.test.name}" + job_collection_name = "${azurerm_scheduler_job_collection.test.name}" -func testAccAzureRMSchedulerJob_block_retry_complete() string { - return ` - retry { - interval = "00:05:00" //5 min - count = 10 - } -` -} -func checkAccAzureRMSchedulerJob_retry_complete(resourceName string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "retry.0.interval", "00:05:00"), - resource.TestCheckResourceAttr(resourceName, "retry.0.count", "10"), - ) -} + action_web { + url = "https://example.com" + method = "get" + } -func testAccAzureRMSchedulerJob_block_actionWeb_basic(blockName string) string { - //need a valid URL here otherwise on a slow connection job might fault before the test check - return fmt.Sprintf(` - %s { - url = "http://example.com" + error_action_web { + url = "https://example.com" method = "get" - } -`, blockName) + } + +}`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_web_basic(resourceName, blockName string) resource.TestCheckFunc { +func checkAccAzureRMSchedulerJob_web_errorAction(resourceName string) resource.TestCheckFunc { return resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.url", blockName), "http://example.com"), + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + resource.TestCheckResourceAttr(resourceName, "error_action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "error_action_web.0.method", "get"), ) } -func testAccAzureRMSchedulerJob_block_actionWeb_put(blockName string) string { - return fmt.Sprintf(` - %s { +func testAccAzureRMSchedulerJob_web_complete(rInt int, location, time string) string { + return fmt.Sprintf(`%s +resource "azurerm_scheduler_job" "test" { + name = "acctestRG-%d-job" + resource_group_name = "${azurerm_resource_group.test.name}" + job_collection_name = "${azurerm_scheduler_job_collection.test.name}" + + + action_web { url = "http://example.com" method = "put" body = "this is some text" + headers = { - Content-Type = "text" + "Content-Type" = "text" } } -`, blockName) -} - -func checkAccAzureRMSchedulerJob_web_put(resourceName, blockName string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.url", blockName), "http://example.com"), - resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.method", blockName), "put"), - resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.body", blockName), "this is some text"), - resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.headers.%%", blockName), "1"), - ) -} - -func testAccAzureRMSchedulerJob_block_actionWeb_authBasic(blockName string) string { - return fmt.Sprintf(` - %s { - url = "https://example.com" - method = "get" - authentication_basic { - username = "login" - password = "apassword" - } - } -`, blockName) -} - -func checkAccAzureRMSchedulerJob_web_authBasic(resourceName string, blockName string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.url", blockName), "https://example.com"), - resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.method", blockName), "get"), - resource.TestCheckResourceAttr(resourceName, fmt.Sprintf("%s.0.authentication_basic.0.username", blockName), "login"), - resource.TestCheckResourceAttrSet(resourceName, fmt.Sprintf("%s.0.authentication_basic.0.password", blockName)), - ) -} - -func testAccAzureRMSchedulerJob_block_actionWeb_authCert() string { - return ` - action_web { - url = "https://example.com" - method = "get" - - authentication_certificate { - pfx = "${base64encode(file("testdata/application_gateway_test.pfx"))}" - password = "terraform" - } - } -` -} + retry { + interval = "00:05:00" //5 min + count = 10 + } -func checkAccAzureRMSchedulerJob_web_authCert(resourceName string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), - resource.TestCheckResourceAttrSet(resourceName, "action_web.0.authentication_certificate.0.pfx"), - resource.TestCheckResourceAttrSet(resourceName, "action_web.0.authentication_certificate.0.password"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_certificate.0.thumbprint", "42C107874FD0E4A9583292A2F1098E8FE4B2EDDA"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_certificate.0.subject_name", "CN=Terraform App Gateway, OU=Azure, O=Terraform Tests, S=Some-State, C=US"), - ) -} + recurrence { + frequency = "month" + count = 100 + month_days = [-11,-1,1,11] + } -func testAccAzureRMSchedulerJob_block_actionWeb_authAd(tenantId, clientId, secret string) string { - return fmt.Sprintf(` - action_web { - url = "https://example.com" - method = "get" + start_time = "%s" - authentication_active_directory { - tenant_id = "%s" - client_id = "%s" - secret = "%s" - audience = "https://management.core.windows.net/" - } - } -`, tenantId, clientId, secret) +}`, testAccAzureRMSchedulerJob_template(rInt, location), rInt, time) } -func checkAccAzureRMSchedulerJob_web_authAd(resourceName, tenantId, clientId string) resource.TestCheckFunc { +func checkAccAzureRMSchedulerJob_web_complete(resourceName, time string) resource.TestCheckFunc { return resource.ComposeAggregateTestCheckFunc( - resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_active_directory.0.tenant_id", tenantId), - resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_active_directory.0.client_id", clientId), - resource.TestCheckResourceAttrSet(resourceName, "action_web.0.authentication_active_directory.0.secret"), - resource.TestCheckResourceAttrSet(resourceName, "action_web.0.authentication_active_directory.0.audience"), + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "http://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "put"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.body", "this is some text"), + resource.TestCheckResourceAttr(resourceName, "retry.0.interval", "00:05:00"), + resource.TestCheckResourceAttr(resourceName, "retry.0.count", "10"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "month"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.month_days.#", "4"), + resource.TestCheckResourceAttr(resourceName, "start_time", time), ) } diff --git a/examples/scheduler-jobs/main.tf b/examples/scheduler-jobs/main.tf index 791a99110f1d..d54280ea29ed 100644 --- a/examples/scheduler-jobs/main.tf +++ b/examples/scheduler-jobs/main.tf @@ -25,7 +25,8 @@ resource "azurerm_scheduler_job" "web-once-now" { state = "enabled" action_web { - url = "http://example.com" + url = "http://example.com" + method = "get" } retry { diff --git a/examples/scheduler-jobs/outputs.tf b/examples/scheduler-jobs/outputs.tf index c09ef605928d..f8ed3606c353 100644 --- a/examples/scheduler-jobs/outputs.tf +++ b/examples/scheduler-jobs/outputs.tf @@ -6,18 +6,3 @@ output "job-web-once-url" { value = "${azurerm_scheduler_job.web-once-now.action_web.0.url}" } -output "job-web-once-count" { - value = "${azurerm_scheduler_job.web-once-now.execution_count}" -} - -output "job-web-recurring_weekly-authCert_thumb" { - value = "${azurerm_scheduler_job.web-recurring_weekly-auth_cert.action_web.0.authentication_certificate.0.thumbprint}" -} - -output "job-web-recurring_weekly-authCert_expire" { - value = "${azurerm_scheduler_job.web-recurring_weekly-auth_cert.action_web.0.authentication_certificate.0.expiration}" -} - -output "job-web-recurring_weekly-authCert_san" { - value = "${azurerm_scheduler_job.web-recurring_weekly-auth_cert.action_web.0.authentication_certificate.0.subject_name}" -} diff --git a/website/docs/r/scheduler_job.html.markdown b/website/docs/r/scheduler_job.html.markdown index 17245d180175..ffbc39deedb9 100644 --- a/website/docs/r/scheduler_job.html.markdown +++ b/website/docs/r/scheduler_job.html.markdown @@ -89,7 +89,7 @@ resource "azurerm_scheduler_job" "web-recurring-daily" { body = "The job failed" headers = { - Content-Type = "text" + "Content-Type" = "text" } authentication_basic { @@ -135,11 +135,11 @@ The following arguments are supported: * `error_action_web` - (Optional) A `error_action_web` block defining the action to take on an error as described below. Note this is identical to an `action_web` block. -* `retry` - (Optional) A `retry` block defining how to retry as described below. Omitting this block defaults to no retry. +* `retry` - (Optional) A `retry` block defining how to retry as described below. -* `recurrence` - (Optional) A `recurrence` block defining a job occurrence schedule. Omitting this block causes the job to run just once. +* `recurrence` - (Optional) A `recurrence` block defining a job occurrence schedule. -* `start_time` - (Optional) The time the first instance of the job is to start running at. Omitting this causes the job to start now. +* `start_time` - (Optional) The time the first instance of the job is to start running at. * `state` - (Optional) The sets or gets the current state of the job. Can be set to either `Enabled` or `Completed` @@ -150,9 +150,9 @@ The following arguments are supported: * `method` - (Optional) Specifies the method of the request. Defaults to `Get` and must be one of `Get`, `Put`, `Post`, `Delete`. * `body` - (Optional) Specifies the request body. * `headers` - (Optional) A map specifying the headers sent with the request. -* `authentication_basic` - (Optional) A `authentication_basic` block allowing HTTP basic authentication to be used. -* `authentication_certificate` - (Optional) A `authentication_certificate` block allowing a client certificate information to be used for authentication. -* `authentication_active_directory` - (Optional) A `authentication_active_directory` block to configure OAUTH Active Directory authentication. +* `authentication_basic` - (Optional) An `authentication_active_directory` block which defines the Active Directory oauth configuration to use. +* `authentication_certificate` - (Optional) An `authentication_certificate` block which defines the client certificate information to be use. +* `authentication_active_directory` - (Optional) An `authentication_active_directory` block which defines the OAUTH Active Directory information to use. `authentication_basic` block supports the following: From 9836428148223283c5df1799f037acf4d6546665 Mon Sep 17 00:00:00 2001 From: kt Date: Mon, 25 Jun 2018 10:03:58 -0700 Subject: [PATCH 13/18] scheduler job - minor fix to tests --- azurerm/resource_arm_scheduler_job_test.go | 33 ++++++++++++---------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/azurerm/resource_arm_scheduler_job_test.go b/azurerm/resource_arm_scheduler_job_test.go index 1f2d0d83443d..889288818f23 100644 --- a/azurerm/resource_arm_scheduler_job_test.go +++ b/azurerm/resource_arm_scheduler_job_test.go @@ -12,8 +12,8 @@ import ( ) func TestAccAzureRMSchedulerJob_web_basic(t *testing.T) { - ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" + ri := acctest.RandInt() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -34,8 +34,8 @@ func TestAccAzureRMSchedulerJob_web_basic(t *testing.T) { } func TestAccAzureRMSchedulerJob_web_put(t *testing.T) { - ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" + ri := acctest.RandInt() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -56,8 +56,8 @@ func TestAccAzureRMSchedulerJob_web_put(t *testing.T) { } func TestAccAzureRMSchedulerJob_web_authBasic(t *testing.T) { - ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" + ri := acctest.RandInt() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -79,8 +79,8 @@ func TestAccAzureRMSchedulerJob_web_authBasic(t *testing.T) { } func TestAccAzureRMSchedulerJob_web_authCert(t *testing.T) { - ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" + ri := acctest.RandInt() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -105,14 +105,17 @@ func TestAccAzureRMSchedulerJob_web_authCert(t *testing.T) { } func TestAccAzureRMSchedulerJob_web_authAd(t *testing.T) { - ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" + ri := acctest.RandInt() clientId := os.Getenv("ARM_CLIENT_ID") tenantId := os.Getenv("ARM_TENANT_ID") secret := os.Getenv("ARM_CLIENT_SECRET") - audiance := testAccProvider.Meta().(*ArmClient).environment.ServiceManagementEndpoint + audience := "" + if os.Getenv(resource.TestEnvVar) != "" { + audience = testAccProvider.Meta().(*ArmClient).environment.ServiceManagementEndpoint + } resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -120,7 +123,7 @@ func TestAccAzureRMSchedulerJob_web_authAd(t *testing.T) { CheckDestroy: testCheckAzureRMSchedulerJobDestroy, Steps: []resource.TestStep{ { - Config: testAccAzureRMSchedulerJob_web_authAd(ri, testLocation(), tenantId, clientId, secret, audiance), + Config: testAccAzureRMSchedulerJob_web_authAd(ri, testLocation(), tenantId, clientId, secret, audience), Check: checkAccAzureRMSchedulerJob_web_authAd(resourceName, tenantId, clientId), }, { @@ -134,8 +137,8 @@ func TestAccAzureRMSchedulerJob_web_authAd(t *testing.T) { } func TestAccAzureRMSchedulerJob_web_retry(t *testing.T) { - ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" + ri := acctest.RandInt() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -156,8 +159,8 @@ func TestAccAzureRMSchedulerJob_web_retry(t *testing.T) { } func TestAccAzureRMSchedulerJob_web_recurring(t *testing.T) { - ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" + ri := acctest.RandInt() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -178,8 +181,8 @@ func TestAccAzureRMSchedulerJob_web_recurring(t *testing.T) { } func TestAccAzureRMSchedulerJob_web_recurringDaily(t *testing.T) { - ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" + ri := acctest.RandInt() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -200,8 +203,8 @@ func TestAccAzureRMSchedulerJob_web_recurringDaily(t *testing.T) { } func TestAccAzureRMSchedulerJob_web_recurringWeekly(t *testing.T) { - ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" + ri := acctest.RandInt() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -222,8 +225,8 @@ func TestAccAzureRMSchedulerJob_web_recurringWeekly(t *testing.T) { } func TestAccAzureRMSchedulerJob_web_recurringMonthly(t *testing.T) { - ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" + ri := acctest.RandInt() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -244,8 +247,8 @@ func TestAccAzureRMSchedulerJob_web_recurringMonthly(t *testing.T) { } func TestAccAzureRMSchedulerJob_web_recurringMonthlyOccurrences(t *testing.T) { - ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" + ri := acctest.RandInt() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -266,8 +269,8 @@ func TestAccAzureRMSchedulerJob_web_recurringMonthlyOccurrences(t *testing.T) { } func TestAccAzureRMSchedulerJob_web_errorAction(t *testing.T) { - ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" + ri := acctest.RandInt() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -288,8 +291,8 @@ func TestAccAzureRMSchedulerJob_web_errorAction(t *testing.T) { } func TestAccAzureRMSchedulerJob_web_complete(t *testing.T) { - ri := acctest.RandInt() resourceName := "azurerm_scheduler_job.test" + ri := acctest.RandInt() resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, From 770beb3b04e54bdafd20ac5618f5d5cb8fdc8710 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 3 Jul 2018 13:28:22 +0200 Subject: [PATCH 14/18] Adding tests for the validation functions --- azurerm/helpers/validate/validate.go | 13 +++++-- azurerm/helpers/validate/validate_test.go | 44 +++++++++++++++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/azurerm/helpers/validate/validate.go b/azurerm/helpers/validate/validate.go index 1faad3ad7754..1fde2d3a9e01 100644 --- a/azurerm/helpers/validate/validate.go +++ b/azurerm/helpers/validate/validate.go @@ -4,6 +4,8 @@ import ( "fmt" "net/url" + "strings" + "github.com/hashicorp/terraform/helper/schema" ) @@ -51,12 +53,19 @@ func UrlWithScheme(validSchemes []string) schema.SchemaValidateFunc { errors = append(errors, fmt.Errorf("%q url has no host: %q", k, url)) } + found := false for _, s := range validSchemes { - if url.Scheme == s { - return //last check so just return + if strings.EqualFold(url.Scheme, s) { + found = true + break } } + if !found { + schemes := strings.Join(validSchemes, ",") + errors = append(errors, fmt.Errorf("URL scheme %q isn't valid - supported scheme's are %q", url.Scheme, schemes)) + } + return } } diff --git a/azurerm/helpers/validate/validate_test.go b/azurerm/helpers/validate/validate_test.go index 77fb273799a5..4011884c879f 100644 --- a/azurerm/helpers/validate/validate_test.go +++ b/azurerm/helpers/validate/validate_test.go @@ -1 +1,45 @@ package validate + +import "testing" + +func TestUrlWithScheme(t *testing.T) { + validSchemes := []string{"example"} + testCases := []struct { + Url string + ShouldHaveError bool + }{ + { + Url: "example://mysite.com", + ShouldHaveError: false, + }, + { + Url: "http://mysite.com", + ShouldHaveError: true, + }, + { + Url: "example://", + ShouldHaveError: true, + }, + { + Url: "example://validhost", + ShouldHaveError: false, + }, + } + + t.Run("TestUrlWithScheme", func(t *testing.T) { + for _, v := range testCases { + _, errors := UrlWithScheme(validSchemes)(v.Url, "field_name") + + hasErrors := len(errors) > 0 + if v.ShouldHaveError && !hasErrors { + t.Fatalf("Expected an error but didn't get one for %q", v.Url) + return + } + + if !v.ShouldHaveError && hasErrors { + t.Fatalf("Expected %q to return no errors, but got some %+v", v.Url, errors) + return + } + } + }) +} From f32ecc08a5fbcf9a0757d368cdc58cb858799b2c Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 3 Jul 2018 13:50:04 +0200 Subject: [PATCH 15/18] inline-ing the check methods --- azurerm/resource_arm_scheduler_job_test.go | 266 +++++++++------------ examples/scheduler-jobs/main.tf | 2 +- 2 files changed, 108 insertions(+), 160 deletions(-) diff --git a/azurerm/resource_arm_scheduler_job_test.go b/azurerm/resource_arm_scheduler_job_test.go index 889288818f23..2c94da22a436 100644 --- a/azurerm/resource_arm_scheduler_job_test.go +++ b/azurerm/resource_arm_scheduler_job_test.go @@ -22,7 +22,11 @@ func TestAccAzureRMSchedulerJob_web_basic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAzureRMSchedulerJob_web_basic(ri, testLocation()), - Check: checkAccAzureRMSchedulerJob_web_basic(resourceName), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "http://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + ), }, { ResourceName: resourceName, @@ -44,7 +48,12 @@ func TestAccAzureRMSchedulerJob_web_put(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAzureRMSchedulerJob_web_put(ri, testLocation()), - Check: checkAccAzureRMSchedulerJob_web_put(resourceName), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "http://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "put"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.body", "this is some text"), + ), }, { ResourceName: resourceName, @@ -66,7 +75,12 @@ func TestAccAzureRMSchedulerJob_web_authBasic(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAzureRMSchedulerJob_web_authBasic(ri, testLocation()), - Check: checkAccAzureRMSchedulerJob_web_authBasic(resourceName), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_basic.0.username", "login"), + ), }, { ResourceName: resourceName, @@ -89,7 +103,13 @@ func TestAccAzureRMSchedulerJob_web_authCert(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAzureRMSchedulerJob_web_authCert(ri, testLocation()), - Check: checkAccAzureRMSchedulerJob_web_authCert(resourceName), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_certificate.0.thumbprint", "42C107874FD0E4A9583292A2F1098E8FE4B2EDDA"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_certificate.0.subject_name", "CN=Terraform App Gateway, OU=Azure, O=Terraform Tests, S=Some-State, C=US"), + ), }, { ResourceName: resourceName, @@ -124,7 +144,14 @@ func TestAccAzureRMSchedulerJob_web_authAd(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAzureRMSchedulerJob_web_authAd(ri, testLocation(), tenantId, clientId, secret, audience), - Check: checkAccAzureRMSchedulerJob_web_authAd(resourceName, tenantId, clientId), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_active_directory.0.tenant_id", tenantId), + resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_active_directory.0.client_id", clientId), + resource.TestCheckResourceAttrSet(resourceName, "action_web.0.authentication_active_directory.0.audience"), + ), }, { ResourceName: resourceName, @@ -147,7 +174,13 @@ func TestAccAzureRMSchedulerJob_web_retry(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAzureRMSchedulerJob_web_retry(ri, testLocation()), - Check: checkAccAzureRMSchedulerJob_web_retry(resourceName), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + resource.TestCheckResourceAttr(resourceName, "retry.0.interval", "00:05:00"), + resource.TestCheckResourceAttr(resourceName, "retry.0.count", "10"), + ), }, { ResourceName: resourceName, @@ -169,7 +202,14 @@ func TestAccAzureRMSchedulerJob_web_recurring(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAzureRMSchedulerJob_web_recurring(ri, testLocation()), - Check: checkAccAzureRMSchedulerJob_web_recurring(resourceName), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "minute"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.interval", "5"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "10"), + ), }, { ResourceName: resourceName, @@ -191,7 +231,15 @@ func TestAccAzureRMSchedulerJob_web_recurringDaily(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAzureRMSchedulerJob_web_recurringDaily(ri, testLocation()), - Check: checkAccAzureRMSchedulerJob_web_recurringDaily(resourceName), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "day"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.hours.#", "2"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.minutes.#", "4"), + ), }, { ResourceName: resourceName, @@ -213,7 +261,14 @@ func TestAccAzureRMSchedulerJob_web_recurringWeekly(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAzureRMSchedulerJob_web_recurringWeekly(ri, testLocation()), - Check: checkAccAzureRMSchedulerJob_web_recurringWeekly(resourceName), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "week"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.week_days.#", "2"), + ), }, { ResourceName: resourceName, @@ -235,7 +290,14 @@ func TestAccAzureRMSchedulerJob_web_recurringMonthly(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAzureRMSchedulerJob_web_recurringMonthly(ri, testLocation()), - Check: checkAccAzureRMSchedulerJob_web_recurringMonthly(resourceName), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "month"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.month_days.#", "4"), + ), }, { ResourceName: resourceName, @@ -257,7 +319,20 @@ func TestAccAzureRMSchedulerJob_web_recurringMonthlyOccurrences(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAzureRMSchedulerJob_web_recurringMonthlyOccurrences(ri, testLocation()), - Check: checkAccAzureRMSchedulerJob_web_recurringMonthlyOccurrences(resourceName), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "month"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.#", "3"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.2181640481.day", "sunday"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.2181640481.occurrence", "1"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.2956940195.day", "sunday"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.2956940195.occurrence", "3"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.679325150.day", "sunday"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.679325150.occurrence", "-1"), + ), }, { ResourceName: resourceName, @@ -279,7 +354,13 @@ func TestAccAzureRMSchedulerJob_web_errorAction(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAzureRMSchedulerJob_web_errorAction(ri, testLocation()), - Check: checkAccAzureRMSchedulerJob_web_errorAction(resourceName), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), + resource.TestCheckResourceAttr(resourceName, "error_action_web.0.url", "https://example.com"), + resource.TestCheckResourceAttr(resourceName, "error_action_web.0.method", "get"), + ), }, { ResourceName: resourceName, @@ -301,7 +382,18 @@ func TestAccAzureRMSchedulerJob_web_complete(t *testing.T) { Steps: []resource.TestStep{ { Config: testAccAzureRMSchedulerJob_web_complete(ri, testLocation(), "2019-07-07T07:07:07-07:00"), - Check: checkAccAzureRMSchedulerJob_web_complete(resourceName, "2019-07-07T14:07:07Z"), + Check: resource.ComposeAggregateTestCheckFunc( + testCheckAzureRMSchedulerJobExists(resourceName), + resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "http://example.com"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "put"), + resource.TestCheckResourceAttr(resourceName, "action_web.0.body", "this is some text"), + resource.TestCheckResourceAttr(resourceName, "retry.0.interval", "00:05:00"), + resource.TestCheckResourceAttr(resourceName, "retry.0.count", "10"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "month"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), + resource.TestCheckResourceAttr(resourceName, "recurrence.0.month_days.#", "4"), + resource.TestCheckResourceAttr(resourceName, "start_time", "2019-07-07T14:07:07Z"), + ), }, { ResourceName: resourceName, @@ -404,14 +496,6 @@ resource "azurerm_scheduler_job" "test" { }`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_web_basic(resourceName string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - testCheckAzureRMSchedulerJobExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "http://example.com"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), - ) -} - func testAccAzureRMSchedulerJob_web_put(rInt int, location string) string { return fmt.Sprintf(`%s resource "azurerm_scheduler_job" "test" { @@ -427,20 +511,11 @@ resource "azurerm_scheduler_job" "test" { headers = { "Content-Type" = "text" - } + } } }`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_web_put(resourceName string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - testCheckAzureRMSchedulerJobExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "http://example.com"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "put"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.body", "this is some text"), - ) -} - func testAccAzureRMSchedulerJob_web_authBasic(rInt int, location string) string { return fmt.Sprintf(`%s resource "azurerm_scheduler_job" "test" { @@ -461,15 +536,6 @@ resource "azurerm_scheduler_job" "test" { }`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_web_authBasic(resourceName string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - testCheckAzureRMSchedulerJobExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_basic.0.username", "login"), - ) -} - func testAccAzureRMSchedulerJob_web_authCert(rInt int, location string) string { return fmt.Sprintf(`%s resource "azurerm_scheduler_job" "test" { @@ -490,16 +556,6 @@ resource "azurerm_scheduler_job" "test" { }`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_web_authCert(resourceName string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - testCheckAzureRMSchedulerJobExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_certificate.0.thumbprint", "42C107874FD0E4A9583292A2F1098E8FE4B2EDDA"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_certificate.0.subject_name", "CN=Terraform App Gateway, OU=Azure, O=Terraform Tests, S=Some-State, C=US"), - ) -} - func testAccAzureRMSchedulerJob_web_authAd(rInt int, location, tenantId, clientId, secret, audience string) string { return fmt.Sprintf(`%s resource "azurerm_scheduler_job" "test" { @@ -522,17 +578,6 @@ resource "azurerm_scheduler_job" "test" { }`, testAccAzureRMSchedulerJob_template(rInt, location), rInt, tenantId, clientId, secret, audience) } -func checkAccAzureRMSchedulerJob_web_authAd(resourceName, tenantId, clientId string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - testCheckAzureRMSchedulerJobExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_active_directory.0.tenant_id", tenantId), - resource.TestCheckResourceAttr(resourceName, "action_web.0.authentication_active_directory.0.client_id", clientId), - resource.TestCheckResourceAttrSet(resourceName, "action_web.0.authentication_active_directory.0.audience"), - ) -} - func testAccAzureRMSchedulerJob_web_retry(rInt int, location string) string { return fmt.Sprintf(`%s resource "azurerm_scheduler_job" "test" { @@ -554,16 +599,6 @@ resource "azurerm_scheduler_job" "test" { }`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_web_retry(resourceName string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - testCheckAzureRMSchedulerJobExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), - resource.TestCheckResourceAttr(resourceName, "retry.0.interval", "00:05:00"), - resource.TestCheckResourceAttr(resourceName, "retry.0.count", "10"), - ) -} - func testAccAzureRMSchedulerJob_web_recurring(rInt int, location string) string { return fmt.Sprintf(`%s resource "azurerm_scheduler_job" "test" { @@ -586,17 +621,6 @@ resource "azurerm_scheduler_job" "test" { }`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_web_recurring(resourceName string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - testCheckAzureRMSchedulerJobExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "minute"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.interval", "5"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "10"), - ) -} - func testAccAzureRMSchedulerJob_web_recurringDaily(rInt int, location string) string { return fmt.Sprintf(`%s resource "azurerm_scheduler_job" "test" { @@ -620,18 +644,6 @@ resource "azurerm_scheduler_job" "test" { }`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_web_recurringDaily(resourceName string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - testCheckAzureRMSchedulerJobExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "day"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.hours.#", "2"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.minutes.#", "4"), - ) -} - func testAccAzureRMSchedulerJob_web_recurringWeekly(rInt int, location string) string { return fmt.Sprintf(`%s resource "azurerm_scheduler_job" "test" { @@ -654,17 +666,6 @@ resource "azurerm_scheduler_job" "test" { }`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_web_recurringWeekly(resourceName string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - testCheckAzureRMSchedulerJobExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "week"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.week_days.#", "2"), - ) -} - func testAccAzureRMSchedulerJob_web_recurringMonthly(rInt int, location string) string { return fmt.Sprintf(`%s resource "azurerm_scheduler_job" "test" { @@ -687,17 +688,6 @@ resource "azurerm_scheduler_job" "test" { }`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_web_recurringMonthly(resourceName string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - testCheckAzureRMSchedulerJobExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "month"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.month_days.#", "4"), - ) -} - func testAccAzureRMSchedulerJob_web_recurringMonthlyOccurrences(rInt int, location string) string { return fmt.Sprintf(`%s resource "azurerm_scheduler_job" "test" { @@ -733,23 +723,6 @@ resource "azurerm_scheduler_job" "test" { }`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_web_recurringMonthlyOccurrences(resourceName string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - testCheckAzureRMSchedulerJobExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "month"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.#", "3"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.2181640481.day", "sunday"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.2181640481.occurrence", "1"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.2956940195.day", "sunday"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.2956940195.occurrence", "3"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.679325150.day", "sunday"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.monthly_occurrences.679325150.occurrence", "-1"), - ) -} - func testAccAzureRMSchedulerJob_web_errorAction(rInt int, location string) string { return fmt.Sprintf(`%s resource "azurerm_scheduler_job" "test" { @@ -771,16 +744,6 @@ resource "azurerm_scheduler_job" "test" { }`, testAccAzureRMSchedulerJob_template(rInt, location), rInt) } -func checkAccAzureRMSchedulerJob_web_errorAction(resourceName string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - testCheckAzureRMSchedulerJobExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "https://example.com"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "get"), - resource.TestCheckResourceAttr(resourceName, "error_action_web.0.url", "https://example.com"), - resource.TestCheckResourceAttr(resourceName, "error_action_web.0.method", "get"), - ) -} - func testAccAzureRMSchedulerJob_web_complete(rInt int, location, time string) string { return fmt.Sprintf(`%s resource "azurerm_scheduler_job" "test" { @@ -796,7 +759,7 @@ resource "azurerm_scheduler_job" "test" { headers = { "Content-Type" = "text" - } + } } retry { @@ -814,18 +777,3 @@ resource "azurerm_scheduler_job" "test" { }`, testAccAzureRMSchedulerJob_template(rInt, location), rInt, time) } - -func checkAccAzureRMSchedulerJob_web_complete(resourceName, time string) resource.TestCheckFunc { - return resource.ComposeAggregateTestCheckFunc( - testCheckAzureRMSchedulerJobExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "action_web.0.url", "http://example.com"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.method", "put"), - resource.TestCheckResourceAttr(resourceName, "action_web.0.body", "this is some text"), - resource.TestCheckResourceAttr(resourceName, "retry.0.interval", "00:05:00"), - resource.TestCheckResourceAttr(resourceName, "retry.0.count", "10"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.frequency", "month"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.count", "100"), - resource.TestCheckResourceAttr(resourceName, "recurrence.0.month_days.#", "4"), - resource.TestCheckResourceAttr(resourceName, "start_time", time), - ) -} diff --git a/examples/scheduler-jobs/main.tf b/examples/scheduler-jobs/main.tf index d54280ea29ed..f277a945b96a 100644 --- a/examples/scheduler-jobs/main.tf +++ b/examples/scheduler-jobs/main.tf @@ -34,7 +34,7 @@ resource "azurerm_scheduler_job" "web-once-now" { count = 4 } - //times in the past start imediatly and run once, + //times in the past start immediatly and run once, start_time = "1987-07-07T07:07:07-07:00" } From 184a879a33d0cdaf3df93c99ef1530a9b6974ce7 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 3 Jul 2018 13:50:31 +0200 Subject: [PATCH 16/18] Fixing the highlight in the sidebar --- website/azurerm.erb | 4 ++-- website/docs/d/scheduler_job_collection.html.markdown | 2 +- website/docs/r/scheduler_job.html.markdown | 4 ++-- website/docs/r/scheduler_job_collection.html.markdown | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/website/azurerm.erb b/website/azurerm.erb index 0c69b4a71c39..c69ade156983 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -732,12 +732,12 @@ > Scheduler Resources diff --git a/website/docs/d/scheduler_job_collection.html.markdown b/website/docs/d/scheduler_job_collection.html.markdown index 83727ba78864..896c2c7ed8aa 100644 --- a/website/docs/d/scheduler_job_collection.html.markdown +++ b/website/docs/d/scheduler_job_collection.html.markdown @@ -1,7 +1,7 @@ --- layout: "azurerm" page_title: "Azure Resource Manager: azurerm_scheduler_job_collection" -sidebar_current: "docs-azurerm-datasource-scheduler_job_collection" +sidebar_current: "docs-azurerm-datasource-scheduler-job-collection" description: |- Get information about the specified scheduler job collection. --- diff --git a/website/docs/r/scheduler_job.html.markdown b/website/docs/r/scheduler_job.html.markdown index ffbc39deedb9..94b5c4ee825a 100644 --- a/website/docs/r/scheduler_job.html.markdown +++ b/website/docs/r/scheduler_job.html.markdown @@ -1,7 +1,7 @@ --- layout: "azurerm" page_title: "Azure Resource Manager: azurerm_scheduler_job" -sidebar_current: "docs-azurerm-resource-scheduler_job +sidebar_current: "docs-azurerm-resource-scheduler-job-x description: |- Manages a Scheduler Job. --- @@ -215,5 +215,5 @@ The following attributes are exported: Scheduler Job can be imported using a `resource id`, e.g. ```shell -terraform import azurerm_search_service.service1 /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resourceGroup1/providers/Microsoft.Scheduler/jobCollections/jobCollection1/jobs/job1 +terraform import azurerm_scheduler_job.job1 /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/resourceGroup1/providers/Microsoft.Scheduler/jobCollections/jobCollection1/jobs/job1 ``` diff --git a/website/docs/r/scheduler_job_collection.html.markdown b/website/docs/r/scheduler_job_collection.html.markdown index 330b75c8800a..a717ce2865c2 100644 --- a/website/docs/r/scheduler_job_collection.html.markdown +++ b/website/docs/r/scheduler_job_collection.html.markdown @@ -1,7 +1,7 @@ --- layout: "azurerm" page_title: "Azure Resource Manager: azurerm_scheduler_job_collection" -sidebar_current: "docs-azurerm-resource-scheduler_job_collection" +sidebar_current: "docs-azurerm-resource-scheduler-job-collection" description: |- Manages a Scheduler Job Collection. --- From c1ae37ee19687509406e2ccae6f737ba1078132c Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 3 Jul 2018 13:54:46 +0200 Subject: [PATCH 17/18] Fixing merge issues --- azurerm/provider.go | 2 +- azurerm/resource_arm_scheduler_job.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/azurerm/provider.go b/azurerm/provider.go index 79caeb3b72ca..c9ad8f102de9 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -207,7 +207,7 @@ func Provider() terraform.ResourceProvider { "azurerm_servicebus_topic": resourceArmServiceBusTopic(), "azurerm_servicebus_topic_authorization_rule": resourceArmServiceBusTopicAuthorizationRule(), "azurerm_snapshot": resourceArmSnapshot(), - "azurerm_scheduler_job": resourceArmSchedulerJob(), + "azurerm_scheduler_job": resourceArmSchedulerJob(), "azurerm_scheduler_job_collection": resourceArmSchedulerJobCollection(), "azurerm_sql_database": resourceArmSqlDatabase(), "azurerm_sql_elasticpool": resourceArmSqlElasticPool(), diff --git a/azurerm/resource_arm_scheduler_job.go b/azurerm/resource_arm_scheduler_job.go index 29f8d871a677..4ecc68121598 100644 --- a/azurerm/resource_arm_scheduler_job.go +++ b/azurerm/resource_arm_scheduler_job.go @@ -139,8 +139,8 @@ func resourceArmSchedulerJob() *schema.Resource { Type: schema.TypeString, Optional: true, Computed: true, - DiffSuppressFunc: suppress.Rfc3339Time, - ValidateFunc: validate.Rfc3339Time, + DiffSuppressFunc: suppress.RFC3339Time, + ValidateFunc: validate.RFC3339Time, }, "minutes": { @@ -236,8 +236,8 @@ func resourceArmSchedulerJob() *schema.Resource { Type: schema.TypeString, Optional: true, Computed: true, //defaults to now in create function - DiffSuppressFunc: suppress.Rfc3339Time, - ValidateFunc: validate.Rfc3339Time, //times in the past just start immediately + DiffSuppressFunc: suppress.RFC3339Time, + ValidateFunc: validate.RFC3339Time, //times in the past just start immediately }, "state": { From f0a03158be1eae0623daeba70e5339521b432b99 Mon Sep 17 00:00:00 2001 From: tombuildsstuff Date: Tue, 3 Jul 2018 14:22:00 +0200 Subject: [PATCH 18/18] Fixing a crash when loading the environment --- azurerm/resource_arm_scheduler_job_test.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/azurerm/resource_arm_scheduler_job_test.go b/azurerm/resource_arm_scheduler_job_test.go index 2c94da22a436..ff5f64c1360a 100644 --- a/azurerm/resource_arm_scheduler_job_test.go +++ b/azurerm/resource_arm_scheduler_job_test.go @@ -125,6 +125,11 @@ func TestAccAzureRMSchedulerJob_web_authCert(t *testing.T) { } func TestAccAzureRMSchedulerJob_web_authAd(t *testing.T) { + if os.Getenv(resource.TestEnvVar) == "" { + t.Skipf("Skipping since %q isn't set", resource.TestEnvVar) + return + } + resourceName := "azurerm_scheduler_job.test" ri := acctest.RandInt() @@ -132,11 +137,13 @@ func TestAccAzureRMSchedulerJob_web_authAd(t *testing.T) { tenantId := os.Getenv("ARM_TENANT_ID") secret := os.Getenv("ARM_CLIENT_SECRET") - audience := "" - if os.Getenv(resource.TestEnvVar) != "" { - audience = testAccProvider.Meta().(*ArmClient).environment.ServiceManagementEndpoint + env, err := testArmEnvironment() + if err != nil { + t.Fatalf("Error loading Environment: %+v", err) + return } + audience := env.ServiceManagementEndpoint resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders,