From 1644400470daf72470fd30fa496217f5015e008c Mon Sep 17 00:00:00 2001 From: zahar Date: Mon, 24 Jun 2024 21:12:55 +0300 Subject: [PATCH] basic generic api examples Signed-off-by: zahar --- examples/kubectl/equivalents/apply.js | 21 +++++++ examples/kubectl/equivalents/create.js | 14 +++++ examples/kubectl/equivalents/delete.js | 14 +++++ examples/kubectl/equivalents/get.js | 15 +++++ examples/typescript/apply/apply-example.ts | 61 ++++++------------- .../apply/apply-from-file-example.ts | 53 ++++++++++++++++ 6 files changed, 136 insertions(+), 42 deletions(-) create mode 100644 examples/kubectl/equivalents/apply.js create mode 100644 examples/kubectl/equivalents/create.js create mode 100644 examples/kubectl/equivalents/delete.js create mode 100644 examples/kubectl/equivalents/get.js create mode 100644 examples/typescript/apply/apply-from-file-example.ts diff --git a/examples/kubectl/equivalents/apply.js b/examples/kubectl/equivalents/apply.js new file mode 100644 index 0000000000..8cd39b178b --- /dev/null +++ b/examples/kubectl/equivalents/apply.js @@ -0,0 +1,21 @@ +const k8s = require('@kubernetes/client-node'); + +const kc = new k8s.KubeConfig(); +kc.loadFromDefault(); + +const client = k8s.KubernetesObjectApi.makeApiClient(kc); + +// update deployment "my-deployment" in namespace "my-namespace" to 3 replicas +const deployment = { + apiVersion: 'apps/v1', + kind: 'Deployment', + metadata: { + name: 'my-deployment', + namespace: 'my-namespace' + }, + spec: { + replicas: 3 + } +} + +client.patch(deployment) \ No newline at end of file diff --git a/examples/kubectl/equivalents/create.js b/examples/kubectl/equivalents/create.js new file mode 100644 index 0000000000..fecb28782d --- /dev/null +++ b/examples/kubectl/equivalents/create.js @@ -0,0 +1,14 @@ +const k8s = require('@kubernetes/client-node'); + +const kc = new k8s.KubeConfig(); +kc.loadFromDefault(); + +const client = k8s.KubernetesObjectApi.makeApiClient(kc); + +const namespace = { + metadata: { + name: 'test' + } +} + +client.create(namespace) \ No newline at end of file diff --git a/examples/kubectl/equivalents/delete.js b/examples/kubectl/equivalents/delete.js new file mode 100644 index 0000000000..d0de0ba9ee --- /dev/null +++ b/examples/kubectl/equivalents/delete.js @@ -0,0 +1,14 @@ +const k8s = require('@kubernetes/client-node'); + +const kc = new k8s.KubeConfig(); +kc.loadFromDefault(); + +const client = k8s.KubernetesObjectApi.makeApiClient(kc); + +const namespace = { + metadata: { + name: 'test' + } +} + +client.delete(namespace) \ No newline at end of file diff --git a/examples/kubectl/equivalents/get.js b/examples/kubectl/equivalents/get.js new file mode 100644 index 0000000000..f46c69b92b --- /dev/null +++ b/examples/kubectl/equivalents/get.js @@ -0,0 +1,15 @@ +const k8s = require('@kubernetes/client-node'); + +const kc = new k8s.KubeConfig(); +kc.loadFromDefault(); + +const client = k8s.KubernetesObjectApi.makeApiClient(kc); + +const namespace = { + metadata: { + name: 'test' + } +} + +const live_namespace = (await client.read(namespace)).body +console.log(live_namespace) \ No newline at end of file diff --git a/examples/typescript/apply/apply-example.ts b/examples/typescript/apply/apply-example.ts index d3bf20568b..a44c595448 100644 --- a/examples/typescript/apply/apply-example.ts +++ b/examples/typescript/apply/apply-example.ts @@ -1,44 +1,21 @@ -// 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'; +import * as k8s from '@kubernetes/client-node'; -/** - * Replicate the functionality of `kubectl apply`. That is, create the resources defined in the `specFile` if they do - * not exist, patch them if they do exist. - * - * @param specPath File system path to a YAML Kubernetes spec. - * @return Array of resources created - */ -export async function apply(specPath: string): Promise { - const kc = new k8s.KubeConfig(); - kc.loadFromDefault(); - const client = k8s.KubernetesObjectApi.makeApiClient(kc); - const fsReadFileP = promisify(fs.readFile); - const specString = await fsReadFileP(specPath, 'utf8'); - 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) { - // this is to convince the old version of TypeScript that metadata exists even though we already filtered specs - // without metadata out - spec.metadata = spec.metadata || {}; - spec.metadata.annotations = spec.metadata.annotations || {}; - delete spec.metadata.annotations['kubectl.kubernetes.io/last-applied-configuration']; - spec.metadata.annotations['kubectl.kubernetes.io/last-applied-configuration'] = JSON.stringify(spec); - try { - // try to get the resource, if it does not exist an error will be thrown and we will end up in the catch - // block. - await client.read(spec); - // we got the resource, so it exists, so patch it - const response = await client.patch(spec); - created.push(response); - } catch (e) { - // we did not get the resource, so it does not exist, so create it - const response = await client.create(spec); - created.push(response); - } - } - return created; +const kc = new k8s.KubeConfig(); +kc.loadFromDefault(); + +const client = k8s.KubernetesObjectApi.makeApiClient(kc); + +// update deployment "my-deployment" in namespace "my-namespace" to 3 replicas +const deployment = { + apiVersion: 'apps/v1', + kind: 'Deployment', + metadata: { + name: 'my-deployment', + namespace: 'my-namespace' + }, + spec: { + replicas: 3 + } } + +client.patch(deployment) \ No newline at end of file diff --git a/examples/typescript/apply/apply-from-file-example.ts b/examples/typescript/apply/apply-from-file-example.ts new file mode 100644 index 0000000000..0c8d19609f --- /dev/null +++ b/examples/typescript/apply/apply-from-file-example.ts @@ -0,0 +1,53 @@ +import * as k8s from '@kubernetes/client-node'; +import * as yaml from 'js-yaml'; +import { promises as fs } from 'fs'; + +/** + * Replicate the functionality of `kubectl apply`. That is, create the resources defined in the `specFile` if they do + * not exist, patch them if they do exist. + * + * @param specPath File system path to a YAML Kubernetes spec. + * @return Array of resources created + */ +export async function apply(specPath: string): Promise { + const kc = new k8s.KubeConfig(); + kc.loadFromDefault(); + + const client = k8s.KubernetesObjectApi.makeApiClient(kc); + + const specString = await fs.readFile(specPath, 'utf8'); + const specs: k8s.KubernetesObject[] = yaml.loadAll(specString); + const validSpecs = specs.filter((s) => s && s.kind && s.metadata); + const created: k8s.KubernetesObject[] = []; + for (const spec of validSpecs) { + // this is to convince the old version of TypeScript that metadata exists even though we already filtered specs + // without metadata out + spec.metadata = spec.metadata || {}; + spec.metadata.annotations = spec.metadata.annotations || {}; + delete spec.metadata.annotations['kubectl.kubernetes.io/last-applied-configuration']; + spec.metadata.annotations['kubectl.kubernetes.io/last-applied-configuration'] = JSON.stringify(spec); + try { + // try to get the resource, if it does not exist an error will be thrown and we will end up in the catch + // block. + await client.read(spec); + // we got the resource, so it exists, so patch it + // + // Note that this could fail if the spec refers to a custom resource. For custom resources you may need + // to specify a different patch merge strategy in the content-type header. + // + // See: https://github.com/kubernetes/kubernetes/issues/97423 + const response = await client.patch(spec); + created.push(response.body); + } catch (err) { + // if the resource doesnt exist then create it + if (err instanceof k8s.HttpError && err.statusCode === 404) { + const response = await client.create(spec); + created.push(response.body); + } else { + throw err + } + } + } + + return created; +} \ No newline at end of file