2015-03-11 21:53:36 +00:00
|
|
|
/*
|
2015-05-01 16:19:44 +00:00
|
|
|
Copyright 2015 The Kubernetes Authors All rights reserved.
|
2015-03-11 21:53:36 +00:00
|
|
|
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
you may not use this file except in compliance with the License.
|
|
|
|
You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
package container
|
|
|
|
|
|
|
|
import (
|
2015-08-13 12:59:15 +00:00
|
|
|
"errors"
|
2015-03-23 17:14:30 +00:00
|
|
|
"fmt"
|
2015-04-23 01:09:24 +00:00
|
|
|
"io"
|
2015-06-05 21:10:45 +00:00
|
|
|
"reflect"
|
2015-03-23 17:14:30 +00:00
|
|
|
"strings"
|
2015-11-10 22:18:47 +00:00
|
|
|
"time"
|
2015-03-23 17:14:30 +00:00
|
|
|
|
2015-10-07 17:58:05 +00:00
|
|
|
"github.com/golang/glog"
|
2015-08-05 22:03:47 +00:00
|
|
|
"k8s.io/kubernetes/pkg/api"
|
|
|
|
"k8s.io/kubernetes/pkg/types"
|
2015-08-13 12:59:15 +00:00
|
|
|
"k8s.io/kubernetes/pkg/util"
|
2015-08-05 22:03:47 +00:00
|
|
|
"k8s.io/kubernetes/pkg/volume"
|
2015-03-11 21:53:36 +00:00
|
|
|
)
|
|
|
|
|
2015-08-13 12:59:15 +00:00
|
|
|
// Container Terminated and Kubelet is backing off the restart
|
|
|
|
var ErrCrashLoopBackOff = errors.New("CrashLoopBackOff")
|
|
|
|
|
2015-10-02 13:45:46 +00:00
|
|
|
var (
|
|
|
|
// Container image pull failed, kubelet is backing off image pull
|
|
|
|
ErrImagePullBackOff = errors.New("ImagePullBackOff")
|
|
|
|
|
|
|
|
// Unable to inspect image
|
|
|
|
ErrImageInspect = errors.New("ImageInspectError")
|
|
|
|
|
|
|
|
// General image pull error
|
|
|
|
ErrImagePull = errors.New("ErrImagePull")
|
|
|
|
|
|
|
|
// Required Image is absent on host and PullPolicy is NeverPullImage
|
|
|
|
ErrImageNeverPull = errors.New("ErrImageNeverPull")
|
2015-09-18 16:09:16 +00:00
|
|
|
|
|
|
|
// Get http error when pulling image from registry
|
|
|
|
RegistryUnavailable = errors.New("RegistryUnavailable")
|
2015-10-02 13:45:46 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var ErrRunContainer = errors.New("RunContainerError")
|
|
|
|
|
2015-04-21 20:02:50 +00:00
|
|
|
type Version interface {
|
|
|
|
// Compare compares two versions of the runtime. On success it returns -1
|
|
|
|
// if the version is less than the other, 1 if it is greater than the other,
|
|
|
|
// or 0 if they are equal.
|
|
|
|
Compare(other string) (int, error)
|
|
|
|
// String returns a string that represents the version.
|
|
|
|
String() string
|
|
|
|
}
|
|
|
|
|
2015-05-06 21:42:03 +00:00
|
|
|
// ImageSpec is an internal representation of an image. Currently, it wraps the
|
|
|
|
// value of a Container's Image field, but in the future it will include more detailed
|
|
|
|
// information about the different image types.
|
|
|
|
type ImageSpec struct {
|
|
|
|
Image string
|
|
|
|
}
|
|
|
|
|
2015-03-11 21:53:36 +00:00
|
|
|
// Runtime interface defines the interfaces that should be implemented
|
|
|
|
// by a container runtime.
|
2015-10-20 00:35:33 +00:00
|
|
|
// Thread safety is required from implementations of this interface.
|
2015-03-11 21:53:36 +00:00
|
|
|
type Runtime interface {
|
2015-10-21 20:04:10 +00:00
|
|
|
// Type returns the type of the container runtime.
|
|
|
|
Type() string
|
|
|
|
|
2015-04-21 20:02:50 +00:00
|
|
|
// Version returns the version information of the container runtime.
|
|
|
|
Version() (Version, error)
|
2015-03-11 21:53:36 +00:00
|
|
|
// GetPods returns a list containers group by pods. The boolean parameter
|
|
|
|
// specifies whether the runtime returns all containers including those already
|
|
|
|
// exited and dead containers (used for garbage collection).
|
|
|
|
GetPods(all bool) ([]*Pod, error)
|
2015-10-05 22:35:32 +00:00
|
|
|
// GarbageCollect removes dead containers using the specified container gc policy
|
|
|
|
GarbageCollect(gcPolicy ContainerGCPolicy) error
|
2015-04-30 23:48:15 +00:00
|
|
|
// Syncs the running pod into the desired pod.
|
2015-08-13 12:59:15 +00:00
|
|
|
SyncPod(pod *api.Pod, runningPod Pod, podStatus api.PodStatus, pullSecrets []api.Secret, backOff *util.Backoff) error
|
2015-08-20 01:57:58 +00:00
|
|
|
// KillPod kills all the containers of a pod. Pod may be nil, running pod must not be.
|
|
|
|
KillPod(pod *api.Pod, runningPod Pod) error
|
2015-03-11 21:53:36 +00:00
|
|
|
// GetPodStatus retrieves the status of the pod, including the information of
|
2015-11-10 22:18:47 +00:00
|
|
|
// all containers in the pod. Clients of this interface assume the
|
|
|
|
// containers' statuses in a pod always have a deterministic ordering
|
|
|
|
// (e.g., sorted by name).
|
|
|
|
// TODO: Rename this to GetAPIPodStatus, and eventually deprecate the
|
|
|
|
// function in favor of GetRawPodStatus.
|
2015-04-30 17:12:23 +00:00
|
|
|
GetPodStatus(*api.Pod) (*api.PodStatus, error)
|
2015-11-10 22:18:47 +00:00
|
|
|
// GetRawPodStatus retrieves the status of the pod, including the
|
|
|
|
// information of all containers in the pod that are visble in Runtime.
|
|
|
|
// TODO: Rename this to GetPodStatus to replace the original function.
|
|
|
|
GetRawPodStatus(uid types.UID, name, namespace string) (*RawPodStatus, error)
|
|
|
|
// ConvertRawToPodStatus converts the RawPodStatus object to api.PodStatus.
|
|
|
|
// This function is needed because Docker generates some high-level and/or
|
|
|
|
// pod-level information for api.PodStatus (e.g., check whether the image
|
|
|
|
// exists to determine the reason).
|
|
|
|
// TODO: Deprecate this function once we generalize the logic for all
|
|
|
|
// container runtimes in kubelet.
|
|
|
|
ConvertRawToPodStatus(*api.Pod, *RawPodStatus) (*api.PodStatus, error)
|
2015-05-06 21:42:03 +00:00
|
|
|
// PullImage pulls an image from the network to local storage using the supplied
|
|
|
|
// secrets if necessary.
|
2015-05-08 17:53:00 +00:00
|
|
|
PullImage(image ImageSpec, pullSecrets []api.Secret) error
|
2015-04-23 17:35:14 +00:00
|
|
|
// IsImagePresent checks whether the container image is already in the local storage.
|
2015-05-06 21:42:03 +00:00
|
|
|
IsImagePresent(image ImageSpec) (bool, error)
|
2015-04-29 23:00:36 +00:00
|
|
|
// Gets all images currently on the machine.
|
|
|
|
ListImages() ([]Image, error)
|
|
|
|
// Removes the specified image.
|
2015-05-06 21:42:03 +00:00
|
|
|
RemoveImage(image ImageSpec) error
|
2015-05-01 23:07:05 +00:00
|
|
|
// TODO(vmarmol): Unify pod and containerID args.
|
2015-04-29 03:25:25 +00:00
|
|
|
// GetContainerLogs returns logs of a specific container. By
|
|
|
|
// default, it returns a snapshot of the container log. Set 'follow' to true to
|
|
|
|
// stream the log. Set 'follow' to false and specify the number of lines (e.g.
|
|
|
|
// "100" or "all") to tail the log.
|
2015-10-07 17:58:05 +00:00
|
|
|
GetContainerLogs(pod *api.Pod, containerID ContainerID, logOptions *api.PodLogOptions, stdout, stderr io.Writer) (err error)
|
2015-05-11 22:32:51 +00:00
|
|
|
// ContainerCommandRunner encapsulates the command runner interfaces for testability.
|
|
|
|
ContainerCommandRunner
|
2015-07-28 04:48:55 +00:00
|
|
|
// ContainerAttach encapsulates the attaching to containers for testability
|
|
|
|
ContainerAttacher
|
|
|
|
}
|
|
|
|
|
|
|
|
type ContainerAttacher interface {
|
2015-10-07 17:58:05 +00:00
|
|
|
AttachContainer(id ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool) (err error)
|
2015-05-11 22:32:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// CommandRunner encapsulates the command runner interfaces for testability.
|
|
|
|
type ContainerCommandRunner interface {
|
|
|
|
// TODO(vmarmol): Merge RunInContainer and ExecInContainer.
|
|
|
|
// Runs the command in the container of the specified pod using nsinit.
|
2015-10-07 17:58:05 +00:00
|
|
|
RunInContainer(containerID ContainerID, cmd []string) ([]byte, error)
|
2015-05-11 22:32:51 +00:00
|
|
|
// Runs the command in the container of the specified pod using nsenter.
|
|
|
|
// Attaches the processes stdin, stdout, and stderr. Optionally uses a
|
|
|
|
// tty.
|
2015-10-07 17:58:05 +00:00
|
|
|
ExecInContainer(containerID ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool) error
|
2015-05-11 22:32:51 +00:00
|
|
|
// Forward the specified port from the specified pod to the stream.
|
|
|
|
PortForward(pod *Pod, port uint16, stream io.ReadWriteCloser) error
|
2015-03-11 21:53:36 +00:00
|
|
|
}
|
|
|
|
|
2015-08-10 17:28:39 +00:00
|
|
|
// ImagePuller wraps Runtime.PullImage() to pull a container image.
|
|
|
|
// It will check the presence of the image, and report the 'image pulling',
|
|
|
|
// 'image pulled' events correspondingly.
|
|
|
|
type ImagePuller interface {
|
2015-10-02 13:45:46 +00:00
|
|
|
PullImage(pod *api.Pod, container *api.Container, pullSecrets []api.Secret) (error, string)
|
2015-04-29 20:35:37 +00:00
|
|
|
}
|
|
|
|
|
2015-11-10 22:18:47 +00:00
|
|
|
// Pod is a group of containers.
|
2015-03-11 21:53:36 +00:00
|
|
|
type Pod struct {
|
|
|
|
// The ID of the pod, which can be used to retrieve a particular pod
|
|
|
|
// from the pod list returned by GetPods().
|
|
|
|
ID types.UID
|
|
|
|
// The name and namespace of the pod, which is readable by human.
|
|
|
|
Name string
|
|
|
|
Namespace string
|
|
|
|
// List of containers that belongs to this pod. It may contain only
|
|
|
|
// running containers, or mixed with dead ones (when GetPods(true)).
|
|
|
|
Containers []*Container
|
|
|
|
}
|
|
|
|
|
2015-04-22 23:19:05 +00:00
|
|
|
// ContainerID is a type that identifies a container.
|
|
|
|
type ContainerID struct {
|
|
|
|
// The type of the container runtime. e.g. 'docker', 'rkt'.
|
|
|
|
Type string
|
|
|
|
// The identification of the container, this is comsumable by
|
|
|
|
// the underlying container runtime. (Note that the container
|
|
|
|
// runtime interface still takes the whole struct as input).
|
|
|
|
ID string
|
|
|
|
}
|
|
|
|
|
|
|
|
func BuildContainerID(typ, ID string) ContainerID {
|
|
|
|
return ContainerID{Type: typ, ID: ID}
|
|
|
|
}
|
|
|
|
|
2015-10-07 17:58:05 +00:00
|
|
|
// Convenience method for creating a ContainerID from an ID string.
|
|
|
|
func ParseContainerID(containerID string) ContainerID {
|
|
|
|
var id ContainerID
|
|
|
|
if err := id.ParseString(containerID); err != nil {
|
|
|
|
glog.Error(err)
|
|
|
|
}
|
|
|
|
return id
|
|
|
|
}
|
|
|
|
|
2015-04-22 23:19:05 +00:00
|
|
|
func (c *ContainerID) ParseString(data string) error {
|
|
|
|
// Trim the quotes and split the type and ID.
|
|
|
|
parts := strings.Split(strings.Trim(data, "\""), "://")
|
|
|
|
if len(parts) != 2 {
|
|
|
|
return fmt.Errorf("invalid container ID: %q", data)
|
|
|
|
}
|
|
|
|
c.Type, c.ID = parts[0], parts[1]
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *ContainerID) String() string {
|
|
|
|
return fmt.Sprintf("%s://%s", c.Type, c.ID)
|
|
|
|
}
|
|
|
|
|
2015-10-07 17:58:05 +00:00
|
|
|
func (c *ContainerID) IsEmpty() bool {
|
|
|
|
return *c == ContainerID{}
|
|
|
|
}
|
|
|
|
|
2015-04-22 23:19:05 +00:00
|
|
|
func (c *ContainerID) MarshalJSON() ([]byte, error) {
|
|
|
|
return []byte(fmt.Sprintf("%q", c.String())), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *ContainerID) UnmarshalJSON(data []byte) error {
|
|
|
|
return c.ParseString(string(data))
|
|
|
|
}
|
|
|
|
|
2015-11-06 02:19:45 +00:00
|
|
|
type ContainerStatus string
|
|
|
|
|
|
|
|
const (
|
|
|
|
ContainerStatusRunning ContainerStatus = "running"
|
|
|
|
ContainerStatusExited ContainerStatus = "exited"
|
|
|
|
// This unknown encompasses all the statuses that we currently don't care.
|
|
|
|
ContainerStatusUnknown ContainerStatus = "unknown"
|
|
|
|
)
|
|
|
|
|
2015-03-11 21:53:36 +00:00
|
|
|
// Container provides the runtime information for a container, such as ID, hash,
|
|
|
|
// status of the container.
|
|
|
|
type Container struct {
|
|
|
|
// The ID of the container, used by the container runtime to identify
|
|
|
|
// a container.
|
2015-10-07 17:58:05 +00:00
|
|
|
ID ContainerID
|
2015-03-11 21:53:36 +00:00
|
|
|
// The name of the container, which should be the same as specified by
|
|
|
|
// api.Container.
|
|
|
|
Name string
|
|
|
|
// The image name of the container.
|
|
|
|
Image string
|
|
|
|
// Hash of the container, used for comparison. Optional for containers
|
|
|
|
// not managed by kubelet.
|
|
|
|
Hash uint64
|
2015-03-20 21:16:55 +00:00
|
|
|
// The timestamp of the creation time of the container.
|
|
|
|
// TODO(yifan): Consider to move it to api.ContainerStatus.
|
|
|
|
Created int64
|
2015-11-06 02:19:45 +00:00
|
|
|
// Status is the status of the container.
|
|
|
|
Status ContainerStatus
|
2015-03-20 21:16:55 +00:00
|
|
|
}
|
|
|
|
|
2015-11-10 22:18:47 +00:00
|
|
|
// RawPodStatus represents the status of the pod and its containers.
|
|
|
|
// api.PodStatus can be derived from examining RawPodStatus and api.Pod.
|
|
|
|
type RawPodStatus struct {
|
|
|
|
// ID of the pod.
|
|
|
|
ID types.UID
|
|
|
|
// Name of the pod.
|
|
|
|
Name string
|
|
|
|
// Namspace of the pod.
|
|
|
|
Namespace string
|
|
|
|
// IP of the pod.
|
|
|
|
IP string
|
|
|
|
// Status of containers in the pod.
|
|
|
|
ContainerStatuses []*RawContainerStatus
|
|
|
|
}
|
|
|
|
|
|
|
|
// RawPodContainer represents the status of a container.
|
|
|
|
type RawContainerStatus struct {
|
|
|
|
// ID of the container.
|
|
|
|
ID ContainerID
|
|
|
|
// Name of the container.
|
|
|
|
Name string
|
|
|
|
// Status of the container.
|
|
|
|
Status ContainerStatus
|
|
|
|
// Creation time of the container.
|
|
|
|
CreatedAt time.Time
|
|
|
|
// Start time of the container.
|
|
|
|
StartedAt time.Time
|
|
|
|
// Finish time of the container.
|
|
|
|
FinishedAt time.Time
|
|
|
|
// Exit code of the container.
|
|
|
|
ExitCode int
|
|
|
|
// Name of the image.
|
|
|
|
Image string
|
|
|
|
// ID of the image.
|
|
|
|
ImageID string
|
|
|
|
// Hash of the container, used for comparison.
|
|
|
|
Hash string
|
|
|
|
// Number of times that the container has been restarted.
|
|
|
|
RestartCount int
|
|
|
|
// A string explains why container is in such a status.
|
|
|
|
Reason string
|
|
|
|
// Message written by the container before exiting (stored in
|
|
|
|
// TerminationMessagePath).
|
|
|
|
Message string
|
|
|
|
}
|
|
|
|
|
2015-04-29 23:00:36 +00:00
|
|
|
// Basic information about a container image.
|
|
|
|
type Image struct {
|
|
|
|
// ID of the image.
|
|
|
|
ID string
|
|
|
|
// Other names by which this image is known.
|
|
|
|
Tags []string
|
|
|
|
// The size of the image in bytes.
|
|
|
|
Size int64
|
|
|
|
}
|
|
|
|
|
2015-05-12 21:49:35 +00:00
|
|
|
type EnvVar struct {
|
|
|
|
Name string
|
|
|
|
Value string
|
|
|
|
}
|
|
|
|
|
|
|
|
type Mount struct {
|
|
|
|
// Name of the volume mount.
|
|
|
|
Name string
|
|
|
|
// Path of the mount within the container.
|
|
|
|
ContainerPath string
|
|
|
|
// Path of the mount on the host.
|
|
|
|
HostPath string
|
|
|
|
// Whether the mount is read-only.
|
|
|
|
ReadOnly bool
|
2015-10-07 19:19:06 +00:00
|
|
|
// Whether the mount needs SELinux relabeling
|
|
|
|
SELinuxRelabel bool
|
2015-05-12 21:49:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
type PortMapping struct {
|
|
|
|
// Name of the port mapping
|
|
|
|
Name string
|
|
|
|
// Protocol of the port mapping.
|
|
|
|
Protocol api.Protocol
|
|
|
|
// The port number within the container.
|
|
|
|
ContainerPort int
|
|
|
|
// The port number on the host.
|
|
|
|
HostPort int
|
|
|
|
// The host IP.
|
|
|
|
HostIP string
|
|
|
|
}
|
|
|
|
|
2015-03-26 18:59:41 +00:00
|
|
|
// RunContainerOptions specify the options which are necessary for running containers
|
|
|
|
type RunContainerOptions struct {
|
2015-05-12 21:49:35 +00:00
|
|
|
// The environment variables list.
|
|
|
|
Envs []EnvVar
|
|
|
|
// The mounts for the containers.
|
|
|
|
Mounts []Mount
|
|
|
|
// The port mappings for the containers.
|
|
|
|
PortMappings []PortMapping
|
2015-03-26 18:59:41 +00:00
|
|
|
// If the container has specified the TerminationMessagePath, then
|
|
|
|
// this directory will be used to create and mount the log file to
|
|
|
|
// container.TerminationMessagePath
|
|
|
|
PodContainerDir string
|
|
|
|
// The list of DNS servers for the container to use.
|
|
|
|
DNS []string
|
|
|
|
// The list of DNS search domains.
|
|
|
|
DNSSearch []string
|
2015-04-24 00:07:52 +00:00
|
|
|
// The parent cgroup to pass to Docker
|
|
|
|
CgroupParent string
|
2015-03-26 18:59:41 +00:00
|
|
|
}
|
|
|
|
|
2015-10-07 19:19:06 +00:00
|
|
|
// VolumeInfo contains information about the volume.
|
|
|
|
type VolumeInfo struct {
|
|
|
|
// Builder is the volume's builder
|
|
|
|
Builder volume.Builder
|
|
|
|
// SELinuxLabeled indicates whether this volume has had the
|
|
|
|
// pod's SELinux label applied to it or not
|
|
|
|
SELinuxLabeled bool
|
|
|
|
}
|
|
|
|
|
|
|
|
type VolumeMap map[string]VolumeInfo
|
2015-05-06 23:50:57 +00:00
|
|
|
|
2015-03-20 21:16:55 +00:00
|
|
|
type Pods []*Pod
|
|
|
|
|
2015-04-06 23:58:34 +00:00
|
|
|
// FindPodByID finds and returns a pod in the pod list by UID. It will return an empty pod
|
2015-03-20 21:16:55 +00:00
|
|
|
// if not found.
|
|
|
|
func (p Pods) FindPodByID(podUID types.UID) Pod {
|
|
|
|
for i := range p {
|
|
|
|
if p[i].ID == podUID {
|
|
|
|
return *p[i]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Pod{}
|
|
|
|
}
|
|
|
|
|
2015-04-06 23:58:34 +00:00
|
|
|
// FindPodByFullName finds and returns a pod in the pod list by the full name.
|
|
|
|
// It will return an empty pod if not found.
|
|
|
|
func (p Pods) FindPodByFullName(podFullName string) Pod {
|
|
|
|
for i := range p {
|
|
|
|
if BuildPodFullName(p[i].Name, p[i].Namespace) == podFullName {
|
|
|
|
return *p[i]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Pod{}
|
|
|
|
}
|
|
|
|
|
|
|
|
// FindPod combines FindPodByID and FindPodByFullName, it finds and returns a pod in the
|
|
|
|
// pod list either by the full name or the pod ID. It will return an empty pod
|
|
|
|
// if not found.
|
|
|
|
func (p Pods) FindPod(podFullName string, podUID types.UID) Pod {
|
|
|
|
if len(podFullName) > 0 {
|
|
|
|
return p.FindPodByFullName(podFullName)
|
|
|
|
}
|
|
|
|
return p.FindPodByID(podUID)
|
|
|
|
}
|
|
|
|
|
2015-03-20 21:16:55 +00:00
|
|
|
// FindContainerByName returns a container in the pod with the given name.
|
|
|
|
// When there are multiple containers with the same name, the first match will
|
|
|
|
// be returned.
|
|
|
|
func (p *Pod) FindContainerByName(containerName string) *Container {
|
|
|
|
for _, c := range p.Containers {
|
|
|
|
if c.Name == containerName {
|
|
|
|
return c
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
2015-03-11 21:53:36 +00:00
|
|
|
}
|
2015-03-23 17:14:30 +00:00
|
|
|
|
2015-06-23 23:01:12 +00:00
|
|
|
// 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
|
|
|
|
}
|
|
|
|
|
2015-06-05 21:10:45 +00:00
|
|
|
// IsEmpty returns true if the pod is empty.
|
|
|
|
func (p *Pod) IsEmpty() bool {
|
|
|
|
return reflect.DeepEqual(p, &Pod{})
|
|
|
|
}
|
|
|
|
|
2015-03-23 17:14:30 +00:00
|
|
|
// GetPodFullName returns a name that uniquely identifies a pod.
|
|
|
|
func GetPodFullName(pod *api.Pod) string {
|
|
|
|
// Use underscore as the delimiter because it is not allowed in pod name
|
|
|
|
// (DNS subdomain format), while allowed in the container name format.
|
2015-10-29 08:22:33 +00:00
|
|
|
return pod.Name + "_" + pod.Namespace
|
2015-03-23 17:14:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Build the pod full name from pod name and namespace.
|
|
|
|
func BuildPodFullName(name, namespace string) string {
|
|
|
|
return name + "_" + namespace
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse the pod full name.
|
|
|
|
func ParsePodFullName(podFullName string) (string, string, error) {
|
|
|
|
parts := strings.Split(podFullName, "_")
|
|
|
|
if len(parts) != 2 {
|
|
|
|
return "", "", fmt.Errorf("failed to parse the pod full name %q", podFullName)
|
|
|
|
}
|
|
|
|
return parts[0], parts[1], nil
|
|
|
|
}
|