github.com/jd3nn1s/terraform@v0.9.6-0.20170906225847-13878347b7a1/backend/remote-state/consul/backend.go (about)

     1  package consul
     2  
     3  import (
     4  	"context"
     5  	"strings"
     6  
     7  	consulapi "github.com/hashicorp/consul/api"
     8  	"github.com/hashicorp/terraform/backend"
     9  	"github.com/hashicorp/terraform/helper/schema"
    10  )
    11  
    12  // New creates a new backend for Consul remote state.
    13  func New() backend.Backend {
    14  	s := &schema.Backend{
    15  		Schema: map[string]*schema.Schema{
    16  			"path": &schema.Schema{
    17  				Type:        schema.TypeString,
    18  				Required:    true,
    19  				Description: "Path to store state in Consul",
    20  			},
    21  
    22  			"access_token": &schema.Schema{
    23  				Type:        schema.TypeString,
    24  				Optional:    true,
    25  				Description: "Access token for a Consul ACL",
    26  				Default:     "", // To prevent input
    27  			},
    28  
    29  			"address": &schema.Schema{
    30  				Type:        schema.TypeString,
    31  				Optional:    true,
    32  				Description: "Address to the Consul Cluster",
    33  				Default:     "", // To prevent input
    34  			},
    35  
    36  			"scheme": &schema.Schema{
    37  				Type:        schema.TypeString,
    38  				Optional:    true,
    39  				Description: "Scheme to communicate to Consul with",
    40  				Default:     "", // To prevent input
    41  			},
    42  
    43  			"datacenter": &schema.Schema{
    44  				Type:        schema.TypeString,
    45  				Optional:    true,
    46  				Description: "Datacenter to communicate with",
    47  				Default:     "", // To prevent input
    48  			},
    49  
    50  			"http_auth": &schema.Schema{
    51  				Type:        schema.TypeString,
    52  				Optional:    true,
    53  				Description: "HTTP Auth in the format of 'username:password'",
    54  				Default:     "", // To prevent input
    55  			},
    56  
    57  			"gzip": &schema.Schema{
    58  				Type:        schema.TypeBool,
    59  				Optional:    true,
    60  				Description: "Compress the state data using gzip",
    61  				Default:     false,
    62  			},
    63  
    64  			"lock": &schema.Schema{
    65  				Type:        schema.TypeBool,
    66  				Optional:    true,
    67  				Description: "Lock state access",
    68  				Default:     true,
    69  			},
    70  
    71  			"ca_file": &schema.Schema{
    72  				Type:        schema.TypeString,
    73  				Optional:    true,
    74  				Description: "A path to a PEM-encoded certificate authority used to verify the remote agent's certificate.",
    75  				DefaultFunc: schema.EnvDefaultFunc("CONSUL_CACERT", ""),
    76  			},
    77  
    78  			"cert_file": &schema.Schema{
    79  				Type:        schema.TypeString,
    80  				Optional:    true,
    81  				Description: "A path to a PEM-encoded certificate provided to the remote agent; requires use of key_file.",
    82  				DefaultFunc: schema.EnvDefaultFunc("CONSUL_CLIENT_CERT", ""),
    83  			},
    84  
    85  			"key_file": &schema.Schema{
    86  				Type:        schema.TypeString,
    87  				Optional:    true,
    88  				Description: "A path to a PEM-encoded private key, required if cert_file is specified.",
    89  				DefaultFunc: schema.EnvDefaultFunc("CONSUL_CLIENT_KEY", ""),
    90  			},
    91  		},
    92  	}
    93  
    94  	result := &Backend{Backend: s}
    95  	result.Backend.ConfigureFunc = result.configure
    96  	return result
    97  }
    98  
    99  type Backend struct {
   100  	*schema.Backend
   101  
   102  	// The fields below are set from configure
   103  	configData *schema.ResourceData
   104  	lock       bool
   105  }
   106  
   107  func (b *Backend) configure(ctx context.Context) error {
   108  	// Grab the resource data
   109  	b.configData = schema.FromContextBackendConfig(ctx)
   110  
   111  	// Store the lock information
   112  	b.lock = b.configData.Get("lock").(bool)
   113  
   114  	// Initialize a client to test config
   115  	_, err := b.clientRaw()
   116  	return err
   117  }
   118  
   119  func (b *Backend) clientRaw() (*consulapi.Client, error) {
   120  	data := b.configData
   121  
   122  	// Configure the client
   123  	config := consulapi.DefaultConfig()
   124  	if v, ok := data.GetOk("access_token"); ok && v.(string) != "" {
   125  		config.Token = v.(string)
   126  	}
   127  	if v, ok := data.GetOk("address"); ok && v.(string) != "" {
   128  		config.Address = v.(string)
   129  	}
   130  	if v, ok := data.GetOk("scheme"); ok && v.(string) != "" {
   131  		config.Scheme = v.(string)
   132  	}
   133  	if v, ok := data.GetOk("datacenter"); ok && v.(string) != "" {
   134  		config.Datacenter = v.(string)
   135  	}
   136  
   137  	if v, ok := data.GetOk("ca_file"); ok && v.(string) != "" {
   138  		config.TLSConfig.CAFile = v.(string)
   139  	}
   140  	if v, ok := data.GetOk("cert_file"); ok && v.(string) != "" {
   141  		config.TLSConfig.CertFile = v.(string)
   142  	}
   143  	if v, ok := data.GetOk("key_file"); ok && v.(string) != "" {
   144  		config.TLSConfig.KeyFile = v.(string)
   145  	}
   146  
   147  	if v, ok := data.GetOk("http_auth"); ok && v.(string) != "" {
   148  		auth := v.(string)
   149  
   150  		var username, password string
   151  		if strings.Contains(auth, ":") {
   152  			split := strings.SplitN(auth, ":", 2)
   153  			username = split[0]
   154  			password = split[1]
   155  		} else {
   156  			username = auth
   157  		}
   158  
   159  		config.HttpAuth = &consulapi.HttpBasicAuth{
   160  			Username: username,
   161  			Password: password,
   162  		}
   163  	}
   164  
   165  	return consulapi.NewClient(config)
   166  }