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