github.com/jsoriano/terraform@v0.6.7-0.20151026070445-8b70867fdd95/builtin/providers/google/config.go (about)

     1  package google
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"log"
     8  	"net/http"
     9  	"os"
    10  	"runtime"
    11  	"strings"
    12  
    13  	"github.com/hashicorp/terraform/terraform"
    14  	"golang.org/x/oauth2"
    15  	"golang.org/x/oauth2/google"
    16  	"golang.org/x/oauth2/jwt"
    17  	"google.golang.org/api/compute/v1"
    18  	"google.golang.org/api/container/v1"
    19  	"google.golang.org/api/dns/v1"
    20  	"google.golang.org/api/storage/v1"
    21  )
    22  
    23  // Config is the configuration structure used to instantiate the Google
    24  // provider.
    25  type Config struct {
    26  	AccountFile string
    27  	Project     string
    28  	Region      string
    29  
    30  	clientCompute   *compute.Service
    31  	clientContainer *container.Service
    32  	clientDns       *dns.Service
    33  	clientStorage   *storage.Service
    34  }
    35  
    36  func (c *Config) loadAndValidate() error {
    37  	var account accountFile
    38  	clientScopes := []string{
    39  		"https://www.googleapis.com/auth/compute",
    40  		"https://www.googleapis.com/auth/cloud-platform",
    41  		"https://www.googleapis.com/auth/ndev.clouddns.readwrite",
    42  		"https://www.googleapis.com/auth/devstorage.full_control",
    43  	}
    44  
    45  
    46  	if c.AccountFile == "" {
    47  		c.AccountFile = os.Getenv("GOOGLE_ACCOUNT_FILE")
    48  	}
    49  	if c.Project == "" {
    50  		c.Project = os.Getenv("GOOGLE_PROJECT")
    51  	}
    52  	if c.Region == "" {
    53  		c.Region = os.Getenv("GOOGLE_REGION")
    54  	}
    55  
    56  	var client *http.Client
    57  
    58  	if c.AccountFile != "" {
    59  		contents := c.AccountFile
    60  
    61  		// Assume account_file is a JSON string
    62  		if err := parseJSON(&account, contents); err != nil {
    63  			// If account_file was not JSON, assume it is a file path instead
    64  			if _, err := os.Stat(c.AccountFile); os.IsNotExist(err) {
    65  				return fmt.Errorf(
    66  					"account_file path does not exist: %s",
    67  					c.AccountFile)
    68  			}
    69  
    70  			b, err := ioutil.ReadFile(c.AccountFile)
    71  			if err != nil {
    72  				return fmt.Errorf(
    73  					"Error reading account_file from path '%s': %s",
    74  					c.AccountFile,
    75  					err)
    76  			}
    77  
    78  			contents = string(b)
    79  
    80  			if err := parseJSON(&account, contents); err != nil {
    81  				return fmt.Errorf(
    82  					"Error parsing account file '%s': %s",
    83  					contents,
    84  					err)
    85  			}
    86  		}
    87  
    88  		// Get the token for use in our requests
    89  		log.Printf("[INFO] Requesting Google token...")
    90  		log.Printf("[INFO]   -- Email: %s", account.ClientEmail)
    91  		log.Printf("[INFO]   -- Scopes: %s", clientScopes)
    92  		log.Printf("[INFO]   -- Private Key Length: %d", len(account.PrivateKey))
    93  
    94  		conf := jwt.Config{
    95  			Email:      account.ClientEmail,
    96  			PrivateKey: []byte(account.PrivateKey),
    97  			Scopes:     clientScopes,
    98  			TokenURL:   "https://accounts.google.com/o/oauth2/token",
    99  		}
   100  
   101  		// Initiate an http.Client. The following GET request will be
   102  		// authorized and authenticated on the behalf of
   103  		// your service account.
   104  		client = conf.Client(oauth2.NoContext)
   105  
   106  	} else {
   107  		log.Printf("[INFO] Authenticating using DefaultClient");
   108  		err := error(nil)
   109  		client, err = google.DefaultClient(oauth2.NoContext, clientScopes...)
   110  		if err != nil {
   111  			return err
   112  		}
   113  	}
   114  
   115  	versionString := terraform.Version
   116  	prerelease := terraform.VersionPrerelease
   117  	if len(prerelease) > 0 {
   118  		versionString = fmt.Sprintf("%s-%s", versionString, prerelease)
   119  	}
   120  	userAgent := fmt.Sprintf(
   121  		"(%s %s) Terraform/%s", runtime.GOOS, runtime.GOARCH, versionString)
   122  
   123  	var err error
   124  
   125  	log.Printf("[INFO] Instantiating GCE client...")
   126  	c.clientCompute, err = compute.New(client)
   127  	if err != nil {
   128  		return err
   129  	}
   130  	c.clientCompute.UserAgent = userAgent
   131  
   132  	log.Printf("[INFO] Instantiating GKE client...")
   133  	c.clientContainer, err = container.New(client)
   134  	if err != nil {
   135  		return err
   136  	}
   137  	c.clientContainer.UserAgent = userAgent
   138  
   139  	log.Printf("[INFO] Instantiating Google Cloud DNS client...")
   140  	c.clientDns, err = dns.New(client)
   141  	if err != nil {
   142  		return err
   143  	}
   144  	c.clientDns.UserAgent = userAgent
   145  
   146  	log.Printf("[INFO] Instantiating Google Storage Client...")
   147  	c.clientStorage, err = storage.New(client)
   148  	if err != nil {
   149  		return err
   150  	}
   151  	c.clientStorage.UserAgent = userAgent
   152  
   153  	return nil
   154  }
   155  
   156  // accountFile represents the structure of the account file JSON file.
   157  type accountFile struct {
   158  	PrivateKeyId string `json:"private_key_id"`
   159  	PrivateKey   string `json:"private_key"`
   160  	ClientEmail  string `json:"client_email"`
   161  	ClientId     string `json:"client_id"`
   162  }
   163  
   164  func parseJSON(result interface{}, contents string) error {
   165  	r := strings.NewReader(contents)
   166  	dec := json.NewDecoder(r)
   167  
   168  	return dec.Decode(result)
   169  }