func waitForGuestAttribute()

in step_wait_for_instances_signal.go [237:304]


func waitForGuestAttribute(s *Step, project, zone, name string, ga *GuestAttribute, interval time.Duration) DError {
	var keyTokens []string
	if ga.Namespace != "" {
		keyTokens = append(keyTokens, ga.Namespace)
	}
	keyTokens = append(keyTokens, ga.KeyName)
	varkey := strings.Join(keyTokens, "/")

	w := s.w
	msg := fmt.Sprintf("Instance %q: watching for key %s", name, varkey)
	if ga.SuccessValue != "" {
		msg += fmt.Sprintf(", SuccessValue: %q", ga.SuccessValue)
	}
	w.LogStepInfo(s.name, "WaitForInstancesSignal", msg+".")
	// The limit for querying guest attributes is documented as 10 queries/minute.
	minInterval, err := time.ParseDuration("6s")
	if err == nil && interval < minInterval {
		interval = minInterval
	}
	tick := time.Tick(interval)
	var errs int
	for {
		select {
		case <-s.w.Cancel:
			return nil
		case <-tick:
			resp, err := w.ComputeClient.GetGuestAttributes(project, zone, name, "", varkey)
			if err != nil {
				if apiErr, ok := err.(*googleapi.Error); ok && apiErr.Code == 404 {
					// 404 is OK, that means the key isn't present yet. Retry until timeout.
					continue
				}
				status, sErr := w.ComputeClient.InstanceStatus(project, zone, name)
				if sErr != nil {
					err = fmt.Errorf("%v, error getting InstanceStatus: %v", err, sErr)
					errs++
				} else {
					errs = 0
				}

				// Wait until machine restarts to get Guest Attributes
				if status == "TERMINATED" || status == "STOPPED" || status == "STOPPING" {
					continue
				}

				// Permit up to 3 consecutive non-404 errors getting guest attrs so long as we can get instance
				// status.
				if errs < 3 {
					continue
				}

				return Errf("WaitForInstancesSignal: instance %q: error getting guest attribute: %v", name, err)
			}

			if ga.SuccessValue != "" {
				if resp.VariableValue != ga.SuccessValue {
					errMsg := strings.TrimSpace(resp.VariableValue)
					format := "WaitForInstancesSignal bad guest attribute value found for %q: %q"
					return Errf(format, name, errMsg)
				}
				w.LogStepInfo(s.name, "WaitForInstancesSignal", "Instance %q: SuccessValue found for key %q", name, ga.KeyName)
				return nil
			}
			w.LogStepInfo(s.name, "WaitForInstancesSignal", "Instance %q found key %q", name, ga.KeyName)
			return nil
		}
	}
}