From e2bbe0d2c5f8928d29cffc2c3d5e21f700f913f6 Mon Sep 17 00:00:00 2001 From: Jon Edvald Date: Wed, 24 Feb 2021 00:53:03 +0100 Subject: [PATCH] fix(k8s): error with missing metadata field This should fix a user-reported error of ``` Cannot read property 'namespace' of undefined ``` which is most likely due to an assumption of a metadata field existing on a resource. There may be a further underlying error, but this should at the very least reveal what that is. --- core/src/plugins/kubernetes/api.ts | 2 +- core/src/plugins/kubernetes/kubernetes-module/common.ts | 6 +++++- core/src/plugins/kubernetes/logs.ts | 4 ++-- core/src/plugins/kubernetes/namespace.ts | 2 +- core/src/plugins/kubernetes/status/events.ts | 2 +- core/src/plugins/kubernetes/status/service.ts | 2 +- core/src/plugins/kubernetes/status/status.ts | 6 +++--- core/src/plugins/kubernetes/util.ts | 6 +++--- 8 files changed, 17 insertions(+), 13 deletions(-) diff --git a/core/src/plugins/kubernetes/api.ts b/core/src/plugins/kubernetes/api.ts index 17de3809e6..08aca04278 100644 --- a/core/src/plugins/kubernetes/api.ts +++ b/core/src/plugins/kubernetes/api.ts @@ -476,7 +476,7 @@ export class KubeApi { } if (!namespace) { - namespace = manifest.metadata.namespace + namespace = manifest.metadata?.namespace } if (!namespace) { diff --git a/core/src/plugins/kubernetes/kubernetes-module/common.ts b/core/src/plugins/kubernetes/kubernetes-module/common.ts index 75f7ef172d..9e2ea8aee1 100644 --- a/core/src/plugins/kubernetes/kubernetes-module/common.ts +++ b/core/src/plugins/kubernetes/kubernetes-module/common.ts @@ -39,7 +39,11 @@ export async function getManifests({ return Bluebird.map(manifests, async (manifest) => { // Ensure a namespace is set, if not already set, and if required by the resource type - if (!manifest.metadata.namespace) { + if (!manifest.metadata?.namespace) { + if (!manifest.metadata) { + manifest.metadata = {} + } + try { const info = await api.getApiResourceInfo(log, manifest.apiVersion, manifest.kind) diff --git a/core/src/plugins/kubernetes/logs.ts b/core/src/plugins/kubernetes/logs.ts index f6e8a36e9a..3ffa45ac75 100644 --- a/core/src/plugins/kubernetes/logs.ts +++ b/core/src/plugins/kubernetes/logs.ts @@ -87,7 +87,7 @@ async function readLogsFromApi({ const logs = await getPodLogs({ api, - namespace: pod.metadata.namespace || defaultNamespace, + namespace: pod.metadata?.namespace || defaultNamespace, pod, lineLimit: tail === -1 ? undefined : tail, timestamps: true, @@ -137,7 +137,7 @@ async function followLogs({ }) { const sternArgs = [ `--context=${provider.config.context}`, - `--namespace=${pod.metadata.namespace || defaultNamespace}`, + `--namespace=${pod.metadata?.namespace || defaultNamespace}`, `--exclude-container=garden-*`, "--tail", String(tail), diff --git a/core/src/plugins/kubernetes/namespace.ts b/core/src/plugins/kubernetes/namespace.ts index f328ae13e9..e49a7d0230 100644 --- a/core/src/plugins/kubernetes/namespace.ts +++ b/core/src/plugins/kubernetes/namespace.ts @@ -229,7 +229,7 @@ export async function getModuleNamespace({ return getNamespace({ log, ctx, - override: module.spec.namespace ? { name: module.spec.namespace } : undefined, + override: module.spec?.namespace ? { name: module.spec.namespace } : undefined, provider, skipCreate, }) diff --git a/core/src/plugins/kubernetes/status/events.ts b/core/src/plugins/kubernetes/status/events.ts index 8462c1ec44..925e0d89e7 100644 --- a/core/src/plugins/kubernetes/status/events.ts +++ b/core/src/plugins/kubernetes/status/events.ts @@ -15,7 +15,7 @@ export async function getResourceEvents(api: KubeApi, resource: KubernetesResour `involvedObject.kind=${resource.kind},` + `involvedObject.name=${resource.metadata.name}` - const namespace = resource.metadata.namespace + const namespace = resource.metadata?.namespace const res = namespace ? await api.core.listNamespacedEvent(namespace, undefined, undefined, undefined, fieldSelector) diff --git a/core/src/plugins/kubernetes/status/service.ts b/core/src/plugins/kubernetes/status/service.ts index 167f1b9ae7..b8e7aeb7ba 100644 --- a/core/src/plugins/kubernetes/status/service.ts +++ b/core/src/plugins/kubernetes/status/service.ts @@ -40,7 +40,7 @@ export async function waitForServiceEndpoints( } const serviceName = service.metadata.name - const serviceNamespace = service.metadata.namespace || namespace + const serviceNamespace = service.metadata?.namespace || namespace const pods = await getPods(api, serviceNamespace, selector) const readyPodNames = pods diff --git a/core/src/plugins/kubernetes/status/status.ts b/core/src/plugins/kubernetes/status/status.ts index 93d286535b..7c799ca0a1 100644 --- a/core/src/plugins/kubernetes/status/status.ts +++ b/core/src/plugins/kubernetes/status/status.ts @@ -131,7 +131,7 @@ export async function checkResourceStatus( ) { const handler = objHandlers[manifest.kind] - if (manifest.metadata.namespace) { + if (manifest.metadata?.namespace) { namespace = manifest.metadata.namespace } @@ -364,7 +364,7 @@ export async function compareDeployedResources( manifest.apiVersion = deployedResource.apiVersion // the namespace property is silently dropped when added to non-namespaced resources - if (manifest.metadata.namespace && deployedResource.metadata.namespace === undefined) { + if (manifest.metadata?.namespace && deployedResource.metadata?.namespace === undefined) { delete manifest.metadata.namespace } @@ -420,7 +420,7 @@ export async function getDeployedResource( log: LogEntry ): Promise { const api = await KubeApi.factory(log, ctx, provider) - const namespace = resource.metadata.namespace || (await getAppNamespace(ctx, log, provider)) + const namespace = resource.metadata?.namespace || (await getAppNamespace(ctx, log, provider)) try { const res = await api.readBySpec({ namespace, manifest: resource, log }) diff --git a/core/src/plugins/kubernetes/util.ts b/core/src/plugins/kubernetes/util.ts index fb9f89f101..b273c19eb7 100644 --- a/core/src/plugins/kubernetes/util.ts +++ b/core/src/plugins/kubernetes/util.ts @@ -61,7 +61,7 @@ export async function getAllPods( } if (isWorkload(resource)) { - return getWorkloadPods(api, resource.metadata.namespace || defaultNamespace, resource) + return getWorkloadPods(api, resource.metadata?.namespace || defaultNamespace, resource) } return [] @@ -126,13 +126,13 @@ export async function getCurrentWorkloadPods(api: KubeApi, namespace: string, re export async function getWorkloadPods(api: KubeApi, namespace: string, resource: KubernetesWorkload) { // We don't match on the garden.io/version label because it can fall out of sync during hot reloads const selector = omit(getSelectorFromResource(resource), gardenAnnotationKey("version")) - const pods = await getPods(api, resource.metadata.namespace || namespace, selector) + const pods = await getPods(api, resource.metadata?.namespace || namespace, selector) if (resource.kind === "Deployment") { // Make sure we only return the pods from the current ReplicaSet const selectorString = labelSelectorToString(selector) const replicaSetRes = await api.apps.listNamespacedReplicaSet( - resource.metadata.namespace || namespace, + resource.metadata?.namespace || namespace, undefined, // pretty undefined, // allowWatchBookmarks undefined, // _continue