func applyDefaults(pod *api.Pod, url string) error { if len(pod.UID) == 0 { hasher := md5.New() fmt.Fprintf(hasher, "url:%s", url) util.DeepHashObject(hasher, pod) pod.UID = types.UID(hex.EncodeToString(hasher.Sum(nil)[0:])) glog.V(5).Infof("Generated UID %q for pod %q from URL %s", pod.UID, pod.Name, url) } // This is required for backward compatibility, and should be removed once we // completely deprecate ContainerManifest. var err error if len(pod.Name) == 0 { pod.Name = string(pod.UID) } pod.Name, err = GeneratePodName(pod.Name) if err != nil { return err } glog.V(5).Infof("Generated Name %q for UID %q from URL %s", pod.Name, pod.UID, url) // Always overrides the namespace. pod.Namespace = kubelet.NamespaceDefault glog.V(5).Infof("Using namespace %q for pod %q from URL %s", pod.Namespace, pod.Name, url) return nil }
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) } util.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) } // This is required for backward compatibility, and should be removed once we // completely deprecate ContainerManifest. if len(pod.Name) == 0 { pod.Name = string(pod.UID) } 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 = kubelet.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) return nil }
// 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 }
// 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 pod.Status = p.Status 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 }
// ValidatePodUpdate tests to see if the update is legal for an end user to make. newPod is updated with fields // that cannot be changed. func ValidatePodUpdate(newPod, oldPod *api.Pod) errs.ValidationErrorList { allErrs := errs.ValidationErrorList{} allErrs = append(allErrs, ValidateObjectMetaUpdate(&oldPod.ObjectMeta, &newPod.ObjectMeta).Prefix("metadata")...) if len(newPod.Spec.Containers) != len(oldPod.Spec.Containers) { allErrs = append(allErrs, errs.NewFieldInvalid("spec.containers", newPod.Spec.Containers, "may not add or remove containers")) return allErrs } pod := *newPod // Tricky, we need to copy the container list so that we don't overwrite the update var newContainers []api.Container for ix, container := range pod.Spec.Containers { container.Image = oldPod.Spec.Containers[ix].Image newContainers = append(newContainers, container) } pod.Spec.Containers = newContainers if !api.Semantic.DeepEqual(pod.Spec, oldPod.Spec) { // TODO: a better error would include all immutable fields explicitly. allErrs = append(allErrs, errs.NewFieldInvalid("spec.containers", newPod.Spec.Containers, "some fields are immutable")) } newPod.Status = oldPod.Status return allErrs }
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 = util.NewTime(util.Now().Add(time.Duration(-1*ageInMinutes) * time.Minute)) } return pod }
func TestExtractJson(t *testing.T) { mockRegistry := MockPodRegistry{} storage := PodRegistryStorage{ registry: &mockRegistry, } pod := api.Pod{ JSONBase: api.JSONBase{ ID: "foo", }, } body, err := json.Marshal(pod) expectNoError(t, err) podOut, err := storage.Extract(string(body)) expectNoError(t, err) // Extract adds in a kind pod.Kind = "cluster#pod" if !reflect.DeepEqual(pod, podOut) { t.Errorf("Expected %#v, found %#v", pod, podOut) } }
func (f *typeBasedFactoryStrategy) CreateBuildPod(build *buildapi.Build) (*kapi.Pod, error) { var pod *kapi.Pod var err error switch build.Parameters.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.Parameters.Strategy.Type) } if pod != nil { if pod.Annotations == nil { pod.Annotations = map[string]string{} } pod.Annotations[buildapi.BuildAnnotation] = build.Name } return pod, err }
// ValidatePodStatusUpdate tests to see if the update is legal for an end user to make. newPod is updated with fields // that cannot be changed. func ValidatePodStatusUpdate(newPod, oldPod *api.Pod) errs.ValidationErrorList { allErrs := errs.ValidationErrorList{} allErrs = append(allErrs, ValidateObjectMetaUpdate(&oldPod.ObjectMeta, &newPod.ObjectMeta).Prefix("metadata")...) // TODO: allow change when bindings are properly decoupled from pods if newPod.Status.Host != oldPod.Status.Host { allErrs = append(allErrs, errs.NewFieldInvalid("status.host", newPod.Status.Host, "pod host cannot be changed directly")) } // For status update we ignore changes to pod spec. newPod.Spec = oldPod.Spec return allErrs }
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 } if updateElement(pod.Annotations, "nic_uuid", nic.GetUuid()) { doUpdate = true } 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()) } if updateElement(pod.Annotations, "mac_address", mac_address) { doUpdate = true } if updateElement(pod.Annotations, "ip_address", address) { doUpdate = true } if updateElement(pod.Annotations, "gateway", gateway) { doUpdate = true } if !doUpdate { return } _, 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 (storage *PodRegistryStorage) Extract(body string) (interface{}, error) { pod := api.Pod{} err := json.Unmarshal([]byte(body), &pod) pod.Kind = "cluster#pod" return pod, err }
func extractFromFile(filename string) (api.Pod, error) { var pod api.Pod glog.V(3).Infof("Reading config file %q", filename) file, err := os.Open(filename) if err != nil { return pod, err } defer file.Close() data, err := ioutil.ReadAll(file) if err != nil { return pod, err } // TODO: use api.Scheme.DecodeInto // This is awful. DecodeInto() expects to find an APIObject, which // Manifest is not. We keep reading manifest for now for compat, but // we will eventually change it to read Pod (at which point this all // becomes nicer). Until then, we assert that the ContainerManifest // structure on disk is always v1beta1. Read that, convert it to a // "current" ContainerManifest (should be ~identical), then convert // that to a Pod (which is a well-understood conversion). This // avoids writing a v1beta1.ContainerManifest -> api.Pod // conversion which would be identical to the api.ContainerManifest -> // api.Pod conversion. oldManifest := &v1beta1.ContainerManifest{} if err := yaml.Unmarshal(data, oldManifest); err != nil { return pod, fmt.Errorf("can't unmarshal file %q: %v", filename, err) } newManifest := &api.ContainerManifest{} if err := api.Scheme.Convert(oldManifest, newManifest); err != nil { return pod, fmt.Errorf("can't convert pod from file %q: %v", filename, err) } if err := api.Scheme.Convert(newManifest, &pod); err != nil { return pod, fmt.Errorf("can't convert pod from file %q: %v", filename, err) } hostname, err := os.Hostname() //TODO: kubelet name would be better if err != nil { return pod, err } hostname = strings.ToLower(hostname) if len(pod.UID) == 0 { hasher := md5.New() fmt.Fprintf(hasher, "host:%s", hostname) fmt.Fprintf(hasher, "file:%s", filename) util.DeepHashObject(hasher, pod) pod.UID = types.UID(hex.EncodeToString(hasher.Sum(nil)[0:])) glog.V(5).Infof("Generated UID %q for pod %q from file %s", pod.UID, pod.Name, filename) } // This is required for backward compatibility, and should be removed once we // completely deprecate ContainerManifest. if len(pod.Name) == 0 { pod.Name = string(pod.UID) } if pod.Name, err = GeneratePodName(pod.Name); err != nil { return pod, err } glog.V(5).Infof("Generated Name %q for UID %q from file %s", pod.Name, pod.UID, filename) // Always overrides the namespace provided by the file. pod.Namespace = kubelet.NamespaceDefault glog.V(5).Infof("Using namespace %q for pod %q from file %s", pod.Namespace, pod.Name, filename) // TODO(dchen1107): BoundPod is not type of runtime.Object. Once we allow kubelet talks // about Pod directly, we can use SelfLinker defined in package: latest // Currently just simply follow the same format in resthandler.go pod.ObjectMeta.SelfLink = fmt.Sprintf("/api/v1beta2/pods/%s?namespace=%s", pod.Name, pod.Namespace) if glog.V(4) { glog.Infof("Got pod from file %q: %#v", filename, pod) } else { glog.V(5).Infof("Got pod from file %q: %s.%s (%s)", filename, pod.Namespace, pod.Name, pod.UID) } return pod, nil }
func TestGetRestartCount(t *testing.T) { dm, fakeDocker := newTestDockerManager() containers := []api.Container{ {Name: "bar"}, } pod := api.Pod{ ObjectMeta: api.ObjectMeta{ UID: "12345678", Name: "foo", Namespace: "new", }, Spec: api.PodSpec{ Containers: containers, }, } // format is // k8s_<container-id>_<pod-fullname>_<pod-uid> names := []string{"/k8s_bar." + strconv.FormatUint(kubecontainer.HashContainer(&containers[0]), 16) + "_foo_new_12345678_0"} currTime := time.Now() containerMap := map[string]*docker.Container{ "1234": { ID: "1234", Name: "bar", Config: &docker.Config{}, State: docker.State{ ExitCode: 42, StartedAt: currTime.Add(-60 * time.Second), FinishedAt: currTime.Add(-60 * time.Second), }, }, "5678": { ID: "5678", Name: "bar", Config: &docker.Config{}, State: docker.State{ ExitCode: 42, StartedAt: currTime.Add(-30 * time.Second), FinishedAt: currTime.Add(-30 * time.Second), }, }, "9101": { ID: "9101", Name: "bar", Config: &docker.Config{}, State: docker.State{ ExitCode: 42, StartedAt: currTime.Add(30 * time.Minute), FinishedAt: currTime.Add(30 * time.Minute), }, }, } fakeDocker.ContainerMap = containerMap // Helper function for verifying the restart count. verifyRestartCount := func(pod *api.Pod, expectedCount int) api.PodStatus { status, err := dm.GetPodStatus(pod) if err != nil { t.Fatalf("unexpected error %v", err) } restartCount := status.ContainerStatuses[0].RestartCount if restartCount != expectedCount { t.Errorf("expected %d restart count, got %d", expectedCount, restartCount) } return *status } // Container "bar" has failed twice; create two dead docker containers. // TODO: container lists are expected to be sorted reversely by time. // We should fix FakeDockerClient to sort the list before returning. fakeDocker.ExitedContainerList = []docker.APIContainers{{Names: names, ID: "5678"}, {Names: names, ID: "1234"}} pod.Status = verifyRestartCount(&pod, 1) // Found a new dead container. The restart count should be incremented. fakeDocker.ExitedContainerList = []docker.APIContainers{ {Names: names, ID: "9101"}, {Names: names, ID: "5678"}, {Names: names, ID: "1234"}} pod.Status = verifyRestartCount(&pod, 2) // All dead containers have been GC'd. The restart count should persist // (i.e., remain the same). fakeDocker.ExitedContainerList = []docker.APIContainers{} verifyRestartCount(&pod, 2) }