Esempio n. 1
30
func messageListener(o *gomegle.Omegle, logger *log.Logger) {
	for {
		err := o.ShowTyping()
		if err != nil {
			logger.Print(err)
		}

		reader := bufio.NewReader(os.Stdin)
		text, err := reader.ReadString('\n')
		if err != nil {
			err = o.Disconnect()
			if err != nil {
				logger.Fatal(err)
			}
			fmt.Println("- Disconnected")
			ret := o.GetID()
			if ret != nil {
				logger.Fatal(ret)
			}
			continue
		}

		err = o.StopTyping()
		if err != nil {
			logger.Print(err)
		}

		err = o.SendMessage(text)
		if err != nil {
			logger.Fatal(err)
			continue
		}
	}
}
Esempio n. 2
0
func PurgeURL(url string, log *log.Logger) error {
	timeout := time.Duration(2 * time.Second)
	client := &http.Client{
		Timeout: timeout,
	}

	// Invalidate the file
	req, err := http.NewRequest("PURGE", url, nil)
	if err != nil {
		log.Println("Unable to purge " + url + ": " + err.Error())
		return err
	}

	resp, err := client.Do(req)
	if err == nil {
		defer resp.Body.Close()
	}

	if err != nil {
		log.Println("Unable to purge " + url + ": " + err.Error())
		return err
	}

	log.Println("Purging " + url + ": " + resp.Status)

	return nil
}
Esempio n. 3
0
// NewTaskRunner is used to create a new task context
func NewTaskRunner(logger *log.Logger, config *config.Config,
	updater TaskStateUpdater, ctx *driver.ExecContext,
	alloc *structs.Allocation, task *structs.Task,
	consulService *ConsulService) *TaskRunner {

	// Merge in the task resources
	task.Resources = alloc.TaskResources[task.Name]

	// Build the restart tracker.
	tg := alloc.Job.LookupTaskGroup(alloc.TaskGroup)
	if tg == nil {
		logger.Printf("[ERR] client: alloc '%s' for missing task group '%s'", alloc.ID, alloc.TaskGroup)
		return nil
	}
	restartTracker := newRestartTracker(tg.RestartPolicy, alloc.Job.Type)

	tc := &TaskRunner{
		config:         config,
		updater:        updater,
		logger:         logger,
		restartTracker: restartTracker,
		consulService:  consulService,
		ctx:            ctx,
		alloc:          alloc,
		task:           task,
		updateCh:       make(chan *structs.Allocation, 8),
		destroyCh:      make(chan struct{}),
		waitCh:         make(chan struct{}),
	}
	return tc
}
Esempio n. 4
0
// ZmqPubSubProxy Implements a many-to-many device on a zmq PUB-SUB connection
func ZmqPubSubProxy(host string, portIn int, portOut int, logger *log.Logger) {
	xsub, _ := zmq.NewSocket(zmq.SUB)
	xpub, _ := zmq.NewSocket(zmq.PUB)

	defer xsub.Close()
	defer xpub.Close()

	addrIn := fmt.Sprintf("tcp://*:%d", portIn)
	addrOut := fmt.Sprintf("tcp://*:%d", portOut)

	logger.Println("ZMQ XSUB on", addrIn)
	xsub.Bind(addrIn)
	xsub.SetSubscribe("")

	logger.Println("ZMQ XPUB on", addrOut)
	xpub.Bind(addrOut)

	poller := zmq.NewPoller()
	poller.Add(xsub, zmq.POLLIN)

	for {
		// keep looping
		sockets, _ := poller.Poll(5 * time.Second)
		for _, socket := range sockets {
			switch s := socket.Socket; s {
			case xsub:
				ZmqSendMulti(xpub, ZmqRecvMulti(s))
			}
		}
	}
}
Esempio n. 5
0
// Write an CLF formatted access log to 'logger'
func AccessLog(logger *log.Logger) Pipe {
	return func(conn *Conn, req *http.Request) bool {
		var remoteHost = req.RemoteAddr // FIXME
		var ident string = "-"
		var authuser string = "-"
		var now *time.Time = time.UTC()
		var timestamp string = now.Format("[07/Jan/2006:15:04:05 -0700]")
		var request string = fmt.Sprintf("%s %s %s", req.Method, req.RawURL, req.Proto)
		var status int = conn.status
		var size int64 = conn.written
		var referer string = "-"
		var userAgent string = "-"

		if len(req.Referer()) > 0 {
			referer = req.Referer()
		}

		if len(req.UserAgent()) > 0 {
			userAgent = req.UserAgent()
		}

		// Spawn a new goroutine to perform the actual print to the logfile
		// instead of making the pipeline wait.

		go func() {
			logger.Printf("%s %s %s %s \"%s\" %d %d \"%s\" \"%s\"\n",
				remoteHost, ident, authuser, timestamp, request, status, size,
				referer, userAgent)
		}()
		return true
	}
}
Esempio n. 6
0
File: http.go Progetto: stanim/karta
// ListenAndServe creates a context, registers all handlers
// using the provided routes function, and starts listening on the port
func ListenAndServe(l *log.Logger, port string, routes func(*context)) error {
	routes(&context{Logger: l})

	l.Printf("Listening on http://0.0.0.0:%s\n", port)

	return http.ListenAndServe(":"+port, nil)
}
Esempio n. 7
0
func loadImageDataBase(baseDir string, objSrv objectserver.ObjectServer,
	logger *log.Logger) (*ImageDataBase, error) {
	fi, err := os.Stat(baseDir)
	if err != nil {
		return nil, errors.New(
			fmt.Sprintf("Cannot stat: %s\t%s\n", baseDir, err))
	}
	if !fi.IsDir() {
		return nil, errors.New(fmt.Sprintf("%s is not a directory\n", baseDir))
	}
	imdb := new(ImageDataBase)
	imdb.baseDir = baseDir
	imdb.imageMap = make(map[string]*image.Image)
	imdb.objectServer = objSrv
	startTime := time.Now()
	if err = imdb.scanDirectory(""); err != nil {
		return nil, err
	}
	if logger != nil {
		plural := ""
		if imdb.CountImages() != 1 {
			plural = "s"
		}
		logger.Printf("Loaded %d image%s in %s\n",
			imdb.CountImages(), plural, time.Since(startTime))
	}
	return imdb, nil
}
Esempio n. 8
0
// invokeEventScript will execute the given event script with the given
// event. Depending on the event, the semantics of how data are passed
// are a bit different. For all events, the SERF_EVENT environmental
// variable is the type of the event. For user events, the SERF_USER_EVENT
// environmental variable is also set, containing the name of the user
// event that was fired.
//
// In all events, data is passed in via stdin to faciliate piping. See
// the various stdin functions below for more information.
func invokeEventScript(logger *log.Logger, script string, self serf.Member, event serf.Event) error {
	defer metrics.MeasureSince([]string{"agent", "invoke", script}, time.Now())
	var output bytes.Buffer

	// Determine the shell invocation based on OS
	var shell, flag string
	if runtime.GOOS == windows {
		shell = "cmd"
		flag = "/C"
	} else {
		shell = "/bin/sh"
		flag = "-c"
	}

	cmd := exec.Command(shell, flag, script)
	cmd.Args[0] = "serf-event"
	cmd.Env = append(os.Environ(),
		"SERF_EVENT="+event.EventType().String(),
		"SERF_SELF_NAME="+self.Name,
		"SERF_SELF_ROLE="+self.Tags["role"],
	)
	cmd.Stderr = &output
	cmd.Stdout = &output

	// Add all the tags
	for name, val := range self.Tags {
		tag_env := fmt.Sprintf("SERF_TAG_%s=%s", strings.ToUpper(name), val)
		cmd.Env = append(cmd.Env, tag_env)
	}

	stdin, err := cmd.StdinPipe()
	if err != nil {
		return err
	}

	switch e := event.(type) {
	case serf.MemberEvent:
		go memberEventStdin(logger, stdin, &e)
	case serf.UserEvent:
		cmd.Env = append(cmd.Env, "SERF_USER_EVENT="+e.Name)
		cmd.Env = append(cmd.Env, fmt.Sprintf("SERF_USER_LTIME=%d", e.LTime))
		go userEventStdin(logger, stdin, &e)
	default:
		return fmt.Errorf("Unknown event type: %s", event.EventType().String())
	}

	if err := cmd.Start(); err != nil {
		return err
	}

	err = cmd.Wait()
	logger.Printf("[DEBUG] Event '%s' script output: %s",
		event.EventType().String(), output.String())

	if err != nil {
		return err
	}

	return nil
}
Esempio n. 9
0
func (m *MultiLogger) AddLogger(l *log.Logger) {
	m.loggers = append(m.loggers, l)
	//Update the just added logger to be consistent with the style of the
	//rest of the loggers.
	l.SetFlags(m.loggers[0].Flags())
	l.SetPrefix(m.loggers[0].Prefix())
}
Esempio n. 10
0
func LockMetrics(logger *log.Logger, dbs []string, HOSTNAME string, dbConn *sql.DB) []Metric {
	logger.Println("get lock metrics 3.1")

	var metrics = make([]Metric, 0)

	for i := 0; i < len(dbs); i++ {
		metric := Metric{}

		var lockCount int64
		var lockType, lockMode string
		err := dbConn.QueryRow("select locktype,mode, count(*) from pg_locks, pg_database where pg_locks.database = pg_database.oid and pg_database.datname = '"+dbs[i]+"' group by pg_locks.locktype, pg_locks.mode").Scan(&lockType, &lockMode, &lockCount)
		if err != nil {
			logger.Println("error: " + err.Error())
			return metrics
		}

		metric.Hostname = HOSTNAME
		metric.MetricName = "lock_count"
		metric.Units = "count"
		metric.Value = lockCount
		metric.LockType = lockType
		metric.LockMode = lockMode
		metric.DatabaseName = dbs[i]
		metrics = append(metrics, metric)
	}

	return metrics

}
Esempio n. 11
0
func incomingEmail(tc *twilio.Client, req *http.Request, log *log.Logger) {
	if err := verifyMailgunSig(
		req.FormValue("token"),
		req.FormValue("timestamp"),
		req.FormValue("signature"),
	); err != nil {
		log.Println("Mailgun request verification failed:", err)
		return
	}

	dkim := req.FormValue("X-Mailgun-Spf")
	spf := req.FormValue("X-Mailgun-Dkim-Check-Result")
	sender := req.FormValue("sender")
	if dkim != "Pass" || spf != "Pass" || sender != emailTo {
		log.Printf("Email verification failed: SPF: %s, DKIM: %s, addr: %s", spf, dkim, sender)
		return
	}

	params := twilio.MessageParams{Body: req.FormValue("stripped-text")}
	dest := strings.SplitN(req.FormValue("recipient"), "@", 2)[0]
	_, _, err := tc.Messages.Send(smsFrom, dest, params)
	if err != nil {
		log.Println("SMS send failed:", err)
		return
	}
	log.Println("SMS sent to", dest)
}
Esempio n. 12
0
func incomingVoicemail(tc *twilio.Client, m mailgun.Mailgun, req *http.Request, log *log.Logger) {
	log.Printf("%#v", req.Form)
	transReq, err := tc.NewRequest("GET", req.FormValue("TranscriptionUrl")+".json", nil)
	if err != nil {
		log.Println("Transcription req build error:", err)
		return
	}
	var trans transcription
	_, err = tc.Do(transReq, &trans)
	if err != nil {
		log.Println("Transcription req error:", err)
		return
	}

	var buf bytes.Buffer
	err = voicemailTemplate.Execute(&buf, &voicemailData{
		From:      req.FormValue("From"),
		Duration:  trans.Duration,
		Recording: req.FormValue("RecordingUrl"),
		Text:      trans.Text,
	})
	if err != nil {
		log.Println("Email template error:", err)
		return
	}

	msg := mailgun.NewMessage("voicemail@"+emailDomain, "New voicemail from "+req.FormValue("From"), buf.String(), emailTo)
	msg.SetDKIM(true)
	_, _, err = m.Send(msg)
	if err != nil {
		log.Println("Voicemail send error:", err)
		return
	}
}
Esempio n. 13
0
func newObjectServer(baseDir string, logger *log.Logger) (
	*ObjectServer, error) {
	fi, err := os.Stat(baseDir)
	if err != nil {
		return nil, errors.New(
			fmt.Sprintf("Cannot stat: %s\t%s\n", baseDir, err))
	}
	if !fi.IsDir() {
		return nil, errors.New(fmt.Sprintf("%s is not a directory\n", baseDir))
	}
	var objSrv ObjectServer
	objSrv.baseDir = baseDir
	objSrv.sizesMap = make(map[hash.Hash]uint64)
	if logger == nil {
		logger = log.New(os.Stdout, "", log.LstdFlags)
	}
	objSrv.logger = logger
	startTime := time.Now()
	if err = scanDirectory(&objSrv, baseDir, ""); err != nil {
		return nil, err
	}
	plural := ""
	if len(objSrv.sizesMap) != 1 {
		plural = "s"
	}
	logger.Printf("Scanned %d object%s in %s\n",
		len(objSrv.sizesMap), plural, time.Since(startTime))
	return &objSrv, nil
}
Esempio n. 14
0
// WithLog is a decorator that calls Println method
// of provided logger to log received requests.
// Format is:
// <http method> <remote addr> <requested url>
func WithLog(logger *log.Logger, fn http.HandlerFunc) http.HandlerFunc {
	//TODO use constants to define format like in log package.
	return func(w http.ResponseWriter, r *http.Request) {
		logger.Println(r.Method, r.RemoteAddr, r.URL)
		fn(w, r)
	}
}
Esempio n. 15
0
func (p *proberType) proberLoop(defaultProbeInterval uint, logger *log.Logger) {
	// Set the initial probe interval to the global default, if less than the
	// interval for this prober. The probe interval will be gradually increased
	// until the target probe interval is reached. This gives faster probing at
	// startup when higher resolution may be helpful, and then backs off.
	probeInterval := time.Duration(defaultProbeInterval) * time.Second
	if probeInterval > p.probeInterval {
		probeInterval = p.probeInterval
	}
	for {
		p.probeStartTime = time.Now()
		if err := p.prober.Probe(); err != nil {
			logger.Println(err)
		}
		probeDuration := time.Since(p.probeStartTime)
		p.probeTimeDistribution.Add(probeDuration)
		time.Sleep(probeInterval - probeDuration)
		// Increase the probe interval until the interval for this prober is
		// reached.
		if probeInterval < p.probeInterval {
			probeInterval += time.Duration(defaultProbeInterval) * time.Second
		}
		if probeInterval > p.probeInterval {
			probeInterval = p.probeInterval
		}
	}
}
Esempio n. 16
0
func validateConfig(logger *log.Logger) {
	c := nbadConfig

	if c.MessageInitBufferTimeSeconds > c.MessageCacheTTLInSeconds {
		logger.Fatalln("init buffer ttl cannot be greater than message cache ttl")
	}
}
Esempio n. 17
0
func GetArtifact(destDir, source, checksum string, logger *log.Logger) (string, error) {
	if source == "" {
		return "", fmt.Errorf("Source url is empty in Artifact Getter")
	}
	u, err := url.Parse(source)
	if err != nil {
		return "", err
	}

	// if checksum is seperate, apply to source
	if checksum != "" {
		source = strings.Join([]string{source, fmt.Sprintf("checksum=%s", checksum)}, "?")
		logger.Printf("[DEBUG] client.getter: Applying checksum to Artifact Source URL, new url: %s", source)
	}

	artifactFile := filepath.Join(destDir, path.Base(u.Path))
	if err := gg.GetFile(artifactFile, source); err != nil {
		return "", fmt.Errorf("Error downloading artifact: %s", err)
	}

	// Add execution permissions to the newly downloaded artifact
	if runtime.GOOS != "windows" {
		if err := syscall.Chmod(artifactFile, 0755); err != nil {
			logger.Printf("[ERR] driver.raw_exec: Error making artifact executable: %s", err)
		}
	}
	return artifactFile, nil
}
Esempio n. 18
0
func addObjects(conn *srpc.Conn, adder ObjectAdder, logger *log.Logger) error {
	defer conn.Flush()
	decoder := gob.NewDecoder(conn)
	encoder := gob.NewEncoder(conn)
	numAdded := 0
	numObj := 0
	for ; ; numObj++ {
		var request objectserver.AddObjectRequest
		var response objectserver.AddObjectResponse
		if err := decoder.Decode(&request); err != nil {
			if err == io.EOF || err == io.ErrUnexpectedEOF {
				break
			}
			return err
		}
		if request.Length < 1 {
			break
		}
		response.Hash, response.Added, response.Error =
			adder.AddObject(conn, request.Length, request.ExpectedHash)
		if response.Added {
			numAdded++
		}
		if err := encoder.Encode(response); err != nil {
			return err
		}
		if response.Error != nil {
			logger.Printf("AddObjects(): failed, %d of %d are new objects %s",
				numAdded, numObj, response.Error.Error())
			return nil
		}
	}
	logger.Printf("AddObjects(): %d of %d are new objects", numAdded, numObj)
	return nil
}
Esempio n. 19
0
func (e *subscriptionEntity) addV2(name string, connected bool,
	statusChannel chan<- *PNStatus,
	messageChannel chan<- *PNMessageResult,
	presenceChannel chan<- *PNPresenceEventResult, logger *log.Logger) {

	logger.Printf("INFO: ITEMS: Adding item '%s', connected: %t", name, connected)

	e.Lock()
	defer e.Unlock()

	if _, ok := e.items[name]; ok {
		logger.Printf("INFO: ITEMS: Item '%s' is not added since it's already exists", name)
		return
	}

	item := &subscriptionItem{
		Name:            name,
		StatusChannel:   statusChannel,
		MessageChannel:  messageChannel,
		PresenceChannel: presenceChannel,
		Connected:       connected,
		IsV2:            true,
	}

	e.items[name] = item
}
Esempio n. 20
0
// DefaultFormat returns a middleware that logs http requests
// to the given logger using the default log format.
func DefaultFormat(l *log.Logger) httpmux.MiddlewareFunc {
	return func(next http.HandlerFunc) http.HandlerFunc {
		return func(w http.ResponseWriter, r *http.Request) {
			start := time.Now()
			rw := NewResponseWriter(w)
			next(rw, r)
			b := getBuffer()
			b.WriteString(r.Proto)
			b.Write([]byte(" "))
			b.WriteString(strconv.Itoa(rw.Code()))
			b.Write([]byte(" "))
			b.WriteString(r.Method)
			b.Write([]byte(" "))
			b.WriteString(r.URL.RequestURI())
			b.Write([]byte(" from "))
			b.WriteString(r.RemoteAddr)
			b.Write([]byte(" "))
			fmt.Fprintf(b, "%q", r.Header.Get("User-Agent"))
			b.Write([]byte(" "))
			b.WriteString(strconv.Itoa(rw.Bytes()))
			b.Write([]byte(" bytes in "))
			b.WriteString(time.Since(start).String())
			if err := httpmux.Context(r).Value(ErrorID); err != nil {
				fmt.Fprintf(b, " err: %v", err)
			}
			l.Print(b.String())
			putBuffer(b)
		}
	}
}
Esempio n. 21
0
func runMain(logger *log.Logger) {
	parseFlags()

	var err error
	var wd string

	projectPath = srcPath + projectFlag + "/"

	if err = os.Chdir(projectPath); err != nil {
		logger.Printf("\n**invalid project path '%s'\n%s\n", projectFlag, err)
		help()
		os.Exit(1)
	}

	if debugFlag {
		wd, err = os.Getwd()
		if err != nil {
			fmt.Println(err)
		}

		logger.Println("Working DIR:", wd)
	}

	testFiles(logger)
}
Esempio n. 22
0
func logPrintf(l *log.Logger, format string, v ...interface{}) {
	if l == nil {
		log.Printf(format, v...)
	} else {
		l.Printf(format, v...)
	}
}
Esempio n. 23
0
func watchDaemon(mdbFileName string, mdbChannel chan<- *mdb.Mdb,
	logger *log.Logger) {
	var lastStat syscall.Stat_t
	var lastMdb *mdb.Mdb
	for ; ; time.Sleep(time.Second) {
		var stat syscall.Stat_t
		if err := syscall.Stat(mdbFileName, &stat); err != nil {
			logger.Printf("Error stating file: %s\t%s\n", mdbFileName, err)
			continue
		}
		stat.Atim = lastStat.Atim
		if stat != lastStat {
			mdb := loadFile(mdbFileName, logger)
			if mdb == nil {
				continue
			}
			compareStartTime := time.Now()
			if lastMdb == nil || !compare(lastMdb, mdb) {
				if lastMdb != nil {
					mdbCompareTimeDistribution.Add(time.Since(compareStartTime))
				}
				mdbChannel <- mdb
				lastMdb = mdb
			}
			lastStat = stat
		}
	}
}
Esempio n. 24
0
func PostIdeaHandler(req *http.Request, render render.Render, log *log.Logger) {
	log.Println("Receive post data.")
	name := req.FormValue("name")
	email := req.FormValue("email")
	link := req.FormValue("link")
	content := req.FormValue("content")
	log.Println("Name: " + name)
	log.Println("Email: " + email)
	log.Println("Link: " + link)
	log.Println("Content: " + content)
	if len(name) == 0 {
		render.JSON(400, map[string]interface{}{"error": 1, "message": "Empty name."})
		return
	}
	if len(email) == 0 {
		render.JSON(400, map[string]interface{}{"error": 2, "message": "Empty email."})
		return
	}
	if len(content) == 0 {
		render.JSON(400, map[string]interface{}{"error": 3, "message": "Empty content."})
		return
	}
	AddIdea(name, email, link, content)
	render.JSON(200, map[string]interface{}{"error": 0})
}
Esempio n. 25
0
func waitForNotifyEvents(watcher *fsnotify.Watcher, pathname string,
	channel chan<- io.ReadCloser, logger *log.Logger) {
	if file, err := os.Open(pathname); err == nil {
		channel <- file
	}
	for {
		select {
		case event, ok := <-watcher.Event:
			if !ok {
				return
			}
			if event.Name != pathname {
				continue
			}
			if file, err := os.Open(pathname); err != nil {
				if os.IsNotExist(err) {
					continue
				}
				if logger != nil {
					logger.Printf("Error opening file: %s: %s\n", pathname, err)
				}
			} else {
				channel <- file
			}
		case err, ok := <-watcher.Error:
			if !ok {
				return
			}
			logger.Println("Error with watcher:", err)
		}
	}
}
Esempio n. 26
0
// Sends data on stdin for a user event. The stdin simply contains the
// payload (if any) of the event.
func userEventStdin(logger *log.Logger, stdin io.WriteCloser, e *serf.UserEvent) {
	defer stdin.Close()
	if _, err := stdin.Write(e.Payload); err != nil {
		logger.Printf("[ERR] Error writing user event payload: %s", err)
		return
	}
}
Esempio n. 27
0
func timeMe(logger *log.Logger, label string) func() {
	t0 := time.Now()
	logger.Printf("%s: start", label)
	return func() {
		logger.Printf("%s: took %v", label, time.Since(t0))
	}
}
Esempio n. 28
0
func NewSessionManager(logger *log.Logger) *SessionManager {
	manager := new(SessionManager)
	manager.sessionMap = make(map[string]*Session)
	manager.timeout = 300
	go func(manager *SessionManager) {
		for {
			l := time.Now().Unix()
			for id, v := range (*manager).sessionMap {
				if v.expire < l {
					// expire
					if logger != nil {
						logger.Printf("Expired session(id:%s)", id)
					}
					f := (*manager).onEnd
					if f != nil {
						f((*manager).sessionMap[id])
					}
					delete((*manager).sessionMap, id)
				}
			}
			time.Sleep(1000000000)
		}
	}(manager)
	return manager
}
Esempio n. 29
0
func scannerDaemon(rootDirectoryName string, cacheDirectoryName string,
	configuration *Configuration, fsChannel chan<- *FileSystem,
	logger *log.Logger) {
	runtime.LockOSThread()
	loweredPriority := false
	var oldFS FileSystem
	for {
		fs, err := scanFileSystem(rootDirectoryName, cacheDirectoryName,
			configuration, &oldFS)
		if err != nil {
			if err.Error() == "DisableScan" {
				disableScanAcknowledge <- true
				<-disableScanAcknowledge
				continue
			}
			logger.Printf("Error scanning: %s\n", err)
		} else {
			oldFS.InodeTable = fs.InodeTable
			oldFS.DirectoryInode = fs.DirectoryInode
			fsChannel <- fs
			runtime.GC()
			if !loweredPriority {
				syscall.Setpriority(syscall.PRIO_PROCESS, 0, 15)
				loweredPriority = true
			}
		}
	}
}
Esempio n. 30
0
// gceDiscoverZones discovers a list of zones from a supplied zone pattern, or
// all of the zones available to a project.
func gceDiscoverZones(logger *log.Logger, ctx context.Context, computeService *compute.Service, project, pattern string) ([]string, error) {
	var zones []string

	if pattern != "" {
		logger.Printf("[INFO] agent: Discovering zones for project %s matching pattern: %s", project, pattern)
	} else {
		logger.Printf("[INFO] agent: Discovering all zones available to project: %s", project)
	}

	call := computeService.Zones.List(project)
	if pattern != "" {
		call = call.Filter(fmt.Sprintf("name eq %s", pattern))
	}

	if err := call.Pages(ctx, func(page *compute.ZoneList) error {
		for _, v := range page.Items {
			zones = append(zones, v.Name)
		}
		return nil
	}); err != nil {
		return zones, err
	}

	logger.Printf("[INFO] agent: Discovered GCE zones: %s", strings.Join(zones, ", "))
	return zones, nil
}