diff --git a/FETCH_MIGRATION.md b/FETCH_MIGRATION.md index fc29dc6138..5fe7464c52 100644 --- a/FETCH_MIGRATION.md +++ b/FETCH_MIGRATION.md @@ -67,27 +67,27 @@ Code will be on the `master` branch. - [ ] in-cluster-create-job-from-cronjob // done but unable to test with media type problems - [x] in-cluster - [x] ingress - - [ ] namespace // done but unable to test with media type problems - - [ ] patch-example + - [x] namespace + - [ ] patch-example // throws an error `TypeError: Cannot read properties of undefined (reading 'makeRequestContext')` - [x] raw-example (note: uses request lib directly, will require full fetch migration not just client param swap) - - [ ] scale-deployment // done but unable to test with media type problems + - [x] scale-deployment - [x] top_pods - [x] top - - [ ] yaml-example // done but unable to test with media type problems + - [ ] yaml-example // create works but deletion throws an error `TypeError: Cannot read properties of undefined (reading 'makeRequestContext')` - [ ] Fix TypeScript examples and validate their param signatures (due to new api) - - [ ] apply-example - - [ ] attach-example - - [ ] cp-example - - [ ] exec-example - - [ ] informer-with-label-selector // done but unable to test with media type problems + - [ ] apply-example // KubernetesObjectApi is missing + - [x] attach-example + - [x] cp-example + - [x] exec-example + - [x] informer-with-label-selector - [x] informer - - [ ] port-forward + - [x] port-forward - [x] example - [x] watch-example - [ ] Update docs - [ ] Update README examples - [ ] Document breaking changes for users -- [ ] Release initial version (1.0.0) + [ ] Release initial version (1.0.0) diff --git a/examples/cache-example.js b/examples/cache-example.js index 3094f80a34..198feb5e67 100644 --- a/examples/cache-example.js +++ b/examples/cache-example.js @@ -6,6 +6,8 @@ kc.loadFromDefault(); const k8sApi = kc.makeApiClient(k8s.CoreV1Api); +const namespace = 'default'; + const path = '/api/v1/pods'; const watch = new k8s.Watch(kc); @@ -14,7 +16,7 @@ const listFn = () => k8sApi.listPodForAllNamespaces(); const cache = new k8s.ListWatch(path, watch, listFn); const looper = () => { - const list = cache.list('default'); + const list = cache.list(namespace); if (list) { let names = []; for (let i = 0; i < list.length; i++) { diff --git a/examples/example.js b/examples/example.js index 849c0d2ecb..c69e12582e 100644 --- a/examples/example.js +++ b/examples/example.js @@ -6,8 +6,10 @@ kc.loadFromDefault(); const k8sApi = kc.makeApiClient(k8s.CoreV1Api); +const namespace = 'default'; + k8sApi - .listNamespacedPod({ namespace: 'default' }) + .listNamespacedPod({ namespace }) .then((res) => { console.log(res); }) diff --git a/examples/follow-logs.js b/examples/follow-logs.js index 40fabbdc66..8947c398c9 100644 --- a/examples/follow-logs.js +++ b/examples/follow-logs.js @@ -1,6 +1,6 @@ -const stream = require('stream'); // in a real program use require('@kubernetes/client-node') const k8s = require('../dist/index'); +const stream = require('stream'); const kc = new k8s.KubeConfig(); kc.loadFromDefault(); @@ -9,12 +9,16 @@ const log = new k8s.Log(kc); const logStream = new stream.PassThrough(); +const namespace = 'default'; +const pod = 'pod1'; +const container = 'container1'; + logStream.on('data', (chunk) => { // use write rather than console.log to prevent double line feed process.stdout.write(chunk); }); -log.log('default', 'pod1', 'container1', logStream, { +log.log(namespace, pod, container, logStream, { follow: true, tailLines: 50, pretty: false, diff --git a/examples/in-cluster-create-job-from-cronjob.js b/examples/in-cluster-create-job-from-cronjob.js index 73ba21eca5..b26cc9cf07 100644 --- a/examples/in-cluster-create-job-from-cronjob.js +++ b/examples/in-cluster-create-job-from-cronjob.js @@ -1,6 +1,8 @@ // in a real program use require('@kubernetes/client-node') const k8s = require('../dist/index'); +const namespace = 'default'; + const kc = new k8s.KubeConfig(); kc.loadFromCluster(); @@ -20,11 +22,11 @@ metadata.annotations = { job.metadata = metadata; batchV1beta1Api - .readNamespacedCronJob({ name: cronJobName, namespace: 'default' }) + .readNamespacedCronJob({ name: cronJobName, namespace }) .then((cronJobRes) => { job.spec = cronJobRes?.spec?.jobTemplate.spec; batchV1Api - .createNamespacedJob({ namespace: 'default', body: job }) + .createNamespacedJob({ namespace, body: job }) .then((res) => { console.log(res); }) diff --git a/examples/in-cluster.js b/examples/in-cluster.js index 5e99afbf2b..9da478d32f 100644 --- a/examples/in-cluster.js +++ b/examples/in-cluster.js @@ -6,8 +6,10 @@ kc.loadFromCluster(); const k8sApi = kc.makeApiClient(k8s.CoreV1Api); +const namespace = 'default'; + k8sApi - .listNamespacedPod({ namespace: 'default' }) + .listNamespacedPod({ namespace }) .then((res) => { console.log(res); }) diff --git a/examples/ingress.js b/examples/ingress.js index 0b38216138..0c79fa7bbb 100644 --- a/examples/ingress.js +++ b/examples/ingress.js @@ -5,11 +5,13 @@ const kc = new k8s.KubeConfig(); kc.loadFromDefault(); const k8sApi = kc.makeApiClient(k8s.NetworkingV1Api); + +const namespace = 'default'; const clientIdentifier = 'my-subdomain'; k8sApi .createNamespacedIngress({ - namespace: 'default', + namespace, body: { apiVersion: 'networking.k8s.io/v1', kind: 'Ingress', diff --git a/examples/patch-example.js b/examples/patch-example.js index d6f0220d6e..23d3e3bc9b 100644 --- a/examples/patch-example.js +++ b/examples/patch-example.js @@ -6,7 +6,9 @@ kc.loadFromDefault(); const k8sApi = kc.makeApiClient(k8s.CoreV1Api); -k8sApi.listNamespacedPod({ namespace: 'default' }).then((res) => { +const namespace = 'default'; + +k8sApi.listNamespacedPod({ namespace }).then((res) => { const patch = [ { op: 'replace', @@ -19,10 +21,7 @@ k8sApi.listNamespacedPod({ namespace: 'default' }).then((res) => { // TODO this method of passing the content type will change when we figure out a way to properly do this const options = { headers: { 'Content-type': k8s.PatchUtils.PATCH_FORMAT_JSON_PATCH } }; k8sApi - .patchNamespacedPod( - { name: res?.items?.[0].metadata?.name ?? '', namespace: 'default', body: patch }, - options, - ) + .patchNamespacedPod({ name: res?.items?.[0].metadata?.name ?? '', namespace, body: patch }, options) .then(() => { console.log('Patched.'); }) diff --git a/examples/scale-deployment.js b/examples/scale-deployment.js index 592c78d686..1dc89c0807 100644 --- a/examples/scale-deployment.js +++ b/examples/scale-deployment.js @@ -10,15 +10,15 @@ const targetNamespaceName = 'default'; const targetDeploymentName = 'docker-test-deployment'; const numberOfTargetReplicas = 3; -async function scale(deploymentNamespace, deploymentName, replicas) { +async function scale(namespace, name, replicas) { // find the particular deployment const deployment = await k8sApi.readNamespacedDeployment({ - name: deploymentName, - namespace: deploymentNamespace, + name, + namespace, }); if (!deployment || !deployment.spec) { - throw new Error(`Deployment ${deploymentName} not found in namespace ${deploymentNamespace}`); + throw new Error(`Deployment ${name} not found in namespace ${namespace}`); } // edit const newDeployment = { @@ -31,8 +31,8 @@ async function scale(deploymentNamespace, deploymentName, replicas) { // replace await k8sApi.replaceNamespacedDeployment({ - name: deploymentName, - namespace: deploymentNamespace, + name, + namespace, body: newDeployment, }); } diff --git a/examples/top_pods.js b/examples/top_pods.js index 37e94c7498..d99cf641f0 100644 --- a/examples/top_pods.js +++ b/examples/top_pods.js @@ -7,7 +7,9 @@ kc.loadFromDefault(); const k8sApi = kc.makeApiClient(k8s.CoreV1Api); const metricsClient = new k8s.Metrics(kc); -k8s.topPods(k8sApi, metricsClient, 'kube-system').then((pods) => { +const namespace = 'kube-system'; + +k8s.topPods(k8sApi, metricsClient, namespace).then((pods) => { const podsColumns = pods.map((pod) => { return { POD: pod.Pod.metadata?.name, @@ -19,7 +21,7 @@ k8s.topPods(k8sApi, metricsClient, 'kube-system').then((pods) => { console.table(podsColumns); }); -k8s.topPods(k8sApi, metricsClient, 'kube-system').then((pods) => { +k8s.topPods(k8sApi, metricsClient, namespace).then((pods) => { const podsAndContainersColumns = pods.flatMap((pod) => { return pod.Containers.map((containerUsage) => { return { diff --git a/examples/typescript/apply/apply-example.ts b/examples/typescript/apply/apply-example.ts index 348e40b6d5..0dc2572e4d 100644 --- a/examples/typescript/apply/apply-example.ts +++ b/examples/typescript/apply/apply-example.ts @@ -1,4 +1,5 @@ -import * as k8s from '@kubernetes/client-node'; +// in a real program use require('@kubernetes/client-node') +import * as k8s from '../../../dist'; import * as fs from 'fs'; import * as yaml from 'js-yaml'; import { promisify } from 'util'; @@ -16,7 +17,7 @@ export async function apply(specPath: string): Promise { const client = k8s.KubernetesObjectApi.makeApiClient(kc); const fsReadFileP = promisify(fs.readFile); const specString = await fsReadFileP(specPath, 'utf8'); - const specs: k8s.KubernetesObject[] = yaml.loadAll(specString); + const specs = yaml.loadAll(specString) as k8s.KubernetesObject[]; const validSpecs = specs.filter((s) => s && s.kind && s.metadata); const created: k8s.KubernetesObject[] = []; for (const spec of validSpecs) { diff --git a/examples/typescript/attach/attach-example.ts b/examples/typescript/attach/attach-example.ts index 9fc78eca47..fc9a504bc0 100644 --- a/examples/typescript/attach/attach-example.ts +++ b/examples/typescript/attach/attach-example.ts @@ -1,8 +1,13 @@ -import k8s = require('@kubernetes/client-node'); +// in a real program use require('@kubernetes/client-node') +import * as k8s from '../../../dist'; const kc = new k8s.KubeConfig(); kc.loadFromDefault(); const attach = new k8s.Attach(kc); -attach.attach('default', 'nginx-4217019353-9gl4s', 'nginx', - process.stdout, process.stderr, null /* stdin */, false /* tty */); + +const namespace = 'default'; +const pod = 'nginx-4217019353-9gl4s'; +const container = 'nginx'; + +attach.attach(namespace, pod, container, process.stdout, process.stderr, null /* stdin */, false /* tty */); diff --git a/examples/typescript/cp/cp-example.ts b/examples/typescript/cp/cp-example.ts index fcd35b77dc..16e9e3c175 100644 --- a/examples/typescript/cp/cp-example.ts +++ b/examples/typescript/cp/cp-example.ts @@ -1,7 +1,15 @@ -import * as k8s from '@kubernetes/client-node'; +// in a real program use require('@kubernetes/client-node') +import * as k8s from '../../../dist'; const kc = new k8s.KubeConfig(); kc.loadFromDefault(); const cp = new k8s.Cp(kc); -cp.cpFromPod('default', 'nginx-4217019353-9gl4s', 'nginx', './test.txt', '/tmp'); + +const namespace = 'default'; +const pod = 'nginx-4217019353-9gl4s'; +const container = 'nginx'; +const srcPath = '/test.txt'; +const targetPath = '/tmp'; + +cp.cpFromPod(namespace, pod, container, srcPath, targetPath); diff --git a/examples/typescript/exec/exec-example.ts b/examples/typescript/exec/exec-example.ts index 3b2334ede6..6b1d72d655 100644 --- a/examples/typescript/exec/exec-example.ts +++ b/examples/typescript/exec/exec-example.ts @@ -1,4 +1,5 @@ -import * as k8s from '@kubernetes/client-node'; +// in a real program use require('@kubernetes/client-node') +import * as k8s from '../../../dist'; import * as stream from 'stream'; const command = process.argv[2]; @@ -7,12 +8,24 @@ const kc = new k8s.KubeConfig(); kc.loadFromDefault(); const exec = new k8s.Exec(kc); -exec.exec('default', 'nginx-4217019353-9gl4s', 'nginx', command, - process.stdout as stream.Writable, process.stderr as stream.Writable, process.stdin as stream.Readable, + +const namespace = 'default'; +const pod = 'nginx-4217019353-9gl4s'; +const container = 'nginx'; + +exec.exec( + namespace, + pod, + container, + command, + process.stdout as stream.Writable, + process.stderr as stream.Writable, + process.stdin as stream.Readable, true /* tty */, (status: k8s.V1Status) => { // tslint:disable-next-line:no-console console.log('Exited with status:'); // tslint:disable-next-line:no-console console.log(JSON.stringify(status, null, 2)); - }); + }, +); diff --git a/examples/typescript/informer/informer-with-label-selector.ts b/examples/typescript/informer/informer-with-label-selector.ts index 8f050b5eb7..541eab8878 100644 --- a/examples/typescript/informer/informer-with-label-selector.ts +++ b/examples/typescript/informer/informer-with-label-selector.ts @@ -7,11 +7,12 @@ kc.loadFromDefault(); const k8sApi = kc.makeApiClient(k8s.CoreV1Api); +const namespace = 'default'; const APP_LABEL_SELECTOR = 'app=foo'; const listFn = () => k8sApi.listNamespacedPod({ - namespace: 'default', + namespace, labelSelector: APP_LABEL_SELECTOR, }); @@ -32,20 +33,20 @@ const createPod = async (name: string, app: string) => { containers: [appPodContainer], }, } as k8s.V1Pod; - await k8sApi.createNamespacedPod({ namespace: 'default', body: appPod }).catch((e) => console.error(e)); + await k8sApi.createNamespacedPod({ namespace, body: appPod }).catch((e) => console.error(e)); console.log('create', name); }; const deletePod = async (podName: string, podNamespace: string) => { await k8sApi.deleteNamespacedPod({ name: podName, namespace: podNamespace }); - console.log('delete', name); + console.log('delete', podName); }; const delay = (ms: number) => { return new Promise((resolve) => setTimeout(resolve, ms)); }; -const informer = k8s.makeInformer(kc, '/api/v1/namespaces/default/pods', listFn, APP_LABEL_SELECTOR); +const informer = k8s.makeInformer(kc, `/api/v1/namespaces/${namespace}/pods`, listFn, APP_LABEL_SELECTOR); informer.on('add', (obj: k8s.V1Pod) => { console.log(`Added: ${obj.metadata!.name}`); @@ -70,7 +71,7 @@ informer.start().then(() => { await delay(5000); await createPod('server-bar', 'bar'); await delay(5000); - await deletePod('server-foo', 'default'); - await deletePod('server-bar', 'default'); + await deletePod('server-foo', namespace); + await deletePod('server-bar', namespace); }, 5000); }); diff --git a/examples/typescript/informer/informer.ts b/examples/typescript/informer/informer.ts index c2f01af8df..c370ae87a4 100644 --- a/examples/typescript/informer/informer.ts +++ b/examples/typescript/informer/informer.ts @@ -9,9 +9,11 @@ kc.loadFromDefault(); const k8sApi = kc.makeApiClient(k8s.CoreV1Api); -const listFn = () => k8sApi.listNamespacedPod({ namespace: 'default' }); +const namespace = 'default'; -const informer = k8s.makeInformer(kc, '/api/v1/namespaces/default/pods', listFn); +const listFn = () => k8sApi.listNamespacedPod({ namespace }); + +const informer = k8s.makeInformer(kc, `/api/v1/namespaces/${namespace}/pods`, listFn); informer.on('add', (obj: k8s.V1Pod) => { console.log(`Added: ${obj.metadata!.name}`); diff --git a/examples/typescript/port-forward/port-forward.ts b/examples/typescript/port-forward/port-forward.ts index 51e1a112ce..459dc486af 100644 --- a/examples/typescript/port-forward/port-forward.ts +++ b/examples/typescript/port-forward/port-forward.ts @@ -1,18 +1,21 @@ -import * as k8s from '@kubernetes/client-node'; +// in a real program use require('@kubernetes/client-node') +import * as k8s from '../../../dist'; import * as net from 'net'; -const command = process.argv[2]; - const kc = new k8s.KubeConfig(); kc.loadFromDefault(); const forward = new k8s.PortForward(kc); +const namespace = 'default'; +const pod = 'demo'; +const port = 8080; + // This simple server just forwards traffic from itself to a service running in kubernetes // -> localhost:8080 -> port-forward-tunnel -> kubernetes-pod // This is basically equivalent to 'kubectl port-forward ...' but in TypeScript. const server = net.createServer((socket) => { - forward.portForward('default', 'demo', [8080], socket, null, socket); + forward.portForward(namespace, pod, [port], socket, null, socket); }); -server.listen(8080, '127.0.0.1'); +server.listen(port, '127.0.0.1'); diff --git a/examples/typescript/simple/example.ts b/examples/typescript/simple/example.ts index a67c1e407b..078d07311a 100644 --- a/examples/typescript/simple/example.ts +++ b/examples/typescript/simple/example.ts @@ -6,7 +6,9 @@ kc.loadFromDefault(); const k8sApi = kc.makeApiClient(k8s.CoreV1Api); -k8sApi.listNamespacedPod({ namespace: 'default' }).then((res) => { +const namespace = 'default'; + +k8sApi.listNamespacedPod({ namespace }).then((res) => { // tslint:disable-next-line:no-console console.log(res.body); });