github.com/GoogleCloudPlatform/terraformer@v0.8.18/providers/azure/data_factory.go (about)

     1  // Copyright 2021 The Terraformer Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package azure
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"log"
    21  	"reflect"
    22  	"strings"
    23  
    24  	"github.com/Azure/azure-sdk-for-go/services/datafactory/mgmt/2018-06-01/datafactory"
    25  	"github.com/GoogleCloudPlatform/terraformer/terraformutils"
    26  )
    27  
    28  type DataFactoryGenerator struct {
    29  	AzureService
    30  }
    31  
    32  // Maps item.Properties.Type -> terraform.ResoruceType
    33  // Information extracted from
    34  //   SupportedResources are in:
    35  //   @ github.com/azure/azure-sdk-for-go@v42.3.0+incompatible/services/datafactory/mgmt/2018-06-01/datafactory/models.go
    36  //   PossibleTypeBasicDatasetValues, PossibleTypeBasicIntegrationRuntimeValues, PossibleTypeBasicLinkedServiceValues, PossibleTypeBasicTriggerValues
    37  //   TypeBasicDataset,TypeBasicIntegrationRuntime, TypeBasicLinkedService, TypeBasicTrigger, TypeBasicDataFlow
    38  
    39  var (
    40  	SupportedResources = map[string]string{
    41  		"AzureBlob":                "azurerm_data_factory_dataset_azure_blob",
    42  		"Binary":                   "azurerm_data_factory_dataset_binary",
    43  		"CosmosDbSqlApiCollection": "azurerm_data_factory_dataset_cosmosdb_sqlapi",
    44  		"CustomDataset":            "azurerm_data_factory_custom_dataset",
    45  		"DelimitedText":            "azurerm_data_factory_dataset_delimited_text",
    46  		"HttpFile":                 "azurerm_data_factory_dataset_http",
    47  		"Json":                     "azurerm_data_factory_dataset_json",
    48  		"MySqlTable":               "azurerm_data_factory_dataset_mysql",
    49  		"Parquet":                  "azurerm_data_factory_dataset_parquet",
    50  		"PostgreSqlTable":          "azurerm_data_factory_dataset_postgresql",
    51  		"SnowflakeTable":           "azurerm_data_factory_dataset_snowflake",
    52  		"SqlServerTable":           "azurerm_data_factory_dataset_sql_server_table",
    53  		"IntegrationRuntime":       "azurerm_data_factory_integration_runtime_azure",
    54  		"Managed":                  "azurerm_data_factory_integration_runtime_azure_ssis",
    55  		"SelfHosted":               "azurerm_data_factory_integration_runtime_self_hosted",
    56  		"AzureBlobStorage":         "azurerm_data_factory_linked_service_azure_blob_storage",
    57  		"AzureDatabricks":          "azurerm_data_factory_linked_service_azure_databricks",
    58  		"AzureFileStorage":         "azurerm_data_factory_linked_service_azure_file_storage",
    59  		"AzureFunction":            "azurerm_data_factory_linked_service_azure_function",
    60  		"AzureSearch":              "azurerm_data_factory_linked_service_azure_search",
    61  		"AzureSqlDatabase":         "azurerm_data_factory_linked_service_azure_sql_database",
    62  		"AzureTableStorage":        "azurerm_data_factory_linked_service_azure_table_storage",
    63  		"CosmosDb":                 "azurerm_data_factory_linked_service_cosmosdb",
    64  		"CustomDataSource":         "azurerm_data_factory_linked_custom_service",
    65  		"AzureBlobFS":              "azurerm_data_factory_linked_service_data_lake_storage_gen2",
    66  		"AzureKeyVault":            "azurerm_data_factory_linked_service_key_vault",
    67  		"AzureDataExplore":         "azurerm_data_factory_linked_service_kusto",
    68  		"MySql":                    "azurerm_data_factory_linked_service_mysql",
    69  		"OData":                    "azurerm_data_factory_linked_service_odata",
    70  		"PostgreSql":               "azurerm_data_factory_linked_service_postgresql",
    71  		"Sftp":                     "azurerm_data_factory_linked_service_sftp",
    72  		"Snowflake":                "azurerm_data_factory_linked_service_snowflake",
    73  		"SqlServer":                "azurerm_data_factory_linked_service_sql_server",
    74  		"AzureSqlDW":               "azurerm_data_factory_linked_service_synapse",
    75  		"Web":                      "azurerm_data_factory_linked_service_web",
    76  		"BlobEventsTrigger":        "azurerm_data_factory_trigger_blob_event",
    77  		"ScheduleTrigger":          "azurerm_data_factory_trigger_schedule",
    78  		"TumblingWindowTrigger":    "azurerm_data_factory_trigger_tumbling_window",
    79  	}
    80  )
    81  
    82  func getResourceTypeFrom(azureResourceName string) string {
    83  	return SupportedResources[azureResourceName]
    84  }
    85  
    86  func getFieldFrom(v interface{}, field string) reflect.Value {
    87  	reflected := reflect.ValueOf(v)
    88  	if reflected.IsValid() {
    89  		indirected := reflect.Indirect(reflected)
    90  		if indirected.Kind() == reflect.Struct {
    91  			fieldValue := indirected.FieldByName(field)
    92  			return fieldValue
    93  		}
    94  	}
    95  	return reflect.Value{}
    96  }
    97  
    98  func getFieldAsString(v interface{}, field string) string {
    99  	fieldValue := getFieldFrom(v, field)
   100  	if fieldValue.IsValid() {
   101  		return fieldValue.String()
   102  	}
   103  	return ""
   104  }
   105  
   106  func (az *AzureService) appendResourceAs(resources []terraformutils.Resource, itemID string, itemName string, resourceType string, abbreviation string) []terraformutils.Resource {
   107  	prefix := strings.ReplaceAll(resourceType, resourceType, abbreviation)
   108  	suffix := strings.ReplaceAll(itemName, "-", "_")
   109  	resourceName := prefix + "_" + suffix
   110  	res := terraformutils.NewSimpleResource(itemID, resourceName, resourceType, az.ProviderName, []string{})
   111  	resources = append(resources, res)
   112  	return resources
   113  }
   114  
   115  func (az *DataFactoryGenerator) appendResourceFrom(resources []terraformutils.Resource, id string, name string, properties interface{}) []terraformutils.Resource {
   116  	azureType := getFieldAsString(properties, "Type")
   117  	if azureType != "" {
   118  		resourceType := getResourceTypeFrom(azureType)
   119  		if resourceType == "" {
   120  			msg := fmt.Sprintf(`azurerm_data_factory: resource "%s" id: %s type: %s not handled yet by terraform or terraformer`, name, id, azureType)
   121  			log.Println(msg)
   122  		} else {
   123  			resources = az.appendResourceAs(resources, id, name, resourceType, "adf")
   124  		}
   125  	}
   126  	return resources
   127  }
   128  
   129  func (az *DataFactoryGenerator) listFactories() ([]datafactory.Factory, error) {
   130  	subscriptionID, resourceGroup, authorizer := az.getClientArgs()
   131  	client := datafactory.NewFactoriesClient(subscriptionID)
   132  	client.Authorizer = authorizer
   133  	var (
   134  		iterator datafactory.FactoryListResponseIterator
   135  		err      error
   136  	)
   137  	ctx := context.Background()
   138  	if resourceGroup != "" {
   139  		iterator, err = client.ListByResourceGroupComplete(ctx, resourceGroup)
   140  	} else {
   141  		iterator, err = client.ListComplete(ctx)
   142  	}
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  	var resources []datafactory.Factory
   147  	for iterator.NotDone() {
   148  		item := iterator.Value()
   149  		resources = append(resources, item)
   150  		if err := iterator.NextWithContext(ctx); err != nil {
   151  			log.Println(err)
   152  			return resources, err
   153  		}
   154  	}
   155  	return resources, nil
   156  }
   157  
   158  func (az *DataFactoryGenerator) createDataFactoryResources(dataFactories []datafactory.Factory) ([]terraformutils.Resource, error) {
   159  	var resources []terraformutils.Resource
   160  	for _, item := range dataFactories {
   161  		resources = az.appendResourceAs(resources, *item.ID, *item.Name, "azurerm_data_factory", "adf")
   162  	}
   163  	return resources, nil
   164  }
   165  
   166  func getIntegrationRuntimeType(properties interface{}) string {
   167  	azureType := getFieldAsString(properties, "Type")
   168  	if azureType == "SelfHosted" {
   169  		return "azurerm_data_factory_integration_runtime_self_hosted"
   170  	}
   171  	// item.Properties.ManagedIntegrationRuntimeTypeProperties.SsisProperties
   172  	if typeProperties := getFieldFrom(properties, "ManagedIntegrationRuntimeTypeProperties"); typeProperties.IsValid() {
   173  		managedRuntime := typeProperties.Interface()
   174  		SsisProperties := getFieldFrom(managedRuntime, "SsisProperties")
   175  		if SsisProperties.IsNil() {
   176  			return "azurerm_data_factory_integration_runtime_azure"
   177  		}
   178  	}
   179  	return "azurerm_data_factory_integration_runtime_azure_ssis"
   180  }
   181  
   182  func (az *DataFactoryGenerator) createIntegrationRuntimesResources(dataFactories []datafactory.Factory) ([]terraformutils.Resource, error) {
   183  	subscriptionID, _, authorizer := az.getClientArgs()
   184  	client := datafactory.NewIntegrationRuntimesClient(subscriptionID)
   185  	client.Authorizer = authorizer
   186  	ctx := context.Background()
   187  	var resources []terraformutils.Resource
   188  	for _, factory := range dataFactories {
   189  		id, err := ParseAzureResourceID(*factory.ID)
   190  		if err != nil {
   191  			return nil, err
   192  		}
   193  		iterator, err := client.ListByFactoryComplete(ctx, id.ResourceGroup, *factory.Name)
   194  		if err != nil {
   195  			return nil, err
   196  		}
   197  		for iterator.NotDone() {
   198  			item := iterator.Value()
   199  			resourceType := getIntegrationRuntimeType(item.Properties)
   200  			resources = az.appendResourceAs(resources, *item.ID, *item.Name, resourceType, "adfr")
   201  			if err := iterator.NextWithContext(ctx); err != nil {
   202  				log.Println(err)
   203  				return resources, err
   204  			}
   205  		}
   206  	}
   207  	return resources, nil
   208  }
   209  
   210  func (az *DataFactoryGenerator) createLinkedServiceResources(dataFactories []datafactory.Factory) ([]terraformutils.Resource, error) {
   211  	subscriptionID, _, authorizer := az.getClientArgs()
   212  	client := datafactory.NewLinkedServicesClient(subscriptionID)
   213  	client.Authorizer = authorizer
   214  	ctx := context.Background()
   215  	var resources []terraformutils.Resource
   216  	for _, factory := range dataFactories {
   217  		id, err := ParseAzureResourceID(*factory.ID)
   218  		if err != nil {
   219  			return nil, err
   220  		}
   221  		iterator, err := client.ListByFactoryComplete(ctx, id.ResourceGroup, *factory.Name)
   222  		if err != nil {
   223  			return nil, err
   224  		}
   225  		for iterator.NotDone() {
   226  			item := iterator.Value()
   227  			resources = az.appendResourceFrom(resources, *item.ID, *item.Name, item.Properties)
   228  			if err = iterator.NextWithContext(ctx); err != nil {
   229  				log.Println(err)
   230  				return resources, err
   231  			}
   232  		}
   233  	}
   234  	return resources, nil
   235  }
   236  
   237  func (az *DataFactoryGenerator) createPipelineResources(dataFactories []datafactory.Factory) ([]terraformutils.Resource, error) {
   238  	subscriptionID, _, authorizer := az.getClientArgs()
   239  	client := datafactory.NewPipelinesClient(subscriptionID)
   240  	client.Authorizer = authorizer
   241  	ctx := context.Background()
   242  	var resources []terraformutils.Resource
   243  	for _, factory := range dataFactories {
   244  		id, err := ParseAzureResourceID(*factory.ID)
   245  		if err != nil {
   246  			return nil, err
   247  		}
   248  		iterator, err := client.ListByFactoryComplete(ctx, id.ResourceGroup, *factory.Name)
   249  		if err != nil {
   250  			return nil, err
   251  		}
   252  		for iterator.NotDone() {
   253  			item := iterator.Value()
   254  			resources = az.appendResourceAs(resources, *item.ID, *item.Name, "azurerm_data_factory_pipeline", "adfp")
   255  			if err := iterator.NextWithContext(ctx); err != nil {
   256  				log.Println(err)
   257  				return resources, err
   258  			}
   259  		}
   260  	}
   261  	return resources, nil
   262  }
   263  
   264  func (az *DataFactoryGenerator) createPipelineTriggerScheduleResources(dataFactories []datafactory.Factory) ([]terraformutils.Resource, error) {
   265  	subscriptionID, _, authorizer := az.getClientArgs()
   266  	client := datafactory.NewTriggersClient(subscriptionID)
   267  	client.Authorizer = authorizer
   268  	ctx := context.Background()
   269  	var resources []terraformutils.Resource
   270  	for _, factory := range dataFactories {
   271  		id, err := ParseAzureResourceID(*factory.ID)
   272  		if err != nil {
   273  			return nil, err
   274  		}
   275  		iterator, err := client.ListByFactoryComplete(ctx, id.ResourceGroup, *factory.Name)
   276  		if err != nil {
   277  			return nil, err
   278  		}
   279  		for iterator.NotDone() {
   280  			item := iterator.Value()
   281  			resources = az.appendResourceFrom(resources, *item.ID, *item.Name, item.Properties)
   282  			if err := iterator.NextWithContext(ctx); err != nil {
   283  				log.Println(err)
   284  				return resources, err
   285  			}
   286  		}
   287  	}
   288  	return resources, nil
   289  }
   290  
   291  func (az *DataFactoryGenerator) createDataFlowResources(dataFactories []datafactory.Factory) ([]terraformutils.Resource, error) {
   292  	subscriptionID, _, authorizer := az.getClientArgs()
   293  	client := datafactory.NewDataFlowsClient(subscriptionID)
   294  	client.Authorizer = authorizer
   295  	ctx := context.Background()
   296  	var resources []terraformutils.Resource
   297  	for _, factory := range dataFactories {
   298  		id, err := ParseAzureResourceID(*factory.ID)
   299  		if err != nil {
   300  			return nil, err
   301  		}
   302  		iterator, err := client.ListByFactoryComplete(ctx, id.ResourceGroup, *factory.Name)
   303  		if err != nil {
   304  			return nil, err
   305  		}
   306  		for iterator.NotDone() {
   307  			item := iterator.Value()
   308  			resources = az.appendResourceAs(resources, *item.ID, *item.Name, "azurerm_data_factory_data_flow", "adfl")
   309  			if err := iterator.NextWithContext(ctx); err != nil {
   310  				log.Println(err)
   311  				return resources, err
   312  			}
   313  		}
   314  	}
   315  	return resources, nil
   316  }
   317  
   318  func (az *DataFactoryGenerator) createPipelineDatasetResources(dataFactories []datafactory.Factory) ([]terraformutils.Resource, error) {
   319  	subscriptionID, _, authorizer := az.getClientArgs()
   320  	client := datafactory.NewDatasetsClient(subscriptionID)
   321  	client.Authorizer = authorizer
   322  	ctx := context.Background()
   323  	var resources []terraformutils.Resource
   324  	for _, factory := range dataFactories {
   325  		id, err := ParseAzureResourceID(*factory.ID)
   326  		if err != nil {
   327  			return nil, err
   328  		}
   329  		iterator, err := client.ListByFactoryComplete(ctx, id.ResourceGroup, *factory.Name)
   330  		if err != nil {
   331  			return nil, err
   332  		}
   333  		for iterator.NotDone() {
   334  			item := iterator.Value()
   335  			resources = az.appendResourceFrom(resources, *item.ID, *item.Name, item.Properties)
   336  			if err := iterator.NextWithContext(ctx); err != nil {
   337  				log.Println(err)
   338  				return resources, err
   339  			}
   340  		}
   341  	}
   342  	return resources, nil
   343  }
   344  
   345  func (az *DataFactoryGenerator) InitResources() error {
   346  
   347  	dataFactories, err := az.listFactories()
   348  	if err != nil {
   349  		return err
   350  	}
   351  
   352  	factoriesFunctions := []func([]datafactory.Factory) ([]terraformutils.Resource, error){
   353  		az.createDataFactoryResources,
   354  		az.createIntegrationRuntimesResources,
   355  		az.createLinkedServiceResources,
   356  		az.createPipelineResources,
   357  		az.createPipelineTriggerScheduleResources,
   358  		az.createPipelineDatasetResources,
   359  		az.createDataFlowResources,
   360  	}
   361  
   362  	for _, f := range factoriesFunctions {
   363  		resources, ero := f(dataFactories)
   364  		if ero != nil {
   365  			return ero
   366  		}
   367  		az.Resources = append(az.Resources, resources...)
   368  	}
   369  	return nil
   370  }
   371  
   372  // PostGenerateHook for formatting json properties as heredoc
   373  // - azurerm_data_factory_pipeline property activities_json
   374  func (az *DataFactoryGenerator) PostConvertHook() error {
   375  	for i, resource := range az.Resources {
   376  		if resource.InstanceInfo.Type == "azurerm_data_factory_pipeline" {
   377  			if val, ok := az.Resources[i].Item["activities_json"]; ok {
   378  				if val != nil {
   379  					json := val.(string)
   380  					// json := asJson(val)
   381  					hereDoc := asHereDoc(json)
   382  					az.Resources[i].Item["activities_json"] = hereDoc
   383  				}
   384  			}
   385  		}
   386  	}
   387  	return nil
   388  }