//TODO(jdef) unit test this, ensure that task's copy of api.Pod is not modified func (b *binder) prepareTaskForLaunch(ctx api.Context, machine string, task *podtask.T, offerId string) error { pod := task.Pod // we make an effort here to avoid making changes to the task's copy of the pod, since // we want that to reflect the initial user spec, and not the modified spec that we // build for the executor to consume. oemCt := pod.Spec.Containers pod.Spec.Containers = append([]api.Container{}, oemCt...) // (shallow) clone before mod 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] = machine task.SaveRecoveryInfo(pod.Annotations) for _, entry := range task.Spec.PortMap { oemPorts := pod.Spec.Containers[entry.ContainerIdx].Ports ports := append([]api.ContainerPort{}, oemPorts...) p := &ports[entry.PortIdx] p.HostPort = int(entry.OfferPort) op := strconv.FormatUint(entry.OfferPort, 10) pod.Annotations[fmt.Sprintf(annotation.PortMappingKeyFormat, p.Protocol, p.ContainerPort)] = op if p.Name != "" { pod.Annotations[fmt.Sprintf(annotation.PortNameMappingKeyFormat, p.Protocol, p.Name)] = op } pod.Spec.Containers[entry.ContainerIdx].Ports = ports } // the qinglet-executor uses this to instantiate the pod log.V(3).Infof("prepared pod spec: %+v", pod) data, err := api.Codec.Encode(&pod) if err != nil { log.V(2).Infof("Failed to marshal the pod spec: %v", err) return err } task.Spec.Data = data return nil }