// execute an explicit task reconciliation, as per http://mesos.apache.org/documentation/latest/reconciliation/ func (k *KubernetesScheduler) explicitlyReconcileTasks(driver bindings.SchedulerDriver, taskToSlave map[string]string, cancel <-chan struct{}) error { log.Info("explicit reconcile tasks") // tell mesos to send us the latest status updates for all the non-terminal tasks that we know about statusList := []*mesos.TaskStatus{} remaining := sets.KeySet(reflect.ValueOf(taskToSlave)) for taskId, slaveId := range taskToSlave { if slaveId == "" { delete(taskToSlave, taskId) continue } statusList = append(statusList, &mesos.TaskStatus{ TaskId: mutil.NewTaskID(taskId), SlaveId: mutil.NewSlaveID(slaveId), State: mesos.TaskState_TASK_RUNNING.Enum(), // req'd field, doesn't have to reflect reality }) } select { case <-cancel: return reconciliationCancelledErr default: if _, err := driver.ReconcileTasks(statusList); err != nil { return err } } start := time.Now() first := true for backoff := 1 * time.Second; first || remaining.Len() > 0; backoff = backoff * 2 { first = false // nothing to do here other than wait for status updates.. if backoff > k.schedcfg.ExplicitReconciliationMaxBackoff.Duration { backoff = k.schedcfg.ExplicitReconciliationMaxBackoff.Duration } select { case <-cancel: return reconciliationCancelledErr case <-time.After(backoff): for taskId := range remaining { if task, _ := k.taskRegistry.Get(taskId); task != nil && explicitTaskFilter(task) && task.UpdatedTime.Before(start) { // keep this task in remaining list continue } remaining.Delete(taskId) } } } return nil }
func newNavigationSteps(path string) (*navigationSteps, error) { steps := []navigationStep{} individualParts := strings.Split(path, ".") currType := reflect.TypeOf(clientcmdapi.Config{}) currPartIndex := 0 for currPartIndex < len(individualParts) { switch currType.Kind() { case reflect.Map: // if we're in a map, we need to locate a name. That name may contain dots, so we need to know what tokens are legal for the map's value type // for example, we could have a set request like: `set clusters.10.10.12.56.insecure-skip-tls-verify true`. We enter this case with // steps representing 10, 10, 12, 56, insecure-skip-tls-verify. The name is "10.10.12.56", so we want to collect all those parts together and // store them as a single step. In order to do that, we need to determine what set of tokens is a legal step AFTER the name of the map key // This set of reflective code pulls the type of the map values, uses that type to look up the set of legal tags. Those legal tags are used to // walk the list of remaining parts until we find a match to a legal tag or the end of the string. That name is used to burn all the used parts. mapValueType := currType.Elem().Elem() mapValueOptions, err := getPotentialTypeValues(mapValueType) if err != nil { return nil, err } nextPart := findNameStep(individualParts[currPartIndex:], sets.KeySet(reflect.ValueOf(mapValueOptions))) steps = append(steps, navigationStep{nextPart, mapValueType}) currPartIndex += len(strings.Split(nextPart, ".")) currType = mapValueType case reflect.Struct: nextPart := individualParts[currPartIndex] options, err := getPotentialTypeValues(currType) if err != nil { return nil, err } fieldType, exists := options[nextPart] if !exists { return nil, fmt.Errorf("unable to parse %v after %v at %v", path, steps, currType) } steps = append(steps, navigationStep{nextPart, fieldType}) currPartIndex += len(strings.Split(nextPart, ".")) currType = fieldType } } return &navigationSteps{steps, 0}, nil }