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  }