Skip to content

Commit 2f9a5d6

Browse files
committed
Add 'kubectl' binary to the distribution
Partially fixes redhat-developer#3987 by taking control over the 'kubectl' binary execution Issue: redhat-developer#3987 Signed-off-by: Victor Rubezhny <[email protected]>
1 parent 908da87 commit 2f9a5d6

File tree

8 files changed

+145
-91
lines changed

8 files changed

+145
-91
lines changed
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
name: check-oc-kubectl
2+
3+
on:
4+
schedule:
5+
- cron: "0 8 * * *"
6+
workflow_dispatch:
7+
jobs:
8+
check-oc-repo:
9+
runs-on: ubuntu-latest
10+
env:
11+
TOOL_REPO: openshift/oc
12+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
13+
steps:
14+
- name: Check Out Code
15+
uses: actions/checkout@v4
16+
- name: Get latest oc and kubectl package version
17+
run: |
18+
echo "REPO_TOOL_VERSION=$(cat src/tools.json | jq -r .oc.version)" >> $GITHUB_ENV
19+
LATEST_TOOL_URL='https://mirror.openshift.com/pub/openshift-v4/clients/ocp/stable/release.txt'
20+
echo "LATEST_TOOL_URL=$(echo ${LATEST_TOOL_URL})" >> $GITHUB_ENV
21+
echo "LATEST_TOOL_RELEASE=$(curl -s -L ${LATEST_TOOL_URL} | grep "Name:" | head -n 1 | sed 's|Name:||' | sed 's| ||g')" >> $GITHUB_ENV
22+
- name: Find existing PR for oc and kubectl package version
23+
run: |
24+
echo PR_EXISTS=$(gh pr --repo ${{ github.repository }} list --state all --search "update oc and kubectl cli to ${{env.LATEST_TOOL_RELEASE}} in:title" --json url | jq length) >> $GITHUB_ENV
25+
- name: Update src/tools.json with latest oc version
26+
if: ${{ (env.LATEST_TOOL_RELEASE != env.REPO_TOOL_VERSION) && (env.PR_EXISTS == 0) }}
27+
run: |
28+
jq --indent 4 '.oc.version = "${{ env.LATEST_TOOL_RELEASE }}"' src/tools.json | jq --indent 4 '.oc.versionRange = "^${{ env.LATEST_TOOL_RELEASE }}"' | jq --indent 4 '.oc.versionRangeLabel = "version >= ${{ env.LATEST_TOOL_RELEASE }} and < 5.0.0"' > src/tools.json.new
29+
mv src/tools.json.new src/tools.json
30+
for platform in win32 darwin darwin-arm64 linux linux-arm64; do
31+
old_url=`jq -r ".oc.platform[\"${platform}\"].url" src/tools.json`
32+
dlFileName=`jq -r ".oc.platform[\"${platform}\"].dlFileName" src/tools.json | sed "s|${{ env.REPO_TOOL_VERSION }}|${{ env.LATEST_TOOL_RELEASE }}|g"`
33+
new_url=`echo ${old_url} | sed "s|${{ env.REPO_TOOL_VERSION }}|${{ env.LATEST_TOOL_RELEASE }}|g"`
34+
checksum_url=`echo "${new_url}" | sed "s|${dlFileName}|sha256sum.txt|"`
35+
checksum=`curl -s -L ${checksum_url} | grep "${dlFileName}" | sed "s|${dlFileName}||" | sed "s| ||g"`
36+
jq --indent 4 ".oc.platform[\"${platform}\"].url = \"${new_url}\"" src/tools.json \
37+
| jq --indent 4 ".oc.platform[\"${platform}\"].sha256sum = \"${checksum}\"" \
38+
| jq --indent 4 ".oc.platform[\"${platform}\"].dlFileName = \"${dlFileName}\"" > src/tools.json.new
39+
mv src/tools.json.new src/tools.json
40+
done
41+
- name: Update src/tools.json with latest kubectl version
42+
if: ${{ (env.LATEST_TOOL_RELEASE != env.REPO_TOOL_VERSION) && (env.PR_EXISTS == 0) }}
43+
run: |
44+
jq --indent 4 '.kubectl.version = "${{ env.LATEST_TOOL_RELEASE }}"' src/tools.json | jq --indent 4 '.kubectl.versionRange = "*"' | jq --indent 4 '.kubectl.versionRangeLabel = "*"' > src/tools.json.new
45+
mv src/tools.json.new src/tools.json
46+
for platform in win32 darwin darwin-arm64 linux linux-arm64; do
47+
old_url=`jq -r ".kubectl.platform[\"${platform}\"].url" src/tools.json`
48+
dlFileName=`jq -r ".kubectl.platform[\"${platform}\"].dlFileName" src/tools.json | sed "s|${{ env.REPO_TOOL_VERSION }}|${{ env.LATEST_TOOL_RELEASE }}|g"`
49+
new_url=`echo ${old_url} | sed "s|${{ env.REPO_TOOL_VERSION }}|${{ env.LATEST_TOOL_RELEASE }}|g"`
50+
checksum_url=`echo "${new_url}" | sed "s|${dlFileName}|sha256sum.txt|"`
51+
checksum=`curl -s -L ${checksum_url} | grep "${dlFileName}" | sed "s|${dlFileName}||" | sed "s| ||g"`
52+
jq --indent 4 ".kubectl.platform[\"${platform}\"].url = \"${new_url}\"" src/tools.json \
53+
| jq --indent 4 ".kubectl.platform[\"${platform}\"].sha256sum = \"${checksum}\"" \
54+
| jq --indent 4 ".kubectl.platform[\"${platform}\"].dlFileName = \"${dlFileName}\"" > src/tools.json.new
55+
mv src/tools.json.new src/tools.json
56+
done
57+
- name: Create pull request
58+
if: ${{ (env.LATEST_TOOL_RELEASE != env.REPO_TOOL_VERSION) && (env.PR_EXISTS == 0) }}
59+
run: |
60+
release_url=`echo "${{ env.LATEST_TOOL_URL }}" | sed "s|stable|${{ env.LATEST_TOOL_RELEASE }}|"`
61+
git config --global user.email "[email protected]"
62+
git config --global user.name "openshifttools-bot"
63+
git checkout -b "oc-${{ env.LATEST_TOOL_RELEASE }}"
64+
git commit -am "Update oc and kubectl CLI to ${{ env.LATEST_TOOL_RELEASE }}"
65+
git push origin "oc-${{ env.LATEST_TOOL_RELEASE }}"
66+
gh pr create --title "Update oc and kubectl CLI to ${{ env.LATEST_TOOL_RELEASE }}" --body "See ${release_url}"

.github/workflows/check-oc.yml

Lines changed: 0 additions & 50 deletions
This file was deleted.

src/k8s/clusterExplorer.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,22 +10,21 @@ import { DeploymentConfig } from './deploymentConfig';
1010
import path = require('path');
1111
import { ClusterServiceVersion } from './csv';
1212
import { isOpenShift } from '../util/kubeUtils';
13+
import { CommandText } from '../base/command';
14+
import { CliChannel } from '../cli';
1315

1416
let clusterExplorer: k8s.ClusterExplorerV1 | undefined;
1517

1618
let lastNamespace = '';
1719

1820
async function initNamespaceName(node: k8s.ClusterExplorerV1.ClusterExplorerResourceNode): Promise<string | undefined> {
19-
const kubectl = await k8s.extension.kubectl.v1;
20-
if (kubectl.available) {
21-
const result = await kubectl.api.invokeCommand('config view -o json');
22-
const config = JSON.parse(result.stdout);
23-
const currentContext = (config.contexts || []).find((ctx) => ctx.name === node.name);
24-
if (!currentContext) {
25-
return '';
26-
}
27-
return currentContext.context.namespace || 'default';
28-
}
21+
const result = await CliChannel.getInstance().executeTool(new CommandText('kubectl', 'config view -o json'));
22+
const config = JSON.parse(result.stdout);
23+
const currentContext = (config.contexts || []).find((ctx) => ctx.name === node.name);
24+
if (!currentContext) {
25+
return '';
26+
}
27+
return currentContext.context.namespace || 'default';
2928
}
3029

3130
async function customizeAsync(node: k8s.ClusterExplorerV1.ClusterExplorerResourceNode, treeItem: vscode.TreeItem): Promise<void> {

src/k8s/common.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ export async function selectResourceByName(config: Promise<QuickPickItem[]> | Qu
3232
}
3333

3434
export async function getChildrenNode(command: CommandText, kind: string, abbreviation: string): Promise<k8s.ClusterExplorerV1.Node[]> {
35-
const kubectl = await k8s.extension.kubectl.v1;
36-
if (kubectl.available) {
37-
const result = await kubectl.api.invokeCommand(`${command}`);
35+
try {
36+
const result = await CliChannel.getInstance().executeTool(new CommandText('kubectl', `${command}`));
3837
const builds = result.stdout.split('\n')
3938
.filter((value) => value !== '')
4039
.map<Node>((item: string) => new Node(item.split(',')[0], item.split(',')[1], Number.parseInt(item.split(',')[2], 10), kind, abbreviation));
4140
return builds;
41+
} catch (error) {
42+
return [];
4243
}
43-
return [];
4444
}

src/serverlessFunction/knative.ts

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,21 @@
33
* Licensed under the MIT License. See LICENSE file in the project root for license information.
44
*-----------------------------------------------------------------------------------------------*/
55

6-
import * as k8s from 'vscode-kubernetes-tools-api';
6+
import { CommandText } from '../base/command';
7+
import { CliChannel } from '../cli';
78

89
/**
910
* Returns true if the cluster has the Knative Serving CRDs, and false otherwise.
1011
*
1112
* @returns true if the cluster has the Knative Serving CRDs, and false otherwise
1213
*/
1314
export async function isKnativeServingAware(): Promise<boolean> {
14-
const kubectl = await k8s.extension.kubectl.v1;
15-
let isKnative = false;
16-
if (kubectl.available) {
17-
const sr = await kubectl.api.invokeCommand('api-versions');
18-
isKnative =
19-
sr &&
20-
sr.code === 0 &&
21-
(sr.stdout.includes('serving.knative.dev/v1') ||
22-
sr.stdout.includes('serving.knative.dev/v1alpha1') ||
23-
sr.stdout.includes('serving.knative.dev/v1beta1'));
15+
try {
16+
const stdout = await CliChannel.getInstance().executeSyncTool(new CommandText('kubectl', 'api-versions'), { timeout: 5000 });
17+
return stdout.includes('serving.knative.dev/v1') ||
18+
stdout.includes('serving.knative.dev/v1alpha1') ||
19+
stdout.includes('serving.knative.dev/v1beta1');
20+
} catch(error) {
21+
return false;
2422
}
25-
return isKnative;
2623
}

src/tekton/tekton.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@
33
* Licensed under the MIT License. See LICENSE file in the project root for license information.
44
*-----------------------------------------------------------------------------------------------*/
55

6-
import * as k8s from 'vscode-kubernetes-tools-api';
6+
import { CommandText } from '../base/command';
7+
import { CliChannel } from '../cli';
78

89
/**
910
* Returns true if the cluster has the Tekton CRDs, and false otherwise.
1011
*
1112
* @returns true if the cluster has the Tekton CRDs, and false otherwise
1213
*/
1314
export async function isTektonAware(): Promise<boolean> {
14-
const kubectl = await k8s.extension.kubectl.v1;
15-
let isTekton = false;
16-
if (kubectl.available) {
17-
const sr = await kubectl.api.invokeCommand('api-versions');
18-
isTekton = sr && sr.code === 0 && sr.stdout.includes('tekton.dev/v1beta1');
15+
try {
16+
const stdout = await CliChannel.getInstance().executeSyncTool(new CommandText('kubectl', 'api-versions'), { timeout: 5000 });
17+
return stdout.includes('tekton.dev/v1beta1');
18+
} catch(error) {
19+
return false;
1920
}
20-
return isTekton;
2121
}

src/tools.json

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,48 @@
8383
}
8484
}
8585
},
86+
"kubectl": {
87+
"description": "OKD Kubernetes CLI client tool",
88+
"vendor": "Red Hat, Inc.",
89+
"name": "kubectl",
90+
"cmdFileName": "kubectl",
91+
"version": "4.15.5",
92+
"versionRange": "*",
93+
"versionRangeLabel": "version >= 4.15.5 and < 5.0.0",
94+
"filePrefix": "",
95+
"platform": {
96+
"win32": {
97+
"url": "https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.15.5/openshift-client-windows-4.15.5.zip",
98+
"sha256sum": "506138836fe89e3d35446909afabea510577f1a3ba660539f61c6c5952a27282",
99+
"dlFileName": "openshift-client-windows-4.15.5.zip",
100+
"cmdFileName": "kubectl.exe"
101+
},
102+
"darwin": {
103+
"url": "https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.15.5/openshift-client-mac-4.15.5.tar.gz",
104+
"sha256sum": "300233cab3514aec4a0f62ea7dee642f9f963bfafb544df9dee7e4b1fbb07700",
105+
"dlFileName": "openshift-client-mac-4.15.5.tar.gz",
106+
"cmdFileName": "kubectl"
107+
},
108+
"darwin-arm64": {
109+
"url": "https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.15.5/openshift-client-mac-arm64-4.15.5.tar.gz",
110+
"sha256sum": "372762372198d95b8aeef2ebe570c154ab6ab365eb0d304c0fec68ac866498e6",
111+
"dlFileName": "openshift-client-mac-arm64-4.15.5.tar.gz",
112+
"cmdFileName": "kubectl"
113+
},
114+
"linux": {
115+
"url": "https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.15.5/openshift-client-linux-4.15.5.tar.gz",
116+
"sha256sum": "0d2bfcf74e81e223808c2007af727b5980b0e3d190b9f0b94c6a04469227b66f",
117+
"dlFileName": "openshift-client-linux-4.15.5.tar.gz",
118+
"cmdFileName": "kubectl"
119+
},
120+
"linux-arm64": {
121+
"url": "https://mirror.openshift.com/pub/openshift-v4/clients/ocp/4.15.5/openshift-client-linux-arm64-4.15.5.tar.gz",
122+
"sha256sum": "3b4680e0e552c9ce0604177786fadd291e70483adfad8f84db8917a54e3e0b30",
123+
"dlFileName": "openshift-client-linux-arm64-4.15.5.tar.gz",
124+
"cmdFileName": "kubectl"
125+
}
126+
}
127+
},
86128
"func": {
87129
"description": "Function CLI tool",
88130
"vendor": "Red Hat, Inc.",

src/util/kubeUtils.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ import * as fs from 'fs';
99
import * as path from 'path';
1010
import { QuickPickItem, window } from 'vscode';
1111
import { Platform } from './platform';
12-
import * as k8s from 'vscode-kubernetes-tools-api';
12+
import { CommandText } from '../base/command';
13+
import { CliChannel } from '../cli';
1314

1415
function fileExists(file: string): boolean {
1516
try {
@@ -184,14 +185,13 @@ export async function setKubeConfig(): Promise<void> {
184185
}
185186

186187
export async function isOpenShift(): Promise<boolean> {
187-
const kubectl = await k8s.extension.kubectl.v1;
188-
let isOS = false;
189-
if (kubectl.available) {
190-
const sr = await kubectl.api.invokeCommand('api-versions');
191-
isOS = sr && sr.code === 0 && sr.stdout.includes('apps.openshift.io/v1');
188+
try {
189+
const stdout = await CliChannel.getInstance().executeSyncTool(new CommandText('kubectl', 'api-versions'), { timeout: 5000 });
190+
return stdout.includes('apps.openshift.io/v1');
191+
} catch(error) {
192+
return false;
192193
}
193-
return isOS;
194-
}
194+
}
195195

196196
export async function getNamespaceKind(): Promise<string> {
197197
return (await isOpenShift()) ? 'Project' : 'Namespace';

0 commit comments

Comments
 (0)