func applyDefaults(pod *api.Pod, source string, isFile bool, nodeName string) error { if len(pod.UID) == 0 { hasher := md5.New() if isFile { fmt.Fprintf(hasher, "host:%s", nodeName) fmt.Fprintf(hasher, "file:%s", source) } else { fmt.Fprintf(hasher, "url:%s", source) } hash.DeepHashObject(hasher, pod) pod.UID = types.UID(hex.EncodeToString(hasher.Sum(nil)[0:])) glog.V(5).Infof("Generated UID %q pod %q from %s", pod.UID, pod.Name, source) } pod.Name = generatePodName(pod.Name, nodeName) glog.V(5).Infof("Generated Name %q for UID %q from URL %s", pod.Name, pod.UID, source) if pod.Namespace == "" { pod.Namespace = kubetypes.NamespaceDefault } glog.V(5).Infof("Using namespace %q for pod %q from %s", pod.Namespace, pod.Name, source) // Set the Host field to indicate this pod is scheduled on the current node. pod.Spec.NodeName = nodeName pod.ObjectMeta.SelfLink = getSelfLink(pod.Name, pod.Namespace) if pod.Annotations == nil { pod.Annotations = make(map[string]string) } // The generated UID is the hash of the file. pod.Annotations[kubetypes.ConfigHashAnnotationKey] = string(pod.UID) return nil }
func TestStoreBasicExport(t *testing.T) { podA := api.Pod{ ObjectMeta: api.ObjectMeta{ Namespace: "test", Name: "foo", Labels: map[string]string{}, }, Spec: api.PodSpec{NodeName: "machine"}, Status: api.PodStatus{HostIP: "1.2.3.4"}, } server, registry := NewTestGenericStoreRegistry(t) defer server.Terminate(t) testContext := api.WithNamespace(api.NewContext(), "test") registry.UpdateStrategy.(*testRESTStrategy).allowCreateOnUpdate = true if !updateAndVerify(t, testContext, registry, &podA) { t.Errorf("Unexpected error updating podA") } obj, err := registry.Export(testContext, podA.Name, unversioned.ExportOptions{}) if err != nil { t.Errorf("unexpected error: %v", err) } exportedPod := obj.(*api.Pod) if exportedPod.Labels["prepare_create"] != "true" { t.Errorf("expected: prepare_create->true, found: %s", exportedPod.Labels["prepare_create"]) } delete(exportedPod.Labels, "prepare_create") exportObjectMeta(&podA.ObjectMeta, false) podA.Spec = exportedPod.Spec if !reflect.DeepEqual(&podA, exportedPod) { t.Errorf("expected:\n%v\nsaw:\n%v\n", &podA, exportedPod) } }
func newFakePodBuilder(uid types.UID, name string) *FakePodBuilder { pod := new(api.Pod) pod.UID = uid pod.Name = name return &FakePodBuilder{ pod: pod, } }
// annotateForExecutorOnSlave sets the BindingHostKey annotation which // marks the pod to be processed by the scheduler and launched as a Mesos // task. The executor on the slave will to the final binding to finish the // scheduling in the kubernetes sense. func annotateForExecutorOnSlave(pod *api.Pod, slave string) { if pod.Annotations == nil { pod.Annotations = make(map[string]string) } else { oemAnn := pod.Annotations pod.Annotations = make(map[string]string) for k, v := range oemAnn { pod.Annotations[k] = v } } pod.Annotations[annotation.BindingHostKey] = slave }
// checkAndUpdatePod updates existing if ref makes a meaningful change and returns true, or // returns false if there was no update. func checkAndUpdatePod(existing, ref *api.Pod) bool { // TODO: it would be better to update the whole object and only preserve certain things // like the source annotation or the UID (to ensure safety) if reflect.DeepEqual(existing.Spec, ref.Spec) && reflect.DeepEqual(existing.DeletionTimestamp, ref.DeletionTimestamp) && reflect.DeepEqual(existing.DeletionGracePeriodSeconds, ref.DeletionGracePeriodSeconds) { return false } // this is an update existing.Spec = ref.Spec existing.DeletionTimestamp = ref.DeletionTimestamp existing.DeletionGracePeriodSeconds = ref.DeletionGracePeriodSeconds return true }
func getTestPod() *api.Pod { container := api.Container{ Name: testContainerName, } pod := api.Pod{ Spec: api.PodSpec{ Containers: []api.Container{container}, RestartPolicy: api.RestartPolicyNever, }, } pod.Name = "testPod" pod.UID = testPodUID return &pod }
// ToAPIPod converts Pod to api.Pod. Note that if a field in api.Pod has no // corresponding field in Pod, the field would not be populated. func (p *Pod) ToAPIPod() *api.Pod { var pod api.Pod pod.UID = p.ID pod.Name = p.Name pod.Namespace = p.Namespace for _, c := range p.Containers { var container api.Container container.Name = c.Name container.Image = c.Image pod.Spec.Containers = append(pod.Spec.Containers, container) } return &pod }
func Convert_v1_Pod_To_api_Pod(in *Pod, out *api.Pod, s conversion.Scope) error { // TODO: when we move init container to beta, remove these conversions if value, ok := in.Annotations[PodInitContainersAnnotationKey]; ok { var values []Container if err := json.Unmarshal([]byte(value), &values); err != nil { return err } in.Spec.InitContainers = values } if value, ok := in.Annotations[PodInitContainerStatusesAnnotationKey]; ok { var values []ContainerStatus if err := json.Unmarshal([]byte(value), &values); err != nil { return err } in.Status.InitContainerStatuses = values } if err := autoConvert_v1_Pod_To_api_Pod(in, out, s); err != nil { return err } if len(out.Annotations) > 0 { old := out.Annotations out.Annotations = make(map[string]string, len(old)) for k, v := range old { out.Annotations[k] = v } delete(out.Annotations, PodInitContainersAnnotationKey) delete(out.Annotations, PodInitContainerStatusesAnnotationKey) } return nil }
// Sets the name of the profile to use with the container. func SetProfileName(pod *api.Pod, containerName, profileName string) error { if pod.Annotations == nil { pod.Annotations = map[string]string{} } pod.Annotations[ContainerAnnotationKeyPrefix+containerName] = profileName return nil }
// checkAndUpdatePod updates existing if ref makes a meaningful change and returns true, or // returns false if there was no update. func checkAndUpdatePod(existing, ref *api.Pod) bool { // TODO: it would be better to update the whole object and only preserve certain things // like the source annotation or the UID (to ensure safety) if !podsDifferSemantically(existing, ref) { return false } // this is an update // Overwrite the first-seen time with the existing one. This is our own // internal annotation, there is no need to update. ref.Annotations[kubelet.ConfigFirstSeenAnnotationKey] = existing.Annotations[kubelet.ConfigFirstSeenAnnotationKey] existing.Spec = ref.Spec existing.DeletionTimestamp = ref.DeletionTimestamp existing.DeletionGracePeriodSeconds = ref.DeletionGracePeriodSeconds updateAnnotations(existing, ref) return true }
func updatePod(t *testing.T, s storage.Interface, obj, old *api.Pod) *api.Pod { key := etcdtest.AddPrefix("pods/ns/" + obj.Name) result := &api.Pod{} if old == nil { if err := s.Create(context.TODO(), key, obj, result, 0); err != nil { t.Errorf("unexpected error: %v", err) } } else { // To force "update" behavior of Set() we need to set ResourceVersion of // previous version of object. obj.ResourceVersion = old.ResourceVersion if err := s.Set(context.TODO(), key, obj, result, 0); err != nil { t.Errorf("unexpected error: %v", err) } obj.ResourceVersion = "" } return result }
func agedPod(namespace, name string, phase kapi.PodPhase, ageInMinutes int64, containerImages ...string) kapi.Pod { pod := kapi.Pod{ ObjectMeta: kapi.ObjectMeta{ Namespace: namespace, Name: name, }, Spec: podSpec(containerImages...), Status: kapi.PodStatus{ Phase: phase, }, } if ageInMinutes >= 0 { pod.CreationTimestamp = unversioned.NewTime(unversioned.Now().Add(time.Duration(-1*ageInMinutes) * time.Minute)) } return pod }
func TestStoreCustomExport(t *testing.T) { podA := api.Pod{ ObjectMeta: api.ObjectMeta{ Namespace: "test", Name: "foo", Labels: map[string]string{}, }, Spec: api.PodSpec{NodeName: "machine"}, } destroyFunc, registry := NewTestGenericStoreRegistry(t) defer destroyFunc() registry.ExportStrategy = testPodExport{} testContext := api.WithNamespace(api.NewContext(), "test") registry.UpdateStrategy.(*testRESTStrategy).allowCreateOnUpdate = true if !updateAndVerify(t, testContext, registry, &podA) { t.Errorf("Unexpected error updating podA") } obj, err := registry.Export(testContext, podA.Name, metav1.ExportOptions{}) if err != nil { t.Errorf("unexpected error: %v", err) } exportedPod := obj.(*api.Pod) if exportedPod.Labels["exported"] != "true" { t.Errorf("expected: exported->true, found: %s", exportedPod.Labels["exported"]) } if exportedPod.Labels["exact"] != "false" { t.Errorf("expected: exact->false, found: %s", exportedPod.Labels["exact"]) } if exportedPod.Labels["prepare_create"] != "true" { t.Errorf("expected: prepare_create->true, found: %s", exportedPod.Labels["prepare_create"]) } delete(exportedPod.Labels, "exported") delete(exportedPod.Labels, "exact") delete(exportedPod.Labels, "prepare_create") exportObjectMeta(&podA.ObjectMeta, false) podA.Spec = exportedPod.Spec if !reflect.DeepEqual(&podA, exportedPod) { t.Errorf("expected:\n%v\nsaw:\n%v\n", &podA, exportedPod) } }
func Convert_v1_Pod_To_api_Pod(in *Pod, out *api.Pod, s conversion.Scope) error { // If there is a beta annotation, copy to alpha key. // See commit log for PR #31026 for why we do this. if valueBeta, okBeta := in.Annotations[PodInitContainersBetaAnnotationKey]; okBeta { in.Annotations[PodInitContainersAnnotationKey] = valueBeta } // TODO: sometime after we move init container to stable, remove these conversions // Move the annotation to the internal repr. field if value, ok := in.Annotations[PodInitContainersAnnotationKey]; ok { var values []Container if err := json.Unmarshal([]byte(value), &values); err != nil { return err } // Conversion from external to internal version exists more to // satisfy the needs of the decoder than it does to be a general // purpose tool. And Decode always creates an intermediate object // to decode to. Thus the caller of UnsafeConvertToVersion is // taking responsibility to ensure mutation of in is not exposed // back to the caller. in.Spec.InitContainers = values } // If there is a beta annotation, copy to alpha key. // See commit log for PR #31026 for why we do this. if valueBeta, okBeta := in.Annotations[PodInitContainerStatusesBetaAnnotationKey]; okBeta { in.Annotations[PodInitContainerStatusesAnnotationKey] = valueBeta } if value, ok := in.Annotations[PodInitContainerStatusesAnnotationKey]; ok { var values []ContainerStatus if err := json.Unmarshal([]byte(value), &values); err != nil { return err } // Conversion from external to internal version exists more to // satisfy the needs of the decoder than it does to be a general // purpose tool. And Decode always creates an intermediate object // to decode to. Thus the caller of UnsafeConvertToVersion is // taking responsibility to ensure mutation of in is not exposed // back to the caller. in.Status.InitContainerStatuses = values } if err := autoConvert_v1_Pod_To_api_Pod(in, out, s); err != nil { return err } if len(out.Annotations) > 0 { old := out.Annotations out.Annotations = make(map[string]string, len(old)) for k, v := range old { out.Annotations[k] = v } delete(out.Annotations, PodInitContainersAnnotationKey) delete(out.Annotations, PodInitContainersBetaAnnotationKey) delete(out.Annotations, PodInitContainerStatusesAnnotationKey) delete(out.Annotations, PodInitContainerStatusesBetaAnnotationKey) } return nil }
func getTestPod(probeType probeType, probeSpec api.Probe) api.Pod { container := api.Container{ Name: containerName, } switch probeType { case readiness: container.ReadinessProbe = &probeSpec case liveness: container.LivenessProbe = &probeSpec } pod := api.Pod{ Spec: api.PodSpec{ Containers: []api.Container{container}, RestartPolicy: api.RestartPolicyNever, }, } pod.UID = podUID return pod }
func validatePod(pod *kube.Pod, ignoreContainers bool) error { errList := validation.ValidatePod(pod) // remove error for no containers if requested if ignoreContainers { errList = errList.Filter(func(e error) bool { return e.Error() == "spec.containers: Required value" }) } meta := pod.GetObjectMeta() if len(meta.GetName()) == 0 && len(meta.GetGenerateName()) > 0 { errList = errList.Filter(func(e error) bool { return e.Error() == "metadata.name: Required value: name or generateName is required" }) } return errList.ToAggregate() }
// ApplyOverrides applies configured overrides to a build in a build pod func (b BuildOverrides) ApplyOverrides(pod *kapi.Pod) error { if b.config == nil { return nil } build, version, err := buildadmission.GetBuildFromPod(pod) if err != nil { return err } glog.V(4).Infof("Applying overrides to build %s/%s", build.Namespace, build.Name) if b.config.ForcePull { if build.Spec.Strategy.DockerStrategy != nil { glog.V(5).Infof("Setting docker strategy ForcePull to true in build %s/%s", build.Namespace, build.Name) build.Spec.Strategy.DockerStrategy.ForcePull = true } if build.Spec.Strategy.SourceStrategy != nil { glog.V(5).Infof("Setting source strategy ForcePull to true in build %s/%s", build.Namespace, build.Name) build.Spec.Strategy.SourceStrategy.ForcePull = true } if build.Spec.Strategy.CustomStrategy != nil { err := applyForcePullToPod(pod) if err != nil { return err } glog.V(5).Infof("Setting custom strategy ForcePull to true in build %s/%s", build.Namespace, build.Name) build.Spec.Strategy.CustomStrategy.ForcePull = true } } // Apply label overrides for _, lbl := range b.config.ImageLabels { glog.V(5).Infof("Overriding image label %s=%s in build %s/%s", lbl.Name, lbl.Value, build.Namespace, build.Name) overrideLabel(lbl, &build.Spec.Output.ImageLabels) } if len(b.config.NodeSelector) != 0 && pod.Spec.NodeSelector == nil { pod.Spec.NodeSelector = map[string]string{} } for k, v := range b.config.NodeSelector { glog.V(5).Infof("Adding override nodeselector %s=%s to build pod %s/%s", k, v, pod.Namespace, pod.Name) pod.Spec.NodeSelector[k] = v } if len(b.config.Annotations) != 0 && pod.Annotations == nil { pod.Annotations = map[string]string{} } for k, v := range b.config.Annotations { glog.V(5).Infof("Adding override annotation %s=%s to build pod %s/%s", k, v, pod.Namespace, pod.Name) pod.Annotations[k] = v } return buildadmission.SetBuildInPod(pod, build, version) }
// same as above func comments, except 'recyclerClient' is a narrower pod API // interface to ease testing func internalRecycleVolumeByWatchingPodUntilCompletion(pvName string, pod *api.Pod, recyclerClient recyclerClient) error { glog.V(5).Infof("creating recycler pod for volume %s\n", pod.Name) // Generate unique name for the recycler pod - we need to get "already // exists" error when a previous controller has already started recycling // the volume. Here we assume that pv.Name is already unique. pod.Name = "recycler-for-" + pvName pod.GenerateName = "" // Start the pod _, err := recyclerClient.CreatePod(pod) if err != nil { if errors.IsAlreadyExists(err) { glog.V(5).Infof("old recycler pod %q found for volume", pod.Name) } else { return fmt.Errorf("Unexpected error creating recycler pod: %+v\n", err) } } defer recyclerClient.DeletePod(pod.Name, pod.Namespace) // Now only the old pod or the new pod run. Watch it until it finishes. stopChannel := make(chan struct{}) defer close(stopChannel) nextPod := recyclerClient.WatchPod(pod.Name, pod.Namespace, stopChannel) for { watchedPod := nextPod() if watchedPod.Status.Phase == api.PodSucceeded { // volume.Recycle() returns nil on success, else error return nil } if watchedPod.Status.Phase == api.PodFailed { // volume.Recycle() returns nil on success, else error if watchedPod.Status.Message != "" { return fmt.Errorf(watchedPod.Status.Message) } else { return fmt.Errorf("pod failed, pod.Status.Message unknown.") } } } }
// updateAnnotations returns an Annotation map containing the api annotation map plus // locally managed annotations func updateAnnotations(existing, ref *api.Pod) { annotations := make(map[string]string, len(ref.Annotations)+len(localAnnotations)) for k, v := range ref.Annotations { annotations[k] = v } for _, k := range localAnnotations { if v, ok := existing.Annotations[k]; ok { annotations[k] = v } } existing.Annotations = annotations }
func (r *fakeRegistry) bind(taskID string, pod *api.Pod) error { r.Lock() defer r.Unlock() pod.Annotations = map[string]string{ "k8s.mesosphere.io/taskId": taskID, } r.boundTasks[taskID] = pod // the normal registry sends a bind.. r.updates <- &PodEvent{pod: pod, taskID: taskID, eventType: PodEventBound} return nil }
func (f *typeBasedFactoryStrategy) CreateBuildPod(build *buildapi.Build) (*kapi.Pod, error) { var pod *kapi.Pod var err error switch build.Spec.Strategy.Type { case buildapi.DockerBuildStrategyType: pod, err = f.DockerBuildStrategy.CreateBuildPod(build) case buildapi.SourceBuildStrategyType: pod, err = f.SourceBuildStrategy.CreateBuildPod(build) case buildapi.CustomBuildStrategyType: pod, err = f.CustomBuildStrategy.CreateBuildPod(build) default: return nil, fmt.Errorf("no supported build strategy defined for Build %s/%s with type %s", build.Namespace, build.Name, build.Spec.Strategy.Type) } if pod != nil { if pod.Annotations == nil { pod.Annotations = map[string]string{} } pod.Annotations[buildapi.BuildAnnotation] = build.Name } return pod, err }
func getTestPod(probeType probeType, probeSpec api.Probe) api.Pod { container := api.Container{ Name: testContainerName, } // All tests rely on the fake exec prober. probeSpec.Handler = api.Handler{ Exec: &api.ExecAction{}, } // Apply test defaults, overwridden for test speed. defaults := map[string]int64{ "TimeoutSeconds": 1, "PeriodSeconds": 1, "SuccessThreshold": 1, "FailureThreshold": 1, } for field, value := range defaults { f := reflect.ValueOf(&probeSpec).Elem().FieldByName(field) if f.Int() == 0 { f.SetInt(value) } } switch probeType { case readiness: container.ReadinessProbe = &probeSpec case liveness: container.LivenessProbe = &probeSpec } pod := api.Pod{ Spec: api.PodSpec{ Containers: []api.Container{container}, RestartPolicy: api.RestartPolicyNever, }, } pod.Name = "testPod" pod.UID = testPodUID return pod }
// checkAndUpdatePod updates existing, and: // * if ref makes a meaningful change, returns needUpdate=true // * if ref makes no meaningful change, but changes the pod status, returns needReconcile=true // * else return both false // Now, needUpdate and needReconcile should never be both true func checkAndUpdatePod(existing, ref *api.Pod) (needUpdate, needReconcile bool) { // TODO: it would be better to update the whole object and only preserve certain things // like the source annotation or the UID (to ensure safety) if !podsDifferSemantically(existing, ref) { // this is not an update // Only check reconcile when it is not an update, because if the pod is going to // be updated, an extra reconcile is unnecessary if !reflect.DeepEqual(existing.Status, ref.Status) { // Pod with changed pod status needs reconcile, because kubelet should // be the source of truth of pod status. existing.Status = ref.Status needReconcile = true } return } // this is an update // Overwrite the first-seen time with the existing one. This is our own // internal annotation, there is no need to update. ref.Annotations[kubetypes.ConfigFirstSeenAnnotationKey] = existing.Annotations[kubetypes.ConfigFirstSeenAnnotationKey] existing.Spec = ref.Spec existing.Labels = ref.Labels existing.DeletionTimestamp = ref.DeletionTimestamp existing.DeletionGracePeriodSeconds = ref.DeletionGracePeriodSeconds existing.Status = ref.Status updateAnnotations(existing, ref) needUpdate = true return }
func updatePod(c *gin.Context) { namespace := c.Param("ns") podname := c.Param("po") podjson := c.PostForm("json") var pod api.Pod err := json.Unmarshal([]byte(podjson), &pod) if err != nil { c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()}) return } r, _ := kubeclient.Get().Pods(namespace).Get(pod.Name) pod.ResourceVersion = r.ResourceVersion _, err = kubeclient.Get().Pods(namespace).Update(&pod) if err != nil { c.HTML(http.StatusInternalServerError, "error", gin.H{"error": err.Error()}) return } c.Redirect(http.StatusMovedPermanently, fmt.Sprintf("/namespaces/%s/pods/%s/edit", namespace, podname)) }
// kubenetes pod to protobuf struct func PodToPbStruct(pod *api.Pod) *types.Pod { todata := &types.Pod{ Id: string(pod.GetUID()), Name: pod.GetName(), } pod_container := pod.Spec.Containers // 解析容器信息 container := make([]*types.Container, len(pod_container)) for k, v := range pod_container { container[k] = &types.Container{ Name: v.Name, Image: v.Image, } // 解析空间挂载信息 VolumeMounts := make([]*types.VolumeMount, len(v.VolumeMounts)) for k2, v2 := range v.VolumeMounts { VolumeMounts[k2] = &types.VolumeMount{ Name: v2.Name, ReadOnly: v2.ReadOnly, MountPath: v2.MountPath, } } // 解析端口映射信息 containerPort := make([]*types.ContainerPort, len(v.Ports)) for k2, port := range v.Ports { containerPort[k2] = &types.ContainerPort{ Name: port.Name, Protocol: string(port.Protocol), ContainerPort: int64(port.ContainerPort), } } container[k].Port = containerPort } todata.Containers = container return todata }
func (b BuildDefaults) applyPodDefaults(pod *kapi.Pod) { if len(b.config.NodeSelector) != 0 && pod.Spec.NodeSelector == nil { // only apply nodeselector defaults if the pod has no nodeselector labels // already. pod.Spec.NodeSelector = map[string]string{} for k, v := range b.config.NodeSelector { addDefaultNodeSelector(k, v, pod.Spec.NodeSelector) } } if len(b.config.Annotations) != 0 && pod.Annotations == nil { pod.Annotations = map[string]string{} } for k, v := range b.config.Annotations { addDefaultAnnotations(k, v, pod.Annotations) } }
func (c *Controller) updateInstanceMetadata( pod *api.Pod, nic *types.VirtualMachineInterface, address, gateway string) { doUpdate := false if pod.Annotations == nil { pod.Annotations = make(map[string]string) doUpdate = true } var newValue, oldValue InstanceMetadata if data, ok := pod.Annotations[MetadataAnnotationTag]; ok { json.Unmarshal([]byte(data), &oldValue) } newValue.Uuid = nic.GetUuid() var mac_address string addressArr := nic.GetVirtualMachineInterfaceMacAddresses() if len(addressArr.MacAddress) > 0 { mac_address = addressArr.MacAddress[0] } else { glog.Errorf("interface %s: no mac-addresses", nic.GetName()) } newValue.MacAddress = mac_address newValue.IpAddress = address newValue.Gateway = gateway if !doUpdate && reflect.DeepEqual(newValue, oldValue) { return } encoded, err := json.Marshal(&newValue) if err != nil { glog.Errorf("JSON encode: %v", err) return } pod.Annotations[MetadataAnnotationTag] = string(encoded) _, err = c.kube.Pods(pod.Namespace).Update(pod) if err != nil { // Update will return an error if the pod object that we are // working with is stale. glog.Infof("Pod Update %s: %v", pod.Name, err) } }
func updatePod(t *testing.T, s storage.Interface, obj, old *api.Pod) *api.Pod { updateFn := func(input runtime.Object, res storage.ResponseMeta) (runtime.Object, *uint64, error) { newObj, err := api.Scheme.DeepCopy(obj) if err != nil { t.Errorf("unexpected error: %v", err) return nil, nil, err } return newObj.(*api.Pod), nil, nil } key := etcdtest.AddPrefix("pods/ns/" + obj.Name) if err := s.GuaranteedUpdate(context.TODO(), key, &api.Pod{}, old == nil, nil, updateFn); err != nil { t.Errorf("unexpected error: %v", err) } obj.ResourceVersion = "" result := &api.Pod{} if err := s.Get(context.TODO(), key, result, false); err != nil { t.Errorf("unexpected error: %v", err) } return result }
// SetIdentity sets the pet namespace and name. func (n *NameIdentityMapper) SetIdentity(id string, pet *api.Pod) { pet.Name = fmt.Sprintf("%v-%v", n.ps.Name, id) pet.Namespace = n.ps.Namespace return }
func TestSyncBatchNoDeadlock(t *testing.T) { client := &fake.Clientset{} m := newTestManager(client) pod := getTestPod() // Setup fake client. var ret api.Pod var err error client.AddReactor("*", "pods", func(action core.Action) (bool, runtime.Object, error) { switch action := action.(type) { case core.GetAction: assert.Equal(t, pod.Name, action.GetName(), "Unexpeted GetAction: %+v", action) case core.UpdateAction: assert.Equal(t, pod.Name, action.GetObject().(*api.Pod).Name, "Unexpeted UpdateAction: %+v", action) default: assert.Fail(t, "Unexpected Action: %+v", action) } return true, &ret, err }) pod.Status.ContainerStatuses = []api.ContainerStatus{{State: api.ContainerState{Running: &api.ContainerStateRunning{}}}} getAction := core.GetActionImpl{ActionImpl: core.ActionImpl{Verb: "get", Resource: "pods"}} updateAction := core.UpdateActionImpl{ActionImpl: core.ActionImpl{Verb: "update", Resource: "pods", Subresource: "status"}} // Pod not found. ret = *pod err = errors.NewNotFound(api.Resource("pods"), pod.Name) m.SetPodStatus(pod, getRandomPodStatus()) m.testSyncBatch() verifyActions(t, client, []core.Action{getAction}) client.ClearActions() // Pod was recreated. ret.UID = "other_pod" err = nil m.SetPodStatus(pod, getRandomPodStatus()) m.testSyncBatch() verifyActions(t, client, []core.Action{getAction}) client.ClearActions() // Pod not deleted (success case). ret = *pod m.SetPodStatus(pod, getRandomPodStatus()) m.testSyncBatch() verifyActions(t, client, []core.Action{getAction, updateAction}) client.ClearActions() // Pod is terminated, but still running. pod.DeletionTimestamp = new(unversioned.Time) m.SetPodStatus(pod, getRandomPodStatus()) m.testSyncBatch() verifyActions(t, client, []core.Action{getAction, updateAction}) client.ClearActions() // Pod is terminated successfully. pod.Status.ContainerStatuses[0].State.Running = nil pod.Status.ContainerStatuses[0].State.Terminated = &api.ContainerStateTerminated{} m.SetPodStatus(pod, getRandomPodStatus()) m.testSyncBatch() verifyActions(t, client, []core.Action{getAction, updateAction}) client.ClearActions() // Error case. err = fmt.Errorf("intentional test error") m.SetPodStatus(pod, getRandomPodStatus()) m.testSyncBatch() verifyActions(t, client, []core.Action{getAction}) client.ClearActions() }