// getOverlappingControllers finds rcs that this controller overlaps, as well as rcs overlapping this controller. func getOverlappingControllers(rcClient coreclient.ReplicationControllerInterface, rc *api.ReplicationController) ([]api.ReplicationController, error) { rcs, err := rcClient.List(api.ListOptions{}) if err != nil { return nil, fmt.Errorf("error getting replication controllers: %v", err) } var matchingRCs []api.ReplicationController rcLabels := labels.Set(rc.Spec.Selector) for _, controller := range rcs.Items { newRCLabels := labels.Set(controller.Spec.Selector) if labels.SelectorFromSet(newRCLabels).Matches(rcLabels) || labels.SelectorFromSet(rcLabels).Matches(newRCLabels) { matchingRCs = append(matchingRCs, controller) } } return matchingRCs, nil }
// updateReplicaCount attempts to update the Status.Replicas of the given controller, with a single GET/PUT retry. func updateReplicaCount(rcClient unversionedcore.ReplicationControllerInterface, controller api.ReplicationController, numReplicas, numFullyLabeledReplicas, numReadyReplicas, numAvailableReplicas int) (updateErr error) { // This is the steady state. It happens when the rc doesn't have any expectations, since // we do a periodic relist every 30s. If the generations differ but the replicas are // the same, a caller might've resized to the same replica count. if int(controller.Status.Replicas) == numReplicas && int(controller.Status.FullyLabeledReplicas) == numFullyLabeledReplicas && int(controller.Status.ReadyReplicas) == numReadyReplicas && int(controller.Status.AvailableReplicas) == numAvailableReplicas && controller.Generation == controller.Status.ObservedGeneration { return nil } // Save the generation number we acted on, otherwise we might wrongfully indicate // that we've seen a spec update when we retry. // TODO: This can clobber an update if we allow multiple agents to write to the // same status. generation := controller.Generation var getErr error for i, rc := 0, &controller; ; i++ { glog.V(4).Infof(fmt.Sprintf("Updating replica count for rc: %s/%s, ", controller.Namespace, controller.Name) + fmt.Sprintf("replicas %d->%d (need %d), ", controller.Status.Replicas, numReplicas, controller.Spec.Replicas) + fmt.Sprintf("fullyLabeledReplicas %d->%d, ", controller.Status.FullyLabeledReplicas, numFullyLabeledReplicas) + fmt.Sprintf("readyReplicas %d->%d, ", controller.Status.ReadyReplicas, numReadyReplicas) + fmt.Sprintf("availableReplicas %d->%d, ", controller.Status.AvailableReplicas, numAvailableReplicas) + fmt.Sprintf("sequence No: %v->%v", controller.Status.ObservedGeneration, generation)) rc.Status = api.ReplicationControllerStatus{ Replicas: int32(numReplicas), FullyLabeledReplicas: int32(numFullyLabeledReplicas), ReadyReplicas: int32(numReadyReplicas), AvailableReplicas: int32(numAvailableReplicas), ObservedGeneration: generation, } _, updateErr = rcClient.UpdateStatus(rc) if updateErr == nil || i >= statusUpdateRetries { return updateErr } // Update the controller with the latest resource version for the next poll if rc, getErr = rcClient.Get(controller.Name); getErr != nil { // If the GET fails we can't trust status.Replicas anymore. This error // is bound to be more interesting than the update failure. return getErr } } }