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