From 7c04615c10ad20ec52b3cd78bd9d08697193eb31 Mon Sep 17 00:00:00 2001 From: Sebastian Malton Date: Fri, 20 May 2022 15:21:44 -0400 Subject: [PATCH] Fix envFrom.prefix not being applied Signed-off-by: Sebastian Malton --- src/common/k8s-api/__tests__/pods.test.ts | 16 +- src/common/k8s-api/endpoints/pod.api.ts | 12 +- .../k8s-api/endpoints/types/container.ts | 2 +- src/common/k8s-api/endpoints/types/index.ts | 1 + .../scale/dialog.test.tsx | 4 +- .../+workloads-pods/pod-container-env.tsx | 146 ++++++++++-------- .../scale-dialog/dialog.test.tsx | 4 +- .../__tests__/deployments.store.test.ts | 4 +- .../components/dock/logs/__test__/pod.mock.ts | 22 +-- 9 files changed, 113 insertions(+), 98 deletions(-) diff --git a/src/common/k8s-api/__tests__/pods.test.ts b/src/common/k8s-api/__tests__/pods.test.ts index 826c2b4617..3ed979face 100644 --- a/src/common/k8s-api/__tests__/pods.test.ts +++ b/src/common/k8s-api/__tests__/pods.test.ts @@ -4,7 +4,7 @@ */ import assert from "assert"; -import type { PodContainer, PodContainerStatus } from "../endpoints"; +import type { Container, PodContainerStatus } from "../endpoints"; import { Pod } from "../endpoints"; interface GetDummyPodOptions { @@ -22,8 +22,8 @@ function getDummyPod(rawOpts: GetDummyPodOptions = {}): Pod { initRunning = 0, } = rawOpts; - const containers: PodContainer[] = []; - const initContainers: PodContainer[] = []; + const containers: Container[] = []; + const initContainers: Container[] = []; const containerStatuses: PodContainerStatus[] = []; const initContainerStatuses: PodContainerStatus[] = []; const pod = new Pod({ @@ -58,7 +58,7 @@ function getDummyPod(rawOpts: GetDummyPodOptions = {}): Pod { containers.push({ image: "dummy", - imagePullPolicy: "dummy", + imagePullPolicy: "Always", name, }); containerStatuses.push({ @@ -80,7 +80,7 @@ function getDummyPod(rawOpts: GetDummyPodOptions = {}): Pod { containers.push({ image: "dummy", - imagePullPolicy: "dummy", + imagePullPolicy: "Always", name, }); containerStatuses.push({ @@ -105,7 +105,7 @@ function getDummyPod(rawOpts: GetDummyPodOptions = {}): Pod { initContainers.push({ image: "dummy", - imagePullPolicy: "dummy", + imagePullPolicy: "Always", name, }); initContainerStatuses.push({ @@ -127,7 +127,7 @@ function getDummyPod(rawOpts: GetDummyPodOptions = {}): Pod { initContainers.push({ image: "dummy", - imagePullPolicy: "dummy", + imagePullPolicy: "Always", name, }); initContainerStatuses.push({ @@ -169,7 +169,7 @@ describe("Pods", () => { function getNamedContainer(name: string) { return { image: "dummy", - imagePullPolicy: "dummy", + imagePullPolicy: "Always", name, }; } diff --git a/src/common/k8s-api/endpoints/pod.api.ts b/src/common/k8s-api/endpoints/pod.api.ts index 35e9b4dcb6..767aff1e9f 100644 --- a/src/common/k8s-api/endpoints/pod.api.ts +++ b/src/common/k8s-api/endpoints/pod.api.ts @@ -16,6 +16,7 @@ import { isDefined } from "../../utils"; import type { PodSecurityContext } from "./types/pod-security-context"; import type { Probe } from "./types/probe"; import type { Container } from "./types/container"; +import type { ObjectFieldSelector, ResourceFieldSelector } from "./types"; export class PodApi extends KubeApi { constructor(opts: DerivedKubeApiOptions & IgnoredKubeApiOptions = {}) { @@ -375,17 +376,6 @@ export interface ConfigMapProjection { optional?: boolean; } -export interface ObjectFieldSelector { - fieldPath: string; - apiVersion?: string; -} - -export interface ResourceFieldSelector { - resource: string; - containerName?: string; - divisor?: string; -} - export interface DownwardAPIVolumeFile { path: string; fieldRef?: ObjectFieldSelector; diff --git a/src/common/k8s-api/endpoints/types/container.ts b/src/common/k8s-api/endpoints/types/container.ts index 227c9dd57b..bccf45eb64 100644 --- a/src/common/k8s-api/endpoints/types/container.ts +++ b/src/common/k8s-api/endpoints/types/container.ts @@ -98,7 +98,7 @@ export interface Container { readinessProbe?: Probe; resources?: ResourceRequirements; - securityContext: SecurityContext; + securityContext?: SecurityContext; startupProbe?: Probe; /** diff --git a/src/common/k8s-api/endpoints/types/index.ts b/src/common/k8s-api/endpoints/types/index.ts index f180a7d893..6fb52e7403 100644 --- a/src/common/k8s-api/endpoints/types/index.ts +++ b/src/common/k8s-api/endpoints/types/index.ts @@ -6,6 +6,7 @@ export * from "./aggregation-rule"; export * from "./capabilities"; export * from "./container"; +export * from "./container-port"; export * from "./env-from-source"; export * from "./env-source"; export * from "./env-var-key-selector"; diff --git a/src/renderer/components/+workloads-deployments/scale/dialog.test.tsx b/src/renderer/components/+workloads-deployments/scale/dialog.test.tsx index 99c1e8e8e9..b7f6ba99cb 100644 --- a/src/renderer/components/+workloads-deployments/scale/dialog.test.tsx +++ b/src/renderer/components/+workloads-deployments/scale/dialog.test.tsx @@ -47,8 +47,8 @@ const dummyDeployment = new Deployment({ }, }, terminationMessagePath: "dummy", - terminationMessagePolicy: "dummy", - imagePullPolicy: "dummy", + terminationMessagePolicy: "File", + imagePullPolicy: "Always", }], restartPolicy: "dummy", terminationGracePeriodSeconds: 10, diff --git a/src/renderer/components/+workloads-pods/pod-container-env.tsx b/src/renderer/components/+workloads-pods/pod-container-env.tsx index 384ea3dd7e..494c4464d4 100644 --- a/src/renderer/components/+workloads-pods/pod-container-env.tsx +++ b/src/renderer/components/+workloads-pods/pod-container-env.tsx @@ -7,26 +7,39 @@ import "./pod-container-env.scss"; import React, { useEffect, useState } from "react"; import { observer } from "mobx-react"; -import type { PodContainer, Secret } from "../../../common/k8s-api/endpoints"; +import type { Container, EnvVarKeySelector, Secret } from "../../../common/k8s-api/endpoints"; import { DrawerItem } from "../drawer"; import { autorun } from "mobx"; -import { secretStore } from "../+config-secrets/legacy-store"; -import { configMapStore } from "../+config-maps/legacy-store"; import { Icon } from "../icon"; -import { base64, cssNames, iter } from "../../utils"; +import { base64, cssNames, object } from "../../utils"; import _ from "lodash"; +import { withInjectables } from "@ogre-tools/injectable-react"; +import type { ConfigMapStore } from "../+config-maps/store"; +import type { SecretStore } from "../+config-secrets/store"; +import configMapStoreInjectable from "../+config-maps/store.injectable"; +import secretStoreInjectable from "../+config-secrets/store.injectable"; export interface ContainerEnvironmentProps { - container: PodContainer; + container: Container; namespace: string; } -export const ContainerEnvironment = observer((props: ContainerEnvironmentProps) => { - const { container: { env, envFrom = [] }, namespace } = props; +interface Dependencies { + configMapStore: ConfigMapStore; + secretStore: SecretStore; +} + +const NonInjectedContainerEnvironment = observer((props: Dependencies & ContainerEnvironmentProps) => { + const { + container: { env, envFrom = [] }, + namespace, + configMapStore, + secretStore, + } = props; useEffect( () => autorun(() => { for (const { valueFrom } of env ?? []) { - if (valueFrom?.configMapKeyRef) { + if (valueFrom?.configMapKeyRef?.name) { configMapStore.load({ name: valueFrom.configMapKeyRef.name, namespace }); } } @@ -51,27 +64,22 @@ export const ContainerEnvironment = observer((props: ContainerEnvironmentProps) if (value) { secretValue = value; - } - - if (valueFrom) { + } else if (valueFrom) { const { fieldRef, secretKeyRef, configMapKeyRef } = valueFrom; if (fieldRef) { const { apiVersion, fieldPath } = fieldRef; secretValue = `fieldRef(${apiVersion}:${fieldPath})`; - } - - if (secretKeyRef) { + } else if (secretKeyRef?.name) { secretValue = ( ); - } - - if (configMapKeyRef) { + } else if (configMapKeyRef?.name) { const { name, key } = configMapKeyRef; const configMap = configMapStore.getByName(name, namespace); @@ -91,60 +99,61 @@ export const ContainerEnvironment = observer((props: ContainerEnvironmentProps) }); }; - const renderEnvFrom = () => { - return Array.from(iter.filterFlatMap(envFrom, vars => { - if (vars.configMapRef?.name) { - return renderEnvFromConfigMap(vars.configMapRef.name); - } + const renderEnvFrom = () => ( + envFrom + .flatMap(({ configMapRef, secretRef, prefix }) => { + if (configMapRef?.name) { + return renderEnvFromConfigMap(configMapRef.name, prefix); + } - if (vars.secretRef?.name) { - return renderEnvFromSecret(vars.secretRef.name); - } + if (secretRef?.name) { + return renderEnvFromSecret(secretRef.name, prefix); + } - return null; - })); - }; + return null; + }) + ); - const renderEnvFromConfigMap = (configMapName: string) => { + const renderEnvFromConfigMap = (configMapName: string, prefix: string | undefined) => { const configMap = configMapStore.getByName(configMapName, namespace); if (!configMap) return null; - return Object.entries(configMap.data).map(([name, value]) => ( -
- {name} - : - {value} -
- )); + return object.entries(configMap.data) + .map(([name, value]) => ( +
+ + {prefix} + {name} + + : + {value} +
+ )); }; - const renderEnvFromSecret = (secretName: string) => { + const renderEnvFromSecret = (secretName: string, prefix: string | undefined) => { const secret = secretStore.getByName(secretName, namespace); if (!secret) return null; - return Object.keys(secret.data).map(key => { - const secretKeyRef = { - name: secret.getName(), - key, - }; - - const value = ( - - ); - - return ( + return Object.keys(secret.data) + .map(key => (
- {key} + + {prefix} + {key} + : - {value} +
- ); - }); + )); }; return ( @@ -155,19 +164,34 @@ export const ContainerEnvironment = observer((props: ContainerEnvironmentProps) ); }); -export interface SecretKeyProps { - reference: { - name: string; - key: string; - }; +export const ContainerEnvironment = withInjectables(NonInjectedContainerEnvironment, { + getProps: (di, props) => ({ + ...props, + configMapStore: di.inject(configMapStoreInjectable), + secretStore: di.inject(secretStoreInjectable), + }), +}); + +interface SecretKeyProps { + reference: EnvVarKeySelector; namespace: string; + secretStore: SecretStore; } const SecretKey = (props: SecretKeyProps) => { - const { reference: { name, key }, namespace } = props; + const { + reference: { name, key }, + namespace, + secretStore, + } = props; + const [loading, setLoading] = useState(false); const [secret, setSecret] = useState(); + if (!name) { + return null; + } + const showKey = async (evt: React.MouseEvent) => { evt.preventDefault(); setLoading(true); diff --git a/src/renderer/components/+workloads-replicasets/scale-dialog/dialog.test.tsx b/src/renderer/components/+workloads-replicasets/scale-dialog/dialog.test.tsx index 0b92b40cf1..d1e2aefd66 100755 --- a/src/renderer/components/+workloads-replicasets/scale-dialog/dialog.test.tsx +++ b/src/renderer/components/+workloads-replicasets/scale-dialog/dialog.test.tsx @@ -43,12 +43,12 @@ const dummyReplicaSet = new ReplicaSet({ containers: [{ name: "dummy", image: "dummy", - imagePullPolicy: "dummy", + imagePullPolicy: "Always", }], initContainers: [{ name: "dummy", image: "dummy", - imagePullPolicy: "dummy", + imagePullPolicy: "Always", }], priority: 1, serviceAccountName: "dummy", diff --git a/src/renderer/components/__tests__/deployments.store.test.ts b/src/renderer/components/__tests__/deployments.store.test.ts index a59ecfe692..a478c03d2a 100644 --- a/src/renderer/components/__tests__/deployments.store.test.ts +++ b/src/renderer/components/__tests__/deployments.store.test.ts @@ -23,8 +23,8 @@ const spec: PodSpec = { }, }, terminationMessagePath: "test", - terminationMessagePolicy: "test", - imagePullPolicy: "test", + terminationMessagePolicy: "File", + imagePullPolicy: "Always", }], restartPolicy: "restart", terminationGracePeriodSeconds: 1200, diff --git a/src/renderer/components/dock/logs/__test__/pod.mock.ts b/src/renderer/components/dock/logs/__test__/pod.mock.ts index 134e9b8f25..1736373077 100644 --- a/src/renderer/components/dock/logs/__test__/pod.mock.ts +++ b/src/renderer/components/dock/logs/__test__/pod.mock.ts @@ -22,7 +22,7 @@ export const dockerPod = new Pod({ { name: "docker-exporter", image: "docker.io/prom/node-exporter:v1.0.0-rc.0", - imagePullPolicy: "pull", + imagePullPolicy: "IfNotPresent", }, ], serviceAccountName: "dummy", @@ -66,24 +66,24 @@ export const deploymentPod1 = new Pod({ { name: "init-node-exporter", image: "docker.io/prom/node-exporter:v1.0.0-rc.0", - imagePullPolicy: "pull", + imagePullPolicy: "IfNotPresent", }, { name: "init-node-exporter-1", image: "docker.io/prom/node-exporter:v1.0.0-rc.0", - imagePullPolicy: "pull", + imagePullPolicy: "IfNotPresent", }, ], containers: [ { name: "node-exporter", image: "docker.io/prom/node-exporter:v1.0.0-rc.0", - imagePullPolicy: "pull", + imagePullPolicy: "IfNotPresent", }, { name: "node-exporter-1", image: "docker.io/prom/node-exporter:v1.0.0-rc.0", - imagePullPolicy: "pull", + imagePullPolicy: "IfNotPresent", }, ], serviceAccountName: "dummy", @@ -127,24 +127,24 @@ export const deploymentPod2 = new Pod({ { name: "init-node-exporter", image: "docker.io/prom/node-exporter:v1.0.0-rc.0", - imagePullPolicy: "pull", + imagePullPolicy: "IfNotPresent", }, { name: "init-node-exporter-1", image: "docker.io/prom/node-exporter:v1.0.0-rc.0", - imagePullPolicy: "pull", + imagePullPolicy: "IfNotPresent", }, ], containers: [ { name: "node-exporter", image: "docker.io/prom/node-exporter:v1.0.0-rc.0", - imagePullPolicy: "pull", + imagePullPolicy: "IfNotPresent", }, { name: "node-exporter-1", image: "docker.io/prom/node-exporter:v1.0.0-rc.0", - imagePullPolicy: "pull", + imagePullPolicy: "IfNotPresent", }, ], serviceAccountName: "dummy", @@ -188,12 +188,12 @@ export const deploymentPod3 = new Pod({ { name: "node-exporter", image: "docker.io/prom/node-exporter:v1.0.0-rc.0", - imagePullPolicy: "pull", + imagePullPolicy: "IfNotPresent", }, { name: "node-exporter-1", image: "docker.io/prom/node-exporter:v1.0.0-rc.0", - imagePullPolicy: "pull", + imagePullPolicy: "IfNotPresent", }, ], serviceAccountName: "dummy",