// encodePods creates an api.PodList object from pods and returns the encoded // PodList. func encodePods(pods []*api.Pod) (data []byte, err error) { podList := new(api.PodList) for _, pod := range pods { podList.Items = append(podList.Items, *pod) } return latest.GroupOrDie("").Codec.Encode(podList) }
// Please note that selector is filtering among the pods that have gotten into // the store; there may have been some filtering that already happened before // that. func (s storePodsNamespacer) List(selector labels.Selector) (api.PodList, error) { pods := api.PodList{} if s.namespace == api.NamespaceAll { for _, m := range s.indexer.List() { pod := m.(*api.Pod) if selector.Matches(labels.Set(pod.Labels)) { pods.Items = append(pods.Items, *pod) } } return pods, nil } key := &api.Pod{ObjectMeta: api.ObjectMeta{Namespace: s.namespace}} items, err := s.indexer.Index(NamespaceIndex, key) if err != nil { // Ignore error; do slow search without index. glog.Warningf("can not retrieve list of objects using index : %v", err) for _, m := range s.indexer.List() { pod := m.(*api.Pod) if s.namespace == pod.Namespace && selector.Matches(labels.Set(pod.Labels)) { pods.Items = append(pods.Items, *pod) } } return pods, nil } for _, m := range items { pod := m.(*api.Pod) if selector.Matches(labels.Set(pod.Labels)) { pods.Items = append(pods.Items, *pod) } } return pods, nil }
func newPodList(names ...string) api.PodList { var list api.PodList for _, name := range names { list.Items = append(list.Items, newPod(name)) } return list }
// encodePods creates an api.PodList object from pods and returns the encoded // PodList. func encodePods(pods []*api.Pod) (data []byte, err error) { podList := new(api.PodList) for _, pod := range pods { podList.Items = append(podList.Items, *pod) } // TODO: this needs to be parameterized to the kubelet, not hardcoded. Depends on Kubelet // as API server refactor. // TODO: Locked to v1, needs to be made generic codec := api.Codecs.LegacyCodec(unversioned.GroupVersion{Group: api.GroupName, Version: "v1"}) return runtime.Encode(codec, podList) }
func (dc *DeploymentController) listPods(deployment *extensions.Deployment) (*api.PodList, error) { return deploymentutil.ListPods(deployment, func(namespace string, options api.ListOptions) (*api.PodList, error) { pods, err := dc.podLister.Pods(namespace).List(options.LabelSelector) result := api.PodList{Items: make([]api.Pod, 0, len(pods))} for i := range pods { result.Items = append(result.Items, *pods[i]) } return &result, err }) }
// Please note that selector is filtering among the pods that have gotten into // the store; there may have been some filtering that already happened before // that. func (s storePodsNamespacer) List(selector labels.Selector) (pods api.PodList, err error) { list := api.PodList{} for _, m := range s.store.List() { pod := m.(*api.Pod) if s.namespace == api.NamespaceAll || s.namespace == pod.Namespace { if selector.Matches(labels.Set(pod.Labels)) { list.Items = append(list.Items, *pod) } } } return list, nil }
// addHashKeyToRSAndPods adds pod-template-hash information to the given rs, if it's not already there, with the following steps: // 1. Add hash label to the rs's pod template, and make sure the controller sees this update so that no orphaned pods will be created // 2. Add hash label to all pods this rs owns, wait until replicaset controller reports rs.Status.FullyLabeledReplicas equal to the desired number of replicas // 3. Add hash label to the rs's label and selector func (dc *DeploymentController) addHashKeyToRSAndPods(rs *extensions.ReplicaSet) (updatedRS *extensions.ReplicaSet, err error) { objCopy, err := api.Scheme.Copy(rs) if err != nil { return nil, err } updatedRS = objCopy.(*extensions.ReplicaSet) // If the rs already has the new hash label in its selector, it's done syncing if labelsutil.SelectorHasLabel(rs.Spec.Selector, extensions.DefaultDeploymentUniqueLabelKey) { return } namespace := rs.Namespace hash := rsutil.GetPodTemplateSpecHash(rs) rsUpdated := false // 1. Add hash template label to the rs. This ensures that any newly created pods will have the new label. updatedRS, rsUpdated, err = rsutil.UpdateRSWithRetries(dc.client.Extensions().ReplicaSets(namespace), updatedRS, func(updated *extensions.ReplicaSet) error { // Precondition: the RS doesn't contain the new hash in its pod template label. if updated.Spec.Template.Labels[extensions.DefaultDeploymentUniqueLabelKey] == hash { return utilerrors.ErrPreconditionViolated } updated.Spec.Template.Labels = labelsutil.AddLabel(updated.Spec.Template.Labels, extensions.DefaultDeploymentUniqueLabelKey, hash) return nil }) if err != nil { return nil, fmt.Errorf("error updating %s %s/%s pod template label with template hash: %v", updatedRS.Kind, updatedRS.Namespace, updatedRS.Name, err) } if !rsUpdated { // If RS wasn't updated but didn't return error in step 1, we've hit a RS not found error. // Return here and retry in the next sync loop. return rs, nil } // Make sure rs pod template is updated so that it won't create pods without the new label (orphaned pods). if updatedRS.Generation > updatedRS.Status.ObservedGeneration { if err = deploymentutil.WaitForReplicaSetUpdated(dc.client, updatedRS.Generation, namespace, updatedRS.Name); err != nil { return nil, fmt.Errorf("error waiting for %s %s/%s generation %d observed by controller: %v", updatedRS.Kind, updatedRS.Namespace, updatedRS.Name, updatedRS.Generation, err) } } glog.V(4).Infof("Observed the update of %s %s/%s's pod template with hash %s.", rs.Kind, rs.Namespace, rs.Name, hash) // 2. Update all pods managed by the rs to have the new hash label, so they will be correctly adopted. selector, err := unversioned.LabelSelectorAsSelector(updatedRS.Spec.Selector) if err != nil { return nil, fmt.Errorf("error in converting selector to label selector for replica set %s: %s", updatedRS.Name, err) } options := api.ListOptions{LabelSelector: selector} pods, err := dc.podLister.Pods(namespace).List(options.LabelSelector) if err != nil { return nil, fmt.Errorf("error in getting pod list for namespace %s and list options %+v: %s", namespace, options, err) } podList := api.PodList{Items: make([]api.Pod, 0, len(pods))} for i := range pods { podList.Items = append(podList.Items, *pods[i]) } allPodsLabeled := false if allPodsLabeled, err = deploymentutil.LabelPodsWithHash(&podList, updatedRS, dc.client, namespace, hash); err != nil { return nil, fmt.Errorf("error in adding template hash label %s to pods %+v: %s", hash, podList, err) } // If not all pods are labeled but didn't return error in step 2, we've hit at least one pod not found error. // Return here and retry in the next sync loop. if !allPodsLabeled { return updatedRS, nil } // We need to wait for the replicaset controller to observe the pods being // labeled with pod template hash. Because previously we've called // WaitForReplicaSetUpdated, the replicaset controller should have dropped // FullyLabeledReplicas to 0 already, we only need to wait it to increase // back to the number of replicas in the spec. if err = deploymentutil.WaitForPodsHashPopulated(dc.client, updatedRS.Generation, namespace, updatedRS.Name); err != nil { return nil, fmt.Errorf("%s %s/%s: error waiting for replicaset controller to observe pods being labeled with template hash: %v", updatedRS.Kind, updatedRS.Namespace, updatedRS.Name, err) } // 3. Update rs label and selector to include the new hash label // Copy the old selector, so that we can scrub out any orphaned pods if updatedRS, rsUpdated, err = rsutil.UpdateRSWithRetries(dc.client.Extensions().ReplicaSets(namespace), updatedRS, func(updated *extensions.ReplicaSet) error { // Precondition: the RS doesn't contain the new hash in its label or selector. if updated.Labels[extensions.DefaultDeploymentUniqueLabelKey] == hash && updated.Spec.Selector.MatchLabels[extensions.DefaultDeploymentUniqueLabelKey] == hash { return utilerrors.ErrPreconditionViolated } updated.Labels = labelsutil.AddLabel(updated.Labels, extensions.DefaultDeploymentUniqueLabelKey, hash) updated.Spec.Selector = labelsutil.AddLabelToSelector(updated.Spec.Selector, extensions.DefaultDeploymentUniqueLabelKey, hash) return nil }); err != nil { return nil, fmt.Errorf("error updating %s %s/%s label and selector with template hash: %v", updatedRS.Kind, updatedRS.Namespace, updatedRS.Name, err) } if rsUpdated { glog.V(4).Infof("Updated %s %s/%s's selector and label with hash %s.", rs.Kind, rs.Namespace, rs.Name, hash) } // If the RS isn't actually updated in step 3, that's okay, we'll retry in the next sync loop since its selector isn't updated yet. // TODO: look for orphaned pods and label them in the background somewhere else periodically return updatedRS, nil }