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