From 07ec2ffe5ed442da2ee153fa4fca4de4cad76613 Mon Sep 17 00:00:00 2001 From: Ali <83188384+testA113@users.noreply.github.com> Date: Mon, 16 Oct 2023 19:15:44 +0100 Subject: [PATCH] fix(namespace): create ns qa feedback [EE-2226] (#10474) --- api/http/models/kubernetes/namespaces.go | 1 + api/kubernetes/cli/namespace.go | 6 +++++ .../resourcePoolsDatatable.html | 2 +- .../CreateView/CreateNamespaceForm.tsx | 8 ++++--- .../kubernetes/namespaces/CreateView/types.ts | 1 + .../kubernetes/namespaces/CreateView/utils.ts | 4 +++- .../components/NamespaceInnerForm.tsx | 4 +--- .../RegistriesFormSection.tsx | 6 ++++- .../ResourceQuotaFormSection.tsx | 22 +++++-------------- .../StorageQuotaFormSection.tsx | 12 ++-------- .../StorageQuotaItem.tsx | 11 +++------- 11 files changed, 34 insertions(+), 43 deletions(-) diff --git a/api/http/models/kubernetes/namespaces.go b/api/http/models/kubernetes/namespaces.go index 3679e684d..dbb71b3ef 100644 --- a/api/http/models/kubernetes/namespaces.go +++ b/api/http/models/kubernetes/namespaces.go @@ -11,6 +11,7 @@ type K8sNamespaceDetails struct { Name string `json:"Name"` Annotations map[string]string `json:"Annotations"` ResourceQuota *K8sResourceQuota `json:"ResourceQuota"` + Owner string `json:"Owner"` } type K8sResourceQuota struct { diff --git a/api/kubernetes/cli/namespace.go b/api/kubernetes/cli/namespace.go index b3dd643cb..d4157c1b6 100644 --- a/api/kubernetes/cli/namespace.go +++ b/api/kubernetes/cli/namespace.go @@ -63,15 +63,21 @@ func (kcl *KubeClient) GetNamespace(name string) (portainer.K8sNamespaceInfo, er // CreateNamespace creates a new ingress in a given namespace in a k8s endpoint. func (kcl *KubeClient) CreateNamespace(info models.K8sNamespaceDetails) error { + portainerLabels := map[string]string{ + "io.portainer.kubernetes.resourcepool.name": info.Name, + "io.portainer.kubernetes.resourcepool.owner": info.Owner, + } var ns v1.Namespace ns.Name = info.Name ns.Annotations = info.Annotations + ns.Labels = portainerLabels resourceQuota := &v1.ResourceQuota{ ObjectMeta: metav1.ObjectMeta{ Name: "portainer-rq-" + info.Name, Namespace: info.Name, + Labels: portainerLabels, }, Spec: v1.ResourceQuotaSpec{ Hard: v1.ResourceList{}, diff --git a/app/kubernetes/components/datatables/resource-pools-datatable/resourcePoolsDatatable.html b/app/kubernetes/components/datatables/resource-pools-datatable/resourcePoolsDatatable.html index 824dc3cba..0359112de 100644 --- a/app/kubernetes/components/datatables/resource-pools-datatable/resourcePoolsDatatable.html +++ b/app/kubernetes/components/datatables/resource-pools-datatable/resourcePoolsDatatable.html @@ -17,7 +17,7 @@ class="searchInput" ng-model="$ctrl.state.textFilter" ng-change="$ctrl.onTextFilterChange()" - placeholder="Search for a namespace..." + placeholder="Search..." auto-focus ng-model-options="{ debounce: 300 }" data-cy="k8sNamespace-namespaceSearchInput" diff --git a/app/react/kubernetes/namespaces/CreateView/CreateNamespaceForm.tsx b/app/react/kubernetes/namespaces/CreateView/CreateNamespaceForm.tsx index 280c6b1d0..134e3b6be 100644 --- a/app/react/kubernetes/namespaces/CreateView/CreateNamespaceForm.tsx +++ b/app/react/kubernetes/namespaces/CreateView/CreateNamespaceForm.tsx @@ -5,6 +5,7 @@ import { useEnvironmentId } from '@/react/hooks/useEnvironmentId'; import { notifySuccess } from '@/portainer/services/notifications'; import { useCurrentEnvironment } from '@/react/hooks/useCurrentEnvironment'; import { useEnvironmentRegistries } from '@/react/portainer/environments/queries/useEnvironmentRegistries'; +import { useCurrentUser } from '@/react/hooks/useUser'; import { Widget, WidgetBody } from '@@/Widget'; @@ -30,6 +31,7 @@ export function CreateNamespaceForm() { const { data: registries } = useEnvironmentRegistries(environmentId, { hideDefault: true, }); + const { user } = useCurrentUser(); // for namespace create, show ingress classes that are allowed in the current environment. // the ingressClasses show the none option, so we don't need to add it here. const { data: ingressClasses } = useIngressControllerClassMapQuery({ @@ -65,7 +67,7 @@ export function CreateNamespaceForm() { handleSubmit(values, user.Username)} validateOnMount validationSchema={getNamespaceValidationSchema( memoryLimit, @@ -78,9 +80,9 @@ export function CreateNamespaceForm() { ); - function handleSubmit(values: CreateNamespaceFormValues) { + function handleSubmit(values: CreateNamespaceFormValues, userName: string) { const createNamespacePayload: CreateNamespacePayload = - transformFormValuesToNamespacePayload(values); + transformFormValuesToNamespacePayload(values, userName); const updateRegistriesPayload: UpdateRegistryPayload[] = values.registries.flatMap((registryFormValues) => { // find the matching registry from the cluster registries diff --git a/app/react/kubernetes/namespaces/CreateView/types.ts b/app/react/kubernetes/namespaces/CreateView/types.ts index 0901f25d9..5a8cd0f5d 100644 --- a/app/react/kubernetes/namespaces/CreateView/types.ts +++ b/app/react/kubernetes/namespaces/CreateView/types.ts @@ -15,6 +15,7 @@ export type CreateNamespaceFormValues = { export type CreateNamespacePayload = { Name: string; + Owner: string; ResourceQuota: ResourceQuotaPayload; }; diff --git a/app/react/kubernetes/namespaces/CreateView/utils.ts b/app/react/kubernetes/namespaces/CreateView/utils.ts index fd2418148..9e3c9379d 100644 --- a/app/react/kubernetes/namespaces/CreateView/utils.ts +++ b/app/react/kubernetes/namespaces/CreateView/utils.ts @@ -1,12 +1,14 @@ import { CreateNamespaceFormValues, CreateNamespacePayload } from './types'; export function transformFormValuesToNamespacePayload( - createNamespaceFormValues: CreateNamespaceFormValues + createNamespaceFormValues: CreateNamespaceFormValues, + owner: string ): CreateNamespacePayload { const memoryInBytes = Number(createNamespaceFormValues.resourceQuota.memory) * 10 ** 6; return { Name: createNamespaceFormValues.name, + Owner: owner, ResourceQuota: { enabled: createNamespaceFormValues.resourceQuota.enabled, cpu: createNamespaceFormValues.resourceQuota.cpu, diff --git a/app/react/kubernetes/namespaces/components/NamespaceInnerForm.tsx b/app/react/kubernetes/namespaces/components/NamespaceInnerForm.tsx index e19242ae7..8d405e5df 100644 --- a/app/react/kubernetes/namespaces/components/NamespaceInnerForm.tsx +++ b/app/react/kubernetes/namespaces/components/NamespaceInnerForm.tsx @@ -97,9 +97,7 @@ export function NamespaceInnerForm({ } errors={errors.registries} /> - {storageClasses.length > 0 && ( - - )} + {storageClasses.length > 0 && } + + Define which registries can be used by users who have access to this + namespace. + {registriesQuery.isLoading && ( diff --git a/app/react/kubernetes/namespaces/components/ResourceQuotaFormSection/ResourceQuotaFormSection.tsx b/app/react/kubernetes/namespaces/components/ResourceQuotaFormSection/ResourceQuotaFormSection.tsx index 14bbc9463..9015aa923 100644 --- a/app/react/kubernetes/namespaces/components/ResourceQuotaFormSection/ResourceQuotaFormSection.tsx +++ b/app/react/kubernetes/namespaces/components/ResourceQuotaFormSection/ResourceQuotaFormSection.tsx @@ -35,22 +35,12 @@ export function ResourceQuotaFormSection({ return ( - {values.enabled ? ( - - A namespace is a logical abstraction of a Kubernetes cluster, to - provide for more flexible management of resources. Best practice is to - set a quota assignment as this ensures greatest security/stability; - alternatively, you can disable assigning a quota for unrestricted - access (not recommended). - - ) : ( - - A namespace is a logical abstraction of a Kubernetes cluster, to - provide for more flexible management of resources. Resource - over-commit is disabled, please assign a capped limit of resources to - this namespace. - - )} + + A resource quota sets boundaries on the compute resources a namespace + can use. It's good practice to set a quota for a namespace to + manage resources effectively. Alternatively, you can disable assigning a + quota for unrestricted access (not recommended). + @@ -19,9 +13,7 @@ export function StorageQuotaFormSection({ storageClasses }: Props) { this namespace. - {storageClasses.map((storageClass) => ( - - ))} + ); } diff --git a/app/react/kubernetes/namespaces/components/StorageQuotaFormSection/StorageQuotaItem.tsx b/app/react/kubernetes/namespaces/components/StorageQuotaFormSection/StorageQuotaItem.tsx index 58205eb47..808992429 100644 --- a/app/react/kubernetes/namespaces/components/StorageQuotaFormSection/StorageQuotaItem.tsx +++ b/app/react/kubernetes/namespaces/components/StorageQuotaFormSection/StorageQuotaItem.tsx @@ -1,23 +1,18 @@ import { Database } from 'lucide-react'; -import { StorageClass } from '@/react/portainer/environments/types'; import { FeatureId } from '@/react/portainer/feature-flags/enums'; import { Icon } from '@@/Icon'; import { FormSectionTitle } from '@@/form-components/FormSectionTitle'; import { SwitchField } from '@@/form-components/SwitchField'; -type Props = { - storageClass: StorageClass; -}; - -export function StorageQuotaItem({ storageClass }: Props) { +export function StorageQuotaItem() { return ( -
+
- {storageClass.Name} + standard