portainer/api/kubernetes/cli/namespace_test.go

184 lines
5.5 KiB
Go

package cli
import (
"context"
"strconv"
"sync"
"testing"
portainer "github.com/portainer/portainer/api"
"github.com/stretchr/testify/assert"
core "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kfake "k8s.io/client-go/kubernetes/fake"
)
func Test_ToggleSystemState(t *testing.T) {
t.Run("should skip is default (exit without error)", func(t *testing.T) {
nsName := "default"
kcl := &KubeClient{
cli: kfake.NewSimpleClientset(&core.Namespace{ObjectMeta: metav1.ObjectMeta{Name: nsName}}),
instanceID: "instance",
lock: &sync.Mutex{},
}
err := kcl.ToggleSystemState(nsName, true)
assert.NoError(t, err)
ns, err := kcl.cli.CoreV1().Namespaces().Get(context.Background(), nsName, metav1.GetOptions{})
assert.NoError(t, err)
_, exists := ns.Labels[systemNamespaceLabel]
assert.False(t, exists, "system label should not exists")
})
t.Run("should fail if namespace doesn't exist", func(t *testing.T) {
nsName := "not-exist"
kcl := &KubeClient{
cli: kfake.NewSimpleClientset(),
instanceID: "instance",
lock: &sync.Mutex{},
}
err := kcl.ToggleSystemState(nsName, true)
assert.Error(t, err)
})
t.Run("if called with the same state, should skip (exit without error)", func(t *testing.T) {
nsName := "namespace"
tests := []struct {
isSystem bool
}{
{isSystem: true},
{isSystem: false},
}
for _, test := range tests {
t.Run(strconv.FormatBool(test.isSystem), func(t *testing.T) {
kcl := &KubeClient{
cli: kfake.NewSimpleClientset(&core.Namespace{ObjectMeta: metav1.ObjectMeta{Name: nsName, Labels: map[string]string{
systemNamespaceLabel: strconv.FormatBool(test.isSystem),
}}}),
instanceID: "instance",
lock: &sync.Mutex{},
}
err := kcl.ToggleSystemState(nsName, test.isSystem)
assert.NoError(t, err)
ns, err := kcl.cli.CoreV1().Namespaces().Get(context.Background(), nsName, metav1.GetOptions{})
assert.NoError(t, err)
assert.Equal(t, test.isSystem, isSystemNamespace(*ns))
})
}
})
t.Run("for regular namespace if isSystem is true and doesn't have a label, should set the label to true", func(t *testing.T) {
nsName := "namespace"
kcl := &KubeClient{
cli: kfake.NewSimpleClientset(&core.Namespace{ObjectMeta: metav1.ObjectMeta{Name: nsName}}),
instanceID: "instance",
lock: &sync.Mutex{},
}
err := kcl.ToggleSystemState(nsName, true)
assert.NoError(t, err)
ns, err := kcl.cli.CoreV1().Namespaces().Get(context.Background(), nsName, metav1.GetOptions{})
assert.NoError(t, err)
labelValue, exists := ns.Labels[systemNamespaceLabel]
assert.True(t, exists, "system label should exists")
assert.Equal(t, "true", labelValue)
})
t.Run("for default system namespace if isSystem is false and doesn't have a label, should set the label to false", func(t *testing.T) {
nsName := "portainer"
kcl := &KubeClient{
cli: kfake.NewSimpleClientset(&core.Namespace{ObjectMeta: metav1.ObjectMeta{Name: nsName}}),
instanceID: "instance",
lock: &sync.Mutex{},
}
err := kcl.ToggleSystemState(nsName, false)
assert.NoError(t, err)
ns, err := kcl.cli.CoreV1().Namespaces().Get(context.Background(), nsName, metav1.GetOptions{})
assert.NoError(t, err)
labelValue, exists := ns.Labels[systemNamespaceLabel]
assert.True(t, exists, "system label should exists")
assert.Equal(t, "false", labelValue)
})
t.Run("for system namespace (with label), if called with false, should set the label", func(t *testing.T) {
nsName := "namespace"
kcl := &KubeClient{
cli: kfake.NewSimpleClientset(&core.Namespace{ObjectMeta: metav1.ObjectMeta{Name: nsName, Labels: map[string]string{
systemNamespaceLabel: "true",
}}}),
instanceID: "instance",
lock: &sync.Mutex{},
}
err := kcl.ToggleSystemState(nsName, false)
assert.NoError(t, err)
ns, err := kcl.cli.CoreV1().Namespaces().Get(context.Background(), nsName, metav1.GetOptions{})
assert.NoError(t, err)
labelValue, exists := ns.Labels[systemNamespaceLabel]
assert.True(t, exists, "system label should exists")
assert.Equal(t, "false", labelValue)
})
t.Run("for non system namespace (with label), if called with true, should set the label, and remove accesses", func(t *testing.T) {
nsName := "ns1"
namespace := &core.Namespace{ObjectMeta: metav1.ObjectMeta{Name: nsName, Labels: map[string]string{
systemNamespaceLabel: "false",
}}}
config := &core.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: portainerConfigMapName,
Namespace: portainerNamespace,
},
Data: map[string]string{
"NamespaceAccessPolicies": `{"ns1":{"UserAccessPolicies":{"2":{"RoleId":0}}}, "ns2":{"UserAccessPolicies":{"2":{"RoleId":0}}}}`,
},
}
kcl := &KubeClient{
cli: kfake.NewSimpleClientset(namespace, config),
instanceID: "instance",
lock: &sync.Mutex{},
}
err := kcl.ToggleSystemState(nsName, true)
assert.NoError(t, err)
ns, err := kcl.cli.CoreV1().Namespaces().Get(context.Background(), nsName, metav1.GetOptions{})
assert.NoError(t, err)
labelValue, exists := ns.Labels[systemNamespaceLabel]
assert.True(t, exists, "system label should exists")
assert.Equal(t, "true", labelValue)
expectedPolicies := map[string]portainer.K8sNamespaceAccessPolicy{
"ns2": {UserAccessPolicies: portainer.UserAccessPolicies{2: {RoleID: 0}}},
}
actualPolicies, err := kcl.GetNamespaceAccessPolicies()
assert.NoError(t, err, "failed to fetch policies")
assert.Equal(t, expectedPolicies, actualPolicies)
})
}