Пример #1
0
// 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
}
Пример #2
0
// 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
}
Пример #3
0
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
}
Пример #4
0
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
}
Пример #5
0
// 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)
}
Пример #6
0
// 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
}
Пример #7
0
// 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
}
Пример #8
0
func onGCE() bool {
	return metadata.OnGCE()
}