mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 02:43:36 +00:00
vendor update for E2E framework
Signed-off-by: Madhu Rajanna <madhupr007@gmail.com>
This commit is contained in:
199
vendor/k8s.io/kubernetes/pkg/kubelet/container/cache.go
generated
vendored
Normal file
199
vendor/k8s.io/kubernetes/pkg/kubelet/container/cache.go
generated
vendored
Normal file
@ -0,0 +1,199 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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 (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
// Cache stores the PodStatus for the pods. It represents *all* the visible
|
||||
// pods/containers in the container runtime. All cache entries are at least as
|
||||
// new or newer than the global timestamp (set by UpdateTime()), while
|
||||
// individual entries may be slightly newer than the global timestamp. If a pod
|
||||
// has no states known by the runtime, Cache returns an empty PodStatus object
|
||||
// with ID populated.
|
||||
//
|
||||
// Cache provides two methods to retrive the PodStatus: the non-blocking Get()
|
||||
// and the blocking GetNewerThan() method. The component responsible for
|
||||
// populating the cache is expected to call Delete() to explicitly free the
|
||||
// cache entries.
|
||||
type Cache interface {
|
||||
Get(types.UID) (*PodStatus, error)
|
||||
Set(types.UID, *PodStatus, error, time.Time)
|
||||
// GetNewerThan is a blocking call that only returns the status
|
||||
// when it is newer than the given time.
|
||||
GetNewerThan(types.UID, time.Time) (*PodStatus, error)
|
||||
Delete(types.UID)
|
||||
UpdateTime(time.Time)
|
||||
}
|
||||
|
||||
type data struct {
|
||||
// Status of the pod.
|
||||
status *PodStatus
|
||||
// Error got when trying to inspect the pod.
|
||||
err error
|
||||
// Time when the data was last modified.
|
||||
modified time.Time
|
||||
}
|
||||
|
||||
type subRecord struct {
|
||||
time time.Time
|
||||
ch chan *data
|
||||
}
|
||||
|
||||
// cache implements Cache.
|
||||
type cache struct {
|
||||
// Lock which guards all internal data structures.
|
||||
lock sync.RWMutex
|
||||
// Map that stores the pod statuses.
|
||||
pods map[types.UID]*data
|
||||
// A global timestamp represents how fresh the cached data is. All
|
||||
// cache content is at the least newer than this timestamp. Note that the
|
||||
// timestamp is nil after initialization, and will only become non-nil when
|
||||
// it is ready to serve the cached statuses.
|
||||
timestamp *time.Time
|
||||
// Map that stores the subscriber records.
|
||||
subscribers map[types.UID][]*subRecord
|
||||
}
|
||||
|
||||
// NewCache creates a pod cache.
|
||||
func NewCache() Cache {
|
||||
return &cache{pods: map[types.UID]*data{}, subscribers: map[types.UID][]*subRecord{}}
|
||||
}
|
||||
|
||||
// Get returns the PodStatus for the pod; callers are expected not to
|
||||
// modify the objects returned.
|
||||
func (c *cache) Get(id types.UID) (*PodStatus, error) {
|
||||
c.lock.RLock()
|
||||
defer c.lock.RUnlock()
|
||||
d := c.get(id)
|
||||
return d.status, d.err
|
||||
}
|
||||
|
||||
func (c *cache) GetNewerThan(id types.UID, minTime time.Time) (*PodStatus, error) {
|
||||
ch := c.subscribe(id, minTime)
|
||||
d := <-ch
|
||||
return d.status, d.err
|
||||
}
|
||||
|
||||
// Set sets the PodStatus for the pod.
|
||||
func (c *cache) Set(id types.UID, status *PodStatus, err error, timestamp time.Time) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
defer c.notify(id, timestamp)
|
||||
c.pods[id] = &data{status: status, err: err, modified: timestamp}
|
||||
}
|
||||
|
||||
// Delete removes the entry of the pod.
|
||||
func (c *cache) Delete(id types.UID) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
delete(c.pods, id)
|
||||
}
|
||||
|
||||
// UpdateTime modifies the global timestamp of the cache and notify
|
||||
// subscribers if needed.
|
||||
func (c *cache) UpdateTime(timestamp time.Time) {
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
c.timestamp = ×tamp
|
||||
// Notify all the subscribers if the condition is met.
|
||||
for id := range c.subscribers {
|
||||
c.notify(id, *c.timestamp)
|
||||
}
|
||||
}
|
||||
|
||||
func makeDefaultData(id types.UID) *data {
|
||||
return &data{status: &PodStatus{ID: id}, err: nil}
|
||||
}
|
||||
|
||||
func (c *cache) get(id types.UID) *data {
|
||||
d, ok := c.pods[id]
|
||||
if !ok {
|
||||
// Cache should store *all* pod/container information known by the
|
||||
// container runtime. A cache miss indicates that there are no states
|
||||
// regarding the pod last time we queried the container runtime.
|
||||
// What this *really* means is that there are no visible pod/containers
|
||||
// associated with this pod. Simply return an default (mostly empty)
|
||||
// PodStatus to reflect this.
|
||||
return makeDefaultData(id)
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// getIfNewerThan returns the data it is newer than the given time.
|
||||
// Otherwise, it returns nil. The caller should acquire the lock.
|
||||
func (c *cache) getIfNewerThan(id types.UID, minTime time.Time) *data {
|
||||
d, ok := c.pods[id]
|
||||
globalTimestampIsNewer := (c.timestamp != nil && c.timestamp.After(minTime))
|
||||
if !ok && globalTimestampIsNewer {
|
||||
// Status is not cached, but the global timestamp is newer than
|
||||
// minTime, return the default status.
|
||||
return makeDefaultData(id)
|
||||
}
|
||||
if ok && (d.modified.After(minTime) || globalTimestampIsNewer) {
|
||||
// Status is cached, return status if either of the following is true.
|
||||
// * status was modified after minTime
|
||||
// * the global timestamp of the cache is newer than minTime.
|
||||
return d
|
||||
}
|
||||
// The pod status is not ready.
|
||||
return nil
|
||||
}
|
||||
|
||||
// notify sends notifications for pod with the given id, if the requirements
|
||||
// are met. Note that the caller should acquire the lock.
|
||||
func (c *cache) notify(id types.UID, timestamp time.Time) {
|
||||
list, ok := c.subscribers[id]
|
||||
if !ok {
|
||||
// No one to notify.
|
||||
return
|
||||
}
|
||||
newList := []*subRecord{}
|
||||
for i, r := range list {
|
||||
if timestamp.Before(r.time) {
|
||||
// Doesn't meet the time requirement; keep the record.
|
||||
newList = append(newList, list[i])
|
||||
continue
|
||||
}
|
||||
r.ch <- c.get(id)
|
||||
close(r.ch)
|
||||
}
|
||||
if len(newList) == 0 {
|
||||
delete(c.subscribers, id)
|
||||
} else {
|
||||
c.subscribers[id] = newList
|
||||
}
|
||||
}
|
||||
|
||||
func (c *cache) subscribe(id types.UID, timestamp time.Time) chan *data {
|
||||
ch := make(chan *data, 1)
|
||||
c.lock.Lock()
|
||||
defer c.lock.Unlock()
|
||||
d := c.getIfNewerThan(id, timestamp)
|
||||
if d != nil {
|
||||
// If the cache entry is ready, send the data and return immediately.
|
||||
ch <- d
|
||||
return ch
|
||||
}
|
||||
// Add the subscription record.
|
||||
c.subscribers[id] = append(c.subscribers[id], &subRecord{time: timestamp, ch: ch})
|
||||
return ch
|
||||
}
|
87
vendor/k8s.io/kubernetes/pkg/kubelet/container/container_gc.go
generated
vendored
Normal file
87
vendor/k8s.io/kubernetes/pkg/kubelet/container/container_gc.go
generated
vendored
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
Copyright 2014 The Kubernetes Authors.
|
||||
|
||||
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 (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// Specified a policy for garbage collecting containers.
|
||||
type ContainerGCPolicy struct {
|
||||
// Minimum age at which a container can be garbage collected, zero for no limit.
|
||||
MinAge time.Duration
|
||||
|
||||
// Max number of dead containers any single pod (UID, container name) pair is
|
||||
// allowed to have, less than zero for no limit.
|
||||
MaxPerPodContainer int
|
||||
|
||||
// Max number of total dead containers, less than zero for no limit.
|
||||
MaxContainers int
|
||||
}
|
||||
|
||||
// Manages garbage collection of dead containers.
|
||||
//
|
||||
// Implementation is thread-compatible.
|
||||
type ContainerGC interface {
|
||||
// Garbage collect containers.
|
||||
GarbageCollect() error
|
||||
// Deletes all unused containers, including containers belonging to pods that are terminated but not deleted
|
||||
DeleteAllUnusedContainers() error
|
||||
}
|
||||
|
||||
// SourcesReadyProvider knows how to determine if configuration sources are ready
|
||||
type SourcesReadyProvider interface {
|
||||
// AllReady returns true if the currently configured sources have all been seen.
|
||||
AllReady() bool
|
||||
}
|
||||
|
||||
// TODO(vmarmol): Preferentially remove pod infra containers.
|
||||
type realContainerGC struct {
|
||||
// Container runtime
|
||||
runtime Runtime
|
||||
|
||||
// Policy for garbage collection.
|
||||
policy ContainerGCPolicy
|
||||
|
||||
// sourcesReadyProvider provides the readiness of kubelet configuration sources.
|
||||
sourcesReadyProvider SourcesReadyProvider
|
||||
}
|
||||
|
||||
// New ContainerGC instance with the specified policy.
|
||||
func NewContainerGC(runtime Runtime, policy ContainerGCPolicy, sourcesReadyProvider SourcesReadyProvider) (ContainerGC, error) {
|
||||
if policy.MinAge < 0 {
|
||||
return nil, fmt.Errorf("invalid minimum garbage collection age: %v", policy.MinAge)
|
||||
}
|
||||
|
||||
return &realContainerGC{
|
||||
runtime: runtime,
|
||||
policy: policy,
|
||||
sourcesReadyProvider: sourcesReadyProvider,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (cgc *realContainerGC) GarbageCollect() error {
|
||||
return cgc.runtime.GarbageCollect(cgc.policy, cgc.sourcesReadyProvider.AllReady(), false)
|
||||
}
|
||||
|
||||
func (cgc *realContainerGC) DeleteAllUnusedContainers() error {
|
||||
klog.Infof("attempting to delete unused containers")
|
||||
return cgc.runtime.GarbageCollect(cgc.policy, cgc.sourcesReadyProvider.AllReady(), true)
|
||||
}
|
60
vendor/k8s.io/kubernetes/pkg/kubelet/container/container_reference_manager.go
generated
vendored
Normal file
60
vendor/k8s.io/kubernetes/pkg/kubelet/container/container_reference_manager.go
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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 (
|
||||
"sync"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
// RefManager manages the references for the containers.
|
||||
// The references are used for reporting events such as creation,
|
||||
// failure, etc. This manager is thread-safe, no locks are necessary
|
||||
// for the caller.
|
||||
type RefManager struct {
|
||||
sync.RWMutex
|
||||
containerIDToRef map[ContainerID]*v1.ObjectReference
|
||||
}
|
||||
|
||||
// NewRefManager creates and returns a container reference manager
|
||||
// with empty contents.
|
||||
func NewRefManager() *RefManager {
|
||||
return &RefManager{containerIDToRef: make(map[ContainerID]*v1.ObjectReference)}
|
||||
}
|
||||
|
||||
// SetRef stores a reference to a pod's container, associating it with the given container ID.
|
||||
func (c *RefManager) SetRef(id ContainerID, ref *v1.ObjectReference) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
c.containerIDToRef[id] = ref
|
||||
}
|
||||
|
||||
// ClearRef forgets the given container id and its associated container reference.
|
||||
func (c *RefManager) ClearRef(id ContainerID) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
delete(c.containerIDToRef, id)
|
||||
}
|
||||
|
||||
// GetRef returns the container reference of the given ID, or (nil, false) if none is stored.
|
||||
func (c *RefManager) GetRef(id ContainerID) (ref *v1.ObjectReference, ok bool) {
|
||||
c.RLock()
|
||||
defer c.RUnlock()
|
||||
ref, ok = c.containerIDToRef[id]
|
||||
return ref, ok
|
||||
}
|
335
vendor/k8s.io/kubernetes/pkg/kubelet/container/helpers.go
generated
vendored
Normal file
335
vendor/k8s.io/kubernetes/pkg/kubelet/container/helpers.go
generated
vendored
Normal file
@ -0,0 +1,335 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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 (
|
||||
"fmt"
|
||||
"hash/fnv"
|
||||
"strings"
|
||||
|
||||
"k8s.io/klog"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/client-go/tools/record"
|
||||
runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
||||
"k8s.io/kubernetes/pkg/kubelet/util/format"
|
||||
hashutil "k8s.io/kubernetes/pkg/util/hash"
|
||||
"k8s.io/kubernetes/third_party/forked/golang/expansion"
|
||||
)
|
||||
|
||||
// HandlerRunner runs a lifecycle handler for a container.
|
||||
type HandlerRunner interface {
|
||||
Run(containerID ContainerID, pod *v1.Pod, container *v1.Container, handler *v1.Handler) (string, error)
|
||||
}
|
||||
|
||||
// RuntimeHelper wraps kubelet to make container runtime
|
||||
// able to get necessary informations like the RunContainerOptions, DNS settings, Host IP.
|
||||
type RuntimeHelper interface {
|
||||
GenerateRunContainerOptions(pod *v1.Pod, container *v1.Container, podIP string) (contOpts *RunContainerOptions, cleanupAction func(), err error)
|
||||
GetPodDNS(pod *v1.Pod) (dnsConfig *runtimeapi.DNSConfig, err error)
|
||||
// GetPodCgroupParent returns the CgroupName identifier, and its literal cgroupfs form on the host
|
||||
// of a pod.
|
||||
GetPodCgroupParent(pod *v1.Pod) string
|
||||
GetPodDir(podUID types.UID) string
|
||||
GeneratePodHostNameAndDomain(pod *v1.Pod) (hostname string, hostDomain string, err error)
|
||||
// GetExtraSupplementalGroupsForPod returns a list of the extra
|
||||
// supplemental groups for the Pod. These extra supplemental groups come
|
||||
// from annotations on persistent volumes that the pod depends on.
|
||||
GetExtraSupplementalGroupsForPod(pod *v1.Pod) []int64
|
||||
}
|
||||
|
||||
// ShouldContainerBeRestarted checks whether a container needs to be restarted.
|
||||
// TODO(yifan): Think about how to refactor this.
|
||||
func ShouldContainerBeRestarted(container *v1.Container, pod *v1.Pod, podStatus *PodStatus) bool {
|
||||
// Get latest container status.
|
||||
status := podStatus.FindContainerStatusByName(container.Name)
|
||||
// If the container was never started before, we should start it.
|
||||
// NOTE(random-liu): If all historical containers were GC'd, we'll also return true here.
|
||||
if status == nil {
|
||||
return true
|
||||
}
|
||||
// Check whether container is running
|
||||
if status.State == ContainerStateRunning {
|
||||
return false
|
||||
}
|
||||
// Always restart container in the unknown, or in the created state.
|
||||
if status.State == ContainerStateUnknown || status.State == ContainerStateCreated {
|
||||
return true
|
||||
}
|
||||
// Check RestartPolicy for dead container
|
||||
if pod.Spec.RestartPolicy == v1.RestartPolicyNever {
|
||||
klog.V(4).Infof("Already ran container %q of pod %q, do nothing", container.Name, format.Pod(pod))
|
||||
return false
|
||||
}
|
||||
if pod.Spec.RestartPolicy == v1.RestartPolicyOnFailure {
|
||||
// Check the exit code.
|
||||
if status.ExitCode == 0 {
|
||||
klog.V(4).Infof("Already successfully ran container %q of pod %q, do nothing", container.Name, format.Pod(pod))
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// HashContainer returns the hash of the container. It is used to compare
|
||||
// the running container with its desired spec.
|
||||
func HashContainer(container *v1.Container) uint64 {
|
||||
hash := fnv.New32a()
|
||||
hashutil.DeepHashObject(hash, *container)
|
||||
return uint64(hash.Sum32())
|
||||
}
|
||||
|
||||
// EnvVarsToMap constructs a map of environment name to value from a slice
|
||||
// of env vars.
|
||||
func EnvVarsToMap(envs []EnvVar) map[string]string {
|
||||
result := map[string]string{}
|
||||
for _, env := range envs {
|
||||
result[env.Name] = env.Value
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// V1EnvVarsToMap constructs a map of environment name to value from a slice
|
||||
// of env vars.
|
||||
func V1EnvVarsToMap(envs []v1.EnvVar) map[string]string {
|
||||
result := map[string]string{}
|
||||
for _, env := range envs {
|
||||
result[env.Name] = env.Value
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// ExpandContainerCommandOnlyStatic substitutes only static environment variable values from the
|
||||
// container environment definitions. This does *not* include valueFrom substitutions.
|
||||
// TODO: callers should use ExpandContainerCommandAndArgs with a fully resolved list of environment.
|
||||
func ExpandContainerCommandOnlyStatic(containerCommand []string, envs []v1.EnvVar) (command []string) {
|
||||
mapping := expansion.MappingFuncFor(V1EnvVarsToMap(envs))
|
||||
if len(containerCommand) != 0 {
|
||||
for _, cmd := range containerCommand {
|
||||
command = append(command, expansion.Expand(cmd, mapping))
|
||||
}
|
||||
}
|
||||
return command
|
||||
}
|
||||
|
||||
func ExpandContainerVolumeMounts(mount v1.VolumeMount, envs []EnvVar) (string, error) {
|
||||
|
||||
envmap := EnvVarsToMap(envs)
|
||||
missingKeys := sets.NewString()
|
||||
expanded := expansion.Expand(mount.SubPathExpr, func(key string) string {
|
||||
value, ok := envmap[key]
|
||||
if !ok || len(value) == 0 {
|
||||
missingKeys.Insert(key)
|
||||
}
|
||||
return value
|
||||
})
|
||||
|
||||
if len(missingKeys) > 0 {
|
||||
return "", fmt.Errorf("missing value for %s", strings.Join(missingKeys.List(), ", "))
|
||||
}
|
||||
return expanded, nil
|
||||
}
|
||||
|
||||
func ExpandContainerCommandAndArgs(container *v1.Container, envs []EnvVar) (command []string, args []string) {
|
||||
mapping := expansion.MappingFuncFor(EnvVarsToMap(envs))
|
||||
|
||||
if len(container.Command) != 0 {
|
||||
for _, cmd := range container.Command {
|
||||
command = append(command, expansion.Expand(cmd, mapping))
|
||||
}
|
||||
}
|
||||
|
||||
if len(container.Args) != 0 {
|
||||
for _, arg := range container.Args {
|
||||
args = append(args, expansion.Expand(arg, mapping))
|
||||
}
|
||||
}
|
||||
|
||||
return command, args
|
||||
}
|
||||
|
||||
// Create an event recorder to record object's event except implicitly required container's, like infra container.
|
||||
func FilterEventRecorder(recorder record.EventRecorder) record.EventRecorder {
|
||||
return &innerEventRecorder{
|
||||
recorder: recorder,
|
||||
}
|
||||
}
|
||||
|
||||
type innerEventRecorder struct {
|
||||
recorder record.EventRecorder
|
||||
}
|
||||
|
||||
func (irecorder *innerEventRecorder) shouldRecordEvent(object runtime.Object) (*v1.ObjectReference, bool) {
|
||||
if object == nil {
|
||||
return nil, false
|
||||
}
|
||||
if ref, ok := object.(*v1.ObjectReference); ok {
|
||||
if !strings.HasPrefix(ref.FieldPath, ImplicitContainerPrefix) {
|
||||
return ref, true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (irecorder *innerEventRecorder) Event(object runtime.Object, eventtype, reason, message string) {
|
||||
if ref, ok := irecorder.shouldRecordEvent(object); ok {
|
||||
irecorder.recorder.Event(ref, eventtype, reason, message)
|
||||
}
|
||||
}
|
||||
|
||||
func (irecorder *innerEventRecorder) Eventf(object runtime.Object, eventtype, reason, messageFmt string, args ...interface{}) {
|
||||
if ref, ok := irecorder.shouldRecordEvent(object); ok {
|
||||
irecorder.recorder.Eventf(ref, eventtype, reason, messageFmt, args...)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (irecorder *innerEventRecorder) PastEventf(object runtime.Object, timestamp metav1.Time, eventtype, reason, messageFmt string, args ...interface{}) {
|
||||
if ref, ok := irecorder.shouldRecordEvent(object); ok {
|
||||
irecorder.recorder.PastEventf(ref, timestamp, eventtype, reason, messageFmt, args...)
|
||||
}
|
||||
}
|
||||
|
||||
func (irecorder *innerEventRecorder) AnnotatedEventf(object runtime.Object, annotations map[string]string, eventtype, reason, messageFmt string, args ...interface{}) {
|
||||
if ref, ok := irecorder.shouldRecordEvent(object); ok {
|
||||
irecorder.recorder.AnnotatedEventf(ref, annotations, eventtype, reason, messageFmt, args...)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Pod must not be nil.
|
||||
func IsHostNetworkPod(pod *v1.Pod) bool {
|
||||
return pod.Spec.HostNetwork
|
||||
}
|
||||
|
||||
// TODO(random-liu): Convert PodStatus to running Pod, should be deprecated soon
|
||||
func ConvertPodStatusToRunningPod(runtimeName string, podStatus *PodStatus) Pod {
|
||||
runningPod := Pod{
|
||||
ID: podStatus.ID,
|
||||
Name: podStatus.Name,
|
||||
Namespace: podStatus.Namespace,
|
||||
}
|
||||
for _, containerStatus := range podStatus.ContainerStatuses {
|
||||
if containerStatus.State != ContainerStateRunning {
|
||||
continue
|
||||
}
|
||||
container := &Container{
|
||||
ID: containerStatus.ID,
|
||||
Name: containerStatus.Name,
|
||||
Image: containerStatus.Image,
|
||||
ImageID: containerStatus.ImageID,
|
||||
Hash: containerStatus.Hash,
|
||||
State: containerStatus.State,
|
||||
}
|
||||
runningPod.Containers = append(runningPod.Containers, container)
|
||||
}
|
||||
|
||||
// Populate sandboxes in kubecontainer.Pod
|
||||
for _, sandbox := range podStatus.SandboxStatuses {
|
||||
runningPod.Sandboxes = append(runningPod.Sandboxes, &Container{
|
||||
ID: ContainerID{Type: runtimeName, ID: sandbox.Id},
|
||||
State: SandboxToContainerState(sandbox.State),
|
||||
})
|
||||
}
|
||||
return runningPod
|
||||
}
|
||||
|
||||
// SandboxToContainerState converts runtimeapi.PodSandboxState to
|
||||
// kubecontainer.ContainerState.
|
||||
// This is only needed because we need to return sandboxes as if they were
|
||||
// kubecontainer.Containers to avoid substantial changes to PLEG.
|
||||
// TODO: Remove this once it becomes obsolete.
|
||||
func SandboxToContainerState(state runtimeapi.PodSandboxState) ContainerState {
|
||||
switch state {
|
||||
case runtimeapi.PodSandboxState_SANDBOX_READY:
|
||||
return ContainerStateRunning
|
||||
case runtimeapi.PodSandboxState_SANDBOX_NOTREADY:
|
||||
return ContainerStateExited
|
||||
}
|
||||
return ContainerStateUnknown
|
||||
}
|
||||
|
||||
// FormatPod returns a string representing a pod in a human readable format,
|
||||
// with pod UID as part of the string.
|
||||
func FormatPod(pod *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.
|
||||
return fmt.Sprintf("%s_%s(%s)", pod.Name, pod.Namespace, pod.ID)
|
||||
}
|
||||
|
||||
// GetContainerSpec gets the container spec by containerName.
|
||||
func GetContainerSpec(pod *v1.Pod, containerName string) *v1.Container {
|
||||
for i, c := range pod.Spec.Containers {
|
||||
if containerName == c.Name {
|
||||
return &pod.Spec.Containers[i]
|
||||
}
|
||||
}
|
||||
for i, c := range pod.Spec.InitContainers {
|
||||
if containerName == c.Name {
|
||||
return &pod.Spec.InitContainers[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// HasPrivilegedContainer returns true if any of the containers in the pod are privileged.
|
||||
func HasPrivilegedContainer(pod *v1.Pod) bool {
|
||||
for _, c := range append(pod.Spec.Containers, pod.Spec.InitContainers...) {
|
||||
if c.SecurityContext != nil &&
|
||||
c.SecurityContext.Privileged != nil &&
|
||||
*c.SecurityContext.Privileged {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// MakePortMappings creates internal port mapping from api port mapping.
|
||||
func MakePortMappings(container *v1.Container) (ports []PortMapping) {
|
||||
names := make(map[string]struct{})
|
||||
for _, p := range container.Ports {
|
||||
pm := PortMapping{
|
||||
HostPort: int(p.HostPort),
|
||||
ContainerPort: int(p.ContainerPort),
|
||||
Protocol: p.Protocol,
|
||||
HostIP: p.HostIP,
|
||||
}
|
||||
|
||||
// We need to create some default port name if it's not specified, since
|
||||
// this is necessary for rkt.
|
||||
// http://issue.k8s.io/7710
|
||||
if p.Name == "" {
|
||||
pm.Name = fmt.Sprintf("%s-%s:%d", container.Name, p.Protocol, p.ContainerPort)
|
||||
} else {
|
||||
pm.Name = fmt.Sprintf("%s-%s", container.Name, p.Name)
|
||||
}
|
||||
|
||||
// Protect against exposing the same protocol-port more than once in a container.
|
||||
if _, ok := names[pm.Name]; ok {
|
||||
klog.Warningf("Port name conflicted, %q is defined more than once", pm.Name)
|
||||
continue
|
||||
}
|
||||
ports = append(ports, pm)
|
||||
names[pm.Name] = struct{}{}
|
||||
}
|
||||
return
|
||||
}
|
107
vendor/k8s.io/kubernetes/pkg/kubelet/container/os.go
generated
vendored
Normal file
107
vendor/k8s.io/kubernetes/pkg/kubelet/container/os.go
generated
vendored
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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 (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
// OSInterface collects system level operations that need to be mocked out
|
||||
// during tests.
|
||||
type OSInterface interface {
|
||||
MkdirAll(path string, perm os.FileMode) error
|
||||
Symlink(oldname string, newname string) error
|
||||
Stat(path string) (os.FileInfo, error)
|
||||
Remove(path string) error
|
||||
RemoveAll(path string) error
|
||||
Create(path string) (*os.File, error)
|
||||
Chmod(path string, perm os.FileMode) error
|
||||
Hostname() (name string, err error)
|
||||
Chtimes(path string, atime time.Time, mtime time.Time) error
|
||||
Pipe() (r *os.File, w *os.File, err error)
|
||||
ReadDir(dirname string) ([]os.FileInfo, error)
|
||||
Glob(pattern string) ([]string, error)
|
||||
}
|
||||
|
||||
// RealOS is used to dispatch the real system level operations.
|
||||
type RealOS struct{}
|
||||
|
||||
// MkdirAll will call os.MkdirAll to create a directory.
|
||||
func (RealOS) MkdirAll(path string, perm os.FileMode) error {
|
||||
return os.MkdirAll(path, perm)
|
||||
}
|
||||
|
||||
// Symlink will call os.Symlink to create a symbolic link.
|
||||
func (RealOS) Symlink(oldname string, newname string) error {
|
||||
return os.Symlink(oldname, newname)
|
||||
}
|
||||
|
||||
// Stat will call os.Stat to get the FileInfo for a given path
|
||||
func (RealOS) Stat(path string) (os.FileInfo, error) {
|
||||
return os.Stat(path)
|
||||
}
|
||||
|
||||
// Remove will call os.Remove to remove the path.
|
||||
func (RealOS) Remove(path string) error {
|
||||
return os.Remove(path)
|
||||
}
|
||||
|
||||
// RemoveAll will call os.RemoveAll to remove the path and its children.
|
||||
func (RealOS) RemoveAll(path string) error {
|
||||
return os.RemoveAll(path)
|
||||
}
|
||||
|
||||
// Create will call os.Create to create and return a file
|
||||
// at path.
|
||||
func (RealOS) Create(path string) (*os.File, error) {
|
||||
return os.Create(path)
|
||||
}
|
||||
|
||||
// Chmod will change the permissions on the specified path or return
|
||||
// an error.
|
||||
func (RealOS) Chmod(path string, perm os.FileMode) error {
|
||||
return os.Chmod(path, perm)
|
||||
}
|
||||
|
||||
// Hostname will call os.Hostname to return the hostname.
|
||||
func (RealOS) Hostname() (name string, err error) {
|
||||
return os.Hostname()
|
||||
}
|
||||
|
||||
// Chtimes will call os.Chtimes to change the atime and mtime of the path
|
||||
func (RealOS) Chtimes(path string, atime time.Time, mtime time.Time) error {
|
||||
return os.Chtimes(path, atime, mtime)
|
||||
}
|
||||
|
||||
// Pipe will call os.Pipe to return a connected pair of pipe.
|
||||
func (RealOS) Pipe() (r *os.File, w *os.File, err error) {
|
||||
return os.Pipe()
|
||||
}
|
||||
|
||||
// ReadDir will call ioutil.ReadDir to return the files under the directory.
|
||||
func (RealOS) ReadDir(dirname string) ([]os.FileInfo, error) {
|
||||
return ioutil.ReadDir(dirname)
|
||||
}
|
||||
|
||||
// Glob will call filepath.Glob to return the names of all files matching
|
||||
// pattern.
|
||||
func (RealOS) Glob(pattern string) ([]string, error) {
|
||||
return filepath.Glob(pattern)
|
||||
}
|
73
vendor/k8s.io/kubernetes/pkg/kubelet/container/ref.go
generated
vendored
Normal file
73
vendor/k8s.io/kubernetes/pkg/kubelet/container/ref.go
generated
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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 (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
ref "k8s.io/client-go/tools/reference"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
)
|
||||
|
||||
var ImplicitContainerPrefix string = "implicitly required container "
|
||||
|
||||
// GenerateContainerRef returns an *v1.ObjectReference which references the given container
|
||||
// within the given pod. Returns an error if the reference can't be constructed or the
|
||||
// container doesn't actually belong to the pod.
|
||||
//
|
||||
// This function will return an error if the provided Pod does not have a selfLink,
|
||||
// but we expect selfLink to be populated at all call sites for the function.
|
||||
func GenerateContainerRef(pod *v1.Pod, container *v1.Container) (*v1.ObjectReference, error) {
|
||||
fieldPath, err := fieldPath(pod, container)
|
||||
if err != nil {
|
||||
// TODO: figure out intelligent way to refer to containers that we implicitly
|
||||
// start (like the pod infra container). This is not a good way, ugh.
|
||||
fieldPath = ImplicitContainerPrefix + container.Name
|
||||
}
|
||||
ref, err := ref.GetPartialReference(legacyscheme.Scheme, pod, fieldPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ref, nil
|
||||
}
|
||||
|
||||
// fieldPath returns a fieldPath locating container within pod.
|
||||
// Returns an error if the container isn't part of the pod.
|
||||
func fieldPath(pod *v1.Pod, container *v1.Container) (string, error) {
|
||||
for i := range pod.Spec.Containers {
|
||||
here := &pod.Spec.Containers[i]
|
||||
if here.Name == container.Name {
|
||||
if here.Name == "" {
|
||||
return fmt.Sprintf("spec.containers[%d]", i), nil
|
||||
} else {
|
||||
return fmt.Sprintf("spec.containers{%s}", here.Name), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
for i := range pod.Spec.InitContainers {
|
||||
here := &pod.Spec.InitContainers[i]
|
||||
if here.Name == container.Name {
|
||||
if here.Name == "" {
|
||||
return fmt.Sprintf("spec.initContainers[%d]", i), nil
|
||||
} else {
|
||||
return fmt.Sprintf("spec.initContainers{%s}", here.Name), nil
|
||||
}
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("container %#v not found in pod %#v", container, pod)
|
||||
}
|
42
vendor/k8s.io/kubernetes/pkg/kubelet/container/resize.go
generated
vendored
Normal file
42
vendor/k8s.io/kubernetes/pkg/kubelet/container/resize.go
generated
vendored
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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 (
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/client-go/tools/remotecommand"
|
||||
)
|
||||
|
||||
// handleResizing spawns a goroutine that processes the resize channel, calling resizeFunc for each
|
||||
// remotecommand.TerminalSize received from the channel. The resize channel must be closed elsewhere to stop the
|
||||
// goroutine.
|
||||
func HandleResizing(resize <-chan remotecommand.TerminalSize, resizeFunc func(size remotecommand.TerminalSize)) {
|
||||
if resize == nil {
|
||||
return
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer runtime.HandleCrash()
|
||||
|
||||
for size := range resize {
|
||||
if size.Height < 1 || size.Width < 1 {
|
||||
continue
|
||||
}
|
||||
resizeFunc(size)
|
||||
}
|
||||
}()
|
||||
}
|
636
vendor/k8s.io/kubernetes/pkg/kubelet/container/runtime.go
generated
vendored
Normal file
636
vendor/k8s.io/kubernetes/pkg/kubelet/container/runtime.go
generated
vendored
Normal file
@ -0,0 +1,636 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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 (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/tools/remotecommand"
|
||||
"k8s.io/client-go/util/flowcontrol"
|
||||
"k8s.io/klog"
|
||||
runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// ImageStats contains statistics about all the images currently available.
|
||||
type ImageStats struct {
|
||||
// Total amount of storage consumed by existing images.
|
||||
TotalStorageBytes uint64
|
||||
}
|
||||
|
||||
// Runtime interface defines the interfaces that should be implemented
|
||||
// by a container runtime.
|
||||
// Thread safety is required from implementations of this interface.
|
||||
type Runtime interface {
|
||||
// Type returns the type of the container runtime.
|
||||
Type() string
|
||||
|
||||
// Version returns the version information of the container runtime.
|
||||
Version() (Version, error)
|
||||
|
||||
// APIVersion returns the cached API version information of the container
|
||||
// runtime. Implementation is expected to update this cache periodically.
|
||||
// This may be different from the runtime engine's version.
|
||||
// TODO(random-liu): We should fold this into Version()
|
||||
APIVersion() (Version, error)
|
||||
// Status returns the status of the runtime. An error is returned if the Status
|
||||
// function itself fails, nil otherwise.
|
||||
Status() (*RuntimeStatus, error)
|
||||
// GetPods returns a list of containers grouped 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)
|
||||
// GarbageCollect removes dead containers using the specified container gc policy
|
||||
// If allSourcesReady is not true, it means that kubelet doesn't have the
|
||||
// complete list of pods from all avialble sources (e.g., apiserver, http,
|
||||
// file). In this case, garbage collector should refrain itself from aggressive
|
||||
// behavior such as removing all containers of unrecognized pods (yet).
|
||||
// If evictNonDeletedPods is set to true, containers and sandboxes belonging to pods
|
||||
// that are terminated, but not deleted will be evicted. Otherwise, only deleted pods will be GC'd.
|
||||
// TODO: Revisit this method and make it cleaner.
|
||||
GarbageCollect(gcPolicy ContainerGCPolicy, allSourcesReady bool, evictNonDeletedPods bool) error
|
||||
// Syncs the running pod into the desired pod.
|
||||
SyncPod(pod *v1.Pod, podStatus *PodStatus, pullSecrets []v1.Secret, backOff *flowcontrol.Backoff) PodSyncResult
|
||||
// KillPod kills all the containers of a pod. Pod may be nil, running pod must not be.
|
||||
// TODO(random-liu): Return PodSyncResult in KillPod.
|
||||
// gracePeriodOverride if specified allows the caller to override the pod default grace period.
|
||||
// only hard kill paths are allowed to specify a gracePeriodOverride in the kubelet in order to not corrupt user data.
|
||||
// it is useful when doing SIGKILL for hard eviction scenarios, or max grace period during soft eviction scenarios.
|
||||
KillPod(pod *v1.Pod, runningPod Pod, gracePeriodOverride *int64) error
|
||||
// GetPodStatus retrieves the status of the pod, including the
|
||||
// information of all containers in the pod that are visible in Runtime.
|
||||
GetPodStatus(uid types.UID, name, namespace string) (*PodStatus, error)
|
||||
// TODO(vmarmol): Unify pod and containerID args.
|
||||
// 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.
|
||||
GetContainerLogs(ctx context.Context, pod *v1.Pod, containerID ContainerID, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) (err error)
|
||||
// Delete a container. If the container is still running, an error is returned.
|
||||
DeleteContainer(containerID ContainerID) error
|
||||
// ImageService provides methods to image-related methods.
|
||||
ImageService
|
||||
// UpdatePodCIDR sends a new podCIDR to the runtime.
|
||||
// This method just proxies a new runtimeConfig with the updated
|
||||
// CIDR value down to the runtime shim.
|
||||
UpdatePodCIDR(podCIDR string) error
|
||||
}
|
||||
|
||||
// StreamingRuntime is the interface implemented by runtimes that handle the serving of the
|
||||
// streaming calls (exec/attach/port-forward) themselves. In this case, Kubelet should redirect to
|
||||
// the runtime server.
|
||||
type StreamingRuntime interface {
|
||||
GetExec(id ContainerID, cmd []string, stdin, stdout, stderr, tty bool) (*url.URL, error)
|
||||
GetAttach(id ContainerID, stdin, stdout, stderr, tty bool) (*url.URL, error)
|
||||
GetPortForward(podName, podNamespace string, podUID types.UID, ports []int32) (*url.URL, error)
|
||||
}
|
||||
|
||||
type ImageService interface {
|
||||
// PullImage pulls an image from the network to local storage using the supplied
|
||||
// secrets if necessary. It returns a reference (digest or ID) to the pulled image.
|
||||
PullImage(image ImageSpec, pullSecrets []v1.Secret, podSandboxConfig *runtimeapi.PodSandboxConfig) (string, error)
|
||||
// GetImageRef gets the reference (digest or ID) of the image which has already been in
|
||||
// the local storage. It returns ("", nil) if the image isn't in the local storage.
|
||||
GetImageRef(image ImageSpec) (string, error)
|
||||
// Gets all images currently on the machine.
|
||||
ListImages() ([]Image, error)
|
||||
// Removes the specified image.
|
||||
RemoveImage(image ImageSpec) error
|
||||
// Returns Image statistics.
|
||||
ImageStats() (*ImageStats, error)
|
||||
}
|
||||
|
||||
type ContainerAttacher interface {
|
||||
AttachContainer(id ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) (err error)
|
||||
}
|
||||
|
||||
type ContainerCommandRunner interface {
|
||||
// RunInContainer synchronously executes the command in the container, and returns the output.
|
||||
// If the command completes with a non-0 exit code, a k8s.io/utils/exec.ExitError will be returned.
|
||||
RunInContainer(id ContainerID, cmd []string, timeout time.Duration) ([]byte, error)
|
||||
}
|
||||
|
||||
// Pod is a group of containers.
|
||||
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
|
||||
// List of sandboxes associated with this pod. The sandboxes are converted
|
||||
// to Container temporariliy to avoid substantial changes to other
|
||||
// components. This is only populated by kuberuntime.
|
||||
// TODO: use the runtimeApi.PodSandbox type directly.
|
||||
Sandboxes []*Container
|
||||
}
|
||||
|
||||
// PodPair contains both runtime#Pod and api#Pod
|
||||
type PodPair struct {
|
||||
// APIPod is the v1.Pod
|
||||
APIPod *v1.Pod
|
||||
// RunningPod is the pod defined in pkg/kubelet/container/runtime#Pod
|
||||
RunningPod *Pod
|
||||
}
|
||||
|
||||
// ContainerID is a type that identifies a container.
|
||||
type ContainerID struct {
|
||||
// The type of the container runtime. e.g. 'docker'.
|
||||
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}
|
||||
}
|
||||
|
||||
// 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 {
|
||||
klog.Error(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
func (c *ContainerID) IsEmpty() bool {
|
||||
return *c == ContainerID{}
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
|
||||
// DockerID is an ID of docker container. It is a type to make it clear when we're working with docker container Ids
|
||||
type DockerID string
|
||||
|
||||
func (id DockerID) ContainerID() ContainerID {
|
||||
return ContainerID{
|
||||
Type: "docker",
|
||||
ID: string(id),
|
||||
}
|
||||
}
|
||||
|
||||
type ContainerState string
|
||||
|
||||
const (
|
||||
ContainerStateCreated ContainerState = "created"
|
||||
ContainerStateRunning ContainerState = "running"
|
||||
ContainerStateExited ContainerState = "exited"
|
||||
// This unknown encompasses all the states that we currently don't care.
|
||||
ContainerStateUnknown ContainerState = "unknown"
|
||||
)
|
||||
|
||||
// Container provides the runtime information for a container, such as ID, hash,
|
||||
// state of the container.
|
||||
type Container struct {
|
||||
// The ID of the container, used by the container runtime to identify
|
||||
// a container.
|
||||
ID ContainerID
|
||||
// The name of the container, which should be the same as specified by
|
||||
// v1.Container.
|
||||
Name string
|
||||
// The image name of the container, this also includes the tag of the image,
|
||||
// the expected form is "NAME:TAG".
|
||||
Image string
|
||||
// The id of the image used by the container.
|
||||
ImageID string
|
||||
// Hash of the container, used for comparison. Optional for containers
|
||||
// not managed by kubelet.
|
||||
Hash uint64
|
||||
// State is the state of the container.
|
||||
State ContainerState
|
||||
}
|
||||
|
||||
// PodStatus represents the status of the pod and its containers.
|
||||
// v1.PodStatus can be derived from examining PodStatus and v1.Pod.
|
||||
type PodStatus struct {
|
||||
// ID of the pod.
|
||||
ID types.UID
|
||||
// Name of the pod.
|
||||
Name string
|
||||
// Namespace of the pod.
|
||||
Namespace string
|
||||
// IP of the pod.
|
||||
IP string
|
||||
// Status of containers in the pod.
|
||||
ContainerStatuses []*ContainerStatus
|
||||
// Status of the pod sandbox.
|
||||
// Only for kuberuntime now, other runtime may keep it nil.
|
||||
SandboxStatuses []*runtimeapi.PodSandboxStatus
|
||||
}
|
||||
|
||||
// ContainerStatus represents the status of a container.
|
||||
type ContainerStatus struct {
|
||||
// ID of the container.
|
||||
ID ContainerID
|
||||
// Name of the container.
|
||||
Name string
|
||||
// Status of the container.
|
||||
State ContainerState
|
||||
// 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, this also includes the tag of the image,
|
||||
// the expected form is "NAME:TAG".
|
||||
Image string
|
||||
// ID of the image.
|
||||
ImageID string
|
||||
// Hash of the container, used for comparison.
|
||||
Hash uint64
|
||||
// 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
|
||||
}
|
||||
|
||||
// FindContainerStatusByName returns container status in the pod status with the given name.
|
||||
// When there are multiple containers' statuses with the same name, the first match will be returned.
|
||||
func (podStatus *PodStatus) FindContainerStatusByName(containerName string) *ContainerStatus {
|
||||
for _, containerStatus := range podStatus.ContainerStatuses {
|
||||
if containerStatus.Name == containerName {
|
||||
return containerStatus
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get container status of all the running containers in a pod
|
||||
func (podStatus *PodStatus) GetRunningContainerStatuses() []*ContainerStatus {
|
||||
runningContainerStatuses := []*ContainerStatus{}
|
||||
for _, containerStatus := range podStatus.ContainerStatuses {
|
||||
if containerStatus.State == ContainerStateRunning {
|
||||
runningContainerStatuses = append(runningContainerStatuses, containerStatus)
|
||||
}
|
||||
}
|
||||
return runningContainerStatuses
|
||||
}
|
||||
|
||||
// Basic information about a container image.
|
||||
type Image struct {
|
||||
// ID of the image.
|
||||
ID string
|
||||
// Other names by which this image is known.
|
||||
RepoTags []string
|
||||
// Digests by which this image is known.
|
||||
RepoDigests []string
|
||||
// The size of the image in bytes.
|
||||
Size int64
|
||||
}
|
||||
|
||||
type EnvVar struct {
|
||||
Name string
|
||||
Value string
|
||||
}
|
||||
|
||||
type Annotation struct {
|
||||
Name string
|
||||
Value string
|
||||
}
|
||||
|
||||
type Mount struct {
|
||||
// Name of the volume mount.
|
||||
// TODO(yifan): Remove this field, as this is not representing the unique name of the mount,
|
||||
// but the volume name only.
|
||||
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
|
||||
// Whether the mount needs SELinux relabeling
|
||||
SELinuxRelabel bool
|
||||
// Requested propagation mode
|
||||
Propagation runtimeapi.MountPropagation
|
||||
}
|
||||
|
||||
type PortMapping struct {
|
||||
// Name of the port mapping
|
||||
Name string
|
||||
// Protocol of the port mapping.
|
||||
Protocol v1.Protocol
|
||||
// The port number within the container.
|
||||
ContainerPort int
|
||||
// The port number on the host.
|
||||
HostPort int
|
||||
// The host IP.
|
||||
HostIP string
|
||||
}
|
||||
|
||||
type DeviceInfo struct {
|
||||
// Path on host for mapping
|
||||
PathOnHost string
|
||||
// Path in Container to map
|
||||
PathInContainer string
|
||||
// Cgroup permissions
|
||||
Permissions string
|
||||
}
|
||||
|
||||
// RunContainerOptions specify the options which are necessary for running containers
|
||||
type RunContainerOptions struct {
|
||||
// The environment variables list.
|
||||
Envs []EnvVar
|
||||
// The mounts for the containers.
|
||||
Mounts []Mount
|
||||
// The host devices mapped into the containers.
|
||||
Devices []DeviceInfo
|
||||
// The port mappings for the containers.
|
||||
PortMappings []PortMapping
|
||||
// The annotations for the container
|
||||
// These annotations are generated by other components (i.e.,
|
||||
// not users). Currently, only device plugins populate the annotations.
|
||||
Annotations []Annotation
|
||||
// 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 type of container rootfs
|
||||
ReadOnly bool
|
||||
// hostname for pod containers
|
||||
Hostname string
|
||||
// EnableHostUserNamespace sets userns=host when users request host namespaces (pid, ipc, net),
|
||||
// are using non-namespaced capabilities (mknod, sys_time, sys_module), the pod contains a privileged container,
|
||||
// or using host path volumes.
|
||||
// This should only be enabled when the container runtime is performing user remapping AND if the
|
||||
// experimental behavior is desired.
|
||||
EnableHostUserNamespace bool
|
||||
}
|
||||
|
||||
// VolumeInfo contains information about the volume.
|
||||
type VolumeInfo struct {
|
||||
// Mounter is the volume's mounter
|
||||
Mounter volume.Mounter
|
||||
// BlockVolumeMapper is the Block volume's mapper
|
||||
BlockVolumeMapper volume.BlockVolumeMapper
|
||||
// SELinuxLabeled indicates whether this volume has had the
|
||||
// pod's SELinux label applied to it or not
|
||||
SELinuxLabeled bool
|
||||
// Whether the volume permission is set to read-only or not
|
||||
// This value is passed from volume.spec
|
||||
ReadOnly bool
|
||||
// Inner volume spec name, which is the PV name if used, otherwise
|
||||
// it is the same as the outer volume spec name.
|
||||
InnerVolumeSpecName string
|
||||
}
|
||||
|
||||
type VolumeMap map[string]VolumeInfo
|
||||
|
||||
// RuntimeConditionType is the types of required runtime conditions.
|
||||
type RuntimeConditionType string
|
||||
|
||||
const (
|
||||
// RuntimeReady means the runtime is up and ready to accept basic containers.
|
||||
RuntimeReady RuntimeConditionType = "RuntimeReady"
|
||||
// NetworkReady means the runtime network is up and ready to accept containers which require network.
|
||||
NetworkReady RuntimeConditionType = "NetworkReady"
|
||||
)
|
||||
|
||||
// RuntimeStatus contains the status of the runtime.
|
||||
type RuntimeStatus struct {
|
||||
// Conditions is an array of current observed runtime conditions.
|
||||
Conditions []RuntimeCondition
|
||||
}
|
||||
|
||||
// GetRuntimeCondition gets a specified runtime condition from the runtime status.
|
||||
func (r *RuntimeStatus) GetRuntimeCondition(t RuntimeConditionType) *RuntimeCondition {
|
||||
for i := range r.Conditions {
|
||||
c := &r.Conditions[i]
|
||||
if c.Type == t {
|
||||
return c
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// String formats the runtime status into human readable string.
|
||||
func (s *RuntimeStatus) String() string {
|
||||
var ss []string
|
||||
for _, c := range s.Conditions {
|
||||
ss = append(ss, c.String())
|
||||
}
|
||||
return fmt.Sprintf("Runtime Conditions: %s", strings.Join(ss, ", "))
|
||||
}
|
||||
|
||||
// RuntimeCondition contains condition information for the runtime.
|
||||
type RuntimeCondition struct {
|
||||
// Type of runtime condition.
|
||||
Type RuntimeConditionType
|
||||
// Status of the condition, one of true/false.
|
||||
Status bool
|
||||
// Reason is brief reason for the condition's last transition.
|
||||
Reason string
|
||||
// Message is human readable message indicating details about last transition.
|
||||
Message string
|
||||
}
|
||||
|
||||
// String formats the runtime condition into human readable string.
|
||||
func (c *RuntimeCondition) String() string {
|
||||
return fmt.Sprintf("%s=%t reason:%s message:%s", c.Type, c.Status, c.Reason, c.Message)
|
||||
}
|
||||
|
||||
type Pods []*Pod
|
||||
|
||||
// FindPodByID finds and returns a pod in the pod list by UID. It will return an empty pod
|
||||
// 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{}
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
func (p *Pod) FindContainerByID(id ContainerID) *Container {
|
||||
for _, c := range p.Containers {
|
||||
if c.ID == id {
|
||||
return c
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Pod) FindSandboxByID(id ContainerID) *Container {
|
||||
for _, c := range p.Sandboxes {
|
||||
if c.ID == id {
|
||||
return c
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ToAPIPod converts Pod to v1.Pod. Note that if a field in v1.Pod has no
|
||||
// corresponding field in Pod, the field would not be populated.
|
||||
func (p *Pod) ToAPIPod() *v1.Pod {
|
||||
var pod v1.Pod
|
||||
pod.UID = p.ID
|
||||
pod.Name = p.Name
|
||||
pod.Namespace = p.Namespace
|
||||
|
||||
for _, c := range p.Containers {
|
||||
var container v1.Container
|
||||
container.Name = c.Name
|
||||
container.Image = c.Image
|
||||
pod.Spec.Containers = append(pod.Spec.Containers, container)
|
||||
}
|
||||
return &pod
|
||||
}
|
||||
|
||||
// IsEmpty returns true if the pod is empty.
|
||||
func (p *Pod) IsEmpty() bool {
|
||||
return reflect.DeepEqual(p, &Pod{})
|
||||
}
|
||||
|
||||
// GetPodFullName returns a name that uniquely identifies a pod.
|
||||
func GetPodFullName(pod *v1.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.
|
||||
return pod.Name + "_" + pod.Namespace
|
||||
}
|
||||
|
||||
// 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 || parts[0] == "" || parts[1] == "" {
|
||||
return "", "", fmt.Errorf("failed to parse the pod full name %q", podFullName)
|
||||
}
|
||||
return parts[0], parts[1], nil
|
||||
}
|
||||
|
||||
// Option is a functional option type for Runtime, useful for
|
||||
// completely optional settings.
|
||||
type Option func(Runtime)
|
||||
|
||||
// Sort the container statuses by creation time.
|
||||
type SortContainerStatusesByCreationTime []*ContainerStatus
|
||||
|
||||
func (s SortContainerStatusesByCreationTime) Len() int { return len(s) }
|
||||
func (s SortContainerStatusesByCreationTime) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
func (s SortContainerStatusesByCreationTime) Less(i, j int) bool {
|
||||
return s[i].CreatedAt.Before(s[j].CreatedAt)
|
||||
}
|
||||
|
||||
const (
|
||||
// MaxPodTerminationMessageLogLength is the maximum bytes any one pod may have written
|
||||
// as termination message output across all containers. Containers will be evenly truncated
|
||||
// until output is below this limit.
|
||||
MaxPodTerminationMessageLogLength = 1024 * 12
|
||||
// MaxContainerTerminationMessageLength is the upper bound any one container may write to
|
||||
// its termination message path. Contents above this length will be truncated.
|
||||
MaxContainerTerminationMessageLength = 1024 * 4
|
||||
// MaxContainerTerminationMessageLogLength is the maximum bytes any one container will
|
||||
// have written to its termination message when the message is read from the logs.
|
||||
MaxContainerTerminationMessageLogLength = 1024 * 2
|
||||
// MaxContainerTerminationMessageLogLines is the maximum number of previous lines of
|
||||
// log output that the termination message can contain.
|
||||
MaxContainerTerminationMessageLogLines = 80
|
||||
)
|
96
vendor/k8s.io/kubernetes/pkg/kubelet/container/runtime_cache.go
generated
vendored
Normal file
96
vendor/k8s.io/kubernetes/pkg/kubelet/container/runtime_cache.go
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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 (
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
// TODO(yifan): Maybe set the them as parameters for NewCache().
|
||||
defaultCachePeriod = time.Second * 2
|
||||
)
|
||||
|
||||
type RuntimeCache interface {
|
||||
GetPods() ([]*Pod, error)
|
||||
ForceUpdateIfOlder(time.Time) error
|
||||
}
|
||||
|
||||
type podsGetter interface {
|
||||
GetPods(bool) ([]*Pod, error)
|
||||
}
|
||||
|
||||
// NewRuntimeCache creates a container runtime cache.
|
||||
func NewRuntimeCache(getter podsGetter) (RuntimeCache, error) {
|
||||
return &runtimeCache{
|
||||
getter: getter,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// runtimeCache caches a list of pods. It records a timestamp (cacheTime) right
|
||||
// before updating the pods, so the timestamp is at most as new as the pods
|
||||
// (and can be slightly older). The timestamp always moves forward. Callers are
|
||||
// expected not to modify the pods returned from GetPods.
|
||||
type runtimeCache struct {
|
||||
sync.Mutex
|
||||
// The underlying container runtime used to update the cache.
|
||||
getter podsGetter
|
||||
// Last time when cache was updated.
|
||||
cacheTime time.Time
|
||||
// The content of the cache.
|
||||
pods []*Pod
|
||||
}
|
||||
|
||||
// GetPods returns the cached pods if they are not outdated; otherwise, it
|
||||
// retrieves the latest pods and return them.
|
||||
func (r *runtimeCache) GetPods() ([]*Pod, error) {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
if time.Since(r.cacheTime) > defaultCachePeriod {
|
||||
if err := r.updateCache(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return r.pods, nil
|
||||
}
|
||||
|
||||
func (r *runtimeCache) ForceUpdateIfOlder(minExpectedCacheTime time.Time) error {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
if r.cacheTime.Before(minExpectedCacheTime) {
|
||||
return r.updateCache()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *runtimeCache) updateCache() error {
|
||||
pods, timestamp, err := r.getPodsWithTimestamp()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.pods, r.cacheTime = pods, timestamp
|
||||
return nil
|
||||
}
|
||||
|
||||
// getPodsWithTimestamp records a timestamp and retrieves pods from the getter.
|
||||
func (r *runtimeCache) getPodsWithTimestamp() ([]*Pod, time.Time, error) {
|
||||
// Always record the timestamp before getting the pods to avoid stale pods.
|
||||
timestamp := time.Now()
|
||||
pods, err := r.getter.GetPods(false)
|
||||
return pods, timestamp, err
|
||||
}
|
45
vendor/k8s.io/kubernetes/pkg/kubelet/container/runtime_cache_fake.go
generated
vendored
Normal file
45
vendor/k8s.io/kubernetes/pkg/kubelet/container/runtime_cache_fake.go
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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
|
||||
|
||||
// TestRunTimeCache embeds runtimeCache with some additional methods for testing.
|
||||
// It must be declared in the container package to have visibility to runtimeCache.
|
||||
// It cannot be in a "..._test.go" file in order for runtime_cache_test.go to have cross-package visibility to it.
|
||||
// (cross-package declarations in test files cannot be used from dot imports if this package is vendored)
|
||||
type TestRuntimeCache struct {
|
||||
runtimeCache
|
||||
}
|
||||
|
||||
func (r *TestRuntimeCache) UpdateCacheWithLock() error {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
return r.updateCache()
|
||||
}
|
||||
|
||||
func (r *TestRuntimeCache) GetCachedPods() []*Pod {
|
||||
r.Lock()
|
||||
defer r.Unlock()
|
||||
return r.pods
|
||||
}
|
||||
|
||||
func NewTestRuntimeCache(getter podsGetter) *TestRuntimeCache {
|
||||
return &TestRuntimeCache{
|
||||
runtimeCache: runtimeCache{
|
||||
getter: getter,
|
||||
},
|
||||
}
|
||||
}
|
128
vendor/k8s.io/kubernetes/pkg/kubelet/container/sync_result.go
generated
vendored
Normal file
128
vendor/k8s.io/kubernetes/pkg/kubelet/container/sync_result.go
generated
vendored
Normal file
@ -0,0 +1,128 @@
|
||||
/*
|
||||
Copyright 2015 The Kubernetes Authors.
|
||||
|
||||
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 (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
)
|
||||
|
||||
// TODO(random-liu): We need to better organize runtime errors for introspection.
|
||||
|
||||
// Container Terminated and Kubelet is backing off the restart
|
||||
var ErrCrashLoopBackOff = errors.New("CrashLoopBackOff")
|
||||
|
||||
var (
|
||||
// ErrContainerNotFound returned when a container in the given pod with the
|
||||
// given container name was not found, amongst those managed by the kubelet.
|
||||
ErrContainerNotFound = errors.New("no matching container")
|
||||
)
|
||||
|
||||
var (
|
||||
ErrRunContainer = errors.New("RunContainerError")
|
||||
ErrKillContainer = errors.New("KillContainerError")
|
||||
ErrVerifyNonRoot = errors.New("VerifyNonRootError")
|
||||
ErrRunInitContainer = errors.New("RunInitContainerError")
|
||||
ErrCreatePodSandbox = errors.New("CreatePodSandboxError")
|
||||
ErrConfigPodSandbox = errors.New("ConfigPodSandboxError")
|
||||
ErrKillPodSandbox = errors.New("KillPodSandboxError")
|
||||
)
|
||||
|
||||
var (
|
||||
ErrSetupNetwork = errors.New("SetupNetworkError")
|
||||
ErrTeardownNetwork = errors.New("TeardownNetworkError")
|
||||
)
|
||||
|
||||
// SyncAction indicates different kind of actions in SyncPod() and KillPod(). Now there are only actions
|
||||
// about start/kill container and setup/teardown network.
|
||||
type SyncAction string
|
||||
|
||||
const (
|
||||
StartContainer SyncAction = "StartContainer"
|
||||
KillContainer SyncAction = "KillContainer"
|
||||
SetupNetwork SyncAction = "SetupNetwork"
|
||||
TeardownNetwork SyncAction = "TeardownNetwork"
|
||||
InitContainer SyncAction = "InitContainer"
|
||||
CreatePodSandbox SyncAction = "CreatePodSandbox"
|
||||
ConfigPodSandbox SyncAction = "ConfigPodSandbox"
|
||||
KillPodSandbox SyncAction = "KillPodSandbox"
|
||||
)
|
||||
|
||||
// SyncResult is the result of sync action.
|
||||
type SyncResult struct {
|
||||
// The associated action of the result
|
||||
Action SyncAction
|
||||
// The target of the action, now the target can only be:
|
||||
// * Container: Target should be container name
|
||||
// * Network: Target is useless now, we just set it as pod full name now
|
||||
Target interface{}
|
||||
// Brief error reason
|
||||
Error error
|
||||
// Human readable error reason
|
||||
Message string
|
||||
}
|
||||
|
||||
// NewSyncResult generates new SyncResult with specific Action and Target
|
||||
func NewSyncResult(action SyncAction, target interface{}) *SyncResult {
|
||||
return &SyncResult{Action: action, Target: target}
|
||||
}
|
||||
|
||||
// Fail fails the SyncResult with specific error and message
|
||||
func (r *SyncResult) Fail(err error, msg string) {
|
||||
r.Error, r.Message = err, msg
|
||||
}
|
||||
|
||||
// PodSyncResult is the summary result of SyncPod() and KillPod()
|
||||
type PodSyncResult struct {
|
||||
// Result of different sync actions
|
||||
SyncResults []*SyncResult
|
||||
// Error encountered in SyncPod() and KillPod() that is not already included in SyncResults
|
||||
SyncError error
|
||||
}
|
||||
|
||||
// AddSyncResult adds multiple SyncResult to current PodSyncResult
|
||||
func (p *PodSyncResult) AddSyncResult(result ...*SyncResult) {
|
||||
p.SyncResults = append(p.SyncResults, result...)
|
||||
}
|
||||
|
||||
// AddPodSyncResult merges a PodSyncResult to current one
|
||||
func (p *PodSyncResult) AddPodSyncResult(result PodSyncResult) {
|
||||
p.AddSyncResult(result.SyncResults...)
|
||||
p.SyncError = result.SyncError
|
||||
}
|
||||
|
||||
// Fail fails the PodSyncResult with an error occurred in SyncPod() and KillPod() itself
|
||||
func (p *PodSyncResult) Fail(err error) {
|
||||
p.SyncError = err
|
||||
}
|
||||
|
||||
// Error returns an error summarizing all the errors in PodSyncResult
|
||||
func (p *PodSyncResult) Error() error {
|
||||
errlist := []error{}
|
||||
if p.SyncError != nil {
|
||||
errlist = append(errlist, fmt.Errorf("failed to SyncPod: %v\n", p.SyncError))
|
||||
}
|
||||
for _, result := range p.SyncResults {
|
||||
if result.Error != nil {
|
||||
errlist = append(errlist, fmt.Errorf("failed to %q for %q with %v: %q\n", result.Action, result.Target,
|
||||
result.Error, result.Message))
|
||||
}
|
||||
}
|
||||
return utilerrors.NewAggregate(errlist)
|
||||
}
|
Reference in New Issue
Block a user