// Returns an implementation of a Google Cloud Logging (GCL) sink. func new() (sink_api.ExternalSink, error) { // TODO: Retry OnGCE call for ~15 seconds before declaring failure. time.Sleep(3 * time.Second) // Only support GCE for now. if !metadata.OnGCE() { return nil, fmt.Errorf("The Google Cloud Logging (GCL) sink failed to start: this process must be running on Google Compute Engine (GCE)") } // Detect project ID projectId, err := metadata.ProjectID() if err != nil { return nil, err } glog.Infof("Project ID for GCL sink is: %q\r\n", projectId) // Check for required auth scopes err = gce.VerifyAuthScope(GCLAuthScope) if err != nil { return nil, err } impl := &gclSink{ projectId: projectId, httpClient: &http.Client{}, } // Get an initial token. err = impl.refreshToken() if err != nil { return nil, err } return impl, nil }
// Returns a thread-compatible implementation of GCM interactions. func NewSink() (sink_api.ExternalSink, error) { // TODO: Retry OnGCE call for ~15 seconds before declaring failure. time.Sleep(3 * time.Second) // Only support GCE for now. if !metadata.OnGCE() { return nil, fmt.Errorf("the GCM sink is currently only supported on GCE") } // Detect project. project, err := metadata.ProjectID() if err != nil { return nil, err } // Check required service accounts err = checkServiceAccounts() if err != nil { return nil, err } impl := &gcmSink{ project: project, exportedMetrics: make(map[string]sink_api.MetricDescriptor), } // Get an initial token. err = impl.refreshToken() if err != nil { return nil, err } return impl, nil }
func (cs computeSource) Token() (*oauth2.Token, error) { if !metadata.OnGCE() { return nil, errors.New("oauth2/google: can't get a token from the metadata service; not running on GCE") } acct := cs.account if acct == "" { acct = "default" } tokenJSON, err := metadata.Get("instance/service-accounts/" + acct + "/token") if err != nil { return nil, err } var res struct { AccessToken string `json:"access_token"` ExpiresInSec int `json:"expires_in"` TokenType string `json:"token_type"` } err = json.NewDecoder(strings.NewReader(tokenJSON)).Decode(&res) if err != nil { return nil, fmt.Errorf("oauth2/google: invalid token JSON from metadata: %v", err) } if res.ExpiresInSec == 0 || res.AccessToken == "" { return nil, fmt.Errorf("oauth2/google: incomplete token received from metadata") } return &oauth2.Token{ AccessToken: res.AccessToken, TokenType: res.TokenType, Expiry: time.Now().Add(time.Duration(res.ExpiresInSec) * time.Second), }, nil }
func getGceIp(hostname string) (string, error) { out, err := exec.Command("gcutil", "getinstance", hostname).CombinedOutput() if err != nil { return "", err } // Use the internal IP within GCE and the external one outside. var matches []string if metadata.OnGCE() { matches = gceInternalIpRegexp.FindStringSubmatch(string(out)) } else { matches = gceExternalIpRegexp.FindStringSubmatch(string(out)) } if len(matches) == 0 { return "", fmt.Errorf("failed to find IP from output %q", string(out)) } return matches[1], nil }
// DefaultTokenSource is a token source that uses // "Application Default Credentials". // // It looks for credentials in the following places, // preferring the first location found: // // 1. A JSON file whose path is specified by the // GOOGLE_APPLICATION_CREDENTIALS environment variable. // 2. A JSON file in a location known to the gcloud command-line tool. // On Windows, this is %APPDATA%/gcloud/application_default_credentials.json. // On other systems, $HOME/.config/gcloud/application_default_credentials.json. // 3. On Google App Engine it uses the appengine.AccessToken function. // 4. On Google Compute Engine, it fetches credentials from the metadata server. // (In this final case any provided scopes are ignored.) // // For more details, see: // https://developers.google.com/accounts/docs/application-default-credentials // func DefaultTokenSource(ctx context.Context, scope ...string) (oauth2.TokenSource, error) { // First, try the environment variable. const envVar = "GOOGLE_APPLICATION_CREDENTIALS" if filename := os.Getenv(envVar); filename != "" { ts, err := tokenSourceFromFile(ctx, filename, scope) if err != nil { return nil, fmt.Errorf("google: error getting credentials using %v environment variable: %v", envVar, err) } return ts, nil } // Second, try a well-known file. filename := wellKnownFile() _, err := os.Stat(filename) if err == nil { ts, err2 := tokenSourceFromFile(ctx, filename, scope) if err2 == nil { return ts, nil } err = err2 } else if os.IsNotExist(err) { err = nil // ignore this error } if err != nil { return nil, fmt.Errorf("google: error getting credentials using well-known file (%v): %v", filename, err) } // Third, if we're on Google App Engine use those credentials. if appengineTokenFunc != nil { return AppEngineTokenSource(ctx, scope...), nil } // Fourth, if we're on Google Compute Engine use the metadata server. if metadata.OnGCE() { return ComputeTokenSource(""), nil } // None are found; return helpful error. const url = "https://developers.google.com/accounts/docs/application-default-credentials" return nil, fmt.Errorf("google: could not find default credentials. See %v for more information.", url) }
// Gets the IP of the specified GCE instance. func GetGceIp(hostname string) (string, error) { if hostname == "localhost" { return "127.0.0.1", nil } out, err := exec.Command("gcloud", "compute", "instances", "describe", GetZoneFlag(), hostname).CombinedOutput() if err != nil { return "", fmt.Errorf("failed to get instance information for %q with error %v and output %s", hostname, err, string(out)) } // Use the internal IP within GCE and the external one outside. var matches []string if metadata.OnGCE() { matches = gceInternalIpRegexp.FindStringSubmatch(string(out)) } else { matches = gceExternalIpRegexp.FindStringSubmatch(string(out)) } if len(matches) == 0 { return "", fmt.Errorf("failed to find IP from output %q", string(out)) } return matches[1], nil }
// Returns a thread-compatible implementation of GCM interactions. func NewCore() (*GcmCore, error) { // TODO: Retry OnGCE call for ~15 seconds before declaring failure. time.Sleep(3 * time.Second) // Only support GCE for now. if !metadata.OnGCE() { return nil, fmt.Errorf("the GCM sink is currently only supported on GCE") } // Detect project. project, err := metadata.ProjectID() if err != nil { return nil, err } // Check required service accounts err = gce.VerifyAuthScope(GCLAuthScope) if err != nil { return nil, err } core := &GcmCore{ project: project, exportedMetrics: make(map[string]metricDescriptor), lastValue: gcstore.New(time.Hour), } // Get an initial token. err = core.refreshToken() if err != nil { return nil, err } if err := core.listMetrics(); err != nil { return nil, err } return core, nil }
func onGCE() bool { return metadata.OnGCE() }