github.com/econnell/terraform@v0.5.4-0.20150722160631-78eb236786a4/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 "google.golang.org/api/container/v1" 18 "google.golang.org/api/dns/v1" 19 "google.golang.org/api/storage/v1" 20 ) 21 22 // Config is the configuration structure used to instantiate the Google 23 // provider. 24 type Config struct { 25 AccountFile string 26 Project string 27 Region string 28 29 clientCompute *compute.Service 30 clientContainer *container.Service 31 clientDns *dns.Service 32 clientStorage *storage.Service 33 } 34 35 func (c *Config) loadAndValidate() error { 36 var account accountFile 37 38 // TODO: validation that it isn't blank 39 if c.AccountFile == "" { 40 c.AccountFile = os.Getenv("GOOGLE_ACCOUNT_FILE") 41 } 42 if c.Project == "" { 43 c.Project = os.Getenv("GOOGLE_PROJECT") 44 } 45 if c.Region == "" { 46 c.Region = os.Getenv("GOOGLE_REGION") 47 } 48 49 var client *http.Client 50 51 if c.AccountFile != "" { 52 if err := loadJSON(&account, c.AccountFile); err != nil { 53 return fmt.Errorf( 54 "Error loading account file '%s': %s", 55 c.AccountFile, 56 err) 57 } 58 59 clientScopes := []string{ 60 "https://www.googleapis.com/auth/compute", 61 "https://www.googleapis.com/auth/cloud-platform", 62 "https://www.googleapis.com/auth/ndev.clouddns.readwrite", 63 "https://www.googleapis.com/auth/devstorage.full_control", 64 } 65 66 // Get the token for use in our requests 67 log.Printf("[INFO] Requesting Google token...") 68 log.Printf("[INFO] -- Email: %s", account.ClientEmail) 69 log.Printf("[INFO] -- Scopes: %s", clientScopes) 70 log.Printf("[INFO] -- Private Key Length: %d", len(account.PrivateKey)) 71 72 conf := jwt.Config{ 73 Email: account.ClientEmail, 74 PrivateKey: []byte(account.PrivateKey), 75 Scopes: clientScopes, 76 TokenURL: "https://accounts.google.com/o/oauth2/token", 77 } 78 79 // Initiate an http.Client. The following GET request will be 80 // authorized and authenticated on the behalf of 81 // your service account. 82 client = conf.Client(oauth2.NoContext) 83 84 } else { 85 log.Printf("[INFO] Requesting Google token via GCE Service Role...") 86 client = &http.Client{ 87 Transport: &oauth2.Transport{ 88 // Fetch from Google Compute Engine's metadata server to retrieve 89 // an access token for the provided account. 90 // If no account is specified, "default" is used. 91 Source: google.ComputeTokenSource(""), 92 }, 93 } 94 95 } 96 97 // Build UserAgent 98 versionString := "0.0.0" 99 // TODO(dcunnin): Use Terraform's version code from version.go 100 // versionString := main.Version 101 // if main.VersionPrerelease != "" { 102 // versionString = fmt.Sprintf("%s-%s", versionString, main.VersionPrerelease) 103 // } 104 userAgent := fmt.Sprintf( 105 "(%s %s) Terraform/%s", runtime.GOOS, runtime.GOARCH, versionString) 106 107 var err error 108 109 log.Printf("[INFO] Instantiating GCE client...") 110 c.clientCompute, err = compute.New(client) 111 if err != nil { 112 return err 113 } 114 c.clientCompute.UserAgent = userAgent 115 116 log.Printf("[INFO] Instantiating GKE client...") 117 c.clientContainer, err = container.New(client) 118 if err != nil { 119 return err 120 } 121 c.clientContainer.UserAgent = userAgent 122 123 log.Printf("[INFO] Instantiating Google Cloud DNS client...") 124 c.clientDns, err = dns.New(client) 125 if err != nil { 126 return err 127 } 128 c.clientDns.UserAgent = userAgent 129 130 log.Printf("[INFO] Instantiating Google Storage Client...") 131 c.clientStorage, err = storage.New(client) 132 if err != nil { 133 return err 134 } 135 c.clientStorage.UserAgent = userAgent 136 137 return nil 138 } 139 140 // accountFile represents the structure of the account file JSON file. 141 type accountFile struct { 142 PrivateKeyId string `json:"private_key_id"` 143 PrivateKey string `json:"private_key"` 144 ClientEmail string `json:"client_email"` 145 ClientId string `json:"client_id"` 146 } 147 148 func loadJSON(result interface{}, path string) error { 149 f, err := os.Open(path) 150 if err != nil { 151 return err 152 } 153 defer f.Close() 154 155 dec := json.NewDecoder(f) 156 return dec.Decode(result) 157 }