diff --git a/azurerm/helpers/validate/datafactory.go b/azurerm/helpers/validate/datafactory.go new file mode 100644 index 000000000000..2a66b38f491a --- /dev/null +++ b/azurerm/helpers/validate/datafactory.go @@ -0,0 +1,30 @@ +package validate + +import ( + "fmt" + "regexp" + + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" +) + +func DataFactoryPipelineAndTriggerName() schema.SchemaValidateFunc { + return func(i interface{}, k string) (warnings []string, errors []error) { + value := i.(string) + if !regexp.MustCompile(`^[A-Za-z0-9_][^<>*#.%&:\\+?/]*$`).MatchString(value) { + errors = append(errors, fmt.Errorf("invalid name, see https://docs.microsoft.com/en-us/azure/data-factory/naming-rules %q: %q", k, value)) + } + + return warnings, errors + } +} + +func DataFactoryName() schema.SchemaValidateFunc { + return func(i interface{}, k string) (warnings []string, errors []error) { + value := i.(string) + if !regexp.MustCompile(`^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$`).MatchString(value) { + errors = append(errors, fmt.Errorf("invalid data_factory_name, see https://docs.microsoft.com/en-us/azure/data-factory/naming-rules %q: %q", k, value)) + } + + return warnings, errors + } +} diff --git a/azurerm/helpers/validate/datafactory_test.go b/azurerm/helpers/validate/datafactory_test.go new file mode 100644 index 000000000000..b0e05dbcfdc9 --- /dev/null +++ b/azurerm/helpers/validate/datafactory_test.go @@ -0,0 +1,57 @@ +package validate + +import "testing" + +func TestValidateDataFactoryPipelineAndTriggerName(t *testing.T) { + validNames := []string{ + "validname", + "valid02name", + "validName1", + } + for _, v := range validNames { + _, errors := DataFactoryPipelineAndTriggerName()(v, "valid") + if len(errors) != 0 { + t.Fatalf("%q should be an invalid DataFactory Pipeline or Trigger Name: %q", v, errors) + } + } + + invalidNames := []string{ + "invalid.", + ":@£", + ">invalid", + "invalid&name", + } + for _, v := range invalidNames { + _, errors := DataFactoryPipelineAndTriggerName()(v, "invalid") + if len(errors) == 0 { + t.Fatalf("%q should be an invalid DataFactory Pipeline or Trigger Name", v) + } + } +} + +func TestValidateDataFactoryName(t *testing.T) { + validNames := []string{ + "valid-name", + "valid02-name", + "validName1", + } + for _, v := range validNames { + _, errors := DataFactoryName()(v, "valid") + if len(errors) != 0 { + t.Fatalf("%q should be a valid DataFactory Name: %q", v, errors) + } + } + + invalidNames := []string{ + "invalid.", + ":@£", + ">invalid", + "invalid&name", + } + for _, v := range invalidNames { + _, errors := DataFactoryName()(v, "invalid") + if len(errors) == 0 { + t.Fatalf("%q should be an invalid DataFactory Name", v) + } + } +} diff --git a/azurerm/internal/services/datafactory/client.go b/azurerm/internal/services/datafactory/client.go index 7d0175c18413..3eb6beaead7e 100644 --- a/azurerm/internal/services/datafactory/client.go +++ b/azurerm/internal/services/datafactory/client.go @@ -11,6 +11,7 @@ type Client struct { IntegrationRuntimesClient *datafactory.IntegrationRuntimesClient LinkedServiceClient *datafactory.LinkedServicesClient PipelinesClient *datafactory.PipelinesClient + TriggersClient *datafactory.TriggersClient } func BuildClient(o *common.ClientOptions) *Client { @@ -29,11 +30,15 @@ func BuildClient(o *common.ClientOptions) *Client { PipelinesClient := datafactory.NewPipelinesClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) o.ConfigureClient(&PipelinesClient.Client, o.ResourceManagerAuthorizer) + TriggersClient := datafactory.NewTriggersClientWithBaseURI(o.ResourceManagerEndpoint, o.SubscriptionId) + o.ConfigureClient(&TriggersClient.Client, o.ResourceManagerAuthorizer) + return &Client{ DatasetClient: &DatasetClient, FactoriesClient: &FactoriesClient, IntegrationRuntimesClient: &IntegrationRuntimesClient, LinkedServiceClient: &LinkedServiceClient, PipelinesClient: &PipelinesClient, + TriggersClient: &TriggersClient, } } diff --git a/azurerm/provider.go b/azurerm/provider.go index 4c401680c0fa..3f7309caea2f 100644 --- a/azurerm/provider.go +++ b/azurerm/provider.go @@ -242,6 +242,7 @@ func Provider() terraform.ResourceProvider { "azurerm_data_factory_linked_service_postgresql": resourceArmDataFactoryLinkedServicePostgreSQL(), "azurerm_data_factory_linked_service_sql_server": resourceArmDataFactoryLinkedServiceSQLServer(), "azurerm_data_factory_pipeline": resourceArmDataFactoryPipeline(), + "azurerm_data_factory_trigger_schedule": resourceArmDataFactoryTriggerSchedule(), "azurerm_data_lake_analytics_account": resourceArmDataLakeAnalyticsAccount(), "azurerm_data_lake_analytics_firewall_rule": resourceArmDataLakeAnalyticsFirewallRule(), "azurerm_data_lake_store_file": resourceArmDataLakeStoreFile(), diff --git a/azurerm/resource_arm_data_factory.go b/azurerm/resource_arm_data_factory.go index a43642a62a52..8a4d95852efc 100644 --- a/azurerm/resource_arm_data_factory.go +++ b/azurerm/resource_arm_data_factory.go @@ -2,7 +2,6 @@ package azurerm import ( "fmt" - "regexp" "time" "github.com/Azure/azure-sdk-for-go/services/datafactory/mgmt/2018-06-01/datafactory" @@ -37,13 +36,10 @@ func resourceArmDataFactory() *schema.Resource { Schema: map[string]*schema.Schema{ "name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringMatch( - regexp.MustCompile(`^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$`), - `Invalid name for Data Factory, see https://docs.microsoft.com/en-us/azure/data-factory/naming-rules`, - ), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.DataFactoryName(), }, "location": azure.SchemaLocation(), diff --git a/azurerm/resource_arm_data_factory_dataset_mysql.go b/azurerm/resource_arm_data_factory_dataset_mysql.go index 5e8932982ef5..0720a1506c1a 100644 --- a/azurerm/resource_arm_data_factory_dataset_mysql.go +++ b/azurerm/resource_arm_data_factory_dataset_mysql.go @@ -3,7 +3,6 @@ package azurerm import ( "fmt" "log" - "regexp" "time" "github.com/Azure/azure-sdk-for-go/services/datafactory/mgmt/2018-06-01/datafactory" @@ -44,13 +43,10 @@ func resourceArmDataFactoryDatasetMySQL() *schema.Resource { }, "data_factory_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringMatch( - regexp.MustCompile(`^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$`), - `Invalid name for Data Factory, see https://docs.microsoft.com/en-us/azure/data-factory/naming-rules`, - ), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.DataFactoryName(), }, // There's a bug in the Azure API where this is returned in lower-case diff --git a/azurerm/resource_arm_data_factory_dataset_postgresql.go b/azurerm/resource_arm_data_factory_dataset_postgresql.go index c7cf88814656..9e2735ae0fcf 100644 --- a/azurerm/resource_arm_data_factory_dataset_postgresql.go +++ b/azurerm/resource_arm_data_factory_dataset_postgresql.go @@ -3,7 +3,6 @@ package azurerm import ( "fmt" "log" - "regexp" "time" "github.com/Azure/azure-sdk-for-go/services/datafactory/mgmt/2018-06-01/datafactory" @@ -44,13 +43,10 @@ func resourceArmDataFactoryDatasetPostgreSQL() *schema.Resource { }, "data_factory_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringMatch( - regexp.MustCompile(`^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$`), - `Invalid name for Data Factory, see https://docs.microsoft.com/en-us/azure/data-factory/naming-rules`, - ), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.DataFactoryName(), }, // There's a bug in the Azure API where this is returned in lower-case diff --git a/azurerm/resource_arm_data_factory_dataset_sql_server_table.go b/azurerm/resource_arm_data_factory_dataset_sql_server_table.go index 137f1135dd2e..80a88cabffd9 100644 --- a/azurerm/resource_arm_data_factory_dataset_sql_server_table.go +++ b/azurerm/resource_arm_data_factory_dataset_sql_server_table.go @@ -3,7 +3,6 @@ package azurerm import ( "fmt" "log" - "regexp" "time" "github.com/Azure/azure-sdk-for-go/services/datafactory/mgmt/2018-06-01/datafactory" @@ -44,13 +43,10 @@ func resourceArmDataFactoryDatasetSQLServerTable() *schema.Resource { }, "data_factory_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringMatch( - regexp.MustCompile(`^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$`), - `Invalid name for Data Factory, see https://docs.microsoft.com/en-us/azure/data-factory/naming-rules`, - ), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.DataFactoryName(), }, // There's a bug in the Azure API where this is returned in lower-case diff --git a/azurerm/resource_arm_data_factory_integration_runtime_managed.go b/azurerm/resource_arm_data_factory_integration_runtime_managed.go index 84e4b034f4bc..e07811b61196 100644 --- a/azurerm/resource_arm_data_factory_integration_runtime_managed.go +++ b/azurerm/resource_arm_data_factory_integration_runtime_managed.go @@ -42,13 +42,10 @@ func resourceArmDataFactoryIntegrationRuntimeManaged() *schema.Resource { }, "data_factory_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringMatch( - regexp.MustCompile(`^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$`), - `Invalid name for Data Factory, see https://docs.microsoft.com/en-us/azure/data-factory/naming-rules`, - ), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.DataFactoryName(), }, "resource_group_name": azure.SchemaResourceGroupName(), diff --git a/azurerm/resource_arm_data_factory_linked_service_data_lake_storage_gen2.go b/azurerm/resource_arm_data_factory_linked_service_data_lake_storage_gen2.go index 3b6346b5acea..fb5cdb6b6ef1 100644 --- a/azurerm/resource_arm_data_factory_linked_service_data_lake_storage_gen2.go +++ b/azurerm/resource_arm_data_factory_linked_service_data_lake_storage_gen2.go @@ -2,12 +2,10 @@ package azurerm import ( "fmt" - "regexp" "time" "github.com/Azure/azure-sdk-for-go/services/datafactory/mgmt/2018-06-01/datafactory" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" @@ -43,13 +41,10 @@ func resourceArmDataFactoryLinkedServiceDataLakeStorageGen2() *schema.Resource { }, "data_factory_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringMatch( - regexp.MustCompile(`^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$`), - `Invalid name for Data Factory, see https://docs.microsoft.com/en-us/azure/data-factory/naming-rules`, - ), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.DataFactoryName(), }, // There's a bug in the Azure API where this is returned in lower-case diff --git a/azurerm/resource_arm_data_factory_linked_service_mysql.go b/azurerm/resource_arm_data_factory_linked_service_mysql.go index 45fd46c09aa3..b1eebd597535 100644 --- a/azurerm/resource_arm_data_factory_linked_service_mysql.go +++ b/azurerm/resource_arm_data_factory_linked_service_mysql.go @@ -2,12 +2,10 @@ package azurerm import ( "fmt" - "regexp" "time" "github.com/Azure/azure-sdk-for-go/services/datafactory/mgmt/2018-06-01/datafactory" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" @@ -43,13 +41,10 @@ func resourceArmDataFactoryLinkedServiceMySQL() *schema.Resource { }, "data_factory_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringMatch( - regexp.MustCompile(`^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$`), - `Invalid name for Data Factory, see https://docs.microsoft.com/en-us/azure/data-factory/naming-rules`, - ), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.DataFactoryName(), }, // There's a bug in the Azure API where this is returned in lower-case diff --git a/azurerm/resource_arm_data_factory_linked_service_postgresql.go b/azurerm/resource_arm_data_factory_linked_service_postgresql.go index bf0559875f26..110510f7673b 100644 --- a/azurerm/resource_arm_data_factory_linked_service_postgresql.go +++ b/azurerm/resource_arm_data_factory_linked_service_postgresql.go @@ -2,12 +2,10 @@ package azurerm import ( "fmt" - "regexp" "time" "github.com/Azure/azure-sdk-for-go/services/datafactory/mgmt/2018-06-01/datafactory" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" @@ -43,13 +41,10 @@ func resourceArmDataFactoryLinkedServicePostgreSQL() *schema.Resource { }, "data_factory_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringMatch( - regexp.MustCompile(`^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$`), - `Invalid name for Data Factory, see https://docs.microsoft.com/en-us/azure/data-factory/naming-rules`, - ), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.DataFactoryName(), }, // There's a bug in the Azure API where this is returned in lower-case diff --git a/azurerm/resource_arm_data_factory_linked_service_sql_server.go b/azurerm/resource_arm_data_factory_linked_service_sql_server.go index ef22a2f16a94..ec236aff6e0e 100644 --- a/azurerm/resource_arm_data_factory_linked_service_sql_server.go +++ b/azurerm/resource_arm_data_factory_linked_service_sql_server.go @@ -3,12 +3,10 @@ package azurerm import ( "fmt" "log" - "regexp" "time" "github.com/Azure/azure-sdk-for-go/services/datafactory/mgmt/2018-06-01/datafactory" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" @@ -44,13 +42,10 @@ func resourceArmDataFactoryLinkedServiceSQLServer() *schema.Resource { }, "data_factory_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringMatch( - regexp.MustCompile(`^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$`), - `Invalid name for Data Factory, see https://docs.microsoft.com/en-us/azure/data-factory/naming-rules`, - ), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.DataFactoryName(), }, // There's a bug in the Azure API where this is returned in lower-case diff --git a/azurerm/resource_arm_data_factory_pipeline.go b/azurerm/resource_arm_data_factory_pipeline.go index a1f7cce34473..5f63b0f3b32b 100644 --- a/azurerm/resource_arm_data_factory_pipeline.go +++ b/azurerm/resource_arm_data_factory_pipeline.go @@ -3,14 +3,13 @@ package azurerm import ( "fmt" "log" - "regexp" "time" "github.com/Azure/azure-sdk-for-go/services/datafactory/mgmt/2018-06-01/datafactory" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" - "github.com/hashicorp/terraform-plugin-sdk/helper/validation" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" @@ -38,17 +37,14 @@ func resourceArmDataFactoryPipeline() *schema.Resource { Type: schema.TypeString, Required: true, ForceNew: true, - ValidateFunc: validateAzureRMDataFactoryPipelineName, + ValidateFunc: validate.DataFactoryPipelineAndTriggerName(), }, "data_factory_name": { - Type: schema.TypeString, - Required: true, - ForceNew: true, - ValidateFunc: validation.StringMatch( - regexp.MustCompile(`^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$`), - `Invalid data_factory_name, see https://docs.microsoft.com/en-us/azure/data-factory/naming-rules`, - ), + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.DataFactoryName(), }, // There's a bug in the Azure API where this is returned in lower-case @@ -215,12 +211,3 @@ func resourceArmDataFactoryPipelineDelete(d *schema.ResourceData, meta interface return nil } - -func validateAzureRMDataFactoryPipelineName(v interface{}, k string) (warnings []string, errors []error) { - value := v.(string) - if regexp.MustCompile(`^[.+?/<>*%&:\\]+$`).MatchString(value) { - errors = append(errors, fmt.Errorf("any of '.', '+', '?', '/', '<', '>', '*', '%%', '&', ':', '\\', are not allowed in %q: %q", k, value)) - } - - return warnings, errors -} diff --git a/azurerm/resource_arm_data_factory_trigger_schedule.go b/azurerm/resource_arm_data_factory_trigger_schedule.go new file mode 100644 index 000000000000..3b31d673b6f3 --- /dev/null +++ b/azurerm/resource_arm_data_factory_trigger_schedule.go @@ -0,0 +1,287 @@ +package azurerm + +import ( + "fmt" + "log" + "time" + + "github.com/Azure/azure-sdk-for-go/services/datafactory/mgmt/2018-06-01/datafactory" + "github.com/Azure/go-autorest/autorest/date" + "github.com/hashicorp/terraform-plugin-sdk/helper/schema" + "github.com/hashicorp/terraform-plugin-sdk/helper/validation" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/azure" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/suppress" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/validate" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/features" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/internal/timeouts" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func resourceArmDataFactoryTriggerSchedule() *schema.Resource { + return &schema.Resource{ + Create: resourceArmDataFactoryTriggerScheduleCreateUpdate, + Read: resourceArmDataFactoryTriggerScheduleRead, + Update: resourceArmDataFactoryTriggerScheduleCreateUpdate, + Delete: resourceArmDataFactoryTriggerScheduleDelete, + Importer: &schema.ResourceImporter{ + State: schema.ImportStatePassthrough, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(30 * time.Minute), + Read: schema.DefaultTimeout(5 * time.Minute), + Update: schema.DefaultTimeout(30 * time.Minute), + Delete: schema.DefaultTimeout(30 * time.Minute), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.DataFactoryPipelineAndTriggerName(), + }, + + // There's a bug in the Azure API where this is returned in lower-case + // BUG: https://github.com/Azure/azure-rest-api-specs/issues/5788 + "resource_group_name": azure.SchemaResourceGroupNameDiffSuppress(), + + "data_factory_name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + ValidateFunc: validate.DataFactoryName(), + }, + + // This time can only be represented in UTC. + // An issue has been filed in the SDK for the timezone attribute that doesn't seem to work + // https://github.com/Azure/azure-sdk-for-go/issues/6244 + "start_time": { + Type: schema.TypeString, + Optional: true, + Computed: true, + DiffSuppressFunc: suppress.RFC3339Time, + ValidateFunc: validate.RFC3339Time, //times in the past just start immediately + }, + + // This time can only be represented in UTC. + // An issue has been filed in the SDK for the timezone attribute that doesn't seem to work + // https://github.com/Azure/azure-sdk-for-go/issues/6244 + "end_time": { + Type: schema.TypeString, + Optional: true, + DiffSuppressFunc: suppress.RFC3339Time, + ValidateFunc: validate.RFC3339Time, //times in the past just start immediately + }, + + "frequency": { + Type: schema.TypeString, + Optional: true, + Default: string(datafactory.Minute), + ValidateFunc: validation.StringInSlice([]string{ + string(datafactory.Minute), + string(datafactory.Hour), + string(datafactory.Day), + string(datafactory.Week), + string(datafactory.Month), + }, false), + }, + + "interval": { + Type: schema.TypeInt, + Optional: true, + Default: 1, + ValidateFunc: validation.IntAtLeast(1), + }, + + "pipeline_name": { + Type: schema.TypeString, + Required: true, + ValidateFunc: validate.DataFactoryPipelineAndTriggerName(), + }, + + "pipeline_parameters": { + Type: schema.TypeMap, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + + "annotations": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + ValidateFunc: validate.NoEmptyStrings, + }, + }, + }, + } +} + +func resourceArmDataFactoryTriggerScheduleCreateUpdate(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).DataFactory.TriggersClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*ArmClient).StopContext, d) + defer cancel() + + log.Printf("[INFO] preparing arguments for Data Factory Trigger Schedule creation.") + + resourceGroupName := d.Get("resource_group_name").(string) + triggerName := d.Get("name").(string) + dataFactoryName := d.Get("data_factory_name").(string) + + if features.ShouldResourcesBeImported() && d.IsNewResource() { + existing, err := client.Get(ctx, resourceGroupName, dataFactoryName, triggerName, "") + if err != nil { + if !utils.ResponseWasNotFound(existing.Response) { + return fmt.Errorf("Error checking for presence of existing Data Factory Trigger Schedule %q (Resource Group %q / Data Factory %q): %s", triggerName, resourceGroupName, dataFactoryName, err) + } + } + + if existing.ID != nil && *existing.ID != "" { + return tf.ImportAsExistsError("azurerm_data_factory_trigger_schedule", *existing.ID) + } + } + + props := &datafactory.ScheduleTriggerTypeProperties{ + Recurrence: &datafactory.ScheduleTriggerRecurrence{ + Frequency: datafactory.RecurrenceFrequency(d.Get("frequency").(string)), + Interval: utils.Int32(int32(d.Get("interval").(int))), + }, + } + + if v, ok := d.GetOk("start_time"); ok { + t, _ := time.Parse(time.RFC3339, v.(string)) //should be validated by the schema + props.Recurrence.StartTime = &date.Time{Time: t} + } else { + props.Recurrence.StartTime = &date.Time{Time: time.Now()} + } + + if v, ok := d.GetOk("end_time"); ok { + t, _ := time.Parse(time.RFC3339, v.(string)) //should be validated by the schema + props.Recurrence.EndTime = &date.Time{Time: t} + } + + reference := &datafactory.PipelineReference{ + ReferenceName: utils.String(d.Get("pipeline_name").(string)), + } + + scheduleProps := &datafactory.ScheduleTrigger{ + ScheduleTriggerTypeProperties: props, + Pipelines: &[]datafactory.TriggerPipelineReference{ + { + PipelineReference: reference, + Parameters: d.Get("pipeline_parameters").(map[string]interface{}), + }, + }, + } + + if v, ok := d.GetOk("annotations"); ok { + annotations := v.([]interface{}) + scheduleProps.Annotations = &annotations + } + + trigger := datafactory.TriggerResource{ + Properties: scheduleProps, + } + + if _, err := client.CreateOrUpdate(ctx, resourceGroupName, dataFactoryName, triggerName, trigger, ""); err != nil { + return fmt.Errorf("Error creating Data Factory Trigger Schedule %q (Resource Group %q / Data Factory %q): %+v", triggerName, resourceGroupName, dataFactoryName, err) + } + + read, err := client.Get(ctx, resourceGroupName, dataFactoryName, triggerName, "") + if err != nil { + return fmt.Errorf("Error retrieving Data Factory Trigger Schedule %q (Resource Group %q / Data Factory %q): %+v", triggerName, resourceGroupName, dataFactoryName, err) + } + + if read.ID == nil { + return fmt.Errorf("Cannot read Data Factory Trigger Schedule %q (Resource Group %q / Data Factory %q) ID", triggerName, resourceGroupName, dataFactoryName) + } + + d.SetId(*read.ID) + + return resourceArmDataFactoryTriggerScheduleRead(d, meta) +} + +func resourceArmDataFactoryTriggerScheduleRead(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).DataFactory.TriggersClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*ArmClient).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + dataFactoryName := id.Path["factories"] + triggerName := id.Path["triggers"] + + resp, err := client.Get(ctx, id.ResourceGroup, dataFactoryName, triggerName, "") + if err != nil { + if utils.ResponseWasNotFound(resp.Response) { + d.SetId("") + log.Printf("[DEBUG] Data Factory Trigger Schedule %q was not found in Resource Group %q - removing from state!", triggerName, id.ResourceGroup) + return nil + } + return fmt.Errorf("Error reading the state of Data Factory Trigger Schedule %q: %+v", triggerName, err) + } + + d.Set("name", resp.Name) + d.Set("resource_group_name", id.ResourceGroup) + d.Set("data_factory_name", dataFactoryName) + + scheduleTriggerProps, ok := resp.Properties.AsScheduleTrigger() + if !ok { + return fmt.Errorf("Error classifiying Data Factory Trigger Schedule %q (Data Factory %q / Resource Group %q): Expected: %q Received: %q", triggerName, dataFactoryName, id.ResourceGroup, datafactory.TypeScheduleTrigger, *resp.Type) + } + + if scheduleTriggerProps != nil { + if recurrence := scheduleTriggerProps.Recurrence; recurrence != nil { + if v := recurrence.StartTime; v != nil { + d.Set("start_time", (*v).Format(time.RFC3339)) + } + if v := recurrence.EndTime; v != nil { + d.Set("end_time", (*v).Format(time.RFC3339)) + } + d.Set("frequency", recurrence.Frequency) + d.Set("interval", recurrence.Interval) + } + + if pipelines := scheduleTriggerProps.Pipelines; pipelines != nil { + if len(*pipelines) > 0 { + pipeline := *pipelines + if reference := pipeline[0].PipelineReference; reference != nil { + d.Set("pipeline_name", reference.ReferenceName) + } + d.Set("pipeline_parameters", pipeline[0].Parameters) + } + } + + annotations := flattenDataFactoryAnnotations(scheduleTriggerProps.Annotations) + if err := d.Set("annotations", annotations); err != nil { + return fmt.Errorf("Error setting `annotations`: %+v", err) + } + } + + return nil +} + +func resourceArmDataFactoryTriggerScheduleDelete(d *schema.ResourceData, meta interface{}) error { + client := meta.(*ArmClient).DataFactory.TriggersClient + ctx, cancel := timeouts.ForCreateUpdate(meta.(*ArmClient).StopContext, d) + defer cancel() + + id, err := azure.ParseAzureResourceID(d.Id()) + if err != nil { + return err + } + dataFactoryName := id.Path["factories"] + triggerName := id.Path["triggers"] + + if _, err = client.Delete(ctx, id.ResourceGroup, dataFactoryName, triggerName); err != nil { + return fmt.Errorf("Error deleting Data Factory Trigger Schedule %q (Resource Group %q / Data Factory %q): %+v", triggerName, id.ResourceGroup, dataFactoryName, err) + } + + return nil +} diff --git a/azurerm/resource_arm_data_factory_trigger_schedule_test.go b/azurerm/resource_arm_data_factory_trigger_schedule_test.go new file mode 100644 index 000000000000..01f459d7ea2d --- /dev/null +++ b/azurerm/resource_arm_data_factory_trigger_schedule_test.go @@ -0,0 +1,207 @@ +package azurerm + +import ( + "fmt" + "net/http" + "testing" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/terraform" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/helpers/tf" + "github.com/terraform-providers/terraform-provider-azurerm/azurerm/utils" +) + +func TestAccAzureRMDataFactoryTriggerSchedule_basic(t *testing.T) { + ri := tf.AccRandTimeInt() + config := testAccAzureRMDataFactoryTriggerSchedule_basic(ri, testLocation()) + resourceName := "azurerm_data_factory_trigger_schedule.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMDataFactoryTriggerScheduleDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDataFactoryTriggerScheduleExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAzureRMDataFactoryTriggerSchedule_complete(t *testing.T) { + ri := tf.AccRandTimeInt() + loc, _ := time.LoadLocation("UTC") + endTime := time.Now().UTC().Add(time.Hour * 7).In(loc).Format("2006-01-02T15:04:00Z07:00") + config := testAccAzureRMDataFactoryTriggerSchedule_basic(ri, testLocation()) + config2 := testAccAzureRMDataFactoryTriggerSchedule_update(ri, testLocation(), endTime) + resourceName := "azurerm_data_factory_trigger_schedule.test" + + resource.ParallelTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testCheckAzureRMDataFactoryTriggerScheduleDestroy, + Steps: []resource.TestStep{ + { + Config: config, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDataFactoryTriggerScheduleExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + { + Config: config2, + Check: resource.ComposeTestCheckFunc( + testCheckAzureRMDataFactoryTriggerScheduleExists(resourceName), + ), + }, + { + ResourceName: resourceName, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testCheckAzureRMDataFactoryTriggerScheduleExists(name string) resource.TestCheckFunc { + return func(s *terraform.State) error { + // Ensure we have enough information in state to look up in API + rs, ok := s.RootModule().Resources[name] + if !ok { + return fmt.Errorf("Not found: %s", name) + } + + name := rs.Primary.Attributes["name"] + resourceGroup, hasResourceGroup := rs.Primary.Attributes["resource_group_name"] + dataFactoryName := rs.Primary.Attributes["data_factory_name"] + if !hasResourceGroup { + return fmt.Errorf("Bad: no resource group found in state for Data Factory: %s", name) + } + + client := testAccProvider.Meta().(*ArmClient).DataFactory.TriggersClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + resp, err := client.Get(ctx, resourceGroup, dataFactoryName, name, "") + if err != nil { + return fmt.Errorf("Bad: Get on dataFactory.TriggersClient: %+v", err) + } + + if utils.ResponseWasNotFound(resp.Response) { + return fmt.Errorf("Bad: Data Factory Trigger Schdule %q (data factory name: %q / resource group: %q) does not exist", name, dataFactoryName, resourceGroup) + } + + return nil + } +} + +func testCheckAzureRMDataFactoryTriggerScheduleDestroy(s *terraform.State) error { + client := testAccProvider.Meta().(*ArmClient).DataFactory.TriggersClient + ctx := testAccProvider.Meta().(*ArmClient).StopContext + + for _, rs := range s.RootModule().Resources { + if rs.Type != "azurerm_data_factory_trigger_schedule" { + continue + } + + name := rs.Primary.Attributes["name"] + resourceGroup := rs.Primary.Attributes["resource_group_name"] + dataFactoryName := rs.Primary.Attributes["data_factory_name"] + + resp, err := client.Get(ctx, resourceGroup, dataFactoryName, name, "") + + if err != nil { + return nil + } + + if resp.StatusCode != http.StatusNotFound { + return fmt.Errorf("Data Factory Trigger Schedule still exists:\n%#v", resp.Properties) + } + } + + return nil +} + +func testAccAzureRMDataFactoryTriggerSchedule_basic(rInt int, location string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-%d" + location = "%s" +} + +resource "azurerm_data_factory" "test" { + name = "acctestdf%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_data_factory_pipeline" "test" { + name = "acctest%d" + resource_group_name = "${azurerm_resource_group.test.name}" + data_factory_name = "${azurerm_data_factory.test.name}" + + parameters = { + test = "testparameter" + } +} + +resource "azurerm_data_factory_trigger_schedule" "test" { + name = "acctestdf%d" + data_factory_name = "${azurerm_data_factory.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + pipeline_name = "${azurerm_data_factory_pipeline.test.name}" + + annotations = ["test1", "test2", "test3"] +} +`, rInt, location, rInt, rInt, rInt) +} + +func testAccAzureRMDataFactoryTriggerSchedule_update(rInt int, location string, endTime string) string { + return fmt.Sprintf(` +resource "azurerm_resource_group" "test" { + name = "acctestRG-datafactory-%d" + location = "%s" +} + +resource "azurerm_data_factory" "test" { + name = "acctestdf%d" + location = "${azurerm_resource_group.test.location}" + resource_group_name = "${azurerm_resource_group.test.name}" +} + +resource "azurerm_data_factory_pipeline" "test" { + name = "acctest%d" + resource_group_name = "${azurerm_resource_group.test.name}" + data_factory_name = "${azurerm_data_factory.test.name}" + + parameters = { + test = "testparameter" + } +} + +resource "azurerm_data_factory_trigger_schedule" "test" { + name = "acctestDFTS%d" + data_factory_name = "${azurerm_data_factory.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + pipeline_name = "${azurerm_data_factory_pipeline.test.name}" + + pipeline_parameters = "${azurerm_data_factory_pipeline.test.parameters}" + annotations = ["test5"] + frequency = "Day" + interval = 5 + end_time = "%s" +} +`, rInt, location, rInt, rInt, rInt, endTime) +} diff --git a/website/azurerm.erb b/website/azurerm.erb index 917a0aefc57a..3854135c2f3e 100644 --- a/website/azurerm.erb +++ b/website/azurerm.erb @@ -1002,6 +1002,10 @@
  • azurerm_data_factory_linked_service_sql_server
  • + +
  • + azurerm_data_factory_trigger_schedule +
  • diff --git a/website/docs/r/data_factory_trigger_schedule.html.markdown b/website/docs/r/data_factory_trigger_schedule.html.markdown new file mode 100644 index 000000000000..2aa6dea20a63 --- /dev/null +++ b/website/docs/r/data_factory_trigger_schedule.html.markdown @@ -0,0 +1,80 @@ +--- +layout: "azurerm" +page_title: "Azure Resource Manager: azurerm_data_factory_trigger_schedule" +sidebar_current: "docs-azurerm-resource-data-factory-trigger-schedule" +description: |- + Manages a Trigger Schedule inside a Azure Data Factory. +--- + +# azurerm_data_factory_trigger_schedule + +Manages a Trigger Schedule inside a Azure Data Factory. + +## Example Usage + +```hcl +resource "azurerm_resource_group" "example" { + name = "example" + location = "northeurope" +} + +resource "azurerm_data_factory" "example" { + name = "example" + location = "${azurerm_resource_group.example.location}" + resource_group_name = "${azurerm_resource_group.example.name}" +} + +resource "azurerm_data_factory_pipeline" "test" { + name = "example" + resource_group_name = "${azurerm_resource_group.test.name}" + data_factory_name = "${azurerm_data_factory.test.name}" +} + +resource "azurerm_data_factory_trigger_schedule" "test" { + name = "example" + data_factory_name = "${azurerm_data_factory.test.name}" + resource_group_name = "${azurerm_resource_group.test.name}" + pipeline_name = "${azurerm_data_factory_pipeline.test.name}" + + interval = 5 + frequency = "Day" +} +``` + +## Argument Reference + +The following arguments are supported: + +* `name` - (Required) Specifies the name of the Data Factory Schedule Trigger. Changing this forces a new resource to be created. Must be globally unique. See the [Microsoft documentation](https://docs.microsoft.com/en-us/azure/data-factory/naming-rules) for all restrictions. + +* `resource_group_name` - (Required) The name of the resource group in which to create the Data Factory Schedule Trigger. Changing this forces a new resource + +* `data_factory_name` - (Required) The Data Factory name in which to associate the Schedule Trigger with. Changing this forces a new resource. + +* `pipeline_name` - (Required) The Data Factory Pipeline name that the trigger will act on. + +* `start_time` - (Optional) The time the Schedule Trigger will start. This defaults to the current time. The time will be represented in UTC. + +* `end_time` - (Optional) The time the Schedule Trigger should end. The time will be represented in UTC. + +* `interval` - (Optional) The interval for how often the trigger occurs. This defaults to 1. + +* `frequency` - (Optional) The trigger freqency. Valid values include `Minute`, `Hour`, `Day`, `Week`, `Month`. Defaults to `Minute`. + +* `pipeline_parameters` - (Optional) The pipeline parameters that the the trigger will act upon. + +* `annotations` - (Optional) List of tags that can be used for describing the Data Factory Schedule Trigger. + +## Attributes Reference + +The following attributes are exported: + +* `id` - The ID of the Data Factory Schedule Trigger. + +## Import + +Data Factory Schedule Trigger can be imported using the `resource id`, e.g. + +```shell +terraform import azurerm_data_factory_schedule_trigger.example /subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/example/providers/Microsoft.DataFactory/factories/example/triggers/example +```