mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Merge pull request #123952 from kinvolk/rata/userns-add-tests-namespacesForPod
pkg/kubelet/kuberuntime: Add userns tests for NamespacesForPod
This commit is contained in:
		@@ -18,10 +18,13 @@ package testing
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
	"fmt"
 | 
			
		||||
 | 
			
		||||
	v1 "k8s.io/api/core/v1"
 | 
			
		||||
	kubetypes "k8s.io/apimachinery/pkg/types"
 | 
			
		||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
			
		||||
	runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
 | 
			
		||||
	"k8s.io/kubernetes/pkg/features"
 | 
			
		||||
	kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -33,6 +36,7 @@ type FakeRuntimeHelper struct {
 | 
			
		||||
	HostName        string
 | 
			
		||||
	HostDomain      string
 | 
			
		||||
	PodContainerDir string
 | 
			
		||||
	RuntimeHandlers map[string]kubecontainer.RuntimeHandler
 | 
			
		||||
	Err             error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -69,7 +73,38 @@ func (f *FakeRuntimeHelper) GetExtraSupplementalGroupsForPod(pod *v1.Pod) []int6
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FakeRuntimeHelper) GetOrCreateUserNamespaceMappings(pod *v1.Pod, runtimeHandler string) (*runtimeapi.UserNamespace, error) {
 | 
			
		||||
	featureEnabled := utilfeature.DefaultFeatureGate.Enabled(features.UserNamespacesSupport)
 | 
			
		||||
	if pod == nil || pod.Spec.HostUsers == nil {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
	// pod.Spec.HostUsers is set to true/false
 | 
			
		||||
	if !featureEnabled {
 | 
			
		||||
		return nil, fmt.Errorf("the feature gate %q is disabled: can't set spec.HostUsers", features.UserNamespacesSupport)
 | 
			
		||||
	}
 | 
			
		||||
	if *pod.Spec.HostUsers {
 | 
			
		||||
		return nil, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// From here onwards, hostUsers=false and the feature gate is enabled.
 | 
			
		||||
 | 
			
		||||
	// if the pod requested a user namespace and the runtime doesn't support user namespaces then return an error.
 | 
			
		||||
	if h, ok := f.RuntimeHandlers[runtimeHandler]; !ok {
 | 
			
		||||
		return nil, fmt.Errorf("RuntimeClass handler %q not found", runtimeHandler)
 | 
			
		||||
	} else if !h.SupportsUserNamespaces {
 | 
			
		||||
		return nil, fmt.Errorf("RuntimeClass handler %q does not support user namespaces", runtimeHandler)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ids := &runtimeapi.IDMapping{
 | 
			
		||||
		HostId:      65536,
 | 
			
		||||
		ContainerId: 0,
 | 
			
		||||
		Length:      65536,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &runtimeapi.UserNamespace{
 | 
			
		||||
		Mode: runtimeapi.NamespaceMode_POD,
 | 
			
		||||
		Uids: []*runtimeapi.IDMapping{ids},
 | 
			
		||||
		Gids: []*runtimeapi.IDMapping{ids},
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *FakeRuntimeHelper) PrepareDynamicResources(pod *v1.Pod) error {
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,10 @@ import (
 | 
			
		||||
	"github.com/stretchr/testify/require"
 | 
			
		||||
 | 
			
		||||
	v1 "k8s.io/api/core/v1"
 | 
			
		||||
	utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
			
		||||
	featuregatetesting "k8s.io/component-base/featuregate/testing"
 | 
			
		||||
	runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
 | 
			
		||||
	pkgfeatures "k8s.io/kubernetes/pkg/features"
 | 
			
		||||
	kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
 | 
			
		||||
	kubecontainertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
 | 
			
		||||
)
 | 
			
		||||
@@ -162,10 +165,25 @@ func TestPodSandboxChanged(t *testing.T) {
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type fakeRuntimeHandlerResolver struct{}
 | 
			
		||||
 | 
			
		||||
func (*fakeRuntimeHandlerResolver) LookupRuntimeHandler(s *string) (string, error) {
 | 
			
		||||
	return "", nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestNamespacesForPod(t *testing.T) {
 | 
			
		||||
	usernsIDs := &runtimeapi.IDMapping{
 | 
			
		||||
		HostId:      65536,
 | 
			
		||||
		ContainerId: 0,
 | 
			
		||||
		Length:      65536,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for desc, test := range map[string]struct {
 | 
			
		||||
		input           *v1.Pod
 | 
			
		||||
		runtimeHandlers map[string]kubecontainer.RuntimeHandler
 | 
			
		||||
		usernsEnabled   bool
 | 
			
		||||
		expected        *runtimeapi.NamespaceOption
 | 
			
		||||
		expErr          bool
 | 
			
		||||
	}{
 | 
			
		||||
		"nil pod -> default v1 namespaces": {
 | 
			
		||||
			input: nil,
 | 
			
		||||
@@ -221,11 +239,84 @@ func TestNamespacesForPod(t *testing.T) {
 | 
			
		||||
				Pid:     runtimeapi.NamespaceMode_CONTAINER,
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		"hostUsers: false and feature enabled": {
 | 
			
		||||
			input: &v1.Pod{
 | 
			
		||||
				Spec: v1.PodSpec{
 | 
			
		||||
					HostUsers: &[]bool{false}[0],
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			usernsEnabled: true,
 | 
			
		||||
			runtimeHandlers: map[string]kubecontainer.RuntimeHandler{
 | 
			
		||||
				"": {
 | 
			
		||||
					SupportsUserNamespaces: true,
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			expected: &runtimeapi.NamespaceOption{
 | 
			
		||||
				Ipc:     runtimeapi.NamespaceMode_POD,
 | 
			
		||||
				Network: runtimeapi.NamespaceMode_POD,
 | 
			
		||||
				Pid:     runtimeapi.NamespaceMode_CONTAINER,
 | 
			
		||||
				UsernsOptions: &runtimeapi.UserNamespace{
 | 
			
		||||
					Mode: runtimeapi.NamespaceMode_POD,
 | 
			
		||||
					Uids: []*runtimeapi.IDMapping{usernsIDs},
 | 
			
		||||
					Gids: []*runtimeapi.IDMapping{usernsIDs},
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
		},
 | 
			
		||||
		// The hostUsers field can't be set to any value if the feature is disabled.
 | 
			
		||||
		"hostUsers: false and feature disabled --> error": {
 | 
			
		||||
			input: &v1.Pod{
 | 
			
		||||
				Spec: v1.PodSpec{
 | 
			
		||||
					HostUsers: &[]bool{false}[0],
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			usernsEnabled: false,
 | 
			
		||||
			expErr:        true,
 | 
			
		||||
		},
 | 
			
		||||
		// The hostUsers field can't be set to any value if the feature is disabled.
 | 
			
		||||
		"hostUsers: true and feature disabled --> error": {
 | 
			
		||||
			input: &v1.Pod{
 | 
			
		||||
				Spec: v1.PodSpec{
 | 
			
		||||
					HostUsers: &[]bool{true}[0],
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			usernsEnabled: false,
 | 
			
		||||
			expErr:        true,
 | 
			
		||||
		},
 | 
			
		||||
		"error if runtime handler not found": {
 | 
			
		||||
			input: &v1.Pod{
 | 
			
		||||
				Spec: v1.PodSpec{
 | 
			
		||||
					HostUsers: &[]bool{false}[0],
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			usernsEnabled: true,
 | 
			
		||||
			runtimeHandlers: map[string]kubecontainer.RuntimeHandler{
 | 
			
		||||
				"other": {},
 | 
			
		||||
			},
 | 
			
		||||
			expErr: true,
 | 
			
		||||
		},
 | 
			
		||||
		"error if runtime handler does not support userns": {
 | 
			
		||||
			input: &v1.Pod{
 | 
			
		||||
				Spec: v1.PodSpec{
 | 
			
		||||
					HostUsers: &[]bool{false}[0],
 | 
			
		||||
				},
 | 
			
		||||
			},
 | 
			
		||||
			usernsEnabled: true,
 | 
			
		||||
			expErr:        true,
 | 
			
		||||
		},
 | 
			
		||||
	} {
 | 
			
		||||
		t.Run(desc, func(t *testing.T) {
 | 
			
		||||
			actual, err := NamespacesForPod(test.input, &kubecontainertest.FakeRuntimeHelper{}, nil)
 | 
			
		||||
			featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, pkgfeatures.UserNamespacesSupport, test.usernsEnabled)
 | 
			
		||||
 | 
			
		||||
			fakeRuntimeHelper := kubecontainertest.FakeRuntimeHelper{
 | 
			
		||||
				RuntimeHandlers: test.runtimeHandlers,
 | 
			
		||||
			}
 | 
			
		||||
			actual, err := NamespacesForPod(test.input, &fakeRuntimeHelper, &fakeRuntimeHandlerResolver{})
 | 
			
		||||
			if test.expErr {
 | 
			
		||||
				require.Error(t, err)
 | 
			
		||||
			} else {
 | 
			
		||||
				require.NoError(t, err)
 | 
			
		||||
				require.Equal(t, test.expected, actual)
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user