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 }