1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-07-25 00:09:40 +02:00

fix(namespace): update portainer-config when delete a namespace (#5330)

This commit is contained in:
Dmitry Salakhov 2021-07-20 14:05:31 +12:00 committed by GitHub
parent 308f828446
commit 8aa3bfc59c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 102 additions and 4 deletions

View file

@ -3,6 +3,7 @@ package cli
import (
"encoding/json"
"github.com/pkg/errors"
portainer "github.com/portainer/portainer/api"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -12,11 +13,24 @@ type (
namespaceAccessPolicies map[string]portainer.K8sNamespaceAccessPolicy
)
// NamespaceAccessPoliciesDeleteNamespace removes stored policies associated with a given namespace
func (kcl *KubeClient) NamespaceAccessPoliciesDeleteNamespace(ns string) error {
kcl.lock.Lock()
defer kcl.lock.Unlock()
policies, err := kcl.GetNamespaceAccessPolicies()
if err != nil {
return errors.WithMessage(err, "failed to fetch access policies")
}
delete(policies, ns)
return kcl.UpdateNamespaceAccessPolicies(policies)
}
// GetNamespaceAccessPolicies gets the namespace access policies
// from config maps in the portainer namespace
func (kcl *KubeClient) GetNamespaceAccessPolicies() (
map[string]portainer.K8sNamespaceAccessPolicy, error,
) {
func (kcl *KubeClient) GetNamespaceAccessPolicies() (map[string]portainer.K8sNamespaceAccessPolicy, error) {
configMap, err := kcl.cli.CoreV1().ConfigMaps(portainerNamespace).Get(portainerConfigMapName, metav1.GetOptions{})
if k8serrors.IsNotFound(err) {
return nil, nil

View file

@ -0,0 +1,68 @@
package cli
import (
"sync"
"testing"
portainer "github.com/portainer/portainer/api"
"github.com/stretchr/testify/assert"
ktypes "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kfake "k8s.io/client-go/kubernetes/fake"
)
func Test_NamespaceAccessPoliciesDeleteNamespace_updatesPortainerConfig_whenConfigExists(t *testing.T) {
testcases := []struct {
name string
namespaceToDelete string
expectedConfig map[string]portainer.K8sNamespaceAccessPolicy
}{
{
name: "doesn't change config, when designated namespace absent",
namespaceToDelete: "missing-namespace",
expectedConfig: map[string]portainer.K8sNamespaceAccessPolicy{
"ns1": {UserAccessPolicies: portainer.UserAccessPolicies{2: {RoleID: 0}}},
"ns2": {UserAccessPolicies: portainer.UserAccessPolicies{2: {RoleID: 0}}},
},
},
{
name: "removes designated namespace from config, when namespace is present",
namespaceToDelete: "ns2",
expectedConfig: map[string]portainer.K8sNamespaceAccessPolicy{
"ns1": {UserAccessPolicies: portainer.UserAccessPolicies{2: {RoleID: 0}}},
},
},
}
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
k := &KubeClient{
cli: kfake.NewSimpleClientset(),
instanceID: "instance",
lock: &sync.Mutex{},
}
config := &ktypes.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: portainerConfigMapName,
Namespace: portainerNamespace,
},
Data: map[string]string{
"NamespaceAccessPolicies": `{"ns1":{"UserAccessPolicies":{"2":{"RoleId":0}}}, "ns2":{"UserAccessPolicies":{"2":{"RoleId":0}}}}`,
},
}
_, err := k.cli.CoreV1().ConfigMaps(portainerNamespace).Create(config)
assert.NoError(t, err, "failed to create a portainer config")
defer func() {
k.cli.CoreV1().ConfigMaps(portainerNamespace).Delete(portainerConfigMapName, nil)
}()
err = k.NamespaceAccessPoliciesDeleteNamespace(test.namespaceToDelete)
assert.NoError(t, err, "failed to delete namespace")
policies, err := k.GetNamespaceAccessPolicies()
assert.NoError(t, err, "failed to fetch policies")
assert.Equal(t, test.expectedConfig, policies)
})
}
}

View file

@ -5,6 +5,7 @@ import (
"fmt"
"net/http"
"strconv"
"sync"
"time"
cmap "github.com/orcaman/concurrent-map"
@ -27,8 +28,9 @@ type (
// KubeClient represent a service used to execute Kubernetes operations
KubeClient struct {
cli *kubernetes.Clientset
cli kubernetes.Interface
instanceID string
lock *sync.Mutex
}
)
@ -75,6 +77,7 @@ func (factory *ClientFactory) createKubeClient(endpoint *portainer.Endpoint) (po
kubecli := &KubeClient{
cli: cli,
instanceID: factory.instanceID,
lock: &sync.Mutex{},
}
return kubecli, nil