@@ -25,6 +25,7 @@ import (
25
25
"os/exec"
26
26
"path/filepath"
27
27
"strings"
28
+ "sync"
28
29
"syscall"
29
30
"time"
30
31
@@ -850,7 +851,12 @@ var _ = framework.KubeDescribe("Security Context", func() {
850
851
851
852
Context ("UserNamespaces" , func () {
852
853
var (
853
- podName string
854
+ podName string
855
+
856
+ // We call rc.Status() once and save the result in statusResp.
857
+ statusOnce sync.Once
858
+ statusResp * runtimeapi.StatusResponse
859
+
854
860
defaultMapping = []* runtimeapi.IDMapping {{
855
861
ContainerId : 0 ,
856
862
HostId : 1000 ,
@@ -863,108 +869,127 @@ var _ = framework.KubeDescribe("Security Context", func() {
863
869
864
870
// Find a working runtime handler if none provided
865
871
By ("searching for runtime handler which supports user namespaces" )
866
- ctx , cancel := context .WithTimeout (context .Background (), time .Minute )
867
- defer cancel ()
868
- resp , err := rc .Status (ctx , true ) // Set verbose to true so the info field is populated.
869
- framework .ExpectNoError (err , "failed to get runtime config: %v" , err )
870
-
871
- supportsUserNamespaces := false
872
- for _ , rh := range resp .GetRuntimeHandlers () {
872
+ statusOnce .Do (func () {
873
+ ctx , cancel := context .WithTimeout (context .Background (), time .Minute )
874
+ defer cancel ()
875
+ // Set verbose to true, other BeforeEachs calls need the info field
876
+ // populated.
877
+ // XXX: Do NOT use ":=" here, it breaks the closure reference to
878
+ // statusResp.
879
+ var err error
880
+ statusResp , err = rc .Status (ctx , true )
881
+ framework .ExpectNoError (err , "failed to get runtime config: %v" , err )
882
+ _ = statusResp // Avoid unused variable error
883
+ })
884
+
885
+ var supportsUserNamespaces bool
886
+ for _ , rh := range statusResp .GetRuntimeHandlers () {
873
887
if rh .GetName () == framework .TestContext .RuntimeHandler {
874
888
if rh .GetFeatures ().GetUserNamespaces () {
875
889
supportsUserNamespaces = true
876
890
break
877
891
}
878
892
}
879
893
}
880
-
881
894
if ! supportsUserNamespaces {
882
895
Skip ("no runtime handler found which supports user namespaces" )
883
896
}
884
-
885
- pathIDMap := rootfsPath (resp .GetInfo ())
886
- if err := supportsIDMap (pathIDMap ); err != nil {
887
- Skip ("ID mapping is not supported" + " with path: " + pathIDMap + ": " + err .Error ())
888
- }
889
897
})
890
898
891
- It ("runtime should support NamespaceMode_POD" , func () {
892
- namespaceOption := & runtimeapi.NamespaceOption {
893
- UsernsOptions : & runtimeapi.UserNamespace {
894
- Mode : runtimeapi .NamespaceMode_POD ,
895
- Uids : defaultMapping ,
896
- Gids : defaultMapping ,
897
- },
898
- }
899
+ When ("Host idmap mount support is needed" , func () {
900
+ BeforeEach (func () {
901
+ pathIDMap := rootfsPath (statusResp .GetInfo ())
902
+ if err := supportsIDMap (pathIDMap ); err != nil {
903
+ Skip ("ID mapping is not supported" + " with path: " + pathIDMap + ": " + err .Error ())
904
+ }
905
+ })
906
+
907
+ It ("runtime should support NamespaceMode_POD" , func () {
908
+ namespaceOption := & runtimeapi.NamespaceOption {
909
+ UsernsOptions : & runtimeapi.UserNamespace {
910
+ Mode : runtimeapi .NamespaceMode_POD ,
911
+ Uids : defaultMapping ,
912
+ Gids : defaultMapping ,
913
+ },
914
+ }
899
915
900
- hostLogPath , podLogPath := createLogTempDir (podName )
901
- defer os .RemoveAll (hostLogPath )
902
- podID , podConfig = createNamespacePodSandbox (rc , namespaceOption , podName , podLogPath )
903
- containerName := runUserNamespaceContainer (rc , ic , podID , podConfig )
916
+ hostLogPath , podLogPath := createLogTempDir (podName )
917
+ defer os .RemoveAll (hostLogPath )
918
+ podID , podConfig = createNamespacePodSandbox (rc , namespaceOption , podName , podLogPath )
919
+ containerName := runUserNamespaceContainer (rc , ic , podID , podConfig )
904
920
905
- matchContainerOutputRe (podConfig , containerName , `\s+0\s+1000\s+100000\n` )
906
- })
921
+ matchContainerOutputRe (podConfig , containerName , `\s+0\s+1000\s+100000\n` )
922
+ })
907
923
908
- It ("runtime should support NamespaceMode_NODE" , func () {
909
- namespaceOption := & runtimeapi.NamespaceOption {
910
- UsernsOptions : & runtimeapi.UserNamespace {
911
- Mode : runtimeapi .NamespaceMode_NODE ,
912
- },
913
- }
924
+ })
914
925
915
- hostLogPath , podLogPath := createLogTempDir (podName )
916
- defer os .RemoveAll (hostLogPath )
917
- podID , podConfig = createNamespacePodSandbox (rc , namespaceOption , podName , podLogPath )
918
- containerName := runUserNamespaceContainer (rc , ic , podID , podConfig )
926
+ When ("Host idmap mount support is not needed" , func () {
927
+ It ("runtime should support NamespaceMode_NODE" , func () {
928
+ namespaceOption := & runtimeapi.NamespaceOption {
929
+ UsernsOptions : & runtimeapi.UserNamespace {
930
+ Mode : runtimeapi .NamespaceMode_NODE ,
931
+ },
932
+ }
919
933
920
- // 4294967295 means that the entire range is available
921
- matchContainerOutputRe (podConfig , containerName , `\s+0\s+0\s+4294967295\n` )
922
- })
934
+ hostLogPath , podLogPath := createLogTempDir (podName )
935
+ defer os .RemoveAll (hostLogPath )
936
+ podID , podConfig = createNamespacePodSandbox (rc , namespaceOption , podName , podLogPath )
937
+ containerName := runUserNamespaceContainer (rc , ic , podID , podConfig )
923
938
924
- It ("runtime should fail if more than one mapping provided" , func () {
925
- wrongMapping := []* runtimeapi.IDMapping {{
926
- ContainerId : 0 ,
927
- HostId : 1000 ,
928
- Length : 100000 ,
929
- }, {
930
- ContainerId : 0 ,
931
- HostId : 2000 ,
932
- Length : 100000 ,
933
- }}
934
- usernsOptions := & runtimeapi.UserNamespace {
935
- Mode : runtimeapi .NamespaceMode_POD ,
936
- Uids : wrongMapping ,
937
- Gids : wrongMapping ,
938
- }
939
+ // 4294967295 means that the entire range is available
940
+ expectedOutput := hostUsernsContent ()
941
+ if expectedOutput == "" {
942
+ Fail ("failed to get host userns content" )
943
+ }
944
+ // 4294967295 means that the entire range is available
945
+ matchContainerOutputRe (podConfig , containerName , `\s+0\s+0\s+4294967295\n` )
946
+ })
947
+
948
+ It ("runtime should fail if more than one mapping provided" , func () {
949
+ wrongMapping := []* runtimeapi.IDMapping {{
950
+ ContainerId : 0 ,
951
+ HostId : 1000 ,
952
+ Length : 100000 ,
953
+ }, {
954
+ ContainerId : 0 ,
955
+ HostId : 2000 ,
956
+ Length : 100000 ,
957
+ }}
958
+ usernsOptions := & runtimeapi.UserNamespace {
959
+ Mode : runtimeapi .NamespaceMode_POD ,
960
+ Uids : wrongMapping ,
961
+ Gids : wrongMapping ,
962
+ }
939
963
940
- runUserNamespacePodWithError (rc , podName , usernsOptions )
941
- })
964
+ runUserNamespacePodWithError (rc , podName , usernsOptions )
965
+ })
942
966
943
- It ("runtime should fail if container ID 0 is not mapped" , func () {
944
- mapping := []* runtimeapi.IDMapping {{
945
- ContainerId : 1 ,
946
- HostId : 1000 ,
947
- Length : 100000 ,
948
- }}
949
- usernsOptions := & runtimeapi.UserNamespace {
950
- Mode : runtimeapi .NamespaceMode_POD ,
951
- Uids : mapping ,
952
- Gids : mapping ,
953
- }
967
+ It ("runtime should fail if container ID 0 is not mapped" , func () {
968
+ mapping := []* runtimeapi.IDMapping {{
969
+ ContainerId : 1 ,
970
+ HostId : 1000 ,
971
+ Length : 100000 ,
972
+ }}
973
+ usernsOptions := & runtimeapi.UserNamespace {
974
+ Mode : runtimeapi .NamespaceMode_POD ,
975
+ Uids : mapping ,
976
+ Gids : mapping ,
977
+ }
954
978
955
- runUserNamespacePodWithError (rc , podName , usernsOptions )
956
- })
979
+ runUserNamespacePodWithError (rc , podName , usernsOptions )
980
+ })
957
981
958
- It ("runtime should fail with NamespaceMode_CONTAINER" , func () {
959
- usernsOptions := & runtimeapi.UserNamespace {Mode : runtimeapi .NamespaceMode_CONTAINER }
982
+ It ("runtime should fail with NamespaceMode_CONTAINER" , func () {
983
+ usernsOptions := & runtimeapi.UserNamespace {Mode : runtimeapi .NamespaceMode_CONTAINER }
960
984
961
- runUserNamespacePodWithError (rc , podName , usernsOptions )
962
- })
985
+ runUserNamespacePodWithError (rc , podName , usernsOptions )
986
+ })
963
987
964
- It ("runtime should fail with NamespaceMode_TARGET" , func () {
965
- usernsOptions := & runtimeapi.UserNamespace {Mode : runtimeapi .NamespaceMode_TARGET }
988
+ It ("runtime should fail with NamespaceMode_TARGET" , func () {
989
+ usernsOptions := & runtimeapi.UserNamespace {Mode : runtimeapi .NamespaceMode_TARGET }
966
990
967
- runUserNamespacePodWithError (rc , podName , usernsOptions )
991
+ runUserNamespacePodWithError (rc , podName , usernsOptions )
992
+ })
968
993
})
969
994
})
970
995
})
0 commit comments