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:
parent
308f828446
commit
8aa3bfc59c
6 changed files with 102 additions and 4 deletions
|
@ -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
|
||||
|
|
68
api/kubernetes/cli/access_test.go
Normal file
68
api/kubernetes/cli/access_test.go
Normal 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)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue