Skip to content

Commit 773a287

Browse files
ci: [sync] Push chectl @ main to devspaces-chectl @ devspaces-3-rhel-8
Signed-off-by: devstudio-release <[email protected]>
1 parent 4170196 commit 773a287

File tree

93 files changed

+6125
-7096
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+6125
-7096
lines changed

package.json

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "dsc",
3-
"version": "3.4.0-CI-e62e-redhat",
3+
"version": "3.4.0-CI-redhat",
44
"description": "Red Hat OpenShift Dev Spaces CLI",
55
"keywords": [
66
"oclif"
@@ -24,8 +24,8 @@
2424
"/prepare-templates.js"
2525
],
2626
"scripts": {
27-
"e2e-minikube-operator": "export PLATFORM=minikube && export INSTALLER=operator && yarn jest ./test/e2e/e2e.test.ts --testRegex='/test/(e2e)/.*.test.ts'",
28-
"e2e-openshift": "export PLATFORM=openshift && export INSTALLER=operator && yarn jest ./test/e2e/e2e.test.ts --testRegex='/test/(e2e)/.*.test.ts'",
27+
"e2e-minikube": "export PLATFORM=minikube && yarn jest ./test/e2e/e2e.test.ts --testRegex='/test/(e2e)/.*.test.ts'",
28+
"e2e-openshift": "export PLATFORM=openshift && yarn jest ./test/e2e/e2e.test.ts --testRegex='/test/(e2e)/.*.test.ts'",
2929
"format": "tsfmt -r --useTsfmt tsfmt.json",
3030
"gnirts-ci": "node .ci/obfuscate/gnirts.js",
3131
"postinstall": "npm run -s postinstall-repositories && npm run -s postinstall-operator && npm run -s postinstall-cleanup",

resources/dex/certificate.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ spec:
3131
secretName: dex.tls
3232
subject:
3333
organizations:
34-
- Local Red Hat OpenShift Dev Spaces
34+
- Local Eclipse Che
3535
usages:
3636
- server auth
3737
- digital signature

resources/dex/configmap.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ data:
2222
- id: {{CLIENT_ID}}
2323
redirectURIs:
2424
- 'https://{{DOMAIN}}/oauth/callback'
25-
name: 'Red Hat OpenShift Dev Spaces'
25+
name: 'Eclipse Che'
2626
secret: {{CLIENT_SECRET}}
2727
enablePasswordDB: true
2828
staticPasswords:

src/api/che-api-client.ts

-139
This file was deleted.

src/api/che-logs-reader.ts

+157
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/**
2+
* Copyright (c) 2019-2021 Red Hat, Inc.
3+
* This program and the accompanying materials are made
4+
* available under the terms of the Eclipse Public License 2.0
5+
* which is available at https://www.eclipse.org/legal/epl-2.0/
6+
*
7+
* SPDX-License-Identifier: EPL-2.0
8+
*
9+
* Contributors:
10+
* Red Hat, Inc. - initial API and implementation
11+
*/
12+
13+
import { V1Pod, Watch } from '@kubernetes/client-node'
14+
import * as cp from 'child_process'
15+
import * as commandExists from 'command-exists'
16+
import * as fs from 'fs-extra'
17+
import * as path from 'path'
18+
import { KubeClient } from './kube-client'
19+
20+
export class CheLogsReader {
21+
private kubeHelper: KubeClient
22+
23+
constructor() {
24+
this.kubeHelper = KubeClient.getInstance()
25+
}
26+
27+
/**
28+
* Reads logs from pods that match a given selector.
29+
*/
30+
async readPodLog(namespace: string, podLabelSelector: string | undefined, directory: string, follow: boolean): Promise<void> {
31+
if (follow) {
32+
await this.watchNamespacedPods(namespace, podLabelSelector, directory)
33+
} else {
34+
await this.readNamespacedPodLog(namespace, podLabelSelector, directory)
35+
}
36+
}
37+
38+
/**
39+
* Reads containers logs inside pod that match a given selector.
40+
*/
41+
private async readNamespacedPodLog(namespace: string, podLabelSelector: string | undefined, directory: string): Promise<void> {
42+
const pods = await this.kubeHelper.listNamespacedPod(namespace, undefined, podLabelSelector)
43+
44+
for (const pod of pods.items) {
45+
if (!pod.status || !pod.status.containerStatuses) {
46+
return
47+
}
48+
49+
const podName = pod.metadata!.name!
50+
for (const containerName of this.getContainers(pod)) {
51+
const fileName = this.doCreateLogFile(namespace, podName, containerName, directory)
52+
await this.doReadNamespacedPodLog(namespace, podName, containerName, fileName, false)
53+
}
54+
}
55+
}
56+
57+
/**
58+
* Reads all namespace events and store into a file.
59+
*/
60+
async readNamespaceEvents(namespace: string, directory: string, follow: boolean): Promise<void> {
61+
const fileName = path.resolve(directory, namespace, 'events.txt')
62+
fs.ensureFileSync(fileName)
63+
64+
const cli = (commandExists.sync('kubectl') && 'kubectl') || (commandExists.sync('oc') && 'oc')
65+
if (cli) {
66+
const command = 'get events'
67+
const namespaceParam = `-n ${namespace}`
68+
const watchParam = follow && '--watch' || ''
69+
70+
cp.exec(`${cli} ${command} ${namespaceParam} ${watchParam} >> ${fileName}`)
71+
} else {
72+
throw new Error('No events are collected. \'kubectl\' or \'oc\' is required to perform the task.')
73+
}
74+
}
75+
76+
private async watchNamespacedPods(namespace: string, podLabelSelector: string | undefined, directory: string): Promise<void> {
77+
const processedContainers = new Map<string, Set<string>>()
78+
79+
const watcher = new Watch(this.kubeHelper.getKubeConfig())
80+
return watcher.watch(`/api/v1/namespaces/${namespace}/pods`, {},
81+
async (_phase: string, obj: any) => {
82+
const pod = obj as V1Pod
83+
if (!pod || !pod.metadata || !pod.metadata.name) {
84+
return
85+
}
86+
const podName = pod.metadata.name!
87+
88+
if (!processedContainers.has(podName)) {
89+
processedContainers.set(podName, new Set<string>())
90+
}
91+
92+
if (!podLabelSelector || this.matchLabels(pod.metadata!.labels || {}, podLabelSelector)) {
93+
for (const containerName of this.getContainers(pod)) {
94+
// not to read logs from the same containers twice
95+
if (!processedContainers.get(podName)!.has(containerName)) {
96+
processedContainers.get(podName)!.add(containerName)
97+
98+
const fileName = this.doCreateLogFile(namespace, podName, containerName, directory)
99+
await this.doReadNamespacedPodLog(namespace, pod.metadata!.name!, containerName, fileName, true)
100+
}
101+
}
102+
}
103+
},
104+
// ignore errors
105+
() => { })
106+
}
107+
108+
/**
109+
* Indicates if pod matches given labels.
110+
*/
111+
private matchLabels(podLabels: { [key: string]: string }, podLabelSelector: string): boolean {
112+
const labels = podLabelSelector.split(',')
113+
for (const label of labels) {
114+
if (label) {
115+
const keyValue = label.split('=')
116+
if (podLabels[keyValue[0]] !== keyValue[1]) {
117+
return false
118+
}
119+
}
120+
}
121+
122+
return true
123+
}
124+
125+
/**
126+
* Returns containers names.
127+
*/
128+
private getContainers(pod: V1Pod): string[] {
129+
if (!pod.status || !pod.status.containerStatuses) {
130+
return []
131+
}
132+
return pod.status.containerStatuses.map(containerStatus => containerStatus.name)
133+
}
134+
135+
/**
136+
* Reads pod log from a specific container of the pod.
137+
*/
138+
private async doReadNamespacedPodLog(namespace: string, podName: string, containerName: string, fileName: string, follow: boolean): Promise<void> {
139+
if (follow) {
140+
try {
141+
await this.kubeHelper.readNamespacedPodLog(podName, namespace, containerName, fileName, follow)
142+
} catch {
143+
// retry in 200ms, container might not be started
144+
setTimeout(async () => this.doReadNamespacedPodLog(namespace, podName, containerName, fileName, follow), 200)
145+
}
146+
} else {
147+
await this.kubeHelper.readNamespacedPodLog(podName, namespace, containerName, fileName, follow)
148+
}
149+
}
150+
151+
private doCreateLogFile(namespace: string, podName: string, containerName: string, directory: string): string {
152+
const fileName = path.resolve(directory, namespace, podName, `${containerName}.log`)
153+
fs.ensureFileSync(fileName)
154+
155+
return fileName
156+
}
157+
}

0 commit comments

Comments
 (0)