forked from hashicorp/terraform
-
Notifications
You must be signed in to change notification settings - Fork 0
/
provider.go
146 lines (123 loc) · 4.73 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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package azure
import (
"encoding/xml"
"fmt"
"github.com/hashicorp/terraform/helper/pathorcontents"
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/terraform"
)
// 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,
Deprecated: "Use the publish_settings field instead",
},
"publish_settings": &schema.Schema{
Type: schema.TypeString,
Optional: true,
DefaultFunc: schema.EnvDefaultFunc("AZURE_PUBLISH_SETTINGS", nil),
ValidateFunc: validatePublishSettings,
},
"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)),
}
publishSettings := d.Get("publish_settings").(string)
if publishSettings == "" {
publishSettings = d.Get("settings_file").(string)
}
if publishSettings != "" {
// any errors from readSettings would have been caught at the validate
// step, so we can avoid handling them now
settings, _, _ := readSettings(publishSettings)
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
}
func validatePublishSettings(v interface{}, k string) (ws []string, es []error) {
value := v.(string)
if value == "" {
return
}
var settings settingsData
if err := xml.Unmarshal([]byte(value), &settings); err != nil {
es = append(es, fmt.Errorf("error parsing publish_settings as XML: %s", err))
}
return
}
const settingsPathWarnMsg = `
settings_file was provided as 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) {
contents, wasPath, err := pathorcontents.Read(pathOrContents)
if err != nil {
es = append(es, fmt.Errorf("error reading settings_file: %s", err))
}
if wasPath {
ws = append(ws, settingsPathWarnMsg)
}
var settings settingsData
if err := xml.Unmarshal([]byte(contents), &settings); err != nil {
es = append(es, fmt.Errorf("error parsing settings_file as XML: %s", err))
}
s = []byte(contents)
return
}
// 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"`
}