func init() { if !env.OnGCE() { return } osutil.RegisterConfigDirFunc(func() string { v, _ := metadata.InstanceAttributeValue("camlistore-config-dir") if v == "" { return v } return path.Clean("/gcs/" + strings.TrimPrefix(v, "gs://")) }) jsonconfig.RegisterFunc("_gce_instance_meta", func(c *jsonconfig.ConfigParser, v []interface{}) (interface{}, error) { if len(v) != 1 { return nil, errors.New("only 1 argument supported after _gce_instance_meta") } attr, ok := v[0].(string) if !ok { return nil, errors.New("expected argument after _gce_instance_meta to be a string") } val, err := metadata.InstanceAttributeValue(attr) if err != nil { return nil, fmt.Errorf("error reading GCE instance attribute %q: %v", attr, err) } return val, nil }) }
func NewGceCloudConfig() *GceCloudConfig { userData, err := metadata.InstanceAttributeValue("user-data") if err != nil { log.Errorf("Could not retrieve user-data: %s", err) } projectSSHKeys, err := metadata.ProjectAttributeValue("sshKeys") if err != nil { log.Errorf("Could not retrieve project SSH Keys: %s", err) } instanceSSHKeys, err := metadata.InstanceAttributeValue("sshKeys") if err != nil { log.Errorf("Could not retrieve instance SSH Keys: %s", err) } nonUserDataSSHKeysRaw := projectSSHKeys + "\n" + instanceSSHKeys nonUserDataSSHKeys := gceSshKeyFormatter(nonUserDataSSHKeysRaw) gceCC := &GceCloudConfig{ FileName: gceCloudConfigFile, UserData: userData, NonUserDataSSHKeys: nonUserDataSSHKeys, } return gceCC }
// metadataValue returns the GCE metadata instance value for the given key. // If the metadata is not defined, the returned string is empty. // // If not running on GCE, it falls back to using environment variables // for local development. func metadataValue(key string) string { // The common case (on GCE, but not in Kubernetes): if metadata.OnGCE() && !inKube { v, err := metadata.InstanceAttributeValue(key) if _, notDefined := err.(metadata.NotDefinedError); notDefined { return "" } if err != nil { log.Fatalf("metadata.InstanceAttributeValue(%q): %v", key, err) } return v } // Else allow use of environment variables to fake // metadata keys, for Kubernetes pods or local testing. envKey := "META_" + strings.Replace(key, "-", "_", -1) v := os.Getenv(envKey) // Respect curl-style '@' prefix to mean the rest is a filename. if strings.HasPrefix(v, "@") { slurp, err := ioutil.ReadFile(v[1:]) if err != nil { log.Fatalf("Error reading file for GCEMETA_%v: %v", key, err) } return string(slurp) } if v == "" { log.Printf("Warning: not running on GCE, and no %v environment variable defined", envKey) } return v }
// Build list of Servers as defined in the Configuration func buildServersMap() { Servers = make(map[MailSender]bool) for _, conf := range config.MailServers { if Debug { InfoLog.Println("Adding Server: " + conf.Name) } var server MailSender if conf.Name == "MailGun" { server = &MailGunServer{conf} } else if conf.Name == "SendGrid" { server = &SendGridServer{conf} } else if conf.Name == "Mandrill" { server = &MandrillServer{conf} } else if conf.Name == "AWS" { server = &AwsServer{conf} } else { if Debug { ErrorLog.Println("Unknown MailServer: " + conf.Name) } continue } var apiKey string if gce { apiKey, _ = metadata.InstanceAttributeValue(conf.Name) } else { apiKey = conf.ApiKey } server.SetKey(apiKey) Servers[server] = false } checkServers() }
func detectGCE() { if !metadata.OnGCE() { return } v, _ := metadata.InstanceAttributeValue("camlistore-config-dir") isGCE = v != "" }
func buildletURL() string { if !metadata.OnGCE() { if v := os.Getenv("META_BUILDLET_BINARY_URL"); v != "" { return v } sleepFatalf("Not on GCE, and no META_BUILDLET_BINARY_URL specified.") } v, err := metadata.InstanceAttributeValue(attr) if err != nil { sleepFatalf("Failed to look up %q attribute value: %v", attr, err) } return v }
func main() { // Parse command line args flag.BoolVar(&Debug, "debug", true, "Turn on debug logging.") flag.StringVar(&Password, "password", "", "Password needed by users to send emails.") flag.Parse() // Check GCE for Password if gce { pw, _ := metadata.InstanceAttributeValue("emailPW") if len(pw) > 0 { Password = pw } } // Initiate throttle throttle = make(chan int, config.EmailThrottle) buildServersMap() initiatePing() // Create Database datastore = &MongoDatastore{} if datastore.Ping() { InfoLog.Println("MongoDB running.") } else { ErrorLog.Println("MongoDB connection unsuccessful.") } http.HandleFunc("/", errorHandler(rootHandler)) http.HandleFunc("/messages/", errorHandler(messageHandler)) http.HandleFunc("/status", errorHandler(statusHandler)) http.HandleFunc("/contacts/", errorHandler(contactsHandler)) // To Serve CSS and JS files http.Handle("/resources/", http.StripPrefix("/resources/", http.FileServer(http.Dir("resources")))) // Read Port from Env port := os.Getenv("PORT") if port == "" { port = "8123" } if Debug { InfoLog.Println("Server running on Port:", port) } http.ListenAndServe(":"+port, nil) }
func (db *MongoDatastore) Ping() bool { if gce { mongoUrl, _ = metadata.InstanceAttributeValue("mongoUrl") if Debug { InfoLog.Println("Mongo URL pulled from GCE Metadata: " + mongoUrl) } } session, err := mgo.Dial(mongoUrl) if err != nil { return false } session.Close() return true }
func main() { flag.Parse() s := NewServer(*resolverAddr, *refreshPeriod) http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { if r.URL.Path == "/" && *anusEnabled { anus(w, r) return } s.ServeHTTP(w, r) }) if *httpsAddr != "" { if !metadata.OnGCE() { log.Fatal("Not on GCE. HTTPS only supported on GCE using letsencrypt. Exiting.") } v := func(key string) string { v, err := metadata.InstanceAttributeValue(key) if err != nil { log.Fatalf("Couldn't read %q metadata value: %v", key, err) } return v } var m letsencrypt.Manager if err := letscloud.Cache(&m, v("letscloud-get-url"), v("letscloud-put-url")); err != nil { log.Fatal(err) } srv := &http.Server{ Addr: *httpsAddr, TLSConfig: &tls.Config{GetCertificate: m.GetCertificate}, } go func() { log.Println("Starting HTTPS server on", *httpsAddr) log.Fatal(srv.ListenAndServeTLS("", "")) }() } if *httpAddr != "" { var h http.Handler if *redirectHTTP { h = http.HandlerFunc(letsencrypt.RedirectHTTP) } go func() { log.Println("Starting HTTP server on", *httpAddr) log.Fatal(http.ListenAndServe(*httpAddr, h)) }() } select {} }
func main() { buildletURL, err := metadata.InstanceAttributeValue(attr) if err != nil { sleepFatalf("Failed to look up %q attribute value: %v", attr, err) } target := filepath.FromSlash("./buildlet.exe") if err := download(target, buildletURL); err != nil { sleepFatalf("Downloading %s: %v", buildletURL, err) } cmd := exec.Command(target) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { sleepFatalf("Error running buildlet: %v", err) } }
func windowsBaseEnv() (e []string) { e = append(e, "GOBUILDEXIT=1") // exit all.bat with completion status btype, err := metadata.InstanceAttributeValue("builder-type") if err != nil { log.Fatalf("Failed to get builder-type: %v", err) return nil } is64 := strings.HasPrefix(btype, "windows-amd64") for _, pair := range os.Environ() { const pathEq = "PATH=" if hasPrefixFold(pair, pathEq) { e = append(e, "PATH="+windowsPath(pair[len(pathEq):], is64)) } else { e = append(e, pair) } } return e }
func buildletURL() string { // The buildlet download URL is located in an env var // when the buildlet is not running on GCE, or is running // on Kubernetes. if !metadata.OnGCE() || os.Getenv("IN_KUBERNETES") == "1" { if v := os.Getenv("META_BUILDLET_BINARY_URL"); v != "" { return v } if onScaleway { if scalewayMeta.IsStaging() { return "https://storage.googleapis.com/dev-go-builder-data/buildlet.linux-arm" } else { return "https://storage.googleapis.com/go-builder-data/buildlet.linux-arm" } } sleepFatalf("Not on GCE, and no META_BUILDLET_BINARY_URL specified.") } v, err := metadata.InstanceAttributeValue(attr) if err != nil { sleepFatalf("Failed to look up %q attribute value: %v", attr, err) } return v }
// DefaultEnvConfig returns the default configuration when running on a known // environment. Currently this just includes Google Compute Engine. // If the environment isn't known (nil, nil) is returned. func DefaultEnvConfig() (*Config, error) { if !env.OnGCE() { return nil, nil } auth := "none" user, _ := metadata.InstanceAttributeValue("camlistore-username") pass, _ := metadata.InstanceAttributeValue("camlistore-password") confBucket, err := metadata.InstanceAttributeValue("camlistore-config-dir") if confBucket == "" || err != nil { return nil, fmt.Errorf("VM instance metadata key 'camlistore-config-dir' not set: %v", err) } blobBucket, err := metadata.InstanceAttributeValue("camlistore-blob-dir") if blobBucket == "" || err != nil { return nil, fmt.Errorf("VM instance metadata key 'camlistore-blob-dir' not set: %v", err) } if user != "" && pass != "" { auth = "userpass:"******":" + pass } if v := osutil.SecretRingFile(); !strings.HasPrefix(v, "/gcs/") { return nil, fmt.Errorf("Internal error: secret ring path on GCE should be at /gcs/, not %q", v) } keyId, secRing, err := getOrMakeKeyring() if err != nil { return nil, err } ipOrHost, _ := metadata.ExternalIP() host, _ := metadata.InstanceAttributeValue("camlistore-hostname") if host != "" && host != "localhost" { ipOrHost = host } highConf := &serverconfig.Config{ Auth: auth, BaseURL: fmt.Sprintf("https://%s", ipOrHost), HTTPS: true, Listen: "0.0.0.0:443", Identity: keyId, IdentitySecretRing: secRing, GoogleCloudStorage: ":" + strings.TrimPrefix(blobBucket, "gs://"), DBNames: map[string]string{}, PackRelated: true, // SourceRoot is where we look for the UI js/css/html files, and the Closure resources. // Must be in sync with misc/docker/server/Dockerfile. SourceRoot: "/camlistore", } // Detect a linked Docker MySQL container. It must have alias "mysqldb". if v := os.Getenv("MYSQLDB_PORT"); strings.HasPrefix(v, "tcp://") { hostPort := strings.TrimPrefix(v, "tcp://") highConf.MySQL = "root@" + hostPort + ":" // no password highConf.DBNames["queue-sync-to-index"] = "sync_index_queue" highConf.DBNames["ui_thumbcache"] = "ui_thumbmeta_cache" highConf.DBNames["blobpacked_index"] = "blobpacked_index" } else { // TODO: also detect Cloud SQL. highConf.KVFile = "/index.kv" } return genLowLevelConfig(highConf) }