@@ -54,14 +54,15 @@ import (
54
54
"k8s.io/apimachinery/pkg/util/wait"
55
55
utilyaml "k8s.io/apimachinery/pkg/util/yaml"
56
56
"k8s.io/apimachinery/pkg/watch"
57
+ utilfeature "k8s.io/apiserver/pkg/util/feature"
57
58
clientset "k8s.io/client-go/kubernetes"
58
59
"k8s.io/client-go/kubernetes/scheme"
59
60
"k8s.io/client-go/rest"
60
61
restclient "k8s.io/client-go/rest"
61
62
"k8s.io/client-go/tools/clientcmd"
62
63
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
63
64
watchtools "k8s.io/client-go/tools/watch"
64
- podutil "k8s.io/kubernetes/pkg/api/v1/pod "
65
+ "k8s.io/component-base/featuregate "
65
66
"k8s.io/kubernetes/pkg/controller"
66
67
testutils "k8s.io/kubernetes/test/utils"
67
68
imageutils "k8s.io/kubernetes/test/utils/image"
@@ -142,6 +143,10 @@ const (
142
143
143
144
// TODO(justinsb): Avoid hardcoding this.
144
145
awsMasterIP = "172.20.0.9"
146
+
147
+ // AllContainers specifies that all containers be visited
148
+ // Copied from pkg/api/v1/pod to avoid pulling extra dependencies
149
+ AllContainers = InitContainers | Containers | EphemeralContainers
145
150
)
146
151
147
152
var (
@@ -734,6 +739,66 @@ func (f *Framework) testContainerOutputMatcher(scenarioName string,
734
739
ExpectNoError (f .MatchContainerOutput (pod , pod .Spec .Containers [containerIndex ].Name , expectedOutput , matcher ))
735
740
}
736
741
742
+ // ContainerType signifies container type
743
+ type ContainerType int
744
+
745
+ const (
746
+ // FeatureEphemeralContainers allows running an ephemeral container in pod namespaces to troubleshoot a running pod
747
+ FeatureEphemeralContainers featuregate.Feature = "EphemeralContainers"
748
+ // Containers is for normal containers
749
+ Containers ContainerType = 1 << iota
750
+ // InitContainers is for init containers
751
+ InitContainers
752
+ // EphemeralContainers is for ephemeral containers
753
+ EphemeralContainers
754
+ )
755
+
756
+ // allFeatureEnabledContainers returns a ContainerType mask which includes all container
757
+ // types except for the ones guarded by feature gate.
758
+ // Copied from pkg/api/v1/pod to avoid pulling extra dependencies
759
+ func allFeatureEnabledContainers () ContainerType {
760
+ containerType := AllContainers
761
+ if ! utilfeature .DefaultFeatureGate .Enabled (FeatureEphemeralContainers ) {
762
+ containerType &= ^ EphemeralContainers
763
+ }
764
+ return containerType
765
+ }
766
+
767
+ // ContainerVisitor is called with each container spec, and returns true
768
+ // if visiting should continue.
769
+ // Copied from pkg/api/v1/pod to avoid pulling extra dependencies
770
+ type ContainerVisitor func (container * v1.Container , containerType ContainerType ) (shouldContinue bool )
771
+
772
+ // visitContainers invokes the visitor function with a pointer to every container
773
+ // spec in the given pod spec with type set in mask. If visitor returns false,
774
+ // visiting is short-circuited. visitContainers returns true if visiting completes,
775
+ // false if visiting was short-circuited.
776
+ // Copied from pkg/api/v1/pod to avoid pulling extra dependencies
777
+ func visitContainers (podSpec * v1.PodSpec , mask ContainerType , visitor ContainerVisitor ) bool {
778
+ if mask & InitContainers != 0 {
779
+ for i := range podSpec .InitContainers {
780
+ if ! visitor (& podSpec .InitContainers [i ], InitContainers ) {
781
+ return false
782
+ }
783
+ }
784
+ }
785
+ if mask & Containers != 0 {
786
+ for i := range podSpec .Containers {
787
+ if ! visitor (& podSpec .Containers [i ], Containers ) {
788
+ return false
789
+ }
790
+ }
791
+ }
792
+ if mask & EphemeralContainers != 0 {
793
+ for i := range podSpec .EphemeralContainers {
794
+ if ! visitor ((* v1 .Container )(& podSpec .EphemeralContainers [i ].EphemeralContainerCommon ), EphemeralContainers ) {
795
+ return false
796
+ }
797
+ }
798
+ }
799
+ return true
800
+ }
801
+
737
802
// MatchContainerOutput creates a pod and waits for all it's containers to exit with success.
738
803
// It then tests that the matcher with each expectedOutput matches the output of the specified container.
739
804
func (f * Framework ) MatchContainerOutput (
@@ -764,7 +829,7 @@ func (f *Framework) MatchContainerOutput(
764
829
765
830
if podErr != nil {
766
831
// Pod failed. Dump all logs from all containers to see what's wrong
767
- _ = podutil . VisitContainers (& podStatus .Spec , podutil . AllFeatureEnabledContainers (), func (c * v1.Container , containerType podutil. ContainerType ) bool {
832
+ _ = visitContainers (& podStatus .Spec , allFeatureEnabledContainers (), func (c * v1.Container , containerType ContainerType ) bool {
768
833
logs , err := e2epod .GetPodLogs (f .ClientSet , ns , podStatus .Name , c .Name )
769
834
if err != nil {
770
835
Logf ("Failed to get logs from node %q pod %q container %q: %v" ,
0 commit comments