From ecb488266d6585229476a3dab1dfa4ab3045e434 Mon Sep 17 00:00:00 2001 From: Oliver King Date: Mon, 6 Feb 2023 13:42:55 -0500 Subject: [PATCH] Fixes multiple namespaces bug (#276) * fix ns bug * add tests * rename some variables * rename ns to namespace * fix delete + correctly type * add typing to input obj parser --- src/actions/deploy.ts | 4 +- .../blueGreen/blueGreenHelper.ts | 8 +- .../blueGreen/ingressBlueGreenHelper.ts | 3 +- .../blueGreen/serviceBlueGreenHelper.ts | 3 +- .../blueGreen/smiBlueGreenHelper.ts | 6 +- src/strategyHelpers/canary/canaryHelper.ts | 13 +- src/strategyHelpers/deploymentHelper.ts | 8 +- src/types/k8sObject.ts | 2 + src/types/kubectl.test.ts | 177 +++++++++++++++++- src/types/kubectl.ts | 84 +++++---- src/types/privatekubectl.ts | 2 - src/utilities/kubectlUtils.ts | 15 +- src/utilities/manifestStabilityUtils.ts | 79 +++++--- src/utilities/manifestUpdateUtils.ts | 3 +- 14 files changed, 326 insertions(+), 81 deletions(-) diff --git a/src/actions/deploy.ts b/src/actions/deploy.ts index e3021217c..8106badd9 100644 --- a/src/actions/deploy.ts +++ b/src/actions/deploy.ts @@ -56,7 +56,9 @@ export async function deploy( for (const ingressResource of ingressResources) { await kubectl.getResource( KubernetesConstants.DiscoveryAndLoadBalancerResource.INGRESS, - ingressResource.name + ingressResource.name, + false, + ingressResource.namespace ) } core.endGroup() diff --git a/src/strategyHelpers/blueGreen/blueGreenHelper.ts b/src/strategyHelpers/blueGreen/blueGreenHelper.ts index ac4543637..b2ba445de 100644 --- a/src/strategyHelpers/blueGreen/blueGreenHelper.ts +++ b/src/strategyHelpers/blueGreen/blueGreenHelper.ts @@ -38,7 +38,8 @@ export async function deleteGreenObjects( const resourcesToDelete: K8sDeleteObject[] = toDelete.map((obj) => { return { name: getBlueGreenResourceName(obj.metadata.name, GREEN_SUFFIX), - kind: obj.kind + kind: obj.kind, + namespace: obj.metadata.namespace } }) @@ -234,9 +235,10 @@ export function isServiceSelectorSubsetOfMatchLabel( export async function fetchResource( kubectl: Kubectl, kind: string, - name: string + name: string, + namespace?: string ): Promise { - const result = await kubectl.getResource(kind, name) + const result = await kubectl.getResource(kind, name, false, namespace) if (result == null || !!result.stderr) { return null } diff --git a/src/strategyHelpers/blueGreen/ingressBlueGreenHelper.ts b/src/strategyHelpers/blueGreen/ingressBlueGreenHelper.ts index 17625d7dd..83bda19f3 100644 --- a/src/strategyHelpers/blueGreen/ingressBlueGreenHelper.ts +++ b/src/strategyHelpers/blueGreen/ingressBlueGreenHelper.ts @@ -97,7 +97,8 @@ export async function validateIngresses( const existingIngress = await fetchResource( kubectl, inputObject.kind, - inputObject.metadata.name + inputObject.metadata.name, + inputObject?.metadata?.namespace ) const isValid = diff --git a/src/strategyHelpers/blueGreen/serviceBlueGreenHelper.ts b/src/strategyHelpers/blueGreen/serviceBlueGreenHelper.ts index 8fde8c409..d3bb50a83 100644 --- a/src/strategyHelpers/blueGreen/serviceBlueGreenHelper.ts +++ b/src/strategyHelpers/blueGreen/serviceBlueGreenHelper.ts @@ -31,7 +31,8 @@ export async function validateServicesState( const existingService = await fetchResource( kubectl, serviceObject.kind, - serviceObject.metadata.name + serviceObject.metadata.name, + serviceObject?.metadata?.namespace ) let isServiceGreen = diff --git a/src/strategyHelpers/blueGreen/smiBlueGreenHelper.ts b/src/strategyHelpers/blueGreen/smiBlueGreenHelper.ts index a6af0c810..144f6eeab 100644 --- a/src/strategyHelpers/blueGreen/smiBlueGreenHelper.ts +++ b/src/strategyHelpers/blueGreen/smiBlueGreenHelper.ts @@ -142,7 +142,8 @@ export async function validateTrafficSplitsState( let trafficSplitObject = await fetchResource( kubectl, TRAFFIC_SPLIT_OBJECT, - getBlueGreenResourceName(name, TRAFFIC_SPLIT_OBJECT_NAME_SUFFIX) + getBlueGreenResourceName(name, TRAFFIC_SPLIT_OBJECT_NAME_SUFFIX), + serviceObject?.metadata?.namespace ) core.debug( `ts object extracted was ${JSON.stringify(trafficSplitObject)}` @@ -183,7 +184,8 @@ export async function cleanupSMI( serviceObject.metadata.name, GREEN_SUFFIX ), - kind: serviceObject.kind + kind: serviceObject.kind, + namespace: serviceObject?.metadata?.namespace }) }) diff --git a/src/strategyHelpers/canary/canaryHelper.ts b/src/strategyHelpers/canary/canaryHelper.ts index 413578d62..194d5a4ae 100644 --- a/src/strategyHelpers/canary/canaryHelper.ts +++ b/src/strategyHelpers/canary/canaryHelper.ts @@ -195,9 +195,13 @@ async function cleanUpCanary( files: string[], includeServices: boolean ): Promise { - const deleteObject = async function (kind, name) { + const deleteObject = async function ( + kind: string, + name: string, + namespace: string | undefined + ) { try { - const result = await kubectl.delete([kind, name]) + const result = await kubectl.delete([kind, name], namespace) checkForErrors([result]) } catch (ex) { // Ignore failures of delete if it doesn't exist @@ -213,6 +217,7 @@ async function cleanUpCanary( for (const inputObject of parsedYaml) { const name = inputObject.metadata.name const kind = inputObject.kind + const namespace: string | undefined = inputObject?.metadata?.namespace if ( isDeploymentEntity(kind) || @@ -222,8 +227,8 @@ async function cleanUpCanary( const canaryObjectName = getCanaryResourceName(name) const baselineObjectName = getBaselineResourceName(name) - await deleteObject(kind, canaryObjectName) - await deleteObject(kind, baselineObjectName) + await deleteObject(kind, canaryObjectName, namespace) + await deleteObject(kind, baselineObjectName, namespace) } } } diff --git a/src/strategyHelpers/deploymentHelper.ts b/src/strategyHelpers/deploymentHelper.ts index 30336e5fb..76e276912 100644 --- a/src/strategyHelpers/deploymentHelper.ts +++ b/src/strategyHelpers/deploymentHelper.ts @@ -218,7 +218,12 @@ async function annotateResources( ) if (annotateNamespace) { annotateResults.push( - await kubectl.annotate('namespace', namespace, annotationKeyValStr) + await kubectl.annotate( + 'namespace', + namespace, + annotationKeyValStr, + namespace + ) ) } for (const file of files) { @@ -243,6 +248,7 @@ async function annotateResources( kubectl, resource.type, resource.name, + resource.namespace, annotationKeyValStr, allPods ) diff --git a/src/types/k8sObject.ts b/src/types/k8sObject.ts index db0c2f755..c23ff1202 100644 --- a/src/types/k8sObject.ts +++ b/src/types/k8sObject.ts @@ -2,6 +2,7 @@ export interface K8sObject { metadata: { name: string labels: Map + namespace?: string } kind: string spec: any @@ -16,6 +17,7 @@ export interface K8sServiceObject extends K8sObject { export interface K8sDeleteObject { name: string kind: string + namespace?: string } export interface K8sIngress extends K8sObject { diff --git a/src/types/kubectl.test.ts b/src/types/kubectl.test.ts index 489a7bed3..352a36cbf 100644 --- a/src/types/kubectl.test.ts +++ b/src/types/kubectl.test.ts @@ -3,7 +3,6 @@ import * as exec from '@actions/exec' import * as io from '@actions/io' import * as core from '@actions/core' import * as toolCache from '@actions/tool-cache' -import {config} from 'process' describe('Kubectl path', () => { const version = '1.1' @@ -38,6 +37,7 @@ describe('Kubectl path', () => { const kubectlPath = 'kubectlPath' const testNamespace = 'testNamespace' const defaultNamespace = 'default' +const otherNamespace = 'otherns' describe('Kubectl class', () => { describe('default namespace behavior', () => { const kubectl = new Kubectl(kubectlPath, defaultNamespace) @@ -122,6 +122,26 @@ describe('Kubectl class', () => { ], {silent: false} ) + + // overrided ns + const silent = false + await kubectl.describe( + resourceType, + resourceName, + silent, + otherNamespace + ) + expect(exec.getExecOutput).toBeCalledWith( + kubectlPath, + [ + 'describe', + resourceType, + resourceName, + '--namespace', + otherNamespace + ], + {silent} + ) }) it('describes a resource silently', async () => { @@ -140,6 +160,26 @@ describe('Kubectl class', () => { ], {silent: true} ) + + // overrided ns + const silent = false + await kubectl.describe( + resourceType, + resourceName, + silent, + otherNamespace + ) + expect(exec.getExecOutput).toBeCalledWith( + kubectlPath, + [ + 'describe', + resourceType, + resourceName, + '--namespace', + otherNamespace + ], + {silent} + ) }) it('annotates resource', async () => { @@ -165,6 +205,27 @@ describe('Kubectl class', () => { ], {silent: false} ) + + // override ns + await kubectl.annotate( + resourceType, + resourceName, + annotation, + otherNamespace + ) + expect(exec.getExecOutput).toBeCalledWith( + kubectlPath, + [ + 'annotate', + resourceType, + resourceName, + annotation, + '--overwrite', + '--namespace', + otherNamespace + ], + {silent: false} + ) }) it('annotates files with single file', async () => { @@ -185,6 +246,22 @@ describe('Kubectl class', () => { ], {silent: false} ) + + // override ns + await kubectl.annotateFiles(file, annotation, otherNamespace) + expect(exec.getExecOutput).toBeCalledWith( + kubectlPath, + [ + 'annotate', + '-f', + file, + annotation, + '--overwrite', + '--namespace', + otherNamespace + ], + {silent: false} + ) }) it('annotates files with mulitple files', async () => { @@ -205,6 +282,22 @@ describe('Kubectl class', () => { ], {silent: false} ) + + // override ns + await kubectl.annotateFiles(files, annotation, otherNamespace) + expect(exec.getExecOutput).toBeCalledWith( + kubectlPath, + [ + 'annotate', + '-f', + files.join(','), + annotation, + '--overwrite', + '--namespace', + otherNamespace + ], + {silent: false} + ) }) it('labels files with single file', async () => { @@ -225,6 +318,21 @@ describe('Kubectl class', () => { ], {silent: false} ) + + await kubectl.labelFiles(file, labels, otherNamespace) + expect(exec.getExecOutput).toBeCalledWith( + kubectlPath, + [ + 'label', + '-f', + file, + ...labels, + '--overwrite', + '--namespace', + otherNamespace + ], + {silent: false} + ) }) it('labels files with multiple files', async () => { @@ -245,6 +353,21 @@ describe('Kubectl class', () => { ], {silent: false} ) + + await kubectl.labelFiles(files, labels, otherNamespace) + expect(exec.getExecOutput).toBeCalledWith( + kubectlPath, + [ + 'label', + '-f', + files.join(','), + ...labels, + '--overwrite', + '--namespace', + otherNamespace + ], + {silent: false} + ) }) it('gets all pods', async () => { @@ -273,6 +396,20 @@ describe('Kubectl class', () => { ], {silent: false} ) + + // override ns + await kubectl.checkRolloutStatus(resourceType, name, otherNamespace) + expect(exec.getExecOutput).toBeCalledWith( + kubectlPath, + [ + 'rollout', + 'status', + `${resourceType}/${name}`, + '--namespace', + otherNamespace + ], + {silent: false} + ) }) it('gets resource', async () => { @@ -291,6 +428,22 @@ describe('Kubectl class', () => { ], {silent: false} ) + + // override ns + const silent = true + await kubectl.getResource(resourceType, name, silent, otherNamespace) + expect(exec.getExecOutput).toBeCalledWith( + kubectlPath, + [ + 'get', + `${resourceType}/${name}`, + '-o', + 'json', + '--namespace', + otherNamespace + ], + {silent} + ) }) it('executes a command', async () => { @@ -321,6 +474,14 @@ describe('Kubectl class', () => { ['delete', arg, '--namespace', testNamespace], {silent: false} ) + + // override ns + await kubectl.delete(arg, otherNamespace) + expect(exec.getExecOutput).toBeCalledWith( + kubectlPath, + ['delete', arg, '--namespace', otherNamespace], + {silent: false} + ) }) it('deletes with multiple arguments', async () => { @@ -331,6 +492,14 @@ describe('Kubectl class', () => { ['delete', ...args, '--namespace', testNamespace], {silent: false} ) + + // override ns + await kubectl.delete(args, otherNamespace) + expect(exec.getExecOutput).toBeCalledWith( + kubectlPath, + ['delete', ...args, '--namespace', otherNamespace], + {silent: false} + ) }) }) @@ -369,5 +538,11 @@ describe('Kubectl class', () => { [command, '--insecure-skip-tls-verify', '--namespace', testNamespace], {silent: false} ) + + const kubectlNoFlags = new Kubectl(kubectlPath) + kubectlNoFlags.executeCommand(command) + expect(exec.getExecOutput).toBeCalledWith(kubectlPath, [command], { + silent: false + }) }) }) diff --git a/src/types/kubectl.ts b/src/types/kubectl.ts index 61e0d8d6a..c096c77e1 100644 --- a/src/types/kubectl.ts +++ b/src/types/kubectl.ts @@ -3,11 +3,11 @@ import {createInlineArray} from '../utilities/arrayUtils' import * as core from '@actions/core' import * as toolCache from '@actions/tool-cache' import * as io from '@actions/io' -import {exec} from 'child_process' export interface Resource { name: string type: string + namespace?: string } export class Kubectl { @@ -20,7 +20,7 @@ export class Kubectl { constructor( kubectlPath: string, - namespace: string = 'default', + namespace: string = '', ignoreSSLErrors: boolean = false, resourceGroup: string = '', name: string = '' @@ -47,7 +47,7 @@ export class Kubectl { ] if (force) applyArgs.push('--force') - return await this.execute(applyArgs) + return await this.execute(applyArgs.concat(this.getFlags())) } catch (err) { core.debug('Kubectl apply failed:' + err) } @@ -56,16 +56,24 @@ export class Kubectl { public async describe( resourceType: string, resourceName: string, - silent: boolean = false + silent: boolean = false, + namespace?: string ): Promise { return await this.execute( - ['describe', resourceType, resourceName], + ['describe', resourceType, resourceName].concat( + this.getFlags(namespace) + ), silent ) } - public async getNewReplicaSet(deployment: string) { - const result = await this.describe('deployment', deployment, true) + public async getNewReplicaSet(deployment: string, namespace?: string) { + const result = await this.describe( + 'deployment', + deployment, + true, + namespace + ) let newReplicaSet = '' if (result?.stdout) { @@ -94,7 +102,8 @@ export class Kubectl { public async annotate( resourceType: string, resourceName: string, - annotation: string + annotation: string, + namespace?: string ): Promise { const args = [ 'annotate', @@ -102,13 +111,14 @@ export class Kubectl { resourceName, annotation, '--overwrite' - ] + ].concat(this.getFlags(namespace)) return await this.execute(args) } public async annotateFiles( files: string | string[], - annotation: string + annotation: string, + namespace?: string ): Promise { const filesToAnnotate = createInlineArray(files) core.debug(`annotating ${filesToAnnotate} with annotation ${annotation}`) @@ -118,16 +128,14 @@ export class Kubectl { filesToAnnotate, annotation, '--overwrite' - ] - core.debug( - `sending args from annotate to execute: ${JSON.stringify(args)}` - ) + ].concat(this.getFlags(namespace)) return await this.execute(args) } public async labelFiles( files: string | string[], - labels: string[] + labels: string[], + namespace?: string ): Promise { const args = [ 'label', @@ -135,51 +143,59 @@ export class Kubectl { createInlineArray(files), ...labels, '--overwrite' - ] + ].concat(this.getFlags(namespace)) return await this.execute(args) } public async getAllPods(): Promise { - return await this.execute(['get', 'pods', '-o', 'json'], true) + return await this.execute( + ['get', 'pods', '-o', 'json'].concat(this.getFlags()), + true + ) } public async checkRolloutStatus( resourceType: string, - name: string + name: string, + namespace?: string ): Promise { - return await this.execute([ - 'rollout', - 'status', - `${resourceType}/${name}` - ]) + return await this.execute( + ['rollout', 'status', `${resourceType}/${name}`].concat( + this.getFlags(namespace) + ) + ) } public async getResource( resourceType: string, name: string, - silentFailure: boolean = false + silentFailure: boolean = false, + namespace?: string ): Promise { core.debug( 'fetching resource of type ' + resourceType + ' and name ' + name ) return await this.execute( - ['get', `${resourceType}/${name}`, '-o', 'json'], + ['get', `${resourceType}/${name}`, '-o', 'json'].concat( + this.getFlags(namespace) + ), silentFailure ) } public executeCommand(command: string, args?: string) { if (!command) throw new Error('Command must be defined') - return args ? this.execute([command, args]) : this.execute([command]) + const a = args ? [args] : [] + return this.execute([command, ...a.concat(this.getFlags())]) } - public delete(args: string | string[]) { - if (typeof args === 'string') return this.execute(['delete', args]) - return this.execute(['delete', ...args]) + public delete(args: string | string[], namespace?: string) { + if (typeof args === 'string') + return this.execute(['delete', args].concat(this.getFlags(namespace))) + return this.execute(['delete', ...args.concat(this.getFlags(namespace))]) } protected async execute(args: string[], silent: boolean = false) { - args = args.concat(this.getExecuteFlags()) core.debug(`Kubectl run with command: ${this.kubectlPath} ${args}`) return await getExecOutput(this.kubectlPath, args, { @@ -187,13 +203,15 @@ export class Kubectl { }) } - protected getExecuteFlags(): string[] { + protected getFlags(namespaceOverride?: string): string[] { const flags = [] if (this.ignoreSSLErrors) { flags.push('--insecure-skip-tls-verify') } - if (this.namespace) { - flags.push('--namespace', this.namespace) + + const ns = namespaceOverride || this.namespace + if (ns) { + flags.push('--namespace', ns) } return flags diff --git a/src/types/privatekubectl.ts b/src/types/privatekubectl.ts index d975103c0..19c80bb82 100644 --- a/src/types/privatekubectl.ts +++ b/src/types/privatekubectl.ts @@ -8,8 +8,6 @@ import * as path from 'path' export class PrivateKubectl extends Kubectl { protected async execute(args: string[], silent: boolean = false) { - args = args.concat(this.getExecuteFlags()) - args.unshift('kubectl') let kubectlCmd = args.join(' ') let addFileFlag = false diff --git a/src/utilities/kubectlUtils.ts b/src/utilities/kubectlUtils.ts index 38d9953bf..05d9f9cce 100644 --- a/src/utilities/kubectlUtils.ts +++ b/src/utilities/kubectlUtils.ts @@ -2,6 +2,8 @@ import * as core from '@actions/core' import {ExecOutput} from '@actions/exec' import {Kubectl} from '../types/kubectl' +const NAMESPACE = 'namespace' + export function checkForErrors( execResults: ExecOutput[], warnIfError?: boolean @@ -30,7 +32,12 @@ export async function getLastSuccessfulRunSha( annotationKey: string ): Promise { try { - const result = await kubectl.getResource('namespace', namespaceName) + const result = await kubectl.getResource( + NAMESPACE, + namespaceName, + false, + namespaceName + ) if (result?.stderr) { core.warning(result.stderr) return process.env.GITHUB_SHA @@ -53,12 +60,13 @@ export async function annotateChildPods( kubectl: Kubectl, resourceType: string, resourceName: string, + namespace: string | undefined, annotationKeyValStr: string, allPods ): Promise { let owner = resourceName if (resourceType.toLowerCase().indexOf('deployment') > -1) { - owner = await kubectl.getNewReplicaSet(resourceName) + owner = await kubectl.getNewReplicaSet(resourceName, namespace) } const commandExecutionResults = [] @@ -72,7 +80,8 @@ export async function annotateChildPods( kubectl.annotate( 'pod', pod.metadata.name, - annotationKeyValStr + annotationKeyValStr, + namespace ) ) break diff --git a/src/utilities/manifestStabilityUtils.ts b/src/utilities/manifestStabilityUtils.ts index 881cfe2f2..cd4b1390b 100644 --- a/src/utilities/manifestStabilityUtils.ts +++ b/src/utilities/manifestStabilityUtils.ts @@ -4,6 +4,9 @@ import {Kubectl, Resource} from '../types/kubectl' import {checkForErrors} from './kubectlUtils' import {sleep} from './timeUtils' +const IS_SILENT = false +const POD = 'pod' + export async function checkManifestStability( kubectl: Kubectl, resources: Resource[] @@ -20,24 +23,35 @@ export async function checkManifestStability( try { const result = await kubectl.checkRolloutStatus( resource.type, - resource.name + resource.name, + resource.namespace ) checkForErrors([result]) } catch (ex) { core.error(ex) - await kubectl.describe(resource.type, resource.name) + await kubectl.describe( + resource.type, + resource.name, + IS_SILENT, + resource.namespace + ) rolloutStatusHasErrors = true } } if (resource.type == KubernetesConstants.KubernetesWorkload.POD) { try { - await checkPodStatus(kubectl, resource.name) + await checkPodStatus(kubectl, resource) } catch (ex) { core.warning( `Could not determine pod status: ${JSON.stringify(ex)}` ) - await kubectl.describe(resource.type, resource.name) + await kubectl.describe( + resource.type, + resource.name, + IS_SILENT, + resource.namespace + ) } } if ( @@ -45,14 +59,11 @@ export async function checkManifestStability( KubernetesConstants.DiscoveryAndLoadBalancerResource.SERVICE ) { try { - const service = await getService(kubectl, resource.name) + const service = await getService(kubectl, resource) const {spec, status} = service if (spec.type === KubernetesConstants.ServiceTypes.LOAD_BALANCER) { if (!isLoadBalancerIPAssigned(status)) { - await waitForServiceExternalIPAssignment( - kubectl, - resource.name - ) + await waitForServiceExternalIPAssignment(kubectl, resource) } else { core.info( `ServiceExternalIP ${resource.name} ${status.loadBalancer.ingress[0].ip}` @@ -63,7 +74,12 @@ export async function checkManifestStability( core.warning( `Could not determine service status of: ${resource.name} Error: ${ex}` ) - await kubectl.describe(resource.type, resource.name) + await kubectl.describe( + resource.type, + resource.name, + IS_SILENT, + resource.namespace + ) } } } @@ -75,7 +91,7 @@ export async function checkManifestStability( export async function checkPodStatus( kubectl: Kubectl, - podName: string + pod: Resource ): Promise { const sleepTimeout = 10 * 1000 // 10 seconds const iterations = 60 // 60 * 10 seconds timeout = 10 minutes max timeout @@ -85,8 +101,8 @@ export async function checkPodStatus( for (let i = 0; i < iterations; i++) { await sleep(sleepTimeout) - core.debug(`Polling for pod status: ${podName}`) - podStatus = await getPodStatus(kubectl, podName) + core.debug(`Polling for pod status: ${pod.name}`) + podStatus = await getPodStatus(kubectl, pod) if ( podStatus && @@ -97,37 +113,42 @@ export async function checkPodStatus( } } - podStatus = await getPodStatus(kubectl, podName) + podStatus = await getPodStatus(kubectl, pod) switch (podStatus.phase) { case 'Succeeded': case 'Running': if (isPodReady(podStatus)) { - console.log(`pod/${podName} is successfully rolled out`) + console.log(`pod/${pod.name} is successfully rolled out`) } else { kubectlDescribeNeeded = true } break case 'Pending': if (!isPodReady(podStatus)) { - core.warning(`pod/${podName} rollout status check timed out`) + core.warning(`pod/${pod.name} rollout status check timed out`) kubectlDescribeNeeded = true } break case 'Failed': - core.error(`pod/${podName} rollout failed`) + core.error(`pod/${pod.name} rollout failed`) kubectlDescribeNeeded = true break default: - core.warning(`pod/${podName} rollout status: ${podStatus.phase}`) + core.warning(`pod/${pod.name} rollout status: ${podStatus.phase}`) } if (kubectlDescribeNeeded) { - await kubectl.describe('pod', podName) + await kubectl.describe(POD, pod.name, IS_SILENT, pod.namespace) } } -async function getPodStatus(kubectl: Kubectl, podName: string) { - const podResult = await kubectl.getResource('pod', podName) +async function getPodStatus(kubectl: Kubectl, pod: Resource) { + const podResult = await kubectl.getResource( + POD, + pod.name, + IS_SILENT, + pod.namespace + ) checkForErrors([podResult]) return JSON.parse(podResult.stdout).status @@ -151,10 +172,12 @@ function isPodReady(podStatus: any): boolean { return allContainersAreReady } -async function getService(kubectl: Kubectl, serviceName) { +async function getService(kubectl: Kubectl, service: Resource) { const serviceResult = await kubectl.getResource( KubernetesConstants.DiscoveryAndLoadBalancerResource.SERVICE, - serviceName + service.name, + IS_SILENT, + service.namespace ) checkForErrors([serviceResult]) @@ -163,25 +186,25 @@ async function getService(kubectl: Kubectl, serviceName) { async function waitForServiceExternalIPAssignment( kubectl: Kubectl, - serviceName: string + service: Resource ): Promise { const sleepTimeout = 10 * 1000 // 10 seconds const iterations = 18 // 18 * 10 seconds timeout = 3 minutes max timeout for (let i = 0; i < iterations; i++) { - core.info(`Wait for service ip assignment : ${serviceName}`) + core.info(`Wait for service ip assignment : ${service.name}`) await sleep(sleepTimeout) - const status = (await getService(kubectl, serviceName)).status + const status = (await getService(kubectl, service)).status if (isLoadBalancerIPAssigned(status)) { core.info( - `ServiceExternalIP ${serviceName} ${status.loadBalancer.ingress[0].ip}` + `ServiceExternalIP ${service.name} ${status.loadBalancer.ingress[0].ip}` ) return } } - core.warning(`Wait for service ip assignment timed out${serviceName}`) + core.warning(`Wait for service ip assignment timed out ${service.name}`) } function isLoadBalancerIPAssigned(status: any) { diff --git a/src/utilities/manifestUpdateUtils.ts b/src/utilities/manifestUpdateUtils.ts index 77f7814b1..468f2ba64 100644 --- a/src/utilities/manifestUpdateUtils.ts +++ b/src/utilities/manifestUpdateUtils.ts @@ -280,7 +280,8 @@ export function getResources( ) { resources.push({ type: inputObject.kind, - name: inputObject.metadata.name + name: inputObject.metadata.name, + namespace: inputObject?.metadata?.namespace }) } })