github.com/alexissmirnov/terraform@v0.4.3-0.20150423153700-1ef9731a2f14/builtin/providers/google/config.go (about)

     1  package google
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"log"
     7  	"net/http"
     8  	"os"
     9  	"runtime"
    10  
    11  	// TODO(dcunnin): Use version code from version.go
    12  	// "github.com/hashicorp/terraform"
    13  	"golang.org/x/oauth2"
    14  	"golang.org/x/oauth2/google"
    15  	"golang.org/x/oauth2/jwt"
    16  	"google.golang.org/api/compute/v1"
    17  )
    18  
    19  // Config is the configuration structure used to instantiate the Google
    20  // provider.
    21  type Config struct {
    22  	AccountFile string
    23  	Project     string
    24  	Region      string
    25  
    26  	clientCompute *compute.Service
    27  }
    28  
    29  func (c *Config) loadAndValidate() error {
    30  	var account accountFile
    31  
    32  	// TODO: validation that it isn't blank
    33  	if c.AccountFile == "" {
    34  		c.AccountFile = os.Getenv("GOOGLE_ACCOUNT_FILE")
    35  	}
    36  	if c.Project == "" {
    37  		c.Project = os.Getenv("GOOGLE_PROJECT")
    38  	}
    39  	if c.Region == "" {
    40  		c.Region = os.Getenv("GOOGLE_REGION")
    41  	}
    42  
    43  	var client *http.Client
    44  
    45  	if c.AccountFile != "" {
    46  		if err := loadJSON(&account, c.AccountFile); err != nil {
    47  			return fmt.Errorf(
    48  				"Error loading account file '%s': %s",
    49  				c.AccountFile,
    50  				err)
    51  		}
    52  
    53  		clientScopes := []string{"https://www.googleapis.com/auth/compute"}
    54  
    55  		// Get the token for use in our requests
    56  		log.Printf("[INFO] Requesting Google token...")
    57  		log.Printf("[INFO]   -- Email: %s", account.ClientEmail)
    58  		log.Printf("[INFO]   -- Scopes: %s", clientScopes)
    59  		log.Printf("[INFO]   -- Private Key Length: %d", len(account.PrivateKey))
    60  
    61  		conf := jwt.Config{
    62  			Email:      account.ClientEmail,
    63  			PrivateKey: []byte(account.PrivateKey),
    64  			Scopes:     clientScopes,
    65  			TokenURL:   "https://accounts.google.com/o/oauth2/token",
    66  		}
    67  
    68  		// Initiate an http.Client. The following GET request will be
    69  		// authorized and authenticated on the behalf of
    70  		// your service account.
    71  		client = conf.Client(oauth2.NoContext)
    72  
    73  	} else {
    74  		log.Printf("[INFO] Requesting Google token via GCE Service Role...")
    75  		client = &http.Client{
    76  			Transport: &oauth2.Transport{
    77  				// Fetch from Google Compute Engine's metadata server to retrieve
    78  				// an access token for the provided account.
    79  				// If no account is specified, "default" is used.
    80  				Source: google.ComputeTokenSource(""),
    81  			},
    82  		}
    83  
    84  	}
    85  
    86  	log.Printf("[INFO] Instantiating GCE client...")
    87  	var err error
    88  	c.clientCompute, err = compute.New(client)
    89  
    90  	// Set UserAgent
    91  	versionString := "0.0.0"
    92  	// TODO(dcunnin): Use Terraform's version code from version.go
    93  	// versionString := main.Version
    94  	// if main.VersionPrerelease != "" {
    95  	// 	versionString = fmt.Sprintf("%s-%s", versionString, main.VersionPrerelease)
    96  	// }
    97  	c.clientCompute.UserAgent = fmt.Sprintf(
    98  		"(%s %s) Terraform/%s", runtime.GOOS, runtime.GOARCH, versionString)
    99  
   100  	if err != nil {
   101  		return err
   102  	}
   103  
   104  	return nil
   105  }
   106  
   107  // accountFile represents the structure of the account file JSON file.
   108  type accountFile struct {
   109  	PrivateKeyId string `json:"private_key_id"`
   110  	PrivateKey   string `json:"private_key"`
   111  	ClientEmail  string `json:"client_email"`
   112  	ClientId     string `json:"client_id"`
   113  }
   114  
   115  func loadJSON(result interface{}, path string) error {
   116  	f, err := os.Open(path)
   117  	if err != nil {
   118  		return err
   119  	}
   120  	defer f.Close()
   121  
   122  	dec := json.NewDecoder(f)
   123  	return dec.Decode(result)
   124  }