mirror of
https://github.com/portainer/portainer.git
synced 2025-08-09 15:55:23 +02:00
move service account isSystem to server
This commit is contained in:
parent
6bc6471562
commit
ee180ed08f
6 changed files with 39 additions and 49 deletions
|
@ -4,13 +4,17 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"net/http"
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
K8sServiceAccount struct {
|
K8sServiceAccount struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
UID types.UID `json:"uid"`
|
||||||
Namespace string `json:"namespace"`
|
Namespace string `json:"namespace"`
|
||||||
CreationDate time.Time `json:"creationDate"`
|
CreationDate time.Time `json:"creationDate"`
|
||||||
|
IsSystem bool `json:"isSystem"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// K8sServiceAcountDeleteRequests is a mapping of namespace names to a slice of service account names.
|
// K8sServiceAcountDeleteRequests is a mapping of namespace names to a slice of service account names.
|
||||||
|
|
|
@ -53,18 +53,20 @@ func (kcl *KubeClient) fetchServiceAccounts(namespace string) ([]models.K8sServi
|
||||||
|
|
||||||
results := make([]models.K8sServiceAccount, 0)
|
results := make([]models.K8sServiceAccount, 0)
|
||||||
for _, serviceAccount := range serviceAccounts.Items {
|
for _, serviceAccount := range serviceAccounts.Items {
|
||||||
results = append(results, parseServiceAccount(serviceAccount))
|
results = append(results, kcl.parseServiceAccount(serviceAccount))
|
||||||
}
|
}
|
||||||
|
|
||||||
return results, nil
|
return results, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseServiceAccount converts a corev1.ServiceAccount object to a models.K8sServiceAccount object.
|
// parseServiceAccount converts a corev1.ServiceAccount object to a models.K8sServiceAccount object.
|
||||||
func parseServiceAccount(serviceAccount corev1.ServiceAccount) models.K8sServiceAccount {
|
func (kcl *KubeClient) parseServiceAccount(serviceAccount corev1.ServiceAccount) models.K8sServiceAccount {
|
||||||
return models.K8sServiceAccount{
|
return models.K8sServiceAccount{
|
||||||
Name: serviceAccount.Name,
|
Name: serviceAccount.Name,
|
||||||
|
UID: serviceAccount.UID,
|
||||||
Namespace: serviceAccount.Namespace,
|
Namespace: serviceAccount.Namespace,
|
||||||
CreationDate: serviceAccount.CreationTimestamp.Time,
|
CreationDate: serviceAccount.CreationTimestamp.Time,
|
||||||
|
IsSystem: kcl.isSystemServiceAccount(serviceAccount.Namespace),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,6 +86,10 @@ func (kcl *KubeClient) GetPortainerUserServiceAccount(tokenData *portainer.Token
|
||||||
return serviceAccount, nil
|
return serviceAccount, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (kcl *KubeClient) isSystemServiceAccount(namespace string) bool {
|
||||||
|
return kcl.isSystemNamespace(namespace)
|
||||||
|
}
|
||||||
|
|
||||||
// DeleteServices processes a K8sServiceDeleteRequest by deleting each service
|
// DeleteServices processes a K8sServiceDeleteRequest by deleting each service
|
||||||
// in its given namespace.
|
// in its given namespace.
|
||||||
func (kcl *KubeClient) DeleteServiceAccounts(reqs kubernetes.K8sServiceAccountDeleteRequests) error {
|
func (kcl *KubeClient) DeleteServiceAccounts(reqs kubernetes.K8sServiceAccountDeleteRequests) error {
|
||||||
|
@ -101,7 +107,7 @@ func (kcl *KubeClient) DeleteServiceAccounts(reqs kubernetes.K8sServiceAccountDe
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if kcl.isSystemNamespace(sa.Namespace) {
|
if kcl.isSystemServiceAccount(sa.Namespace) {
|
||||||
return fmt.Errorf("cannot delete system service account %q", namespace+"/"+serviceName)
|
return fmt.Errorf("cannot delete system service account %q", namespace+"/"+serviceName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,11 @@ import { useEnvironmentId } from '@/react/hooks/useEnvironmentId';
|
||||||
import { Authorized } from '@/react/hooks/useUser';
|
import { Authorized } from '@/react/hooks/useUser';
|
||||||
import { notifyError, notifySuccess } from '@/portainer/services/notifications';
|
import { notifyError, notifySuccess } from '@/portainer/services/notifications';
|
||||||
import { SystemResourceDescription } from '@/react/kubernetes/datatables/SystemResourceDescription';
|
import { SystemResourceDescription } from '@/react/kubernetes/datatables/SystemResourceDescription';
|
||||||
import { useNamespacesQuery } from '@/react/kubernetes/namespaces/queries/useNamespacesQuery';
|
|
||||||
import {
|
import {
|
||||||
DefaultDatatableSettings,
|
DefaultDatatableSettings,
|
||||||
TableSettings as KubeTableSettings,
|
TableSettings as KubeTableSettings,
|
||||||
} from '@/react/kubernetes/datatables/DefaultDatatableSettings';
|
} from '@/react/kubernetes/datatables/DefaultDatatableSettings';
|
||||||
import { CreateFromManifestButton } from '@/react/kubernetes/components/CreateFromManifestButton';
|
import { CreateFromManifestButton } from '@/react/kubernetes/components/CreateFromManifestButton';
|
||||||
import { isSystemNamespace } from '@/react/kubernetes/namespaces/queries/useIsSystemNamespace';
|
|
||||||
import { useKubeStore } from '@/react/kubernetes/datatables/default-kube-datatable-store';
|
import { useKubeStore } from '@/react/kubernetes/datatables/default-kube-datatable-store';
|
||||||
|
|
||||||
import { Datatable, TableSettingsMenu } from '@@/datatables';
|
import { Datatable, TableSettingsMenu } from '@@/datatables';
|
||||||
|
@ -24,7 +22,7 @@ import {
|
||||||
|
|
||||||
import { ServiceAccount } from '../types';
|
import { ServiceAccount } from '../types';
|
||||||
|
|
||||||
import { getColumns } from './columns';
|
import { columns } from './columns';
|
||||||
import { useDeleteServiceAccountsMutation } from './queries/useDeleteServiceAccountsMutation';
|
import { useDeleteServiceAccountsMutation } from './queries/useDeleteServiceAccountsMutation';
|
||||||
import { useGetAllServiceAccountsQuery } from './queries/useGetAllServiceAccountsQuery';
|
import { useGetAllServiceAccountsQuery } from './queries/useGetAllServiceAccountsQuery';
|
||||||
|
|
||||||
|
@ -42,22 +40,15 @@ export function ServiceAccountsDatatable() {
|
||||||
...filteredColumnsSettings(set),
|
...filteredColumnsSettings(set),
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
const namespacesQuery = useNamespacesQuery(environmentId);
|
|
||||||
const namespaces = namespacesQuery.data;
|
|
||||||
const serviceAccountsQuery = useGetAllServiceAccountsQuery(environmentId, {
|
const serviceAccountsQuery = useGetAllServiceAccountsQuery(environmentId, {
|
||||||
refetchInterval: tableState.autoRefreshRate * 1000,
|
refetchInterval: tableState.autoRefreshRate * 1000,
|
||||||
enabled: namespacesQuery.isSuccess,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const columns = getColumns(namespaces);
|
|
||||||
const filteredServiceAccounts = useMemo(
|
const filteredServiceAccounts = useMemo(
|
||||||
() =>
|
() =>
|
||||||
tableState.showSystemResources
|
tableState.showSystemResources
|
||||||
? serviceAccountsQuery.data
|
? serviceAccountsQuery.data
|
||||||
: serviceAccountsQuery.data?.filter(
|
: serviceAccountsQuery.data?.filter((sa) => !sa.isSystem),
|
||||||
(sa) => !isSystemNamespace(sa.namespace, namespaces)
|
[serviceAccountsQuery.data, tableState.showSystemResources]
|
||||||
),
|
|
||||||
[namespaces, serviceAccountsQuery.data, tableState.showSystemResources]
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -69,10 +60,8 @@ export function ServiceAccountsDatatable() {
|
||||||
emptyContentLabel="No service accounts found"
|
emptyContentLabel="No service accounts found"
|
||||||
title="Service Accounts"
|
title="Service Accounts"
|
||||||
titleIcon={User}
|
titleIcon={User}
|
||||||
getRowId={(row) => `${row.namespace}-${row.name}`}
|
getRowId={(row) => row.uid}
|
||||||
isRowSelectable={(row) =>
|
isRowSelectable={(row) => !row.original.isSystem}
|
||||||
!isSystemNamespace(row.original.namespace, namespaces)
|
|
||||||
}
|
|
||||||
renderTableActions={(selectedRows) => (
|
renderTableActions={(selectedRows) => (
|
||||||
<TableActions selectedItems={selectedRows} />
|
<TableActions selectedItems={selectedRows} />
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
import { PortainerNamespace } from '@/react/kubernetes/namespaces/types';
|
|
||||||
|
|
||||||
import { name } from './name';
|
import { name } from './name';
|
||||||
import { namespace } from './namespace';
|
import { namespace } from './namespace';
|
||||||
import { created } from './created';
|
import { created } from './created';
|
||||||
|
|
||||||
export function getColumns(namespaces?: PortainerNamespace[]) {
|
export const columns = [name, namespace, created];
|
||||||
return [name(namespaces), namespace, created];
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,30 +1,23 @@
|
||||||
import { isSystemNamespace } from '@/react/kubernetes/namespaces/queries/useIsSystemNamespace';
|
|
||||||
import { PortainerNamespace } from '@/react/kubernetes/namespaces/types';
|
|
||||||
|
|
||||||
import { SystemBadge } from '@@/Badge/SystemBadge';
|
import { SystemBadge } from '@@/Badge/SystemBadge';
|
||||||
|
|
||||||
import { columnHelper } from './helper';
|
import { columnHelper } from './helper';
|
||||||
|
|
||||||
export function name(namespaces?: PortainerNamespace[]) {
|
export const name = columnHelper.accessor(
|
||||||
return columnHelper.accessor(
|
(row) => {
|
||||||
(row) => {
|
let result = row.name;
|
||||||
let result = row.name;
|
if (row.isSystem) {
|
||||||
if (isSystemNamespace(row.namespace, namespaces)) {
|
result += ' system';
|
||||||
result += ' system';
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
},
|
|
||||||
{
|
|
||||||
header: 'Name',
|
|
||||||
id: 'name',
|
|
||||||
cell: ({ row }) => (
|
|
||||||
<div className="flex gap-2">
|
|
||||||
<div>{row.original.name}</div>
|
|
||||||
{isSystemNamespace(row.original.namespace, namespaces) && (
|
|
||||||
<SystemBadge />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
);
|
return result;
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
header: 'Name',
|
||||||
|
id: 'name',
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<div>{row.original.name}</div>
|
||||||
|
{row.original.isSystem && <SystemBadge />}
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
export type ServiceAccount = {
|
export type ServiceAccount = {
|
||||||
name: string;
|
name: string;
|
||||||
|
uid: string;
|
||||||
namespace: string;
|
namespace: string;
|
||||||
creationDate: string;
|
creationDate: string;
|
||||||
|
isSystem: boolean;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue