Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
K
k3s
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Jacklull
k3s
Commits
73d105e2
Commit
73d105e2
authored
Aug 21, 2015
by
Zach Loafman
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #12959 from smarterclayton/handle_pods_in_kubelet
Support graceful termination in the Kubelet (5/7)
parents
cc172af2
f5c4a3e7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
164 additions
and
34 deletions
+164
-34
config.go
pkg/kubelet/config/config.go
+19
-4
fake_runtime.go
pkg/kubelet/container/fake_runtime.go
+3
-3
runtime.go
pkg/kubelet/container/runtime.go
+2
-2
manager.go
pkg/kubelet/dockertools/manager.go
+0
-0
manager_test.go
pkg/kubelet/dockertools/manager_test.go
+11
-11
kubelet.go
pkg/kubelet/kubelet.go
+37
-6
mirror_client.go
pkg/kubelet/mirror_client.go
+1
-1
rkt.go
pkg/kubelet/rkt/rkt.go
+4
-4
status_manager.go
pkg/kubelet/status_manager.go
+58
-3
status_manager_test.go
pkg/kubelet/status_manager_test.go
+29
-0
No files found.
pkg/kubelet/config/config.go
View file @
73d105e2
...
...
@@ -217,9 +217,8 @@ func (s *podStorage) merge(source string, change interface{}) (adds, updates, de
for
_
,
ref
:=
range
filtered
{
name
:=
kubecontainer
.
GetPodFullName
(
ref
)
if
existing
,
found
:=
pods
[
name
];
found
{
if
!
reflect
.
DeepEqual
(
existing
.
Spec
,
ref
.
Spec
)
{
if
checkAndUpdatePod
(
existing
,
ref
)
{
// this is an update
existing
.
Spec
=
ref
.
Spec
updates
.
Pods
=
append
(
updates
.
Pods
,
existing
)
continue
}
...
...
@@ -261,9 +260,8 @@ func (s *podStorage) merge(source string, change interface{}) (adds, updates, de
name
:=
kubecontainer
.
GetPodFullName
(
ref
)
if
existing
,
found
:=
oldPods
[
name
];
found
{
pods
[
name
]
=
existing
if
!
reflect
.
DeepEqual
(
existing
.
Spec
,
ref
.
Spec
)
{
if
checkAndUpdatePod
(
existing
,
ref
)
{
// this is an update
existing
.
Spec
=
ref
.
Spec
updates
.
Pods
=
append
(
updates
.
Pods
,
existing
)
continue
}
...
...
@@ -335,6 +333,23 @@ func filterInvalidPods(pods []*api.Pod, source string, recorder record.EventReco
return
}
// checkAndUpdatePod updates existing if ref makes a meaningful change and returns true, or
// returns false if there was no update.
func
checkAndUpdatePod
(
existing
,
ref
*
api
.
Pod
)
bool
{
// TODO: it would be better to update the whole object and only preserve certain things
// like the source annotation or the UID (to ensure safety)
if
reflect
.
DeepEqual
(
existing
.
Spec
,
ref
.
Spec
)
&&
reflect
.
DeepEqual
(
existing
.
DeletionTimestamp
,
ref
.
DeletionTimestamp
)
&&
reflect
.
DeepEqual
(
existing
.
DeletionGracePeriodSeconds
,
ref
.
DeletionGracePeriodSeconds
)
{
return
false
}
// this is an update
existing
.
Spec
=
ref
.
Spec
existing
.
DeletionTimestamp
=
ref
.
DeletionTimestamp
existing
.
DeletionGracePeriodSeconds
=
ref
.
DeletionGracePeriodSeconds
return
true
}
// Sync sends a copy of the current state through the update channel.
func
(
s
*
podStorage
)
Sync
()
{
s
.
updateLock
.
Lock
()
...
...
pkg/kubelet/container/fake_runtime.go
View file @
73d105e2
...
...
@@ -163,13 +163,13 @@ func (f *FakeRuntime) SyncPod(pod *api.Pod, _ Pod, _ api.PodStatus, _ []api.Secr
return
f
.
Err
}
func
(
f
*
FakeRuntime
)
KillPod
(
pod
Pod
)
error
{
func
(
f
*
FakeRuntime
)
KillPod
(
pod
*
api
.
Pod
,
runningPod
Pod
)
error
{
f
.
Lock
()
defer
f
.
Unlock
()
f
.
CalledFunctions
=
append
(
f
.
CalledFunctions
,
"KillPod"
)
f
.
KilledPods
=
append
(
f
.
KilledPods
,
string
(
p
od
.
ID
))
for
_
,
c
:=
range
p
od
.
Containers
{
f
.
KilledPods
=
append
(
f
.
KilledPods
,
string
(
runningP
od
.
ID
))
for
_
,
c
:=
range
runningP
od
.
Containers
{
f
.
KilledContainers
=
append
(
f
.
KilledContainers
,
c
.
Name
)
}
return
f
.
Err
...
...
pkg/kubelet/container/runtime.go
View file @
73d105e2
...
...
@@ -54,8 +54,8 @@ type Runtime interface {
GetPods
(
all
bool
)
([]
*
Pod
,
error
)
// Syncs the running pod into the desired pod.
SyncPod
(
pod
*
api
.
Pod
,
runningPod
Pod
,
podStatus
api
.
PodStatus
,
pullSecrets
[]
api
.
Secret
)
error
// KillPod kills all the containers of a pod.
KillPod
(
pod
Pod
)
error
// KillPod kills all the containers of a pod.
Pod may be nil, running pod must not be.
KillPod
(
pod
*
api
.
Pod
,
runningPod
Pod
)
error
// GetPodStatus retrieves the status of the pod, including the information of
// all containers in the pod. Clients of this interface assume the containers
// statuses in a pod always have a deterministic ordering (eg: sorted by name).
...
...
pkg/kubelet/dockertools/manager.go
View file @
73d105e2
This diff is collapsed.
Click to expand it.
pkg/kubelet/dockertools/manager_test.go
View file @
73d105e2
...
...
@@ -405,7 +405,7 @@ func TestKillContainerInPod(t *testing.T) {
manager
.
readinessManager
.
SetReadiness
(
c
.
ID
,
true
)
}
if
err
:=
manager
.
KillContainerInPod
(
pod
.
Spec
.
Containers
[
0
],
pod
);
err
!=
nil
{
if
err
:=
manager
.
KillContainerInPod
(
""
,
&
pod
.
Spec
.
Containers
[
0
],
pod
);
err
!=
nil
{
t
.
Errorf
(
"unexpected error: %v"
,
err
)
}
// Assert the container has been stopped.
...
...
@@ -478,14 +478,14 @@ func TestKillContainerInPodWithPreStop(t *testing.T) {
manager
.
readinessManager
.
SetReadiness
(
c
.
ID
,
true
)
}
if
err
:=
manager
.
KillContainerInPod
(
pod
.
Spec
.
Containers
[
0
],
pod
);
err
!=
nil
{
if
err
:=
manager
.
KillContainerInPod
(
""
,
&
pod
.
Spec
.
Containers
[
0
],
pod
);
err
!=
nil
{
t
.
Errorf
(
"unexpected error: %v"
,
err
)
}
// Assert the container has been stopped.
if
err
:=
fakeDocker
.
AssertStopped
([]
string
{
containerToKill
.
ID
});
err
!=
nil
{
t
.
Errorf
(
"container was not stopped correctly: %v"
,
err
)
}
verifyCalls
(
t
,
fakeDocker
,
[]
string
{
"list"
,
"
inspect_container"
,
"
create_exec"
,
"start_exec"
,
"stop"
})
verifyCalls
(
t
,
fakeDocker
,
[]
string
{
"list"
,
"create_exec"
,
"start_exec"
,
"stop"
})
if
!
reflect
.
DeepEqual
(
expectedCmd
,
fakeDocker
.
execCmd
)
{
t
.
Errorf
(
"expected: %v, got %v"
,
expectedCmd
,
fakeDocker
.
execCmd
)
}
...
...
@@ -522,7 +522,7 @@ func TestKillContainerInPodWithError(t *testing.T) {
manager
.
readinessManager
.
SetReadiness
(
c
.
ID
,
true
)
}
if
err
:=
manager
.
KillContainerInPod
(
pod
.
Spec
.
Containers
[
0
],
pod
);
err
==
nil
{
if
err
:=
manager
.
KillContainerInPod
(
""
,
&
pod
.
Spec
.
Containers
[
0
],
pod
);
err
==
nil
{
t
.
Errorf
(
"expected error, found nil"
)
}
...
...
@@ -1021,7 +1021,7 @@ func TestSyncPodDeletesWithNoPodInfraContainer(t *testing.T) {
verifyCalls
(
t
,
fakeDocker
,
[]
string
{
// Kill the container since pod infra container is not running.
"
inspect_container"
,
"
stop"
,
"stop"
,
// Create pod infra container.
"create"
,
"start"
,
"inspect_container"
,
// Create container.
...
...
@@ -1096,7 +1096,7 @@ func TestSyncPodDeletesDuplicate(t *testing.T) {
// Check the pod infra container.
"inspect_container"
,
// Kill the duplicated container.
"
inspect_container"
,
"
stop"
,
"stop"
,
})
// Expect one of the duplicates to be killed.
if
len
(
fakeDocker
.
Stopped
)
!=
1
||
(
fakeDocker
.
Stopped
[
0
]
!=
"1234"
&&
fakeDocker
.
Stopped
[
0
]
!=
"4567"
)
{
...
...
@@ -1150,7 +1150,7 @@ func TestSyncPodBadHash(t *testing.T) {
// Check the pod infra container.
"inspect_container"
,
// Kill and restart the bad hash container.
"
inspect_container"
,
"
stop"
,
"create"
,
"start"
,
"inspect_container"
,
"stop"
,
"create"
,
"start"
,
"inspect_container"
,
})
if
err
:=
fakeDocker
.
AssertStopped
([]
string
{
"1234"
});
err
!=
nil
{
...
...
@@ -1208,7 +1208,7 @@ func TestSyncPodsUnhealthy(t *testing.T) {
// Check the pod infra container.
"inspect_container"
,
// Kill the unhealthy container.
"
inspect_container"
,
"
stop"
,
"stop"
,
// Restart the unhealthy container.
"create"
,
"start"
,
"inspect_container"
,
})
...
...
@@ -1441,9 +1441,9 @@ func TestSyncPodWithRestartPolicy(t *testing.T) {
api
.
RestartPolicyNever
,
[]
string
{
// Check the pod infra container.
"inspect_container"
,
"inspect_container"
,
"inspect_container"
,
// Stop the last pod infra container.
"
inspect_container"
,
"
stop"
,
"stop"
,
},
[]
string
{},
[]
string
{
"9876"
},
...
...
@@ -1910,7 +1910,7 @@ func TestSyncPodEventHandlerFails(t *testing.T) {
// Create the container.
"create"
,
"start"
,
// Kill the container since event handler fails.
"
inspect_container"
,
"
stop"
,
"stop"
,
})
// TODO(yifan): Check the stopped container's name.
...
...
pkg/kubelet/kubelet.go
View file @
73d105e2
...
...
@@ -1124,8 +1124,8 @@ func parseResolvConf(reader io.Reader) (nameservers []string, searches []string,
}
// Kill all running containers in a pod (includes the pod infra container).
func
(
kl
*
Kubelet
)
killPod
(
pod
kubecontainer
.
Pod
)
error
{
return
kl
.
containerRuntime
.
KillPod
(
pod
)
func
(
kl
*
Kubelet
)
killPod
(
pod
*
api
.
Pod
,
runningPod
kubecontainer
.
Pod
)
error
{
return
kl
.
containerRuntime
.
KillPod
(
pod
,
runningPod
)
}
type
empty
struct
{}
...
...
@@ -1181,9 +1181,10 @@ func (kl *Kubelet) syncPod(pod *api.Pod, mirrorPod *api.Pod, runningPod kubecont
}()
// Kill pods we can't run.
err
:=
canRunPod
(
pod
)
if
err
!=
nil
{
kl
.
killPod
(
runningPod
)
if
err
:=
canRunPod
(
pod
);
err
!=
nil
||
pod
.
DeletionTimestamp
!=
nil
{
if
err
:=
kl
.
killPod
(
pod
,
runningPod
);
err
!=
nil
{
util
.
HandleError
(
err
)
}
return
err
}
...
...
@@ -1370,6 +1371,32 @@ func (kl *Kubelet) cleanupOrphanedVolumes(pods []*api.Pod, runningPods []*kubeco
return
nil
}
// Delete any pods that are no longer running and are marked for deletion.
func
(
kl
*
Kubelet
)
cleanupTerminatedPods
(
pods
[]
*
api
.
Pod
,
runningPods
[]
*
kubecontainer
.
Pod
)
error
{
var
terminating
[]
*
api
.
Pod
for
_
,
pod
:=
range
pods
{
if
pod
.
DeletionTimestamp
!=
nil
{
found
:=
false
for
_
,
runningPod
:=
range
runningPods
{
if
runningPod
.
ID
==
pod
.
UID
{
found
=
true
break
}
}
if
found
{
podFullName
:=
kubecontainer
.
GetPodFullName
(
pod
)
glog
.
V
(
5
)
.
Infof
(
"Keeping terminated pod %q and uid %q, still running"
,
podFullName
,
pod
.
UID
)
continue
}
terminating
=
append
(
terminating
,
pod
)
}
}
if
!
kl
.
statusManager
.
TerminatePods
(
terminating
)
{
return
errors
.
New
(
"not all pods were successfully terminated"
)
}
return
nil
}
// pastActiveDeadline returns true if the pod has been active for more than
// ActiveDeadlineSeconds.
func
(
kl
*
Kubelet
)
pastActiveDeadline
(
pod
*
api
.
Pod
)
bool
{
...
...
@@ -1532,6 +1559,10 @@ func (kl *Kubelet) cleanupPods(allPods []*api.Pod, admittedPods []*api.Pod) erro
// Remove any orphaned mirror pods.
kl
.
podManager
.
DeleteOrphanedMirrorPods
()
if
err
:=
kl
.
cleanupTerminatedPods
(
allPods
,
runningPods
);
err
!=
nil
{
glog
.
Errorf
(
"Failed to cleanup terminated pods: %v"
,
err
)
}
return
err
}
...
...
@@ -1554,7 +1585,7 @@ func (kl *Kubelet) killUnwantedPods(desiredPods map[types.UID]empty,
}()
glog
.
V
(
1
)
.
Infof
(
"Killing unwanted pod %q"
,
pod
.
Name
)
// Stop the containers.
err
=
kl
.
killPod
(
*
pod
)
err
=
kl
.
killPod
(
nil
,
*
pod
)
if
err
!=
nil
{
glog
.
Errorf
(
"Failed killing the pod %q: %v"
,
pod
.
Name
,
err
)
return
...
...
pkg/kubelet/mirror_client.go
View file @
73d105e2
...
...
@@ -64,7 +64,7 @@ func (mc *basicMirrorClient) DeleteMirrorPod(podFullName string) error {
return
err
}
glog
.
V
(
4
)
.
Infof
(
"Deleting a mirror pod %q"
,
podFullName
)
if
err
:=
mc
.
apiserverClient
.
Pods
(
namespace
)
.
Delete
(
name
,
nil
);
err
!=
nil
{
if
err
:=
mc
.
apiserverClient
.
Pods
(
namespace
)
.
Delete
(
name
,
api
.
NewDeleteOptions
(
0
)
);
err
!=
nil
{
glog
.
Errorf
(
"Failed deleting a mirror pod %q: %v"
,
podFullName
,
err
)
}
return
nil
...
...
pkg/kubelet/rkt/rkt.go
View file @
73d105e2
...
...
@@ -693,11 +693,11 @@ func (r *runtime) GetPods(all bool) ([]*kubecontainer.Pod, error) {
}
// KillPod invokes 'systemctl kill' to kill the unit that runs the pod.
func
(
r
*
runtime
)
KillPod
(
pod
kubecontainer
.
Pod
)
error
{
glog
.
V
(
4
)
.
Infof
(
"Rkt is killing pod: name %q."
,
p
od
.
Name
)
func
(
r
*
runtime
)
KillPod
(
pod
*
api
.
Pod
,
runningPod
kubecontainer
.
Pod
)
error
{
glog
.
V
(
4
)
.
Infof
(
"Rkt is killing pod: name %q."
,
runningP
od
.
Name
)
// TODO(yifan): More graceful stop. Replace with StopUnit and wait for a timeout.
r
.
systemd
.
KillUnit
(
makePodServiceFileName
(
p
od
.
ID
),
int32
(
syscall
.
SIGKILL
))
r
.
systemd
.
KillUnit
(
makePodServiceFileName
(
runningP
od
.
ID
),
int32
(
syscall
.
SIGKILL
))
return
r
.
systemd
.
Reload
()
}
...
...
@@ -966,7 +966,7 @@ func (r *runtime) SyncPod(pod *api.Pod, runningPod kubecontainer.Pod, podStatus
if
restartPod
{
// TODO(yifan): Handle network plugin.
if
err
:=
r
.
KillPod
(
runningPod
);
err
!=
nil
{
if
err
:=
r
.
KillPod
(
pod
,
runningPod
);
err
!=
nil
{
return
err
}
if
err
:=
r
.
RunPod
(
pod
,
pullSecrets
);
err
!=
nil
{
...
...
pkg/kubelet/status_manager.go
View file @
73d105e2
...
...
@@ -24,6 +24,7 @@ import (
"github.com/golang/glog"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/api/errors"
client
"k8s.io/kubernetes/pkg/client/unversioned"
kubecontainer
"k8s.io/kubernetes/pkg/kubelet/container"
kubeletTypes
"k8s.io/kubernetes/pkg/kubelet/types"
...
...
@@ -122,7 +123,7 @@ func (s *statusManager) SetPodStatus(pod *api.Pod, status api.PodStatus) {
// Currently this routine is not called for the same pod from multiple
// workers and/or the kubelet but dropping the lock before sending the
// status down the channel feels like an easy way to get a bullet in foot.
if
!
found
||
!
isStatusEqual
(
&
oldStatus
,
&
status
)
{
if
!
found
||
!
isStatusEqual
(
&
oldStatus
,
&
status
)
||
pod
.
DeletionTimestamp
!=
nil
{
s
.
podStatuses
[
podFullName
]
=
status
s
.
podStatusChannel
<-
podStatusSyncRequest
{
pod
,
status
}
}
else
{
...
...
@@ -130,6 +131,29 @@ func (s *statusManager) SetPodStatus(pod *api.Pod, status api.PodStatus) {
}
}
// TerminatePods resets the container status for the provided pods to terminated and triggers
// a status update. This function may not enqueue all the provided pods, in which case it will
// return false
func
(
s
*
statusManager
)
TerminatePods
(
pods
[]
*
api
.
Pod
)
bool
{
sent
:=
true
s
.
podStatusesLock
.
Lock
()
defer
s
.
podStatusesLock
.
Unlock
()
for
_
,
pod
:=
range
pods
{
for
i
:=
range
pod
.
Status
.
ContainerStatuses
{
pod
.
Status
.
ContainerStatuses
[
i
]
.
State
=
api
.
ContainerState
{
Terminated
:
&
api
.
ContainerStateTerminated
{},
}
}
select
{
case
s
.
podStatusChannel
<-
podStatusSyncRequest
{
pod
,
pod
.
Status
}
:
default
:
sent
=
false
glog
.
V
(
4
)
.
Infof
(
"Termination notice for %q was dropped because the status channel is full"
,
kubeletUtil
.
FormatPodName
(
pod
))
}
}
return
sent
}
func
(
s
*
statusManager
)
DeletePodStatus
(
podFullName
string
)
{
s
.
podStatusesLock
.
Lock
()
defer
s
.
podStatusesLock
.
Unlock
()
...
...
@@ -161,13 +185,33 @@ func (s *statusManager) syncBatch() error {
}
// TODO: make me easier to express from client code
statusPod
,
err
=
s
.
kubeClient
.
Pods
(
statusPod
.
Namespace
)
.
Get
(
statusPod
.
Name
)
if
errors
.
IsNotFound
(
err
)
{
glog
.
V
(
3
)
.
Infof
(
"Pod %q was deleted on the server"
,
pod
.
Name
)
return
nil
}
if
err
==
nil
{
if
len
(
pod
.
UID
)
>
0
&&
statusPod
.
UID
!=
pod
.
UID
{
glog
.
V
(
3
)
.
Infof
(
"Pod %q was deleted and then recreated, skipping status update"
,
kubeletUtil
.
FormatPodName
(
pod
))
return
nil
}
statusPod
.
Status
=
status
_
,
err
=
s
.
kubeClient
.
Pods
(
pod
.
Namespace
)
.
UpdateStatus
(
statusPod
)
// TODO: handle conflict as a retry, make that easier too.
statusPod
,
err
=
s
.
kubeClient
.
Pods
(
pod
.
Namespace
)
.
UpdateStatus
(
statusPod
)
if
err
==
nil
{
glog
.
V
(
3
)
.
Infof
(
"Status for pod %q updated successfully"
,
kubeletUtil
.
FormatPodName
(
pod
))
return
nil
if
pod
.
DeletionTimestamp
==
nil
{
return
nil
}
if
!
notRunning
(
pod
.
Status
.
ContainerStatuses
)
{
glog
.
V
(
3
)
.
Infof
(
"Pod %q is terminated, but some pods are still running"
,
pod
.
Name
)
return
nil
}
if
err
:=
s
.
kubeClient
.
Pods
(
statusPod
.
Namespace
)
.
Delete
(
statusPod
.
Name
,
api
.
NewDeleteOptions
(
0
));
err
==
nil
{
glog
.
V
(
3
)
.
Infof
(
"Pod %q fully terminated and removed from etcd"
,
statusPod
.
Name
)
s
.
DeletePodStatus
(
podFullName
)
return
nil
}
}
}
...
...
@@ -181,3 +225,14 @@ func (s *statusManager) syncBatch() error {
go
s
.
DeletePodStatus
(
podFullName
)
return
fmt
.
Errorf
(
"error updating status for pod %q: %v"
,
kubeletUtil
.
FormatPodName
(
pod
),
err
)
}
// notRunning returns true if every status is terminated or waiting, or the status list
// is empty.
func
notRunning
(
statuses
[]
api
.
ContainerStatus
)
bool
{
for
_
,
status
:=
range
statuses
{
if
status
.
State
.
Terminated
==
nil
&&
status
.
State
.
Waiting
==
nil
{
return
false
}
}
return
true
}
pkg/kubelet/status_manager_test.go
View file @
73d105e2
...
...
@@ -153,8 +153,21 @@ func TestUnchangedStatus(t *testing.T) {
verifyUpdates
(
t
,
syncer
,
1
)
}
func
TestSyncBatchIgnoresNotFound
(
t
*
testing
.
T
)
{
syncer
:=
newTestStatusManager
()
syncer
.
SetPodStatus
(
testPod
,
getRandomPodStatus
())
err
:=
syncer
.
syncBatch
()
if
err
!=
nil
{
t
.
Errorf
(
"unexpected syncing error: %v"
,
err
)
}
verifyActions
(
t
,
syncer
.
kubeClient
,
[]
testclient
.
Action
{
testclient
.
GetActionImpl
{
ActionImpl
:
testclient
.
ActionImpl
{
Verb
:
"get"
,
Resource
:
"pods"
}},
})
}
func
TestSyncBatch
(
t
*
testing
.
T
)
{
syncer
:=
newTestStatusManager
()
syncer
.
kubeClient
=
testclient
.
NewSimpleFake
(
testPod
)
syncer
.
SetPodStatus
(
testPod
,
getRandomPodStatus
())
err
:=
syncer
.
syncBatch
()
if
err
!=
nil
{
...
...
@@ -167,6 +180,22 @@ func TestSyncBatch(t *testing.T) {
)
}
func
TestSyncBatchChecksMismatchedUID
(
t
*
testing
.
T
)
{
syncer
:=
newTestStatusManager
()
testPod
.
UID
=
"first"
differentPod
:=
*
testPod
differentPod
.
UID
=
"second"
syncer
.
kubeClient
=
testclient
.
NewSimpleFake
(
testPod
)
syncer
.
SetPodStatus
(
&
differentPod
,
getRandomPodStatus
())
err
:=
syncer
.
syncBatch
()
if
err
!=
nil
{
t
.
Errorf
(
"unexpected syncing error: %v"
,
err
)
}
verifyActions
(
t
,
syncer
.
kubeClient
,
[]
testclient
.
Action
{
testclient
.
GetActionImpl
{
ActionImpl
:
testclient
.
ActionImpl
{
Verb
:
"get"
,
Resource
:
"pods"
}},
})
}
// shuffle returns a new shuffled list of container statuses.
func
shuffle
(
statuses
[]
api
.
ContainerStatus
)
[]
api
.
ContainerStatus
{
numStatuses
:=
len
(
statuses
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment