mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 02:43:36 +00:00
vendor files
This commit is contained in:
98
vendor/k8s.io/kubernetes/pkg/kubelet/container/BUILD
generated
vendored
Normal file
98
vendor/k8s.io/kubernetes/pkg/kubelet/container/BUILD
generated
vendored
Normal file
@ -0,0 +1,98 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"cache.go",
|
||||
"container_gc.go",
|
||||
"container_reference_manager.go",
|
||||
"helpers.go",
|
||||
"os.go",
|
||||
"pty_unsupported.go",
|
||||
"ref.go",
|
||||
"resize.go",
|
||||
"runtime.go",
|
||||
"runtime_cache.go",
|
||||
"runtime_cache_fake.go",
|
||||
"sync_result.go",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||
"pty_linux.go",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
importpath = "k8s.io/kubernetes/pkg/kubelet/container",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/kubelet/apis/cri/v1alpha1/runtime:go_default_library",
|
||||
"//pkg/kubelet/util/format:go_default_library",
|
||||
"//pkg/kubelet/util/ioutils:go_default_library",
|
||||
"//pkg/util/hash:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//third_party/forked/golang/expansion:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/record:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/reference:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/flowcontrol:go_default_library",
|
||||
] + select({
|
||||
"@io_bazel_rules_go//go/platform:linux_amd64": [
|
||||
"//vendor/github.com/kr/pty:go_default_library",
|
||||
],
|
||||
"//conditions:default": [],
|
||||
}),
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"cache_test.go",
|
||||
"helpers_test.go",
|
||||
"ref_test.go",
|
||||
"sync_result_test.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubelet/container",
|
||||
library = ":go_default_library",
|
||||
deps = [
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/apis/core/install:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_xtest",
|
||||
srcs = ["runtime_cache_test.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubelet/container_test",
|
||||
deps = [
|
||||
":go_default_library",
|
||||
"//pkg/kubelet/container/testing:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/kubelet/container/testing:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
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
|
||||
}
|
210
vendor/k8s.io/kubernetes/pkg/kubelet/container/cache_test.go
generated
vendored
Normal file
210
vendor/k8s.io/kubernetes/pkg/kubelet/container/cache_test.go
generated
vendored
Normal file
@ -0,0 +1,210 @@
|
||||
/*
|
||||
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"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
func newTestCache() *cache {
|
||||
c := NewCache()
|
||||
return c.(*cache)
|
||||
}
|
||||
|
||||
func TestCacheNotInitialized(t *testing.T) {
|
||||
cache := newTestCache()
|
||||
// If the global timestamp is not set, always return nil.
|
||||
d := cache.getIfNewerThan(types.UID("1234"), time.Time{})
|
||||
assert.True(t, d == nil, "should return nil since cache is not initialized")
|
||||
}
|
||||
|
||||
func getTestPodIDAndStatus(numContainers int) (types.UID, *PodStatus) {
|
||||
id := types.UID(strconv.FormatInt(time.Now().UnixNano(), 10))
|
||||
name := fmt.Sprintf("cache-foo-%s", string(id))
|
||||
namespace := "ns"
|
||||
var status *PodStatus
|
||||
if numContainers > 0 {
|
||||
status = &PodStatus{ID: id, Name: name, Namespace: namespace}
|
||||
} else {
|
||||
status = &PodStatus{ID: id}
|
||||
}
|
||||
for i := 0; i < numContainers; i++ {
|
||||
status.ContainerStatuses = append(status.ContainerStatuses, &ContainerStatus{Name: string(i)})
|
||||
}
|
||||
return id, status
|
||||
}
|
||||
|
||||
func TestGetIfNewerThanWhenPodExists(t *testing.T) {
|
||||
cache := newTestCache()
|
||||
timestamp := time.Now()
|
||||
|
||||
cases := []struct {
|
||||
cacheTime time.Time
|
||||
modified time.Time
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
// Both the global cache timestamp and the modified time are newer
|
||||
// than the timestamp.
|
||||
cacheTime: timestamp.Add(time.Second),
|
||||
modified: timestamp,
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
// Global cache timestamp is newer, but the pod entry modified
|
||||
// time is older than the given timestamp. This means that the
|
||||
// entry is up-to-date even though it hasn't changed for a while.
|
||||
cacheTime: timestamp.Add(time.Second),
|
||||
modified: timestamp.Add(-time.Second * 10),
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
// Global cache timestamp is older, but the pod entry modified
|
||||
// time is newer than the given timestamp. This means that the
|
||||
// entry is up-to-date but the rest of the cache are still being
|
||||
// updated.
|
||||
cacheTime: timestamp.Add(-time.Second),
|
||||
modified: timestamp.Add(time.Second * 3),
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
// Both the global cache timestamp and the modified time are older
|
||||
// than the given timestamp.
|
||||
cacheTime: timestamp.Add(-time.Second),
|
||||
modified: timestamp.Add(-time.Second),
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
for i, c := range cases {
|
||||
podID, status := getTestPodIDAndStatus(2)
|
||||
cache.UpdateTime(c.cacheTime)
|
||||
cache.Set(podID, status, nil, c.modified)
|
||||
d := cache.getIfNewerThan(podID, timestamp)
|
||||
assert.Equal(t, c.expected, d != nil, "test[%d]", i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPodNewerThanWhenPodDoesNotExist(t *testing.T) {
|
||||
cache := newTestCache()
|
||||
cacheTime := time.Now()
|
||||
cache.UpdateTime(cacheTime)
|
||||
podID := types.UID("1234")
|
||||
|
||||
cases := []struct {
|
||||
timestamp time.Time
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
timestamp: cacheTime.Add(-time.Second),
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
timestamp: cacheTime.Add(time.Second),
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
for i, c := range cases {
|
||||
d := cache.getIfNewerThan(podID, c.timestamp)
|
||||
assert.Equal(t, c.expected, d != nil, "test[%d]", i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCacheSetAndGet(t *testing.T) {
|
||||
cache := NewCache()
|
||||
cases := []struct {
|
||||
numContainers int
|
||||
error error
|
||||
}{
|
||||
{numContainers: 3, error: nil},
|
||||
{numContainers: 2, error: fmt.Errorf("unable to get status")},
|
||||
{numContainers: 0, error: nil},
|
||||
}
|
||||
for i, c := range cases {
|
||||
podID, status := getTestPodIDAndStatus(c.numContainers)
|
||||
cache.Set(podID, status, c.error, time.Time{})
|
||||
// Read back the status and error stored in cache and make sure they
|
||||
// match the original ones.
|
||||
actualStatus, actualErr := cache.Get(podID)
|
||||
assert.Equal(t, status, actualStatus, "test[%d]", i)
|
||||
assert.Equal(t, c.error, actualErr, "test[%d]", i)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCacheGetPodDoesNotExist(t *testing.T) {
|
||||
cache := NewCache()
|
||||
podID, status := getTestPodIDAndStatus(0)
|
||||
// If the pod does not exist in cache, cache should return an status
|
||||
// object with id filled.
|
||||
actualStatus, actualErr := cache.Get(podID)
|
||||
assert.Equal(t, status, actualStatus)
|
||||
assert.Equal(t, nil, actualErr)
|
||||
}
|
||||
|
||||
func TestDelete(t *testing.T) {
|
||||
cache := &cache{pods: map[types.UID]*data{}}
|
||||
// Write a new pod status into the cache.
|
||||
podID, status := getTestPodIDAndStatus(3)
|
||||
cache.Set(podID, status, nil, time.Time{})
|
||||
actualStatus, actualErr := cache.Get(podID)
|
||||
assert.Equal(t, status, actualStatus)
|
||||
assert.Equal(t, nil, actualErr)
|
||||
// Delete the pod from cache, and verify that we get an empty status.
|
||||
cache.Delete(podID)
|
||||
expectedStatus := &PodStatus{ID: podID}
|
||||
actualStatus, actualErr = cache.Get(podID)
|
||||
assert.Equal(t, expectedStatus, actualStatus)
|
||||
assert.Equal(t, nil, actualErr)
|
||||
}
|
||||
|
||||
func verifyNotification(t *testing.T, ch chan *data, expectNotification bool) {
|
||||
if expectNotification {
|
||||
assert.True(t, len(ch) > 0, "Did not receive notification")
|
||||
} else {
|
||||
assert.True(t, len(ch) < 1, "Should not have triggered the notification")
|
||||
}
|
||||
// Drain the channel.
|
||||
for i := 0; i < len(ch); i++ {
|
||||
<-ch
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegisterNotification(t *testing.T) {
|
||||
cache := newTestCache()
|
||||
cacheTime := time.Now()
|
||||
cache.UpdateTime(cacheTime)
|
||||
|
||||
podID, status := getTestPodIDAndStatus(1)
|
||||
ch := cache.subscribe(podID, cacheTime.Add(time.Second))
|
||||
verifyNotification(t, ch, false)
|
||||
cache.Set(podID, status, nil, cacheTime.Add(time.Second))
|
||||
// The Set operation should've triggered the notification.
|
||||
verifyNotification(t, ch, true)
|
||||
|
||||
podID, _ = getTestPodIDAndStatus(1)
|
||||
|
||||
ch = cache.subscribe(podID, cacheTime.Add(time.Second))
|
||||
verifyNotification(t, ch, false)
|
||||
cache.UpdateTime(cacheTime.Add(time.Second * 2))
|
||||
// The advance of cache timestamp should've triggered the notification.
|
||||
verifyNotification(t, ch, true)
|
||||
}
|
84
vendor/k8s.io/kubernetes/pkg/kubelet/container/container_gc.go
generated
vendored
Normal file
84
vendor/k8s.io/kubernetes/pkg/kubelet/container/container_gc.go
generated
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
/*
|
||||
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"
|
||||
)
|
||||
|
||||
// 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 readyness 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 {
|
||||
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
|
||||
}
|
359
vendor/k8s.io/kubernetes/pkg/kubelet/container/helpers.go
generated
vendored
Normal file
359
vendor/k8s.io/kubernetes/pkg/kubelet/container/helpers.go
generated
vendored
Normal file
@ -0,0 +1,359 @@
|
||||
/*
|
||||
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 (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"hash/adler32"
|
||||
"hash/fnv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"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/client-go/tools/record"
|
||||
runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
||||
"k8s.io/kubernetes/pkg/kubelet/util/format"
|
||||
"k8s.io/kubernetes/pkg/kubelet/util/ioutils"
|
||||
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, err error)
|
||||
GetPodDNS(pod *v1.Pod) (dnsConfig *runtimeapi.DNSConfig, err error)
|
||||
// GetPodCgroupParent returns the CgroupName identifer, 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 {
|
||||
glog.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 {
|
||||
glog.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())
|
||||
}
|
||||
|
||||
// HashContainerLegacy returns the hash of the container. It is used to compare
|
||||
// the running container with its desired spec.
|
||||
// This is used by rktnetes and dockershim (for handling <=1.5 containers).
|
||||
// TODO: Remove this function when kubernetes version is >=1.8 AND rktnetes
|
||||
// update its hash function.
|
||||
func HashContainerLegacy(container *v1.Container) uint64 {
|
||||
hash := adler32.New()
|
||||
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 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...)
|
||||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
}
|
||||
|
||||
type containerCommandRunnerWrapper struct {
|
||||
DirectStreamingRuntime
|
||||
}
|
||||
|
||||
var _ ContainerCommandRunner = &containerCommandRunnerWrapper{}
|
||||
|
||||
func DirectStreamingRunner(runtime DirectStreamingRuntime) ContainerCommandRunner {
|
||||
return &containerCommandRunnerWrapper{runtime}
|
||||
}
|
||||
|
||||
func (r *containerCommandRunnerWrapper) RunInContainer(id ContainerID, cmd []string, timeout time.Duration) ([]byte, error) {
|
||||
var buffer bytes.Buffer
|
||||
output := ioutils.WriteCloserWrapper(&buffer)
|
||||
err := r.ExecInContainer(id, cmd, nil, output, output, false, nil, timeout)
|
||||
// Even if err is non-nil, there still may be output (e.g. the exec wrote to stdout or stderr but
|
||||
// the command returned a nonzero exit code). Therefore, always return the output along with the
|
||||
// error.
|
||||
return buffer.Bytes(), err
|
||||
}
|
||||
|
||||
// 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 pod.Spec.Containers {
|
||||
if c.SecurityContext != nil &&
|
||||
c.SecurityContext.Privileged != nil &&
|
||||
*c.SecurityContext.Privileged {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// MakeCapabilities creates string slices from Capability slices
|
||||
func MakeCapabilities(capAdd []v1.Capability, capDrop []v1.Capability) ([]string, []string) {
|
||||
var (
|
||||
addCaps []string
|
||||
dropCaps []string
|
||||
)
|
||||
for _, cap := range capAdd {
|
||||
addCaps = append(addCaps, string(cap))
|
||||
}
|
||||
for _, cap := range capDrop {
|
||||
dropCaps = append(dropCaps, string(cap))
|
||||
}
|
||||
return addCaps, dropCaps
|
||||
}
|
||||
|
||||
// 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 {
|
||||
glog.Warningf("Port name conflicted, %q is defined more than once", pm.Name)
|
||||
continue
|
||||
}
|
||||
ports = append(ports, pm)
|
||||
names[pm.Name] = struct{}{}
|
||||
}
|
||||
return
|
||||
}
|
308
vendor/k8s.io/kubernetes/pkg/kubelet/container/helpers_test.go
generated
vendored
Normal file
308
vendor/k8s.io/kubernetes/pkg/kubelet/container/helpers_test.go
generated
vendored
Normal file
@ -0,0 +1,308 @@
|
||||
/*
|
||||
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 (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func TestEnvVarsToMap(t *testing.T) {
|
||||
vars := []EnvVar{
|
||||
{
|
||||
Name: "foo",
|
||||
Value: "bar",
|
||||
},
|
||||
{
|
||||
Name: "zoo",
|
||||
Value: "baz",
|
||||
},
|
||||
}
|
||||
|
||||
varMap := EnvVarsToMap(vars)
|
||||
|
||||
if e, a := len(vars), len(varMap); e != a {
|
||||
t.Errorf("Unexpected map length; expected: %d, got %d", e, a)
|
||||
}
|
||||
|
||||
if a := varMap["foo"]; a != "bar" {
|
||||
t.Errorf("Unexpected value of key 'foo': %v", a)
|
||||
}
|
||||
|
||||
if a := varMap["zoo"]; a != "baz" {
|
||||
t.Errorf("Unexpected value of key 'zoo': %v", a)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExpandCommandAndArgs(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
container *v1.Container
|
||||
envs []EnvVar
|
||||
expectedCommand []string
|
||||
expectedArgs []string
|
||||
}{
|
||||
{
|
||||
name: "none",
|
||||
container: &v1.Container{},
|
||||
},
|
||||
{
|
||||
name: "command expanded",
|
||||
container: &v1.Container{
|
||||
Command: []string{"foo", "$(VAR_TEST)", "$(VAR_TEST2)"},
|
||||
},
|
||||
envs: []EnvVar{
|
||||
{
|
||||
Name: "VAR_TEST",
|
||||
Value: "zoo",
|
||||
},
|
||||
{
|
||||
Name: "VAR_TEST2",
|
||||
Value: "boo",
|
||||
},
|
||||
},
|
||||
expectedCommand: []string{"foo", "zoo", "boo"},
|
||||
},
|
||||
{
|
||||
name: "args expanded",
|
||||
container: &v1.Container{
|
||||
Args: []string{"zap", "$(VAR_TEST)", "$(VAR_TEST2)"},
|
||||
},
|
||||
envs: []EnvVar{
|
||||
{
|
||||
Name: "VAR_TEST",
|
||||
Value: "hap",
|
||||
},
|
||||
{
|
||||
Name: "VAR_TEST2",
|
||||
Value: "trap",
|
||||
},
|
||||
},
|
||||
expectedArgs: []string{"zap", "hap", "trap"},
|
||||
},
|
||||
{
|
||||
name: "both expanded",
|
||||
container: &v1.Container{
|
||||
Command: []string{"$(VAR_TEST2)--$(VAR_TEST)", "foo", "$(VAR_TEST3)"},
|
||||
Args: []string{"foo", "$(VAR_TEST)", "$(VAR_TEST2)"},
|
||||
},
|
||||
envs: []EnvVar{
|
||||
{
|
||||
Name: "VAR_TEST",
|
||||
Value: "zoo",
|
||||
},
|
||||
{
|
||||
Name: "VAR_TEST2",
|
||||
Value: "boo",
|
||||
},
|
||||
{
|
||||
Name: "VAR_TEST3",
|
||||
Value: "roo",
|
||||
},
|
||||
},
|
||||
expectedCommand: []string{"boo--zoo", "foo", "roo"},
|
||||
expectedArgs: []string{"foo", "zoo", "boo"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
actualCommand, actualArgs := ExpandContainerCommandAndArgs(tc.container, tc.envs)
|
||||
|
||||
if e, a := tc.expectedCommand, actualCommand; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("%v: unexpected command; expected %v, got %v", tc.name, e, a)
|
||||
}
|
||||
|
||||
if e, a := tc.expectedArgs, actualArgs; !reflect.DeepEqual(e, a) {
|
||||
t.Errorf("%v: unexpected args; expected %v, got %v", tc.name, e, a)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldContainerBeRestarted(t *testing.T) {
|
||||
pod := &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
UID: "12345678",
|
||||
Name: "foo",
|
||||
Namespace: "new",
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{Name: "no-history"},
|
||||
{Name: "alive"},
|
||||
{Name: "succeed"},
|
||||
{Name: "failed"},
|
||||
{Name: "unknown"},
|
||||
},
|
||||
},
|
||||
}
|
||||
podStatus := &PodStatus{
|
||||
ID: pod.UID,
|
||||
Name: pod.Name,
|
||||
Namespace: pod.Namespace,
|
||||
ContainerStatuses: []*ContainerStatus{
|
||||
{
|
||||
Name: "alive",
|
||||
State: ContainerStateRunning,
|
||||
},
|
||||
{
|
||||
Name: "succeed",
|
||||
State: ContainerStateExited,
|
||||
ExitCode: 0,
|
||||
},
|
||||
{
|
||||
Name: "failed",
|
||||
State: ContainerStateExited,
|
||||
ExitCode: 1,
|
||||
},
|
||||
{
|
||||
Name: "alive",
|
||||
State: ContainerStateExited,
|
||||
ExitCode: 2,
|
||||
},
|
||||
{
|
||||
Name: "unknown",
|
||||
State: ContainerStateUnknown,
|
||||
},
|
||||
{
|
||||
Name: "failed",
|
||||
State: ContainerStateExited,
|
||||
ExitCode: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
policies := []v1.RestartPolicy{
|
||||
v1.RestartPolicyNever,
|
||||
v1.RestartPolicyOnFailure,
|
||||
v1.RestartPolicyAlways,
|
||||
}
|
||||
expected := map[string][]bool{
|
||||
"no-history": {true, true, true},
|
||||
"alive": {false, false, false},
|
||||
"succeed": {false, false, true},
|
||||
"failed": {false, true, true},
|
||||
"unknown": {true, true, true},
|
||||
}
|
||||
for _, c := range pod.Spec.Containers {
|
||||
for i, policy := range policies {
|
||||
pod.Spec.RestartPolicy = policy
|
||||
e := expected[c.Name][i]
|
||||
r := ShouldContainerBeRestarted(&c, pod, podStatus)
|
||||
if r != e {
|
||||
t.Errorf("Restart for container %q with restart policy %q expected %t, got %t",
|
||||
c.Name, policy, e, r)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHasPrivilegedContainer(t *testing.T) {
|
||||
newBoolPtr := func(b bool) *bool {
|
||||
return &b
|
||||
}
|
||||
tests := map[string]struct {
|
||||
securityContext *v1.SecurityContext
|
||||
expected bool
|
||||
}{
|
||||
"nil security context": {
|
||||
securityContext: nil,
|
||||
expected: false,
|
||||
},
|
||||
"nil privileged": {
|
||||
securityContext: &v1.SecurityContext{},
|
||||
expected: false,
|
||||
},
|
||||
"false privileged": {
|
||||
securityContext: &v1.SecurityContext{Privileged: newBoolPtr(false)},
|
||||
expected: false,
|
||||
},
|
||||
"true privileged": {
|
||||
securityContext: &v1.SecurityContext{Privileged: newBoolPtr(true)},
|
||||
expected: true,
|
||||
},
|
||||
}
|
||||
|
||||
for k, v := range tests {
|
||||
pod := &v1.Pod{
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{SecurityContext: v.securityContext},
|
||||
},
|
||||
},
|
||||
}
|
||||
actual := HasPrivilegedContainer(pod)
|
||||
if actual != v.expected {
|
||||
t.Errorf("%s expected %t but got %t", k, v.expected, actual)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMakePortMappings(t *testing.T) {
|
||||
port := func(name string, protocol v1.Protocol, containerPort, hostPort int32, ip string) v1.ContainerPort {
|
||||
return v1.ContainerPort{
|
||||
Name: name,
|
||||
Protocol: protocol,
|
||||
ContainerPort: containerPort,
|
||||
HostPort: hostPort,
|
||||
HostIP: ip,
|
||||
}
|
||||
}
|
||||
portMapping := func(name string, protocol v1.Protocol, containerPort, hostPort int, ip string) PortMapping {
|
||||
return PortMapping{
|
||||
Name: name,
|
||||
Protocol: protocol,
|
||||
ContainerPort: containerPort,
|
||||
HostPort: hostPort,
|
||||
HostIP: ip,
|
||||
}
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
container *v1.Container
|
||||
expectedPortMappings []PortMapping
|
||||
}{
|
||||
{
|
||||
&v1.Container{
|
||||
Name: "fooContainer",
|
||||
Ports: []v1.ContainerPort{
|
||||
port("", v1.ProtocolTCP, 80, 8080, "127.0.0.1"),
|
||||
port("", v1.ProtocolTCP, 443, 4343, "192.168.0.1"),
|
||||
port("foo", v1.ProtocolUDP, 555, 5555, ""),
|
||||
// Duplicated, should be ignored.
|
||||
port("foo", v1.ProtocolUDP, 888, 8888, ""),
|
||||
// Duplicated, should be ignored.
|
||||
port("", v1.ProtocolTCP, 80, 8888, ""),
|
||||
},
|
||||
},
|
||||
[]PortMapping{
|
||||
portMapping("fooContainer-TCP:80", v1.ProtocolTCP, 80, 8080, "127.0.0.1"),
|
||||
portMapping("fooContainer-TCP:443", v1.ProtocolTCP, 443, 4343, "192.168.0.1"),
|
||||
portMapping("fooContainer-foo", v1.ProtocolUDP, 555, 5555, ""),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
actual := MakePortMappings(tt.container)
|
||||
assert.Equal(t, tt.expectedPortMappings, actual, "[%d]", i)
|
||||
}
|
||||
}
|
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{}
|
||||
|
||||
// MkDir will will call os.Mkdir 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)
|
||||
}
|
30
vendor/k8s.io/kubernetes/pkg/kubelet/container/pty_linux.go
generated
vendored
Normal file
30
vendor/k8s.io/kubernetes/pkg/kubelet/container/pty_linux.go
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
// +build linux
|
||||
|
||||
/*
|
||||
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 (
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/kr/pty"
|
||||
)
|
||||
|
||||
func StartPty(c *exec.Cmd) (*os.File, error) {
|
||||
return pty.Start(c)
|
||||
}
|
28
vendor/k8s.io/kubernetes/pkg/kubelet/container/pty_unsupported.go
generated
vendored
Normal file
28
vendor/k8s.io/kubernetes/pkg/kubelet/container/pty_unsupported.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
// +build !linux
|
||||
|
||||
/*
|
||||
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 (
|
||||
"os"
|
||||
"os/exec"
|
||||
)
|
||||
|
||||
func StartPty(c *exec.Cmd) (pty *os.File, err error) {
|
||||
return nil, nil
|
||||
}
|
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)
|
||||
}
|
213
vendor/k8s.io/kubernetes/pkg/kubelet/container/ref_test.go
generated
vendored
Normal file
213
vendor/k8s.io/kubernetes/pkg/kubelet/container/ref_test.go
generated
vendored
Normal file
@ -0,0 +1,213 @@
|
||||
/*
|
||||
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 (
|
||||
"testing"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
_ "k8s.io/kubernetes/pkg/apis/core/install"
|
||||
)
|
||||
|
||||
func TestFieldPath(t *testing.T) {
|
||||
pod := &v1.Pod{Spec: v1.PodSpec{Containers: []v1.Container{
|
||||
{Name: "foo"},
|
||||
{Name: "bar"},
|
||||
{Name: ""},
|
||||
{Name: "baz"},
|
||||
}}}
|
||||
table := map[string]struct {
|
||||
pod *v1.Pod
|
||||
container *v1.Container
|
||||
path string
|
||||
success bool
|
||||
}{
|
||||
"basic": {pod, &v1.Container{Name: "foo"}, "spec.containers{foo}", true},
|
||||
"basic2": {pod, &v1.Container{Name: "baz"}, "spec.containers{baz}", true},
|
||||
"emptyName": {pod, &v1.Container{Name: ""}, "spec.containers[2]", true},
|
||||
"basicSamePointer": {pod, &pod.Spec.Containers[0], "spec.containers{foo}", true},
|
||||
"missing": {pod, &v1.Container{Name: "qux"}, "", false},
|
||||
}
|
||||
|
||||
for name, item := range table {
|
||||
res, err := fieldPath(item.pod, item.container)
|
||||
if item.success == false {
|
||||
if err == nil {
|
||||
t.Errorf("%v: unexpected non-error", name)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
t.Errorf("%v: unexpected error: %v", name, err)
|
||||
continue
|
||||
}
|
||||
if e, a := item.path, res; e != a {
|
||||
t.Errorf("%v: wanted %v, got %v", name, e, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateContainerRef(t *testing.T) {
|
||||
var (
|
||||
okPod = v1.Pod{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "Pod",
|
||||
APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(),
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "ok",
|
||||
Namespace: "test-ns",
|
||||
UID: "bar",
|
||||
ResourceVersion: "42",
|
||||
SelfLink: "/api/" + legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String() + "/pods/foo",
|
||||
},
|
||||
Spec: v1.PodSpec{
|
||||
Containers: []v1.Container{
|
||||
{
|
||||
Name: "by-name",
|
||||
},
|
||||
{},
|
||||
},
|
||||
},
|
||||
}
|
||||
noSelfLinkPod = okPod
|
||||
defaultedSelfLinkPod = okPod
|
||||
)
|
||||
noSelfLinkPod.Kind = ""
|
||||
noSelfLinkPod.APIVersion = ""
|
||||
noSelfLinkPod.ObjectMeta.SelfLink = ""
|
||||
defaultedSelfLinkPod.ObjectMeta.SelfLink = "/api/" + legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String() + "/pods/ok"
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
pod *v1.Pod
|
||||
container *v1.Container
|
||||
expected *v1.ObjectReference
|
||||
success bool
|
||||
}{
|
||||
{
|
||||
name: "by-name",
|
||||
pod: &okPod,
|
||||
container: &v1.Container{
|
||||
Name: "by-name",
|
||||
},
|
||||
expected: &v1.ObjectReference{
|
||||
Kind: "Pod",
|
||||
APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(),
|
||||
Name: "ok",
|
||||
Namespace: "test-ns",
|
||||
UID: "bar",
|
||||
ResourceVersion: "42",
|
||||
FieldPath: ".spec.containers{by-name}",
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
name: "no-name",
|
||||
pod: &okPod,
|
||||
container: &v1.Container{},
|
||||
expected: &v1.ObjectReference{
|
||||
Kind: "Pod",
|
||||
APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(),
|
||||
Name: "ok",
|
||||
Namespace: "test-ns",
|
||||
UID: "bar",
|
||||
ResourceVersion: "42",
|
||||
FieldPath: ".spec.containers[1]",
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
name: "no-selflink",
|
||||
pod: &noSelfLinkPod,
|
||||
container: &v1.Container{},
|
||||
expected: nil,
|
||||
success: false,
|
||||
},
|
||||
{
|
||||
name: "defaulted-selflink",
|
||||
pod: &defaultedSelfLinkPod,
|
||||
container: &v1.Container{
|
||||
Name: "by-name",
|
||||
},
|
||||
expected: &v1.ObjectReference{
|
||||
Kind: "Pod",
|
||||
APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(),
|
||||
Name: "ok",
|
||||
Namespace: "test-ns",
|
||||
UID: "bar",
|
||||
ResourceVersion: "42",
|
||||
FieldPath: ".spec.containers{by-name}",
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
{
|
||||
name: "implicitly-required",
|
||||
pod: &okPod,
|
||||
container: &v1.Container{
|
||||
Name: "net",
|
||||
},
|
||||
expected: &v1.ObjectReference{
|
||||
Kind: "Pod",
|
||||
APIVersion: legacyscheme.Registry.GroupOrDie(v1.GroupName).GroupVersion.String(),
|
||||
Name: "ok",
|
||||
Namespace: "test-ns",
|
||||
UID: "bar",
|
||||
ResourceVersion: "42",
|
||||
FieldPath: "implicitly required container net",
|
||||
},
|
||||
success: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
actual, err := GenerateContainerRef(tc.pod, tc.container)
|
||||
if err != nil {
|
||||
if tc.success {
|
||||
t.Errorf("%v: unexpected error: %v", tc.name, err)
|
||||
}
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if !tc.success {
|
||||
t.Errorf("%v: unexpected success", tc.name)
|
||||
continue
|
||||
}
|
||||
|
||||
if e, a := tc.expected.Kind, actual.Kind; e != a {
|
||||
t.Errorf("%v: kind: expected %v, got %v", tc.name, e, a)
|
||||
}
|
||||
if e, a := tc.expected.APIVersion, actual.APIVersion; e != a {
|
||||
t.Errorf("%v: apiVersion: expected %v, got %v", tc.name, e, a)
|
||||
}
|
||||
if e, a := tc.expected.Name, actual.Name; e != a {
|
||||
t.Errorf("%v: name: expected %v, got %v", tc.name, e, a)
|
||||
}
|
||||
if e, a := tc.expected.Namespace, actual.Namespace; e != a {
|
||||
t.Errorf("%v: namespace: expected %v, got %v", tc.name, e, a)
|
||||
}
|
||||
if e, a := tc.expected.UID, actual.UID; e != a {
|
||||
t.Errorf("%v: uid: expected %v, got %v", tc.name, e, a)
|
||||
}
|
||||
if e, a := tc.expected.ResourceVersion, actual.ResourceVersion; e != a {
|
||||
t.Errorf("%v: kind: expected %v, got %v", tc.name, e, a)
|
||||
}
|
||||
}
|
||||
}
|
46
vendor/k8s.io/kubernetes/pkg/kubelet/container/resize.go
generated
vendored
Normal file
46
vendor/k8s.io/kubernetes/pkg/kubelet/container/resize.go
generated
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
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, ok := <-resize
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if size.Height < 1 || size.Width < 1 {
|
||||
continue
|
||||
}
|
||||
resizeFunc(size)
|
||||
}
|
||||
}()
|
||||
}
|
648
vendor/k8s.io/kubernetes/pkg/kubelet/container/runtime.go
generated
vendored
Normal file
648
vendor/k8s.io/kubernetes/pkg/kubelet/container/runtime.go
generated
vendored
Normal file
@ -0,0 +1,648 @@
|
||||
/*
|
||||
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"
|
||||
"io"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/tools/remotecommand"
|
||||
"k8s.io/client-go/util/flowcontrol"
|
||||
runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
||||
"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, apiPodStatus v1.PodStatus, 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 visble in Runtime.
|
||||
GetPodStatus(uid types.UID, name, namespace string) (*PodStatus, error)
|
||||
// Returns the filesystem path of the pod's network namespace; if the
|
||||
// runtime does not handle namespace creation itself, or cannot return
|
||||
// the network namespace path, it should return an error.
|
||||
// TODO: Change ContainerID to a Pod ID since the namespace is shared
|
||||
// by all containers in the pod.
|
||||
GetNetNS(containerID ContainerID) (string, error)
|
||||
// Returns the container ID that represents the Pod, as passed to network
|
||||
// plugins. For example, if the runtime uses an infra container, returns
|
||||
// the infra container's ContainerID.
|
||||
// TODO: Change ContainerID to a Pod ID, see GetNetNS()
|
||||
GetPodContainerID(*Pod) (ContainerID, 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(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
|
||||
}
|
||||
|
||||
// DirectStreamingRuntime is the interface implemented by runtimes for which the streaming calls
|
||||
// (exec/attach/port-forward) should be served directly by the Kubelet.
|
||||
type DirectStreamingRuntime interface {
|
||||
// Runs the command in the container of the specified pod. Attaches
|
||||
// the processes stdin, stdout, and stderr. Optionally uses a tty.
|
||||
ExecInContainer(containerID ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error
|
||||
// Forward the specified port from the specified pod to the stream.
|
||||
PortForward(pod *Pod, port int32, stream io.ReadWriteCloser) error
|
||||
// ContainerAttach encapsulates the attaching to containers for testability
|
||||
ContainerAttacher
|
||||
}
|
||||
|
||||
// IndirectStreamingRuntime 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 IndirectStreamingRuntime 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) (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 pkg/util/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', '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}
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
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
|
||||
// Namspace 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 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
|
||||
// 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 parent cgroup to pass to Docker
|
||||
CgroupParent 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
|
||||
}
|
||||
|
||||
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,
|
||||
},
|
||||
}
|
||||
}
|
74
vendor/k8s.io/kubernetes/pkg/kubelet/container/runtime_cache_test.go
generated
vendored
Normal file
74
vendor/k8s.io/kubernetes/pkg/kubelet/container/runtime_cache_test.go
generated
vendored
Normal file
@ -0,0 +1,74 @@
|
||||
/*
|
||||
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_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
. "k8s.io/kubernetes/pkg/kubelet/container"
|
||||
ctest "k8s.io/kubernetes/pkg/kubelet/container/testing"
|
||||
)
|
||||
|
||||
func comparePods(t *testing.T, expected []*ctest.FakePod, actual []*Pod) {
|
||||
if len(expected) != len(actual) {
|
||||
t.Errorf("expected %d pods, got %d instead", len(expected), len(actual))
|
||||
}
|
||||
for i := range expected {
|
||||
if !reflect.DeepEqual(expected[i].Pod, actual[i]) {
|
||||
t.Errorf("expected %#v, got %#v", expected[i].Pod, actual[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetPods(t *testing.T) {
|
||||
runtime := &ctest.FakeRuntime{}
|
||||
expected := []*ctest.FakePod{{Pod: &Pod{ID: "1111"}}, {Pod: &Pod{ID: "2222"}}, {Pod: &Pod{ID: "3333"}}}
|
||||
runtime.PodList = expected
|
||||
cache := NewTestRuntimeCache(runtime)
|
||||
actual, err := cache.GetPods()
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error %v", err)
|
||||
}
|
||||
|
||||
comparePods(t, expected, actual)
|
||||
}
|
||||
|
||||
func TestForceUpdateIfOlder(t *testing.T) {
|
||||
runtime := &ctest.FakeRuntime{}
|
||||
cache := NewTestRuntimeCache(runtime)
|
||||
|
||||
// Cache old pods.
|
||||
oldpods := []*ctest.FakePod{{Pod: &Pod{ID: "1111"}}}
|
||||
runtime.PodList = oldpods
|
||||
cache.UpdateCacheWithLock()
|
||||
|
||||
// Update the runtime to new pods.
|
||||
newpods := []*ctest.FakePod{{Pod: &Pod{ID: "1111"}}, {Pod: &Pod{ID: "2222"}}, {Pod: &Pod{ID: "3333"}}}
|
||||
runtime.PodList = newpods
|
||||
|
||||
// An older timestamp should not force an update.
|
||||
cache.ForceUpdateIfOlder(time.Now().Add(-20 * time.Minute))
|
||||
actual := cache.GetCachedPods()
|
||||
comparePods(t, oldpods, actual)
|
||||
|
||||
// A newer timestamp should force an update.
|
||||
cache.ForceUpdateIfOlder(time.Now().Add(20 * time.Second))
|
||||
actual = cache.GetCachedPods()
|
||||
comparePods(t, newpods, actual)
|
||||
}
|
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)
|
||||
}
|
68
vendor/k8s.io/kubernetes/pkg/kubelet/container/sync_result_test.go
generated
vendored
Normal file
68
vendor/k8s.io/kubernetes/pkg/kubelet/container/sync_result_test.go
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
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"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPodSyncResult(t *testing.T) {
|
||||
okResults := []*SyncResult{
|
||||
NewSyncResult(StartContainer, "container_0"),
|
||||
NewSyncResult(SetupNetwork, "pod"),
|
||||
}
|
||||
errResults := []*SyncResult{
|
||||
NewSyncResult(KillContainer, "container_1"),
|
||||
NewSyncResult(TeardownNetwork, "pod"),
|
||||
}
|
||||
errResults[0].Fail(errors.New("error_0"), "message_0")
|
||||
errResults[1].Fail(errors.New("error_1"), "message_1")
|
||||
|
||||
// If the PodSyncResult doesn't contain error result, it should not be error
|
||||
result := PodSyncResult{}
|
||||
result.AddSyncResult(okResults...)
|
||||
if result.Error() != nil {
|
||||
t.Errorf("PodSyncResult should not be error: %v", result)
|
||||
}
|
||||
|
||||
// If the PodSyncResult contains error result, it should be error
|
||||
result = PodSyncResult{}
|
||||
result.AddSyncResult(okResults...)
|
||||
result.AddSyncResult(errResults...)
|
||||
if result.Error() == nil {
|
||||
t.Errorf("PodSyncResult should be error: %q", result)
|
||||
}
|
||||
|
||||
// If the PodSyncResult is failed, it should be error
|
||||
result = PodSyncResult{}
|
||||
result.AddSyncResult(okResults...)
|
||||
result.Fail(errors.New("error"))
|
||||
if result.Error() == nil {
|
||||
t.Errorf("PodSyncResult should be error: %q", result)
|
||||
}
|
||||
|
||||
// If the PodSyncResult is added an error PodSyncResult, it should be error
|
||||
errResult := PodSyncResult{}
|
||||
errResult.AddSyncResult(errResults...)
|
||||
result = PodSyncResult{}
|
||||
result.AddSyncResult(okResults...)
|
||||
result.AddPodSyncResult(errResult)
|
||||
if result.Error() == nil {
|
||||
t.Errorf("PodSyncResult should be error: %q", result)
|
||||
}
|
||||
}
|
41
vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/BUILD
generated
vendored
Normal file
41
vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/BUILD
generated
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"fake_cache.go",
|
||||
"fake_runtime.go",
|
||||
"fake_runtime_helper.go",
|
||||
"mock_runtime_cache.go",
|
||||
"mockfileinfo.go",
|
||||
"os.go",
|
||||
"runtime_mock.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/kubelet/container/testing",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/kubelet/apis/cri/v1alpha1/runtime:go_default_library",
|
||||
"//pkg/kubelet/container:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//vendor/github.com/golang/mock/gomock:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/mock:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//vendor/k8s.io/client-go/tools/remotecommand:go_default_library",
|
||||
"//vendor/k8s.io/client-go/util/flowcontrol:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
49
vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/fake_cache.go
generated
vendored
Normal file
49
vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/fake_cache.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
Copyright 2016 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 testing
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/kubelet/container"
|
||||
)
|
||||
|
||||
type fakeCache struct {
|
||||
runtime container.Runtime
|
||||
}
|
||||
|
||||
func NewFakeCache(runtime container.Runtime) container.Cache {
|
||||
return &fakeCache{runtime: runtime}
|
||||
}
|
||||
|
||||
func (c *fakeCache) Get(id types.UID) (*container.PodStatus, error) {
|
||||
return c.runtime.GetPodStatus(id, "", "")
|
||||
}
|
||||
|
||||
func (c *fakeCache) GetNewerThan(id types.UID, minTime time.Time) (*container.PodStatus, error) {
|
||||
return c.Get(id)
|
||||
}
|
||||
|
||||
func (c *fakeCache) Set(id types.UID, status *container.PodStatus, err error, timestamp time.Time) {
|
||||
}
|
||||
|
||||
func (c *fakeCache) Delete(id types.UID) {
|
||||
}
|
||||
|
||||
func (c *fakeCache) UpdateTime(_ time.Time) {
|
||||
}
|
500
vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/fake_runtime.go
generated
vendored
Normal file
500
vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/fake_runtime.go
generated
vendored
Normal file
@ -0,0 +1,500 @@
|
||||
/*
|
||||
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 testing
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"sync"
|
||||
"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/kubernetes/pkg/kubelet/container"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
)
|
||||
|
||||
type FakePod struct {
|
||||
Pod *Pod
|
||||
NetnsPath string
|
||||
}
|
||||
|
||||
// FakeRuntime is a fake container runtime for testing.
|
||||
type FakeRuntime struct {
|
||||
sync.Mutex
|
||||
CalledFunctions []string
|
||||
PodList []*FakePod
|
||||
AllPodList []*FakePod
|
||||
ImageList []Image
|
||||
APIPodStatus v1.PodStatus
|
||||
PodStatus PodStatus
|
||||
StartedPods []string
|
||||
KilledPods []string
|
||||
StartedContainers []string
|
||||
KilledContainers []string
|
||||
RuntimeStatus *RuntimeStatus
|
||||
VersionInfo string
|
||||
APIVersionInfo string
|
||||
RuntimeType string
|
||||
Err error
|
||||
InspectErr error
|
||||
StatusErr error
|
||||
}
|
||||
|
||||
type FakeDirectStreamingRuntime struct {
|
||||
*FakeRuntime
|
||||
|
||||
// Arguments to streaming method calls.
|
||||
Args struct {
|
||||
// Attach / Exec args
|
||||
ContainerID ContainerID
|
||||
Cmd []string
|
||||
Stdin io.Reader
|
||||
Stdout io.WriteCloser
|
||||
Stderr io.WriteCloser
|
||||
TTY bool
|
||||
// Port-forward args
|
||||
Pod *Pod
|
||||
Port int32
|
||||
Stream io.ReadWriteCloser
|
||||
}
|
||||
}
|
||||
|
||||
var _ DirectStreamingRuntime = &FakeDirectStreamingRuntime{}
|
||||
|
||||
const FakeHost = "localhost:12345"
|
||||
|
||||
type FakeIndirectStreamingRuntime struct {
|
||||
*FakeRuntime
|
||||
}
|
||||
|
||||
var _ IndirectStreamingRuntime = &FakeIndirectStreamingRuntime{}
|
||||
|
||||
// FakeRuntime should implement Runtime.
|
||||
var _ Runtime = &FakeRuntime{}
|
||||
|
||||
type FakeVersion struct {
|
||||
Version string
|
||||
}
|
||||
|
||||
func (fv *FakeVersion) String() string {
|
||||
return fv.Version
|
||||
}
|
||||
|
||||
func (fv *FakeVersion) Compare(other string) (int, error) {
|
||||
result := 0
|
||||
if fv.Version > other {
|
||||
result = 1
|
||||
} else if fv.Version < other {
|
||||
result = -1
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
type podsGetter interface {
|
||||
GetPods(bool) ([]*Pod, error)
|
||||
}
|
||||
|
||||
type FakeRuntimeCache struct {
|
||||
getter podsGetter
|
||||
}
|
||||
|
||||
func NewFakeRuntimeCache(getter podsGetter) RuntimeCache {
|
||||
return &FakeRuntimeCache{getter}
|
||||
}
|
||||
|
||||
func (f *FakeRuntimeCache) GetPods() ([]*Pod, error) {
|
||||
return f.getter.GetPods(false)
|
||||
}
|
||||
|
||||
func (f *FakeRuntimeCache) ForceUpdateIfOlder(time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ClearCalls resets the FakeRuntime to the initial state.
|
||||
func (f *FakeRuntime) ClearCalls() {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = []string{}
|
||||
f.PodList = []*FakePod{}
|
||||
f.AllPodList = []*FakePod{}
|
||||
f.APIPodStatus = v1.PodStatus{}
|
||||
f.StartedPods = []string{}
|
||||
f.KilledPods = []string{}
|
||||
f.StartedContainers = []string{}
|
||||
f.KilledContainers = []string{}
|
||||
f.RuntimeStatus = nil
|
||||
f.VersionInfo = ""
|
||||
f.RuntimeType = ""
|
||||
f.Err = nil
|
||||
f.InspectErr = nil
|
||||
f.StatusErr = nil
|
||||
}
|
||||
|
||||
// UpdatePodCIDR fulfills the cri interface.
|
||||
func (f *FakeRuntime) UpdatePodCIDR(c string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) assertList(expect []string, test []string) error {
|
||||
if !reflect.DeepEqual(expect, test) {
|
||||
return fmt.Errorf("expected %#v, got %#v", expect, test)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// AssertCalls test if the invoked functions are as expected.
|
||||
func (f *FakeRuntime) AssertCalls(calls []string) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
return f.assertList(calls, f.CalledFunctions)
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) AssertStartedPods(pods []string) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
return f.assertList(pods, f.StartedPods)
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) AssertKilledPods(pods []string) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
return f.assertList(pods, f.KilledPods)
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) AssertStartedContainers(containers []string) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
return f.assertList(containers, f.StartedContainers)
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) AssertKilledContainers(containers []string) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
return f.assertList(containers, f.KilledContainers)
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) Type() string {
|
||||
return f.RuntimeType
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) Version() (Version, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "Version")
|
||||
return &FakeVersion{Version: f.VersionInfo}, f.Err
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) APIVersion() (Version, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "APIVersion")
|
||||
return &FakeVersion{Version: f.APIVersionInfo}, f.Err
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) Status() (*RuntimeStatus, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "Status")
|
||||
return f.RuntimeStatus, f.StatusErr
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) GetPods(all bool) ([]*Pod, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
var pods []*Pod
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "GetPods")
|
||||
if all {
|
||||
for _, fakePod := range f.AllPodList {
|
||||
pods = append(pods, fakePod.Pod)
|
||||
}
|
||||
} else {
|
||||
for _, fakePod := range f.PodList {
|
||||
pods = append(pods, fakePod.Pod)
|
||||
}
|
||||
}
|
||||
return pods, f.Err
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) SyncPod(pod *v1.Pod, _ v1.PodStatus, _ *PodStatus, _ []v1.Secret, backOff *flowcontrol.Backoff) (result PodSyncResult) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "SyncPod")
|
||||
f.StartedPods = append(f.StartedPods, string(pod.UID))
|
||||
for _, c := range pod.Spec.Containers {
|
||||
f.StartedContainers = append(f.StartedContainers, c.Name)
|
||||
}
|
||||
// TODO(random-liu): Add SyncResult for starting and killing containers
|
||||
if f.Err != nil {
|
||||
result.Fail(f.Err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) KillPod(pod *v1.Pod, runningPod Pod, gracePeriodOverride *int64) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "KillPod")
|
||||
f.KilledPods = append(f.KilledPods, string(runningPod.ID))
|
||||
for _, c := range runningPod.Containers {
|
||||
f.KilledContainers = append(f.KilledContainers, c.Name)
|
||||
}
|
||||
return f.Err
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) RunContainerInPod(container v1.Container, pod *v1.Pod, volumeMap map[string]volume.VolumePlugin) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "RunContainerInPod")
|
||||
f.StartedContainers = append(f.StartedContainers, container.Name)
|
||||
|
||||
pod.Spec.Containers = append(pod.Spec.Containers, container)
|
||||
for _, c := range pod.Spec.Containers {
|
||||
if c.Name == container.Name { // Container already in the pod.
|
||||
return f.Err
|
||||
}
|
||||
}
|
||||
pod.Spec.Containers = append(pod.Spec.Containers, container)
|
||||
return f.Err
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) KillContainerInPod(container v1.Container, pod *v1.Pod) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "KillContainerInPod")
|
||||
f.KilledContainers = append(f.KilledContainers, container.Name)
|
||||
|
||||
var containers []v1.Container
|
||||
for _, c := range pod.Spec.Containers {
|
||||
if c.Name == container.Name {
|
||||
continue
|
||||
}
|
||||
containers = append(containers, c)
|
||||
}
|
||||
return f.Err
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) GetPodStatus(uid types.UID, name, namespace string) (*PodStatus, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "GetPodStatus")
|
||||
status := f.PodStatus
|
||||
return &status, f.Err
|
||||
}
|
||||
|
||||
func (f *FakeDirectStreamingRuntime) ExecInContainer(containerID ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "ExecInContainer")
|
||||
f.Args.ContainerID = containerID
|
||||
f.Args.Cmd = cmd
|
||||
f.Args.Stdin = stdin
|
||||
f.Args.Stdout = stdout
|
||||
f.Args.Stderr = stderr
|
||||
f.Args.TTY = tty
|
||||
|
||||
return f.Err
|
||||
}
|
||||
|
||||
func (f *FakeDirectStreamingRuntime) AttachContainer(containerID ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "AttachContainer")
|
||||
f.Args.ContainerID = containerID
|
||||
f.Args.Stdin = stdin
|
||||
f.Args.Stdout = stdout
|
||||
f.Args.Stderr = stderr
|
||||
f.Args.TTY = tty
|
||||
|
||||
return f.Err
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) GetContainerLogs(pod *v1.Pod, containerID ContainerID, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) (err error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "GetContainerLogs")
|
||||
return f.Err
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) PullImage(image ImageSpec, pullSecrets []v1.Secret) (string, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "PullImage")
|
||||
return image.Image, f.Err
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) GetImageRef(image ImageSpec) (string, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "GetImageRef")
|
||||
for _, i := range f.ImageList {
|
||||
if i.ID == image.Image {
|
||||
return i.ID, nil
|
||||
}
|
||||
}
|
||||
return "", f.InspectErr
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) ListImages() ([]Image, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "ListImages")
|
||||
return f.ImageList, f.Err
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) RemoveImage(image ImageSpec) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "RemoveImage")
|
||||
index := 0
|
||||
for i := range f.ImageList {
|
||||
if f.ImageList[i].ID == image.Image {
|
||||
index = i
|
||||
break
|
||||
}
|
||||
}
|
||||
f.ImageList = append(f.ImageList[:index], f.ImageList[index+1:]...)
|
||||
|
||||
return f.Err
|
||||
}
|
||||
|
||||
func (f *FakeDirectStreamingRuntime) PortForward(pod *Pod, port int32, stream io.ReadWriteCloser) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "PortForward")
|
||||
f.Args.Pod = pod
|
||||
f.Args.Port = port
|
||||
f.Args.Stream = stream
|
||||
|
||||
return f.Err
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) GetNetNS(containerID ContainerID) (string, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "GetNetNS")
|
||||
|
||||
for _, fp := range f.AllPodList {
|
||||
for _, c := range fp.Pod.Containers {
|
||||
if c.ID == containerID {
|
||||
return fp.NetnsPath, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return "", f.Err
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) GetPodContainerID(pod *Pod) (ContainerID, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "GetPodContainerID")
|
||||
return ContainerID{}, f.Err
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) GarbageCollect(gcPolicy ContainerGCPolicy, ready bool, evictNonDeletedPods bool) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "GarbageCollect")
|
||||
return f.Err
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) DeleteContainer(containerID ContainerID) error {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "DeleteContainer")
|
||||
return f.Err
|
||||
}
|
||||
|
||||
func (f *FakeRuntime) ImageStats() (*ImageStats, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "ImageStats")
|
||||
return nil, f.Err
|
||||
}
|
||||
|
||||
func (f *FakeIndirectStreamingRuntime) GetExec(id ContainerID, cmd []string, stdin, stdout, stderr, tty bool) (*url.URL, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "GetExec")
|
||||
return &url.URL{Host: FakeHost}, f.Err
|
||||
}
|
||||
|
||||
func (f *FakeIndirectStreamingRuntime) GetAttach(id ContainerID, stdin, stdout, stderr, tty bool) (*url.URL, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "GetAttach")
|
||||
return &url.URL{Host: FakeHost}, f.Err
|
||||
}
|
||||
|
||||
func (f *FakeIndirectStreamingRuntime) GetPortForward(podName, podNamespace string, podUID types.UID, ports []int32) (*url.URL, error) {
|
||||
f.Lock()
|
||||
defer f.Unlock()
|
||||
|
||||
f.CalledFunctions = append(f.CalledFunctions, "GetPortForward")
|
||||
return &url.URL{Host: FakeHost}, f.Err
|
||||
}
|
||||
|
||||
type FakeContainerCommandRunner struct {
|
||||
// what to return
|
||||
Stdout string
|
||||
Err error
|
||||
|
||||
// actual values when invoked
|
||||
ContainerID ContainerID
|
||||
Cmd []string
|
||||
}
|
||||
|
||||
var _ ContainerCommandRunner = &FakeContainerCommandRunner{}
|
||||
|
||||
func (f *FakeContainerCommandRunner) RunInContainer(containerID ContainerID, cmd []string, timeout time.Duration) ([]byte, error) {
|
||||
// record invoked values
|
||||
f.ContainerID = containerID
|
||||
f.Cmd = cmd
|
||||
|
||||
return []byte(f.Stdout), f.Err
|
||||
}
|
67
vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/fake_runtime_helper.go
generated
vendored
Normal file
67
vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/fake_runtime_helper.go
generated
vendored
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
Copyright 2017 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 testing
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
kubetypes "k8s.io/apimachinery/pkg/types"
|
||||
runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/v1alpha1/runtime"
|
||||
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||
)
|
||||
|
||||
// FakeRuntimeHelper implements RuntimeHelper interfaces for testing purposes.
|
||||
type FakeRuntimeHelper struct {
|
||||
DNSServers []string
|
||||
DNSSearches []string
|
||||
DNSOptions []string
|
||||
HostName string
|
||||
HostDomain string
|
||||
PodContainerDir string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (f *FakeRuntimeHelper) GenerateRunContainerOptions(pod *v1.Pod, container *v1.Container, podIP string) (*kubecontainer.RunContainerOptions, error) {
|
||||
var opts kubecontainer.RunContainerOptions
|
||||
if len(container.TerminationMessagePath) != 0 {
|
||||
opts.PodContainerDir = f.PodContainerDir
|
||||
}
|
||||
return &opts, nil
|
||||
}
|
||||
|
||||
func (f *FakeRuntimeHelper) GetPodCgroupParent(pod *v1.Pod) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (f *FakeRuntimeHelper) GetPodDNS(pod *v1.Pod) (*runtimeapi.DNSConfig, error) {
|
||||
return &runtimeapi.DNSConfig{
|
||||
Servers: f.DNSServers,
|
||||
Searches: f.DNSSearches,
|
||||
Options: f.DNSOptions}, f.Err
|
||||
}
|
||||
|
||||
// This is not used by docker runtime.
|
||||
func (f *FakeRuntimeHelper) GeneratePodHostNameAndDomain(pod *v1.Pod) (string, string, error) {
|
||||
return f.HostName, f.HostDomain, f.Err
|
||||
}
|
||||
|
||||
func (f *FakeRuntimeHelper) GetPodDir(podUID kubetypes.UID) string {
|
||||
return "/poddir/" + string(podUID)
|
||||
}
|
||||
|
||||
func (f *FakeRuntimeHelper) GetExtraSupplementalGroupsForPod(pod *v1.Pod) []int64 {
|
||||
return nil
|
||||
}
|
64
vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/mock_runtime_cache.go
generated
vendored
Normal file
64
vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/mock_runtime_cache.go
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
Copyright 2017 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.
|
||||
*/
|
||||
|
||||
// Code generated by mockery v1.0.0
|
||||
package testing
|
||||
|
||||
import container "k8s.io/kubernetes/pkg/kubelet/container"
|
||||
import mock "github.com/stretchr/testify/mock"
|
||||
import time "time"
|
||||
|
||||
// MockRuntimeCache is an autogenerated mock type for the RuntimeCache type
|
||||
type MockRuntimeCache struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// ForceUpdateIfOlder provides a mock function with given fields: _a0
|
||||
func (_m *MockRuntimeCache) ForceUpdateIfOlder(_a0 time.Time) error {
|
||||
ret := _m.Called(_a0)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(time.Time) error); ok {
|
||||
r0 = rf(_a0)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetPods provides a mock function with given fields:
|
||||
func (_m *MockRuntimeCache) GetPods() ([]*container.Pod, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 []*container.Pod
|
||||
if rf, ok := ret.Get(0).(func() []*container.Pod); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*container.Pod)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func() error); ok {
|
||||
r1 = rf()
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
109
vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/mockfileinfo.go
generated
vendored
Normal file
109
vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/mockfileinfo.go
generated
vendored
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
Copyright 2016 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.
|
||||
*/
|
||||
|
||||
// Generated via: mockgen os FileInfo
|
||||
// Edited to include required boilerplate
|
||||
// Source: os (interfaces: FileInfo)
|
||||
|
||||
package testing
|
||||
|
||||
import (
|
||||
os "os"
|
||||
time "time"
|
||||
|
||||
gomock "github.com/golang/mock/gomock"
|
||||
)
|
||||
|
||||
// Mock of FileInfo interface
|
||||
type MockFileInfo struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *_MockFileInfoRecorder
|
||||
}
|
||||
|
||||
// Recorder for MockFileInfo (not exported)
|
||||
type _MockFileInfoRecorder struct {
|
||||
mock *MockFileInfo
|
||||
}
|
||||
|
||||
func NewMockFileInfo(ctrl *gomock.Controller) *MockFileInfo {
|
||||
mock := &MockFileInfo{ctrl: ctrl}
|
||||
mock.recorder = &_MockFileInfoRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
func (_m *MockFileInfo) EXPECT() *_MockFileInfoRecorder {
|
||||
return _m.recorder
|
||||
}
|
||||
|
||||
func (_m *MockFileInfo) IsDir() bool {
|
||||
ret := _m.ctrl.Call(_m, "IsDir")
|
||||
ret0, _ := ret[0].(bool)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockFileInfoRecorder) IsDir() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "IsDir")
|
||||
}
|
||||
|
||||
func (_m *MockFileInfo) ModTime() time.Time {
|
||||
ret := _m.ctrl.Call(_m, "ModTime")
|
||||
ret0, _ := ret[0].(time.Time)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockFileInfoRecorder) ModTime() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "ModTime")
|
||||
}
|
||||
|
||||
func (_m *MockFileInfo) Mode() os.FileMode {
|
||||
ret := _m.ctrl.Call(_m, "Mode")
|
||||
ret0, _ := ret[0].(os.FileMode)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockFileInfoRecorder) Mode() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "Mode")
|
||||
}
|
||||
|
||||
func (_m *MockFileInfo) Name() string {
|
||||
ret := _m.ctrl.Call(_m, "Name")
|
||||
ret0, _ := ret[0].(string)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockFileInfoRecorder) Name() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "Name")
|
||||
}
|
||||
|
||||
func (_m *MockFileInfo) Size() int64 {
|
||||
ret := _m.ctrl.Call(_m, "Size")
|
||||
ret0, _ := ret[0].(int64)
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockFileInfoRecorder) Size() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "Size")
|
||||
}
|
||||
|
||||
func (_m *MockFileInfo) Sys() interface{} {
|
||||
ret := _m.ctrl.Call(_m, "Sys")
|
||||
ret0, _ := ret[0].(interface{})
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (_mr *_MockFileInfoRecorder) Sys() *gomock.Call {
|
||||
return _mr.mock.ctrl.RecordCall(_mr.mock, "Sys")
|
||||
}
|
117
vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/os.go
generated
vendored
Normal file
117
vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/os.go
generated
vendored
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
Copyright 2016 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 testing
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// FakeOS mocks out certain OS calls to avoid perturbing the filesystem
|
||||
// If a member of the form `*Fn` is set, that function will be called in place
|
||||
// of the real call.
|
||||
type FakeOS struct {
|
||||
StatFn func(string) (os.FileInfo, error)
|
||||
ReadDirFn func(string) ([]os.FileInfo, error)
|
||||
MkdirAllFn func(string, os.FileMode) error
|
||||
SymlinkFn func(string, string) error
|
||||
HostName string
|
||||
Removes []string
|
||||
Files map[string][]*os.FileInfo
|
||||
}
|
||||
|
||||
func NewFakeOS() *FakeOS {
|
||||
return &FakeOS{
|
||||
Removes: []string{},
|
||||
Files: make(map[string][]*os.FileInfo),
|
||||
}
|
||||
}
|
||||
|
||||
// Mkdir is a fake call that just returns nil.
|
||||
func (f *FakeOS) MkdirAll(path string, perm os.FileMode) error {
|
||||
if f.MkdirAllFn != nil {
|
||||
return f.MkdirAllFn(path, perm)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Symlink is a fake call that just returns nil.
|
||||
func (f *FakeOS) Symlink(oldname string, newname string) error {
|
||||
if f.SymlinkFn != nil {
|
||||
return f.SymlinkFn(oldname, newname)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Stat is a fake that returns an error
|
||||
func (f FakeOS) Stat(path string) (os.FileInfo, error) {
|
||||
if f.StatFn != nil {
|
||||
return f.StatFn(path)
|
||||
}
|
||||
return nil, errors.New("unimplemented testing mock")
|
||||
}
|
||||
|
||||
// Remove is a fake call that returns nil.
|
||||
func (f *FakeOS) Remove(path string) error {
|
||||
f.Removes = append(f.Removes, path)
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveAll is a fake call that just returns nil.
|
||||
func (f *FakeOS) RemoveAll(path string) error {
|
||||
f.Removes = append(f.Removes, path)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create is a fake call that returns nil.
|
||||
func (FakeOS) Create(path string) (*os.File, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Chmod is a fake call that returns nil.
|
||||
func (FakeOS) Chmod(path string, perm os.FileMode) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Hostname is a fake call that returns nil.
|
||||
func (f *FakeOS) Hostname() (name string, err error) {
|
||||
return f.HostName, nil
|
||||
}
|
||||
|
||||
// Chtimes is a fake call that returns nil.
|
||||
func (FakeOS) Chtimes(path string, atime time.Time, mtime time.Time) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Pipe is a fake call that returns nil.
|
||||
func (FakeOS) Pipe() (r *os.File, w *os.File, err error) {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
// ReadDir is a fake call that returns the files under the directory.
|
||||
func (f *FakeOS) ReadDir(dirname string) ([]os.FileInfo, error) {
|
||||
if f.ReadDirFn != nil {
|
||||
return f.ReadDirFn(dirname)
|
||||
}
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Glob is a fake call that returns nil.
|
||||
func (f *FakeOS) Glob(pattern string) ([]string, error) {
|
||||
return nil, nil
|
||||
}
|
161
vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/runtime_mock.go
generated
vendored
Normal file
161
vendor/k8s.io/kubernetes/pkg/kubelet/container/testing/runtime_mock.go
generated
vendored
Normal file
@ -0,0 +1,161 @@
|
||||
/*
|
||||
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 testing
|
||||
|
||||
import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/mock"
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/tools/remotecommand"
|
||||
"k8s.io/client-go/util/flowcontrol"
|
||||
. "k8s.io/kubernetes/pkg/kubelet/container"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
)
|
||||
|
||||
type Mock struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
var _ Runtime = new(Mock)
|
||||
|
||||
func (r *Mock) Start() error {
|
||||
args := r.Called()
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (r *Mock) Type() string {
|
||||
args := r.Called()
|
||||
return args.Get(0).(string)
|
||||
}
|
||||
|
||||
func (r *Mock) Version() (Version, error) {
|
||||
args := r.Called()
|
||||
return args.Get(0).(Version), args.Error(1)
|
||||
}
|
||||
|
||||
func (r *Mock) APIVersion() (Version, error) {
|
||||
args := r.Called()
|
||||
return args.Get(0).(Version), args.Error(1)
|
||||
}
|
||||
|
||||
func (r *Mock) Status() (*RuntimeStatus, error) {
|
||||
args := r.Called()
|
||||
return args.Get(0).(*RuntimeStatus), args.Error(0)
|
||||
}
|
||||
|
||||
func (r *Mock) GetPods(all bool) ([]*Pod, error) {
|
||||
args := r.Called(all)
|
||||
return args.Get(0).([]*Pod), args.Error(1)
|
||||
}
|
||||
|
||||
func (r *Mock) SyncPod(pod *v1.Pod, apiStatus v1.PodStatus, status *PodStatus, secrets []v1.Secret, backOff *flowcontrol.Backoff) PodSyncResult {
|
||||
args := r.Called(pod, apiStatus, status, secrets, backOff)
|
||||
return args.Get(0).(PodSyncResult)
|
||||
}
|
||||
|
||||
func (r *Mock) KillPod(pod *v1.Pod, runningPod Pod, gracePeriodOverride *int64) error {
|
||||
args := r.Called(pod, runningPod, gracePeriodOverride)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (r *Mock) RunContainerInPod(container v1.Container, pod *v1.Pod, volumeMap map[string]volume.VolumePlugin) error {
|
||||
args := r.Called(pod, pod, volumeMap)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (r *Mock) KillContainerInPod(container v1.Container, pod *v1.Pod) error {
|
||||
args := r.Called(pod, pod)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (r *Mock) GetPodStatus(uid types.UID, name, namespace string) (*PodStatus, error) {
|
||||
args := r.Called(uid, name, namespace)
|
||||
return args.Get(0).(*PodStatus), args.Error(1)
|
||||
}
|
||||
|
||||
func (r *Mock) ExecInContainer(containerID ContainerID, cmd []string, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize, timeout time.Duration) error {
|
||||
args := r.Called(containerID, cmd, stdin, stdout, stderr, tty)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (r *Mock) AttachContainer(containerID ContainerID, stdin io.Reader, stdout, stderr io.WriteCloser, tty bool, resize <-chan remotecommand.TerminalSize) error {
|
||||
args := r.Called(containerID, stdin, stdout, stderr, tty)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (r *Mock) GetContainerLogs(pod *v1.Pod, containerID ContainerID, logOptions *v1.PodLogOptions, stdout, stderr io.Writer) (err error) {
|
||||
args := r.Called(pod, containerID, logOptions, stdout, stderr)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (r *Mock) PullImage(image ImageSpec, pullSecrets []v1.Secret) (string, error) {
|
||||
args := r.Called(image, pullSecrets)
|
||||
return image.Image, args.Error(0)
|
||||
}
|
||||
|
||||
func (r *Mock) GetImageRef(image ImageSpec) (string, error) {
|
||||
args := r.Called(image)
|
||||
return args.Get(0).(string), args.Error(1)
|
||||
}
|
||||
|
||||
func (r *Mock) ListImages() ([]Image, error) {
|
||||
args := r.Called()
|
||||
return args.Get(0).([]Image), args.Error(1)
|
||||
}
|
||||
|
||||
func (r *Mock) RemoveImage(image ImageSpec) error {
|
||||
args := r.Called(image)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (r *Mock) PortForward(pod *Pod, port uint16, stream io.ReadWriteCloser) error {
|
||||
args := r.Called(pod, port, stream)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (r *Mock) GetNetNS(containerID ContainerID) (string, error) {
|
||||
args := r.Called(containerID)
|
||||
return "", args.Error(0)
|
||||
}
|
||||
|
||||
func (r *Mock) GetPodContainerID(pod *Pod) (ContainerID, error) {
|
||||
args := r.Called(pod)
|
||||
return ContainerID{}, args.Error(0)
|
||||
}
|
||||
|
||||
func (r *Mock) GarbageCollect(gcPolicy ContainerGCPolicy, ready bool, evictNonDeletedPods bool) error {
|
||||
args := r.Called(gcPolicy, ready, evictNonDeletedPods)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (r *Mock) DeleteContainer(containerID ContainerID) error {
|
||||
args := r.Called(containerID)
|
||||
return args.Error(0)
|
||||
}
|
||||
|
||||
func (r *Mock) ImageStats() (*ImageStats, error) {
|
||||
args := r.Called()
|
||||
return args.Get(0).(*ImageStats), args.Error(1)
|
||||
}
|
||||
|
||||
// UpdatePodCIDR fulfills the cri interface.
|
||||
func (r *Mock) UpdatePodCIDR(c string) error {
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user