@@ -50,14 +50,15 @@ import (
50
50
"k8s.io/apimachinery/pkg/util/uuid"
51
51
"k8s.io/apimachinery/pkg/util/wait"
52
52
"k8s.io/apimachinery/pkg/watch"
53
+ utilfeature "k8s.io/apiserver/pkg/util/feature"
53
54
clientset "k8s.io/client-go/kubernetes"
54
55
"k8s.io/client-go/rest"
55
56
restclient "k8s.io/client-go/rest"
56
57
"k8s.io/client-go/tools/cache"
57
58
"k8s.io/client-go/tools/clientcmd"
58
59
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
59
60
watchtools "k8s.io/client-go/tools/watch"
60
- podutil "k8s.io/kubernetes/pkg/api/v1/pod "
61
+ "k8s.io/component-base/featuregate "
61
62
"k8s.io/kubernetes/pkg/controller"
62
63
testutils "k8s.io/kubernetes/test/utils"
63
64
imageutils "k8s.io/kubernetes/test/utils/image"
@@ -138,6 +139,10 @@ const (
138
139
139
140
// TODO(justinsb): Avoid hardcoding this.
140
141
awsMasterIP = "172.20.0.9"
142
+
143
+ // AllContainers specifies that all containers be visited
144
+ // Copied from pkg/api/v1/pod to avoid pulling extra dependencies
145
+ AllContainers = InitContainers | Containers | EphemeralContainers
141
146
)
142
147
143
148
var (
@@ -711,6 +716,66 @@ func (f *Framework) testContainerOutputMatcher(scenarioName string,
711
716
ExpectNoError (f .MatchContainerOutput (pod , pod .Spec .Containers [containerIndex ].Name , expectedOutput , matcher ))
712
717
}
713
718
719
+ // ContainerType signifies container type
720
+ type ContainerType int
721
+
722
+ const (
723
+ // FeatureEphemeralContainers allows running an ephemeral container in pod namespaces to troubleshoot a running pod
724
+ FeatureEphemeralContainers featuregate.Feature = "EphemeralContainers"
725
+ // Containers is for normal containers
726
+ Containers ContainerType = 1 << iota
727
+ // InitContainers is for init containers
728
+ InitContainers
729
+ // EphemeralContainers is for ephemeral containers
730
+ EphemeralContainers
731
+ )
732
+
733
+ // allFeatureEnabledContainers returns a ContainerType mask which includes all container
734
+ // types except for the ones guarded by feature gate.
735
+ // Copied from pkg/api/v1/pod to avoid pulling extra dependencies
736
+ func allFeatureEnabledContainers () ContainerType {
737
+ containerType := AllContainers
738
+ if ! utilfeature .DefaultFeatureGate .Enabled (FeatureEphemeralContainers ) {
739
+ containerType &= ^ EphemeralContainers
740
+ }
741
+ return containerType
742
+ }
743
+
744
+ // ContainerVisitor is called with each container spec, and returns true
745
+ // if visiting should continue.
746
+ // Copied from pkg/api/v1/pod to avoid pulling extra dependencies
747
+ type ContainerVisitor func (container * v1.Container , containerType ContainerType ) (shouldContinue bool )
748
+
749
+ // visitContainers invokes the visitor function with a pointer to every container
750
+ // spec in the given pod spec with type set in mask. If visitor returns false,
751
+ // visiting is short-circuited. visitContainers returns true if visiting completes,
752
+ // false if visiting was short-circuited.
753
+ // Copied from pkg/api/v1/pod to avoid pulling extra dependencies
754
+ func visitContainers (podSpec * v1.PodSpec , mask ContainerType , visitor ContainerVisitor ) bool {
755
+ if mask & InitContainers != 0 {
756
+ for i := range podSpec .InitContainers {
757
+ if ! visitor (& podSpec .InitContainers [i ], InitContainers ) {
758
+ return false
759
+ }
760
+ }
761
+ }
762
+ if mask & Containers != 0 {
763
+ for i := range podSpec .Containers {
764
+ if ! visitor (& podSpec .Containers [i ], Containers ) {
765
+ return false
766
+ }
767
+ }
768
+ }
769
+ if mask & EphemeralContainers != 0 {
770
+ for i := range podSpec .EphemeralContainers {
771
+ if ! visitor ((* v1 .Container )(& podSpec .EphemeralContainers [i ].EphemeralContainerCommon ), EphemeralContainers ) {
772
+ return false
773
+ }
774
+ }
775
+ }
776
+ return true
777
+ }
778
+
714
779
// MatchContainerOutput creates a pod and waits for all it's containers to exit with success.
715
780
// It then tests that the matcher with each expectedOutput matches the output of the specified container.
716
781
func (f * Framework ) MatchContainerOutput (
@@ -741,7 +806,7 @@ func (f *Framework) MatchContainerOutput(
741
806
742
807
if podErr != nil {
743
808
// Pod failed. Dump all logs from all containers to see what's wrong
744
- _ = podutil . VisitContainers (& podStatus .Spec , podutil . AllFeatureEnabledContainers (), func (c * v1.Container , containerType podutil. ContainerType ) bool {
809
+ _ = visitContainers (& podStatus .Spec , allFeatureEnabledContainers (), func (c * v1.Container , containerType ContainerType ) bool {
745
810
logs , err := e2epod .GetPodLogs (f .ClientSet , ns , podStatus .Name , c .Name )
746
811
if err != nil {
747
812
Logf ("Failed to get logs from node %q pod %q container %q: %v" ,
0 commit comments