From 7e7dbedd11f5f720b94de500659e879db10c88c4 Mon Sep 17 00:00:00 2001 From: Victor Rubezhny Date: Wed, 22 May 2024 02:38:17 +0200 Subject: [PATCH] Display status information for Deployments in Application Explorer tree #3823 Fixes: #3823 Signed-off-by: Victor Rubezhny --- images/context/component-node-green.png | Bin 0 -> 12792 bytes images/context/component-node-red.png | Bin 0 -> 13320 bytes images/context/component-node-yellow.png | Bin 0 -> 12777 bytes src/explorer.ts | 148 +++++++++++++++++++++-- 4 files changed, 139 insertions(+), 9 deletions(-) create mode 100644 images/context/component-node-green.png create mode 100644 images/context/component-node-red.png create mode 100644 images/context/component-node-yellow.png diff --git a/images/context/component-node-green.png b/images/context/component-node-green.png new file mode 100644 index 0000000000000000000000000000000000000000..f8b7b0177e291fc6bd896f8ab46c6083d789aa29 GIT binary patch literal 12792 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 literal 0 HcmV?d00001 diff --git a/images/context/component-node-red.png b/images/context/component-node-red.png new file mode 100644 index 0000000000000000000000000000000000000000..8c10f69297f74e722286fc8663be6e07a400c582 GIT binary patch literal 13320 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
EUdA_9IH!<8!G~UooX8`EXgGwfVYg*dLg6 z`h1BxnwY8jF1hI0A$xcK?A~mu#;no1 zl@spCLR>HG^jbnn4sF#S$pZSEt4ozUQ6j6XtBko89#^S}!s>sVPw)~AV9*1VI}R$? zW5oF`zOJ{K@AJy8UcF)(IQ~d9pu_&SIhQey&O8;f*+g~WP?o2;-miviRWsK`L9H5= z-t{cdw$$p@dFo$58%U?#`Fw?40?q3Dpo>V$x~)B(+T!Q)42pZ)T}Vjk%lM!!SqRzm zEGNW*boEfL^;n1vMYRFD-7))O?ds_JG@j;8Hw#X6z+8N><`r@M3v^h{s86j@kE^ z)KehV@JZ%$6OyLfzQO_%{n+|;%%%(xV5+oK2c;psnhL%Gr^1X-4)zaDGx1~mU zTg8m&2>o}6GDpUQ5USs~54c)4V%)}Losex%&z^ZCottGbtkLOuHa&G@eny=FkU4Z&fG4p9i>Py%eTuO#o4c<=>pG`0~rN5yO#S?xm@G=6xUV?buHq<&~yF6%*S@ zRV^(EnwISN=-}%hB_Zk;On_;U5KOq9p5OD5;v#2~-I_?#7W;iUiuQRCG{xR;=@qY> z;f3RDr#AFW3r-OM9v_*nT@mPdYkGFokX(BLL}PomTE_6YSofrzP0#Fcj=}kco~h}d zbRx;hhx4AQjgBIc(ptF)r?g|f#?qAsN@qa|LewqCfq6}6m5$}OhliS*pCqLR(c?Dp z5X|Aydnk;H?Ls|zxuIl6LLM~t?DdmG(DW6(;r!m5uR+3TiRxd*9 z)I>KNyH(8tiYw8&N26hoR?srFS&&e`YxwxaeE#CWf;v5AGHJr!Gx#Q9zcByS$BpRp z6q;YVjK&*lU_;`tUcq$!%w~e6qHW|IHAw3(2ul^|O9OtrF+j+&74)1$m; z*7!}2?!%IrmO`nPR~ey)ROU;bEqY>gj7d+T&#D58HTkX@L{)*67PW-9W!+Hn7=Jq{ z3Iu`>kKP5iEckM=DrzF(!u{4&NT#YP$j;m%;1qR>%;wPR7>SYvJjI$ic$3@6EpL4} z21>9O$vrdZ3;ve)K2hLo9MN9_(qTo4`X$*nnpvJ1_FX)EXn)h@W6>^0N59Hl>q@RG z<(aqdviV}nrh;gGYCjAShVQOlKc8((IY_D0uwfzM2Y_YIOlVJ6Nx#jJ+UfE;<}v5EBie9cK?yB0KUk#P3#}5i5_4wRsue zJ=dcHymAo3!u@E&dzCg_dAGG(WwZJ5!x;VL^K}qK(0gijhhqONr1ze6fA7`Rm`*PAK=>6Vfhq0A#z;?0bamOC4b6J9;-m1`A(Rc3>DO&}?I{ zQ;GFO_B$4d&a8;!`pugC0=_xEej?&lQIuwOm?`nB6-FuA3?GFox{Kli^_15j_xy$O zmjQOvyCyH49*OEWw-n0Mj(nakJo0hIv1OtopYA@&uy2aa9X#TcM%?4uOIP$+5{La? e-y5;q3GGOch~M{n3ISeq0qJTPX_lxvg#RzT&p(d< literal 0 HcmV?d00001 diff --git a/images/context/component-node-yellow.png b/images/context/component-node-yellow.png new file mode 100644 index 0000000000000000000000000000000000000000..39d8a5852d652701bae4fe174f97cece0fd433d6 GIT binary patch literal 12777 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, Dispos collapsibleState: TreeItemCollapsibleState.Collapsed } } - const routeURL = await Oc.Instance.getRouteURL(element.metadata.name); - return { + return this.getDeploymentItem(element); + } + return { + label: 'Unknown element' + } + } + + private getDeploymentIconSuffix(pods: DeploymentPodObject[]): string { + // Find all not 'Running' pods + const notRunning = pods.filter((pod) => pod.status && pod.status.phase !== 'Running'); + if (notRunning.length === 0) { + return '-green'; // All running - return 'green' + } + // Find any 'Failed' or 'Unknown' pod - if any return error ('red') + const failed = notRunning.find((pod) => pod.status && + (pod.status.phase === 'Failed' || pod.status.phase === 'Unknown')); + if (failed) { + return '-red'; // At least one failed or unknown - return 'red' + } + // Find any 'Pending' pod - if any return pending ('yellow') + const pending = notRunning.find((pod) => pod.status && pod.status.phase === 'Pending'); + return pending ? '-yellow' : ''; + } + + /* + * Search for 'CrashLoopBackOff` in Pod's opbect: + * status: + * containerStatuses: + * state: + * waiting: + * message: | + * container create failed: time="2024-05-28T10:30:28Z" level=error msg="runc create failed: unable to start container process: exec: \"asdf\": executable file not found in $PATH" + * reason: CreateContainerError + */ + private detectCrashLoopBackOff(pods): DeploymentPodErrors { + let inCrashLoopBackOff = false; + const messages: string[] = []; + + // Search for Pod continers' errors + pods.forEach((pod) => { + pod.status?.containerStatuses && + pod.status.containerStatuses.forEach((cs) => { + if (cs.state?.waiting) { + const reason = cs.state.waiting.reason; + const message = cs.state.waiting.message; + + inCrashLoopBackOff = inCrashLoopBackOff || reason === 'CrashLoopBackOff'; + + const msg = `${reason}: ${message ? message.trim(): 'No valuable message'}`; + // Skip duplicates and show not more than 10 errors + if (messages.length <= 10 && !(messages.find((m) => m === msg))) { + messages.push(msg); + } + } + }); + }); + + return { + inCrashLoopBackOff, + messages + } + } + + private collectDeploymentErrors(deployment): string[] { + const messages: string[] = []; + deployment.status.conditions.filter((c) => c.status === 'False') + .forEach((c) => { + const message = `${c.reason}: ${c.message ? c.message.trim(): 'No valuable message'}`; + + // Skip duplicates and show not more than 10 errors + if (messages.length <= 10 && !(messages.find((m) => m === message))) { + messages.push(message); + } + }); + + return messages; + } + + private async getDeploymentItem(element): Promise { + const shouldHaveReplicas = element.spec.replicas > 0; + const desiredReplicas = element.spec.replicas ? element.spec.replicas : 0; + const actualReplicas = element.status.replicas ? element.status.replicas : 0; + const readyReplicas = element.status.readyReplicas ? element.status.readyReplicas : 0; + const availableReplicas = element.status.availableReplicas ? element.status.availableReplicas : 0; + const unavailableReplicas = element.status.unavailableReplicas ? element.status.unavailableReplicas : 0; + + let pods: DeploymentPodObject[] = []; + if (shouldHaveReplicas) { + try { + pods = await this.getPods(element); + } catch { + // ignore + } + } + + // Look into Pod containers' states for any 'CrashLoopBackOff` status + const podErrors = this.detectCrashLoopBackOff(pods); + let podsMessages = ''; + podErrors.messages.forEach((m) => podsMessages = podsMessages.concat(`\n\t${m}`)); + + // We get Deployment's 'CrashLoopBackOff` status and error messages + const deploymentErrors = this.collectDeploymentErrors(element); + + let errorMessages = ''; + deploymentErrors.forEach((m) => errorMessages = errorMessages.concat(`\n\t${m}`)); + + // const inCrashLoopBackOff = element.status.conditions.find((condition) => condition.status === 'False' && condition.reason === 'CrashLoopBackOff'); + let description = `${this.makeCaps(element.kind)}`; + let tooltip = description; + if (element.kind === 'Deployment') { + description = `${description} (${availableReplicas}/${desiredReplicas})` + tooltip = `${tooltip}: ${element.metadata.name}\n`.concat( + `Desired Replicas: ${desiredReplicas}\n`, + `Actual Replicas: ${actualReplicas}\n`, + 'Of which:\n', + `\tReady Replicas: ${readyReplicas}\n`, + `\tAvailable Replicas: ${availableReplicas}\n`, + `\tUnavailable Replicas: ${unavailableReplicas}\n`, + `---\nCrashLoopBackOff detected: ${podErrors.inCrashLoopBackOff ? 'Yes' : 'No'}\n`, + podsMessages.length > 0 ? `---\nPod Container Failures:${podsMessages}\n` : '', + errorMessages.length > 0 ? `---\nDeployment Failures:${errorMessages}\n` : '' + ); + } + const iconSuffix = !shouldHaveReplicas ? '' : + podErrors.inCrashLoopBackOff ? '-red' : this.getDeploymentIconSuffix(pods); + const iconPath = element.kind === 'Deployment' || element.kind === 'DeploymentConfig' ? + path.resolve(__dirname, `../../images/context/component-node${iconSuffix}.png`) + : undefined; + + const routeURL = await Oc.Instance.getRouteURL(element.metadata.name); + return { contextValue: `openshift.k8sObject.${element.kind}${routeURL ? '.route' : ''}`, label: element.metadata.name, - description: `${element.kind.substring(0, 1).toLocaleUpperCase()}${element.kind.substring(1)}`, + description, + tooltip, collapsibleState: element.kind === 'Deployment' ? TreeItemCollapsibleState.Collapsed : TreeItemCollapsibleState.None, - iconPath: element.kind === 'Deployment' || element.kind === 'DeploymentConfig' ? path.resolve(__dirname, '../../images/context/component-node.png') : undefined, + iconPath, command: { title: 'Load', command: 'openshift.resource.load', arguments: [element] } }; - - } - return { - label: 'Unknown element' - } } private makeCaps(kind: string): string {