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 }