github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/azure/provider.go (about) 1 package azure 2 3 import ( 4 "encoding/xml" 5 "fmt" 6 7 "github.com/hashicorp/terraform/helper/pathorcontents" 8 "github.com/hashicorp/terraform/helper/schema" 9 "github.com/hashicorp/terraform/terraform" 10 ) 11 12 // Provider returns a terraform.ResourceProvider. 13 func Provider() terraform.ResourceProvider { 14 return &schema.Provider{ 15 Schema: map[string]*schema.Schema{ 16 "settings_file": &schema.Schema{ 17 Type: schema.TypeString, 18 Optional: true, 19 DefaultFunc: schema.EnvDefaultFunc("AZURE_SETTINGS_FILE", nil), 20 ValidateFunc: validateSettingsFile, 21 Deprecated: "Use the publish_settings field instead", 22 }, 23 24 "publish_settings": &schema.Schema{ 25 Type: schema.TypeString, 26 Optional: true, 27 DefaultFunc: schema.EnvDefaultFunc("AZURE_PUBLISH_SETTINGS", nil), 28 ValidateFunc: validatePublishSettings, 29 }, 30 31 "subscription_id": &schema.Schema{ 32 Type: schema.TypeString, 33 Optional: true, 34 DefaultFunc: schema.EnvDefaultFunc("AZURE_SUBSCRIPTION_ID", ""), 35 }, 36 37 "certificate": &schema.Schema{ 38 Type: schema.TypeString, 39 Optional: true, 40 DefaultFunc: schema.EnvDefaultFunc("AZURE_CERTIFICATE", ""), 41 }, 42 }, 43 44 ResourcesMap: map[string]*schema.Resource{ 45 "azure_instance": resourceAzureInstance(), 46 "azure_affinity_group": resourceAzureAffinityGroup(), 47 "azure_data_disk": resourceAzureDataDisk(), 48 "azure_sql_database_server": resourceAzureSqlDatabaseServer(), 49 "azure_sql_database_server_firewall_rule": resourceAzureSqlDatabaseServerFirewallRule(), 50 "azure_sql_database_service": resourceAzureSqlDatabaseService(), 51 "azure_hosted_service": resourceAzureHostedService(), 52 "azure_storage_service": resourceAzureStorageService(), 53 "azure_storage_container": resourceAzureStorageContainer(), 54 "azure_storage_blob": resourceAzureStorageBlob(), 55 "azure_storage_queue": resourceAzureStorageQueue(), 56 "azure_virtual_network": resourceAzureVirtualNetwork(), 57 "azure_dns_server": resourceAzureDnsServer(), 58 "azure_local_network_connection": resourceAzureLocalNetworkConnection(), 59 "azure_security_group": resourceAzureSecurityGroup(), 60 "azure_security_group_rule": resourceAzureSecurityGroupRule(), 61 }, 62 63 ConfigureFunc: providerConfigure, 64 } 65 } 66 67 func providerConfigure(d *schema.ResourceData) (interface{}, error) { 68 config := Config{ 69 SubscriptionID: d.Get("subscription_id").(string), 70 Certificate: []byte(d.Get("certificate").(string)), 71 } 72 73 publishSettings := d.Get("publish_settings").(string) 74 if publishSettings == "" { 75 publishSettings = d.Get("settings_file").(string) 76 } 77 if publishSettings != "" { 78 // any errors from readSettings would have been caught at the validate 79 // step, so we can avoid handling them now 80 settings, _, _ := readSettings(publishSettings) 81 config.Settings = settings 82 return config.NewClientFromSettingsData() 83 } 84 85 if config.SubscriptionID != "" && len(config.Certificate) > 0 { 86 return config.NewClient() 87 } 88 89 return nil, fmt.Errorf( 90 "Insufficient configuration data. Please specify either a 'settings_file'\n" + 91 "or both a 'subscription_id' and 'certificate'.") 92 } 93 94 func validateSettingsFile(v interface{}, k string) ([]string, []error) { 95 value := v.(string) 96 if value == "" { 97 return nil, nil 98 } 99 100 _, warnings, errors := readSettings(value) 101 return warnings, errors 102 } 103 104 func validatePublishSettings(v interface{}, k string) (ws []string, es []error) { 105 value := v.(string) 106 if value == "" { 107 return 108 } 109 110 var settings settingsData 111 if err := xml.Unmarshal([]byte(value), &settings); err != nil { 112 es = append(es, fmt.Errorf("error parsing publish_settings as XML: %s", err)) 113 } 114 115 return 116 } 117 118 const settingsPathWarnMsg = ` 119 settings_file was provided as a file path. This support 120 will be removed in the future. Please update your configuration 121 to use ${file("filename.publishsettings")} instead.` 122 123 func readSettings(pathOrContents string) (s []byte, ws []string, es []error) { 124 contents, wasPath, err := pathorcontents.Read(pathOrContents) 125 if err != nil { 126 es = append(es, fmt.Errorf("error reading settings_file: %s", err)) 127 } 128 if wasPath { 129 ws = append(ws, settingsPathWarnMsg) 130 } 131 132 var settings settingsData 133 if err := xml.Unmarshal([]byte(contents), &settings); err != nil { 134 es = append(es, fmt.Errorf("error parsing settings_file as XML: %s", err)) 135 } 136 137 s = []byte(contents) 138 139 return 140 } 141 142 // settingsData is a private struct used to test the unmarshalling of the 143 // settingsFile contents, to determine if the contents are valid XML 144 type settingsData struct { 145 XMLName xml.Name `xml:"PublishData"` 146 }