From 7866af78b293a42ba6b4586502ed149d28e6d837 Mon Sep 17 00:00:00 2001 From: Paul Balogh Date: Fri, 7 Apr 2023 15:06:23 -0500 Subject: [PATCH 01/15] Consolidate ConfigMap examples into single integration test Signed-off-by: Paul Balogh --- README.md | 14 ++--- examples/apply-configmap.js | 32 ------------ examples/configmap_operations.js | 90 ++++++++++++++++++++++++++++++++ examples/get-configmap.js | 12 ----- examples/list-configmaps.js | 17 ------ 5 files changed, 97 insertions(+), 68 deletions(-) delete mode 100644 examples/apply-configmap.js create mode 100644 examples/configmap_operations.js delete mode 100644 examples/get-configmap.js delete mode 100644 examples/list-configmaps.js diff --git a/README.md b/README.md index b770a17..6bc1942 100644 --- a/README.md +++ b/README.md @@ -249,13 +249,13 @@ export default function () { ### (Deprecated) `Client.config_maps` -| Method | Description | | -| ------------ | ------ | ---------------------------------------- | -| apply | creates the Kubernetes resource given a YAML configuration | [apply-configmap.js](./examples/apply-configmap.js) | -| create | creates the Kubernetes resource given an object configuration | | -| delete | removes the named ConfigMap | | -| get | returns the named ConfigMaps | [get-configmap.js](./examples/get-configmap.js) | -| list | returns a collection of ConfigMaps | [list-configmaps.js](./examples/list-configmaps.js) | +| Method | Description | +| ------------ | ------ | +| apply | creates the Kubernetes resource given a YAML configuration | +| create | creates the Kubernetes resource given an object configuration | +| delete | removes the named ConfigMap | +| get | returns the named ConfigMaps | +| list | returns a collection of ConfigMaps | ```javascript import { Kubernetes } from 'k6/x/kubernetes'; diff --git a/examples/apply-configmap.js b/examples/apply-configmap.js deleted file mode 100644 index c597276..0000000 --- a/examples/apply-configmap.js +++ /dev/null @@ -1,32 +0,0 @@ -import { Kubernetes } from 'k6/x/kubernetes'; -import {check, sleep} from 'k6'; - -function getConfigMapYaml(name) { - return `kind: ConfigMap -apiVersion: v1 -metadata: - name: ` + name + ` -data: - configkey: configvalue - - configfile: | - configproperty1=42 - configproperty2=foo -` -} - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const nameSpace = "default"; - const name = "config-map-name"; - - kubernetes.config_maps.apply(getConfigMapYaml(name), nameSpace); - const cm_list = kubernetes.config_maps.list(nameSpace).map(function(cm){ - return cm.name; - }) - sleep(1); - check(cm_list, {'ConfigMap was created': (c) => c.indexOf(name) != -1}); -} - diff --git a/examples/configmap_operations.js b/examples/configmap_operations.js new file mode 100644 index 0000000..8acd5c3 --- /dev/null +++ b/examples/configmap_operations.js @@ -0,0 +1,90 @@ +import { Kubernetes } from "k6/x/kubernetes"; +import { describe, expect } from "https://jslib.k6.io/k6chaijs/4.3.4.2/index.js"; +import { load, dump } from "https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs"; + +let json = { + apiVersion: "v1", + kind: "ConfigMap", + metadata: { + name: "json-configmap", + namespace: "default", + }, + data: { + K6_API_TEST_URL: "https://test.k6.io", + } +} + +let yaml = ` +apiVersion: v1 +kind: ConfigMap +metadata: + name: yaml-configmap + namespace: default +data: + K6_API_TEST_URL: https://test.k6.io +` + +export default function () { + const kubernetes = new Kubernetes(); + + describe('JSON-based resources', () => { + const name = json.metadata.name + const ns = json.metadata.namespace + + let configmap + + describe('Create our ConfigMap using the JSON definition', () => { + configmap = kubernetes.create(json) + expect(configmap.metadata, 'new configmap').to.have.property('uid') + }) + + describe('Retrieve all available ConfigMap', () => { + expect(kubernetes.list("ConfigMap", ns).length, 'total configmaps').to.be.at.least(1) + }) + + describe('Retrieve our ConfigMap by name and namespace', () => { + let fetched = kubernetes.get("ConfigMap", name, ns) + expect(configmap.metadata.uid, 'created and fetched uids').to.equal(fetched.metadata.uid) + }) + + describe('Update our ConfigMap with a modified JSON definition', () => { + const newValue = 'https://test-api.k6.io/' + json.data.K6_API_TEST_URL = newValue + + kubernetes.update(json) + let updated = kubernetes.get("ConfigMap", name, ns) + expect(updated.data.K6_API_TEST_URL, 'changed value').to.be.equal(newValue) + }) + + describe('Remove our ConfigMap to cleanup', () => { + kubernetes.delete("ConfigMap", name, ns) + }) + }) + + describe('YAML-based resources', () => { + let yamlObject = load(yaml) + const name = yamlObject.metadata.name + const ns = yamlObject.metadata.namespace + + describe('Create our ConfigMap using the YAML definition', () => { + kubernetes.apply(yaml) + let created = kubernetes.get("ConfigMap", name, ns) + expect(created.metadata, 'new configmap').to.have.property('uid') + }) + + describe('Update our ConfigMap with a modified YAML definition', () => { + const newValue = 'https://test-api.k6.io/' + yamlObject.data.K6_API_TEST_URL = newValue + let newYaml = dump(yamlObject) + + kubernetes.apply(newYaml) + let updated = kubernetes.get("ConfigMap", name, ns) + expect(updated.data.K6_API_TEST_URL, 'changed value').to.be.equal(newValue) + }) + + describe('Remove our ConfigMap to cleanup', () => { + kubernetes.delete("ConfigMap", name, ns) + }) + }) + +} diff --git a/examples/get-configmap.js b/examples/get-configmap.js deleted file mode 100644 index 41ae8d2..0000000 --- a/examples/get-configmap.js +++ /dev/null @@ -1,12 +0,0 @@ - -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const nameSpace = "default" - const name = "configMap_name" - const configMap = kubernetes.config_maps.get(name, nameSpace) - console.log(JSON.stringify(configMap, null, 2)) -} diff --git a/examples/list-configmaps.js b/examples/list-configmaps.js deleted file mode 100644 index e12b7d4..0000000 --- a/examples/list-configmaps.js +++ /dev/null @@ -1,17 +0,0 @@ - -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const configMaps = kubernetes.config_maps.list() - console.log(`${configMaps.length} ConfigMaps found:`) - const info = configMaps.map(function (configMap) { - return { - namespace: configMap.namespace, - name: configMap.name, - } - }) - console.log(JSON.stringify(info, null, 2)) -} From b1702a87dfeed681cddc0c10205afdf08f631a51 Mon Sep 17 00:00:00 2001 From: Paul Balogh Date: Fri, 7 Apr 2023 15:07:45 -0500 Subject: [PATCH 02/15] Consolidate Namespace examples into single integration test Signed-off-by: Paul Balogh --- README.md | 14 +++--- examples/apply-namespace.js | 27 ---------- examples/get-namespace.js | 11 ---- examples/list-namespaces.js | 16 ------ examples/namespace_operations.js | 86 ++++++++++++++++++++++++++++++++ 5 files changed, 93 insertions(+), 61 deletions(-) delete mode 100644 examples/apply-namespace.js delete mode 100644 examples/get-namespace.js delete mode 100644 examples/list-namespaces.js create mode 100644 examples/namespace_operations.js diff --git a/README.md b/README.md index 6bc1942..e7bea6c 100644 --- a/README.md +++ b/README.md @@ -359,13 +359,13 @@ export default function () { ### (Deprecated) `Client.namespaces` -| Method | Description | | -| ------------ | ------ | ---------------------------------------- | -| apply | creates the Kubernetes resource given a YAML configuration | [apply-namespace.js](./examples/apply-namespace.js) | -| create | creates the Kubernetes resource given an object configuration | | -| delete | removes the named Namespaces | | -| get | returns the named Namespace | [get-namespace.js](./examples/get-namespace.js) | -| list | returns a collection of Namespaces | [list-namespaces.js](./examples/list-namespaces.js) | +| Method | Description | +| ------------ | ------ | +| apply | creates the Kubernetes resource given a YAML configuration | +| create | creates the Kubernetes resource given an object configuration | +| delete | removes the named Namespaces | +| get | returns the named Namespace | +| list | returns a collection of Namespaces | ```javascript diff --git a/examples/apply-namespace.js b/examples/apply-namespace.js deleted file mode 100644 index 545274d..0000000 --- a/examples/apply-namespace.js +++ /dev/null @@ -1,27 +0,0 @@ -import { Kubernetes } from 'k6/x/kubernetes'; -import {check, sleep} from 'k6'; - -function getNamespaceYaml(name) { - return `kind: Namespace -apiVersion: v1 -metadata: - name: ` + name + ` - labels: - name: ` + name + ` -`; -} - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const name = "namespace-name"; - - kubernetes.namespaces.apply(getNamespaceYaml(name)); - const ns_list = kubernetes.namespaces.list().map(function(ns){ - return ns.name; - }) - sleep(1); - check(ns_list, {'Namespace was created': (n) => n.indexOf(name) != -1}); -} - diff --git a/examples/get-namespace.js b/examples/get-namespace.js deleted file mode 100644 index 39c1641..0000000 --- a/examples/get-namespace.js +++ /dev/null @@ -1,11 +0,0 @@ - -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const name = "default" - const ns = kubernetes.namespaces.get(name) - console.log(JSON.stringify(ns, null, 2)) -} diff --git a/examples/list-namespaces.js b/examples/list-namespaces.js deleted file mode 100644 index 579160e..0000000 --- a/examples/list-namespaces.js +++ /dev/null @@ -1,16 +0,0 @@ - -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const nss = kubernetes.namespaces.list() - console.log(`${nss.length} Namespaces found:`) - const info = nss.map(function (ns) { - return { - name: ns.name, - } - }) - console.log(JSON.stringify(info, null, 2)) -} diff --git a/examples/namespace_operations.js b/examples/namespace_operations.js new file mode 100644 index 0000000..d4b6124 --- /dev/null +++ b/examples/namespace_operations.js @@ -0,0 +1,86 @@ +import { Kubernetes } from 'k6/x/kubernetes'; +import { describe, expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.2/index.js'; +import { load, dump } from 'https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs'; + +let json = { + apiVersion: "v1", + kind: "Namespace", + metadata: { + name: "json-namespace", + labels: { + "k6.io/created_by": "xk6-kubernetes", + } + } +} + +let yaml = ` +apiVersion: v1 +kind: Namespace +metadata: + name: yaml-namespace + labels: + k6.io/created_by: xk6-kubernetes +` + +export default function () { + const kubernetes = new Kubernetes(); + + describe('JSON-based resources', () => { + const name = json.metadata.name + + let namespace + + describe('Create our Namespace using the JSON definition', () => { + namespace = kubernetes.create(json) + expect(namespace.metadata, 'new namespace').to.have.property('uid') + }) + + describe('Retrieve all available Namespaces', () => { + expect(kubernetes.list("Namespace").length, 'total namespaces').to.be.at.least(1) + }) + + describe('Retrieve our Namespace by name', () => { + let fetched = kubernetes.get("Namespace", name) + expect(namespace.metadata.uid, 'created and fetched uids').to.equal(fetched.metadata.uid) + }) + + describe('Update our Namespace with a modified JSON definition', () => { + const newValue = "xk6-kubernetes-example" + json.metadata.labels["k6.io/created_by"] = newValue + + kubernetes.update(json) + let updated = kubernetes.get("Namespace", name) + expect(updated.metadata.labels["k6.io/created_by"], 'changed value').to.be.equal(newValue) + }) + + describe('Remove our Namespace to cleanup', () => { + kubernetes.delete("Namespace", name) + }) + }) + + describe('YAML-based resources', () => { + let yamlObject = load(yaml) + const name = yamlObject.metadata.name + + describe('Create our Namespace using the YAML definition', () => { + kubernetes.apply(yaml) + let created = kubernetes.get("Namespace", name) + expect(created.metadata, 'new namespace').to.have.property('uid') + }) + + describe('Update our Namespace with a modified YAML definition', () => { + const newValue = "xk6-kubernetes-example" + yamlObject.metadata.labels["k6.io/created_by"] = newValue + let newYaml = dump(yamlObject) + + kubernetes.apply(newYaml) + let updated = kubernetes.get("Namespace", name) + expect(updated.metadata.labels["k6.io/created_by"], 'changed value').to.be.equal(newValue) + }) + + describe('Remove our Namespace to cleanup', () => { + kubernetes.delete("Namespace", name) + }) + }) + +} From fe7e223b16a778c1fb4178961feb774a4c220e40 Mon Sep 17 00:00:00 2001 From: Paul Balogh Date: Fri, 7 Apr 2023 15:09:28 -0500 Subject: [PATCH 03/15] Consolidate PersistentVolumeClaim examples into single integration test Signed-off-by: Paul Balogh --- README.md | 14 ++-- examples/apply-get-delete-pvc.js | 33 -------- examples/list-pvc.js | 17 ---- examples/persistentvolumeclaim_operations.js | 82 ++++++++++++++++++++ 4 files changed, 89 insertions(+), 57 deletions(-) delete mode 100644 examples/apply-get-delete-pvc.js delete mode 100644 examples/list-pvc.js create mode 100644 examples/persistentvolumeclaim_operations.js diff --git a/README.md b/README.md index e7bea6c..5b4371d 100644 --- a/README.md +++ b/README.md @@ -417,13 +417,13 @@ export default function () { ### (Deprecated) `Client.persistent_volumes_claims` -| Method | Description | Example | -| ------------ | ------ | ---------------------------------------- | -| apply | creates the Kubernetes resource given a YAML configuration | [apply-get-delete-pvc.js](./examples/apply-get-delete-pvc.js) | -| create | creates the Kubernetes resource given an object configuration | | -| delete | removes the named persistent volume claim | [apply-get-delete-pvc.js](./examples/apply-get-delete-pvc.js) | -| get | returns the named persistent volume claim | [apply-get-delete-pvc.js](./examples/apply-get-delete-pvc.js) | -| list | returns a collection of persistent volumen claims | [list-pvc.js](./examples/list-pvc.js) | +| Method | Description | +| ------------ | ------ | +| apply | creates the Kubernetes resource given a YAML configuration | +| create | creates the Kubernetes resource given an object configuration | +| delete | removes the named persistent volume claim | +| get | returns the named persistent volume claim | +| list | returns a collection of persistent volumen claims | ```javascript import { Kubernetes } from 'k6/x/kubernetes'; diff --git a/examples/apply-get-delete-pvc.js b/examples/apply-get-delete-pvc.js deleted file mode 100644 index b5ac60c..0000000 --- a/examples/apply-get-delete-pvc.js +++ /dev/null @@ -1,33 +0,0 @@ -import { Kubernetes } from 'k6/x/kubernetes'; -import { sleep } from 'k6'; - -function getPVCYaml(name, size, storageClass) { - return `apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: ` + name + ` -spec: - accessModes: - - ReadWriteMany - resources: - requests: - storage: ` + size + ` - storageClassName: ` + storageClass -} - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const name = "example-pvc"; - const nameSpace = "default"; - - kubernetes.persistent_volume_claims.apply(getPVCYaml(name, "1Gi", "nfs-csi"), nameSpace); - - sleep(5) - - const pvc_get = kubernetes.persistent_volume_claims.get(name, nameSpace) - console.log(JSON.stringify(pvc_get, null, 2)) - - kubernetes.persistent_volume_claims.delete(name, nameSpace, {}); -} diff --git a/examples/list-pvc.js b/examples/list-pvc.js deleted file mode 100644 index 606b9ef..0000000 --- a/examples/list-pvc.js +++ /dev/null @@ -1,17 +0,0 @@ - -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const nameSpace = "default" - const pvcs = kubernetes.persistent_volume_claims.list(nameSpace) - console.log(`${pvcs.length} PVCs found:`) - const info = pvcs.map(function (pvc) { - return { - name: pvc.name, - } - }) - console.log(JSON.stringify(info, null, 2)) -} diff --git a/examples/persistentvolumeclaim_operations.js b/examples/persistentvolumeclaim_operations.js new file mode 100644 index 0000000..b8f28c0 --- /dev/null +++ b/examples/persistentvolumeclaim_operations.js @@ -0,0 +1,82 @@ +import { Kubernetes } from 'k6/x/kubernetes'; +import { describe, expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.2/index.js'; +import { load, dump } from 'https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs'; + +let json = { + apiVersion: "v1", + kind: "PersistentVolumeClaim", + metadata: { + name: "json-pvc", + namespace: "default", + }, + spec: { + storageClassName: "", + accessModes: ["ReadWriteMany"], + resources: { + requests: { + storage: "10Mi", + } + } + } +} + +let yaml = ` +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: yaml-pvc + namespace: default +spec: + storageClassName: "" + accessModes: + - ReadWriteMany + resources: + requests: + storage: "10Mi" +` + +export default function () { + const kubernetes = new Kubernetes(); + + describe('JSON-based resources', () => { + const name = json.metadata.name + const ns = json.metadata.namespace + + let pvc + + describe('Create our PersistentVolumeClaim using the JSON definition', () => { + pvc = kubernetes.create(json) + expect(pvc.metadata, 'new persistentvolumeclaim').to.have.property('uid') + }) + + describe('Retrieve all available PersistentVolumeClaims', () => { + expect(kubernetes.list("PersistentVolumeClaim", ns).length, 'total persistentvolumeclaims').to.be.at.least(1) + }) + + describe('Retrieve our PersistentVolumeClaim by name', () => { + let fetched = kubernetes.get("PersistentVolumeClaim", name, ns) + expect(pvc.metadata.uid, 'created and fetched uids').to.equal(fetched.metadata.uid) + }) + + describe('Remove our PersistentVolumeClaim to cleanup', () => { + kubernetes.delete("PersistentVolumeClaim", name, ns) + }) + }) + + describe('YAML-based resources', () => { + let yamlObject = load(yaml) + const name = yamlObject.metadata.name + const ns = yamlObject.metadata.namespace + + describe('Create our PersistentVolumeClaim using the YAML definition', () => { + kubernetes.apply(yaml) + let created = kubernetes.get("PersistentVolumeClaim", name, ns) + expect(created.metadata, 'new persistentvolumeclaim').to.have.property('uid') + }) + + describe('Remove our PersistentVolumeClaim to cleanup', () => { + kubernetes.delete("PersistentVolumeClaim", name, ns) + }) + }) + +} From f011fe4cf3e9a260ec3e1b1a671f84ebe6764e2e Mon Sep 17 00:00:00 2001 From: Paul Balogh Date: Fri, 7 Apr 2023 15:12:56 -0500 Subject: [PATCH 04/15] Improve ingress validations in example Signed-off-by: Paul Balogh --- README.md | 14 +++++++------- examples/ingress_operations.js | 29 +++++++++++++++++------------ 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index 5b4371d..1aefbae 100644 --- a/README.md +++ b/README.md @@ -298,13 +298,13 @@ export default function () { ### (Deprecated) `Client.ingresses` -| Method | Description | | -| ------------ | ------ | ---------------------------------------- | -| apply | creates the Kubernetes resource given a YAML configuration | [apply-deployment-service-ingress.js](./examples/apply-deployment-service-ingress.js) | -| create | creates the Kubernetes resource given an object configuration | | -| delete | removes the named Ingress | | -| get | returns the named Ingress | [get-ingress.js](./examples/get-ingress.js) | -| list | returns a collection of Ingresses | [list-ingresses.js](./examples/list-ingresses.js) | +| Method | Description | +| ------------ | ------ | +| apply | creates the Kubernetes resource given a YAML configuration | +| create | creates the Kubernetes resource given an object configuration | +| delete | removes the named Ingress | +| get | returns the named Ingress | +| list | returns a collection of Ingresses | ```javascript import { Kubernetes } from 'k6/x/kubernetes'; diff --git a/examples/ingress_operations.js b/examples/ingress_operations.js index 573e4e6..15c779f 100644 --- a/examples/ingress_operations.js +++ b/examples/ingress_operations.js @@ -1,5 +1,6 @@ import { Kubernetes } from 'k6/x/kubernetes'; import { describe, expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.2/index.js'; +import { load, dump } from 'https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs'; let json = { apiVersion: "networking.k8s.io/v1", @@ -64,16 +65,16 @@ export default function () { describe('Create our ingress using the JSON definition', () => { ingress = kubernetes.create(json) - expect(ingress.metadata).to.have.property('uid') + expect(ingress.metadata, 'new ingress').to.have.property('uid') }) describe('Retrieve all available ingresses', () => { - expect(kubernetes.list("Ingress.networking.k8s.io", ns).length).to.be.at.least(1) + expect(kubernetes.list("Ingress.networking.k8s.io", ns).length, 'total ingresses').to.be.at.least(1) }) describe('Retrieve our ingress by name and namespace', () => { let fetched = kubernetes.get("Ingress.networking.k8s.io", name, ns) - expect(ingress.metadata.uid).to.equal(fetched.metadata.uid) + expect(ingress.metadata.uid, 'created and fetched uids').to.equal(fetched.metadata.uid) }) describe('Update our ingress with a modified JSON definition', () => { @@ -82,7 +83,8 @@ export default function () { kubernetes.update(json) let updated = kubernetes.get("Ingress.networking.k8s.io", name, ns) - expect(updated.spec.rules[0].http.paths[0].path).to.be.equal(newValue) + expect(updated.spec.rules[0].http.paths[0].path, 'changed value').to.be.equal(newValue) + expect(updated.metadata.generation, 'ingress revision').to.be.at.least(2) }) describe('Remove our ingresses to cleanup', () => { @@ -91,22 +93,25 @@ export default function () { }) describe('YAML-based resources', () => { - const name = 'yaml-ingress' - const ns = 'default' - - let uid + let yamlObject = load(yaml) + const name = yamlObject.metadata.name + const ns = yamlObject.metadata.namespace describe('Create our ingress using the YAML definition', () => { kubernetes.apply(yaml) let created = kubernetes.get("Ingress.networking.k8s.io", name, ns) - expect(created.metadata).to.have.property('uid') - uid = created.metadata.uid + expect(created.metadata, 'new ingress').to.have.property('uid') }) describe('Update our ingress with a modified YAML definition', () => { - kubernetes.apply(yaml) + const newValue = yamlObject.spec.rules[0].http.paths[0].path + '-updated' + yamlObject.spec.rules[0].http.paths[0].path = newValue + let newYaml = dump(yamlObject) + + kubernetes.apply(newYaml) let updated = kubernetes.get("Ingress.networking.k8s.io", name, ns) - expect(updated.metadata.uid).to.be.equal(uid) + expect(updated.spec.rules[0].http.paths[0].path, 'changed value').to.be.equal(newValue) + expect(updated.metadata.generation, 'ingress revision').to.be.at.least(2) }) describe('Remove our ingresses to cleanup', () => { From 3a08be6a564e9fea066d28f47f9887e4e165ccbe Mon Sep 17 00:00:00 2001 From: Paul Balogh Date: Fri, 7 Apr 2023 15:17:02 -0500 Subject: [PATCH 05/15] Adding Endpoints integration test Signed-off-by: Paul Balogh --- examples/endpoints_operations.js | 87 ++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 examples/endpoints_operations.js diff --git a/examples/endpoints_operations.js b/examples/endpoints_operations.js new file mode 100644 index 0000000..b42044c --- /dev/null +++ b/examples/endpoints_operations.js @@ -0,0 +1,87 @@ +import { Kubernetes } from "k6/x/kubernetes"; +import { describe, expect } from "https://jslib.k6.io/k6chaijs/4.3.4.2/index.js"; +import { load, dump } from "https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs"; + +let json = { + apiVersion: "v1", + kind: "Endpoints", + metadata: { + name: "json-endpoint", + namespace: "default", + }, + subsets: [ + { + addresses: [ + {ip: "192.168.0.32"}, + ], + ports: [ + { + name: "https", + port: 6443, + protocol: "TCP", + } + ], + } + ] +} + +let yaml = ` +apiVersion: v1 +kind: Endpoints +metadata: + name: yaml-endpoint + namespace: default +subsets: +- addresses: + - ip: 192.168.0.32 + ports: + - name: https + port: 6443 + protocol: TCP +` + +export default function () { + const kubernetes = new Kubernetes(); + + describe('JSON-based resources', () => { + const name = json.metadata.name + const ns = json.metadata.namespace + + let endpoint + + describe('Create our Endpoints using the JSON definition', () => { + endpoint = kubernetes.create(json) + expect(endpoint.metadata, 'new endpoint').to.have.property('uid') + }) + + describe('Retrieve all available Endpoints', () => { + expect(kubernetes.list("Endpoints", ns).length, 'total endpoints').to.be.at.least(1) + }) + + describe('Retrieve our Endpoints by name and namespace', () => { + let fetched = kubernetes.get("Endpoints", name, ns) + expect(endpoint.metadata.uid, 'created and fetched uids').to.equal(fetched.metadata.uid) + }) + + describe('Remove our Endpoints to cleanup', () => { + kubernetes.delete("Endpoints", name, ns) + }) + }) + + describe('YAML-based resources', () => { + let yamlObject = load(yaml) + const name = yamlObject.metadata.name + const ns = yamlObject.metadata.namespace + + describe('Create our Endpoints using the YAML definition', () => { + kubernetes.apply(yaml) + let created = kubernetes.get("Endpoints", name, ns) + expect(created.metadata, 'new endpoint').to.have.property('uid') + }) + + describe('Remove our Endpoints to cleanup', () => { + kubernetes.delete("Endpoints", name, ns) + }) + }) + +} From 36ecea2888ca0dfc81044a26a343351349fdce5a Mon Sep 17 00:00:00 2001 From: Paul Balogh Date: Fri, 7 Apr 2023 16:21:06 -0500 Subject: [PATCH 06/15] Consolidate PersistentVolume examples into single integration test Signed-off-by: Paul Balogh --- README.md | 14 ++-- examples/apply-get-delete-pv.js | 33 --------- examples/list-pv.js | 16 ---- examples/persistentvolume_operations.js | 97 +++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 56 deletions(-) delete mode 100644 examples/apply-get-delete-pv.js delete mode 100644 examples/list-pv.js create mode 100644 examples/persistentvolume_operations.js diff --git a/README.md b/README.md index 1aefbae..ad8cdff 100644 --- a/README.md +++ b/README.md @@ -396,13 +396,13 @@ export default function () { ### (Deprecated) `Client.persistent_volumes` -| Method | Description | Example | -| ------------ | ------ | ---------------------------------------- | -| apply | creates the Kubernetes resource given a YAML configuration | [apply-get-delete-pv.js](./examples/apply-get-delete-pv.js) | -| create | creates the Kubernetes resource given an object configuration | | -| delete | removes the named persistent volume | [apply-get-delete-pv.js](./examples/apply-get-delete-pv.js) | -| get | returns the named persistent volume instance | [apply-get-delete-pv.js](./examples/apply-get-delete-pv.js) | -| list | returns a collection of persistent volumens | [list-pv.js](./examples/list-pv.js) | +| Method | Description | +| ------------ | ------ | +| apply | creates the Kubernetes resource given a YAML configuration | +| create | creates the Kubernetes resource given an object configuration | +| delete | removes the named persistent volume | +| get | returns the named persistent volume instance | +| list | returns a collection of persistent volumens | ```javascript import { Kubernetes } from 'k6/x/kubernetes'; diff --git a/examples/apply-get-delete-pv.js b/examples/apply-get-delete-pv.js deleted file mode 100644 index b2599f8..0000000 --- a/examples/apply-get-delete-pv.js +++ /dev/null @@ -1,33 +0,0 @@ -import { Kubernetes } from 'k6/x/kubernetes'; -import { sleep } from 'k6'; - -function getPVYaml(name, size, storageClass) { - return `apiVersion: v1 -kind: PersistentVolume -metadata: - name: ` + name + ` -spec: - capacity: - storage: ` + size + ` - volumeMode: Filesystem - accessModes: - - ReadWriteMany - persistentVolumeReclaimPolicy: Retain - storageClassName: ` + storageClass -} - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const name = "example-pv"; - - kubernetes.persistent_volumes.apply(getPVYaml(name, "1Gi", "local-storage")); - - sleep(5) - - const pv_get = kubernetes.persistent_volumes.get(name) - console.log(JSON.stringify(pv_get, null, 2)) - - kubernetes.persistent_volumes.delete(name, {}); -} diff --git a/examples/list-pv.js b/examples/list-pv.js deleted file mode 100644 index 9eb7c7b..0000000 --- a/examples/list-pv.js +++ /dev/null @@ -1,16 +0,0 @@ - -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const pvs = kubernetes.persistent_volumes.list() - console.log(`${pvs.length} PVs found:`) - const info = pvs.map(function (pv) { - return { - name: pv.name, - } - }) - console.log(JSON.stringify(info, null, 2)) -} diff --git a/examples/persistentvolume_operations.js b/examples/persistentvolume_operations.js new file mode 100644 index 0000000..515bb25 --- /dev/null +++ b/examples/persistentvolume_operations.js @@ -0,0 +1,97 @@ +import { Kubernetes } from 'k6/x/kubernetes'; +import { describe, expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.2/index.js'; +import { load, dump } from 'https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs'; + +let json = { + apiVersion: "v1", + kind: "PersistentVolume", + metadata: { + name: "json-pv", + }, + spec: { + storageClassName: "manual", + capacity: { + storage: "1Mi", + }, + accessModes: [ + "ReadWriteOnce" + ], + hostPath: { + path: "/tmp/k3dvol", + }, + } +} + +let yaml = ` +apiVersion: v1 +kind: PersistentVolume +metadata: + name: yaml-pv +spec: + storageClassName: "manual" + capacity: + storage: 1Mi + accessModes: + - ReadWriteOnce + hostPath: + path: /tmp/k3dvol +` + +export default function () { + const kubernetes = new Kubernetes(); + + describe('JSON-based resources', () => { + const name = json.metadata.name + + let created + + describe('Create our PersistentVolume using the JSON definition', () => { + created = kubernetes.create(json) + expect(created.metadata, 'new persistentvolume').to.have.property('uid') + }) + + describe('Retrieve our PersistentVolume by name', () => { + let fetched = kubernetes.get("PersistentVolume", name) + expect(created.metadata.uid, 'created and fetched uids').to.equal(fetched.metadata.uid) + }) + + describe('Update our PersistentVolume with a modified JSON definition', () => { + const newValue = "10Mi" + json.spec.capacity.storage = newValue + + kubernetes.update(json) + let updated = kubernetes.get("PersistentVolume", name) + expect(updated.spec.capacity.storage, 'changed value').to.be.equal(newValue) + }) + + describe('Remove our PersistentVolume to cleanup', () => { + kubernetes.delete("PersistentVolume", name) + }) + }) + + describe('YAML-based resources', () => { + let yamlObject = load(yaml) + const name = yamlObject.metadata.name + + describe('Create our PersistentVolume using the YAML definition', () => { + kubernetes.apply(yaml) + let created = kubernetes.get("PersistentVolume", name) + expect(created.metadata, 'new persistentvolume').to.have.property('uid') + }) + + describe('Update our PersistentVolume with a modified YAML definition', () => { + const newValue = "10Mi" + yamlObject.spec.capacity.storage = newValue + let newYaml = dump(yamlObject) + + kubernetes.apply(newYaml) + let updated = kubernetes.get("PersistentVolume", name) + expect(updated.spec.capacity.storage, 'changed value').to.be.equal(newValue) + }) + + describe('Remove our PersistentVolume to cleanup', () => { + kubernetes.delete("PersistentVolume", name) + }) + }) + +} From 66e402e15b09168cfffe4eee1e66989734368d94 Mon Sep 17 00:00:00 2001 From: Paul Balogh Date: Sat, 8 Apr 2023 12:10:21 -0500 Subject: [PATCH 07/15] Adding integration tests for Secrets Signed-off-by: Paul Balogh --- README.md | 14 +++--- examples/apply-secret.js | 29 ----------- examples/get-secret.js | 12 ----- examples/list-secrets.js | 17 ------- examples/secret_operations.js | 92 +++++++++++++++++++++++++++++++++++ 5 files changed, 99 insertions(+), 65 deletions(-) delete mode 100644 examples/apply-secret.js delete mode 100644 examples/get-secret.js delete mode 100644 examples/list-secrets.js create mode 100644 examples/secret_operations.js diff --git a/README.md b/README.md index ad8cdff..9364b8c 100644 --- a/README.md +++ b/README.md @@ -485,13 +485,13 @@ export default function () { ### (Deprecated) `Client.secrets` -| Method | Description | Example | -| ------------ | ------ | ---------------------------------------- | -| apply | creates the Kubernetes resource given a YAML configuration | [apply-secret.js](./examples/apply-secret.js) | -| create | creates the Kubernetes resource given an object configuration | | -| delete | removes the named secret | | -| get | returns the named secret | [get-secret.js](./examples/get-secret.js) | -| list | returns a collection of secrets | [list-secrets.js](./examples/list-secrets.js) | +| Method | Description | +| ------------ | ------ | +| apply | creates the Kubernetes resource given a YAML configuration | +| create | creates the Kubernetes resource given an object configuration | +| delete | removes the named secret | +| get | returns the named secret | +| list | returns a collection of secrets | ```javascript diff --git a/examples/apply-secret.js b/examples/apply-secret.js deleted file mode 100644 index fcae40a..0000000 --- a/examples/apply-secret.js +++ /dev/null @@ -1,29 +0,0 @@ -import { Kubernetes } from 'k6/x/kubernetes'; -import {check, sleep} from 'k6'; - -function getSecretYaml(name) { - return `apiVersion: v1 -kind: Secret -metadata: - name: ` + name + ` -type: Opaque -data: - secretkey: c2VjcmV0dmFsdWUK -` -} - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const nameSpace = "default"; - const name = "secret-name"; - - kubernetes.secrets.apply(getSecretYaml(name), nameSpace); - const sc_list = kubernetes.secrets.list(nameSpace).map(function(sc){ - return sc.name; - }) - sleep(1); - check(sc_list, {'Secret was created': (s) => s.indexOf(name) != -1}); -} - diff --git a/examples/get-secret.js b/examples/get-secret.js deleted file mode 100644 index 0a2b342..0000000 --- a/examples/get-secret.js +++ /dev/null @@ -1,12 +0,0 @@ - -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const nameSpace = "default" - const name = "secret_name" - const secret = kubernetes.secrets.get(name, nameSpace) - console.log(JSON.stringify(secret, null, 2)) -} diff --git a/examples/list-secrets.js b/examples/list-secrets.js deleted file mode 100644 index fa814c6..0000000 --- a/examples/list-secrets.js +++ /dev/null @@ -1,17 +0,0 @@ - -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const secrets = kubernetes.secrets.list() - console.log(`${secrets.length} Secrets found:`) - const info = secrets.map(function (secret) { - return { - namespace: secret.namespace, - name: secret.name, - } - }) - console.log(JSON.stringify(info, null, 2)) -} diff --git a/examples/secret_operations.js b/examples/secret_operations.js new file mode 100644 index 0000000..43990db --- /dev/null +++ b/examples/secret_operations.js @@ -0,0 +1,92 @@ +import { Kubernetes } from "k6/x/kubernetes"; +import { describe, expect } from "https://jslib.k6.io/k6chaijs/4.3.4.2/index.js"; +import { load, dump } from "https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs"; + +let json = { + apiVersion: "v1", + kind: "Secret", + metadata: { + name: "json-secret", + namespace: "default", + }, + type: "Opaque", + data: { + mysecret: "dGhlIHNlY3JldCB3b3JkIGlzLi4u", + } +} + +let yaml = ` +apiVersion: v1 +kind: Secret +metadata: + name: yaml-secret + namespace: default +type: Opaque +data: + mysecret: dGhlIHNlY3JldCB3b3JkIGlzLi4u +` + +export default function () { + const kubernetes = new Kubernetes(); + + describe('JSON-based resources', () => { + const name = json.metadata.name + const ns = json.metadata.namespace + + let secret + + describe('Create our Secret using the JSON definition', () => { + secret = kubernetes.create(json) + expect(secret.metadata, 'new secret').to.have.property('uid') + }) + + describe('Retrieve all available Secret', () => { + expect(kubernetes.list("Secret", ns).length, 'total secrets').to.be.at.least(1) + }) + + describe('Retrieve our Secret by name and namespace', () => { + let fetched = kubernetes.get("Secret", name, ns) + expect(secret.metadata.uid, 'created and fetched uids').to.equal(fetched.metadata.uid) + }) + + describe('Update our Secret with a modified JSON definition', () => { + const newValue = 'bmV3IHNlY3JldCB2YWx1ZQ==' + json.data.mysecret = newValue + + kubernetes.update(json) + let updated = kubernetes.get("Secret", name, ns) + expect(updated.data.mysecret, 'changed value').to.be.equal(newValue) + }) + + describe('Remove our Secret to cleanup', () => { + kubernetes.delete("Secret", name, ns) + }) + }) + + describe('YAML-based resources', () => { + let yamlObject = load(yaml) + const name = yamlObject.metadata.name + const ns = yamlObject.metadata.namespace + + describe('Create our Secret using the YAML definition', () => { + kubernetes.apply(yaml) + let created = kubernetes.get("Secret", name, ns) + expect(created.metadata, 'new secret').to.have.property('uid') + }) + + describe('Update our Secret with a modified YAML definition', () => { + const newValue = 'bmV3IHNlY3JldCB2YWx1ZQ==' + yamlObject.data.mysecret = newValue + let newYaml = dump(yamlObject) + + kubernetes.apply(newYaml) + let updated = kubernetes.get("Secret", name, ns) + expect(updated.data.mysecret, 'changed value').to.be.equal(newValue) + }) + + describe('Remove our Secret to cleanup', () => { + kubernetes.delete("Secret", name, ns) + }) + }) + +} From 23574bb495d77770d582c323341a376958a20a05 Mon Sep 17 00:00:00 2001 From: Paul Balogh Date: Sat, 8 Apr 2023 14:28:13 -0500 Subject: [PATCH 08/15] Adding integration tests for Jobs Signed-off-by: Paul Balogh --- README.md | 16 +++--- examples/apply-job.js | 35 ------------ examples/create-job-autodelete.js | 35 ------------ examples/create-job-by-nodename.js | 35 ------------ examples/create-job.js | 33 ----------- examples/get-job.js | 12 ---- examples/job_operations.js | 89 ++++++++++++++++++++++++++++++ examples/kill-job.js | 25 --------- examples/list-jobs.js | 14 ----- 9 files changed, 97 insertions(+), 197 deletions(-) delete mode 100644 examples/apply-job.js delete mode 100644 examples/create-job-autodelete.js delete mode 100644 examples/create-job-by-nodename.js delete mode 100644 examples/create-job.js delete mode 100644 examples/get-job.js create mode 100644 examples/job_operations.js delete mode 100644 examples/kill-job.js delete mode 100644 examples/list-jobs.js diff --git a/README.md b/README.md index 9364b8c..349b0df 100644 --- a/README.md +++ b/README.md @@ -322,14 +322,14 @@ export default function () { ### (Deprecated) `Client.jobs` -| Method | Description | Example | -| ------------ | ------ | ---------------------------------------- | -| apply | creates the Kubernetes resource given a YAML configuration | [apply-job.js](./examples/apply-job.js) | -| create | creates the Kubernetes resource given an object configuration | [create-job.js](./examples/create-job.js), [create-job-wait.js](./examples/create-job-wait.js), [create-job-by-nodename.js](./examples/create-job-by-nodename.js), [create-job-autodelete.js](./examples/create-job-autodelete.js) | -| delete | removes the named Job | | -| get | returns the named Jobs | [get-job.js](./examples/get-job.js) | -| list | returns a collection of Jobs | [list-jobs.js](./examples/list-jobs.js) | -| wait | wait for all Jobs to complete | [wait-job.js](./examples/wait-job.js) | +| Method | Description | Example | +| ------------ | ------ | --------------------------------------- | +| apply | creates the Kubernetes resource given a YAML configuration || +| create | creates the Kubernetes resource given an object configuration | [create-job-wait.js](./examples/create-job-wait.js) | +| delete | removes the named Job | | +| get | returns the named Jobs | | +| list | returns a collection of Jobs | | +| wait | wait for all Jobs to complete | [wait-job.js](./examples/wait-job.js) | ```javascript import { Kubernetes } from 'k6/x/kubernetes'; diff --git a/examples/apply-job.js b/examples/apply-job.js deleted file mode 100644 index 15f39c9..0000000 --- a/examples/apply-job.js +++ /dev/null @@ -1,35 +0,0 @@ -import { Kubernetes } from 'k6/x/kubernetes'; -import {check, sleep} from 'k6'; - -function getJobYaml(name) { - return `apiVersion: batch/v1 -kind: Job -metadata: - name: ` + name + ` -spec: - template: - spec: - containers: - - name: ` + name + ` - image: perl - command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] - restartPolicy: Never - backoffLimit: 4 -` -} - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const nameSpace = "default"; - const name = "job-name"; - - kubernetes.jobs.apply(getJobYaml(name), nameSpace); - const job_list = kubernetes.jobs.list(nameSpace).map(function(job){ - return job.name; - }) - sleep(1); - check(job_list, {'Job was created': (job) => job.indexOf(name) != -1}); -} - diff --git a/examples/create-job-autodelete.js b/examples/create-job-autodelete.js deleted file mode 100644 index 2c0390f..0000000 --- a/examples/create-job-autodelete.js +++ /dev/null @@ -1,35 +0,0 @@ - -import { sleep } from 'k6'; -import { Kubernetes } from 'k6/x/kubernetes'; - -function getJobNames(nameSpace, kubernetes) { - return kubernetes.jobs.list(nameSpace).map(function(job){ - return job.name - }) -} - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const namespace = "default" - const jobName = "new-job" - const image = "busybox" - const command = ["sh", "-c", "sleep 3"] - - kubernetes.jobs.create({ - namespace: namespace, - name: jobName, - image: image, - command: command, - wait: "10s", - autodelete: true - }) - console.log("job completed") - sleep(3) // wait for garbage collection - const jobPod = kubernetes.pods.list().find(pod => pod.name.startsWith(jobName)) - console.log(jobPod) - if (!jobPod) { - console.log("pods deleted") - } -} diff --git a/examples/create-job-by-nodename.js b/examples/create-job-by-nodename.js deleted file mode 100644 index 6fa26cf..0000000 --- a/examples/create-job-by-nodename.js +++ /dev/null @@ -1,35 +0,0 @@ - -import { sleep } from 'k6'; -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - - const nodes = kubernetes.nodes.list(); - const nodeName = nodes[0].name; - const namespace = "default" - const jobName = "new-nodename-job" - const image = "perl" - const command = ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] - - kubernetes.jobs.create({ - namespace: namespace, - name: jobName, - node_name: nodeName, - image: image, - command: command - }) - sleep(1) - - const job = kubernetes.jobs.list(namespace).find((job) => { - return job.spec.template.spec.node_name === nodeName - }); - - if(job) { - console.log(job.name + " job has been created successfully") - } else { - throw jobName + " job was not created" - } -} diff --git a/examples/create-job.js b/examples/create-job.js deleted file mode 100644 index 814f6b2..0000000 --- a/examples/create-job.js +++ /dev/null @@ -1,33 +0,0 @@ - -import { sleep } from 'k6'; -import { Kubernetes } from 'k6/x/kubernetes'; - -function getJobNames(nameSpace, kubernetes) { - return kubernetes.jobs.list(nameSpace).map(function(job){ - return job.name - }) -} - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const namespace = "default" - const jobName = "new-job" - const image = "perl" - const command = ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] - - kubernetes.jobs.create({ - namespace: namespace, - name: jobName, - image: image, - command: command - }) - sleep(1) - const jobsList = getJobNames(namespace, kubernetes) - if(jobsList.indexOf(jobName) != -1) { - console.log(jobName + " job has been created successfully") - } else { - throw jobName + " job was not created" - } -} diff --git a/examples/get-job.js b/examples/get-job.js deleted file mode 100644 index cbbbd7d..0000000 --- a/examples/get-job.js +++ /dev/null @@ -1,12 +0,0 @@ - -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const nameSpace = "somenamespace" - const name = "jobname" - const pod = kubernetes.jobs.get(name, nameSpace) - console.log(JSON.stringify(pod.object_meta, null, 2)) -} diff --git a/examples/job_operations.js b/examples/job_operations.js new file mode 100644 index 0000000..5f36888 --- /dev/null +++ b/examples/job_operations.js @@ -0,0 +1,89 @@ +import { Kubernetes } from 'k6/x/kubernetes'; +import { describe, expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.2/index.js'; +import { load, dump } from 'https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs'; + +let json = { + apiVersion: "batch/v1", + kind: "Job", + metadata: { + name: "json-job", + namespace: "default", + }, + spec: { + ttlSecondsAfterFinished: 30, + template: { + spec: { + containers: [ + { + name: "myjob", + image: "perl:5.34.0", + command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"], + }, + ], + restartPolicy: "Never", + } + }, + backoffLimit: 4, + } +} + +let yaml = ` +apiVersion: batch/v1 +kind: Job +metadata: + name: yaml-job + namespace: default +spec: + ttlSecondsAfterFinished: 30 + suspend: false + template: + spec: + containers: + - name: myjob + image: perl:5.34.0 + command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"] + restartPolicy: Never + backoffLimit: 4 +` + +export default function () { + const kubernetes = new Kubernetes(); + + describe('JSON-based resources', () => { + const name = json.metadata.name + const ns = json.metadata.namespace + + let job + + describe('Create our job using the JSON definition', () => { + job = kubernetes.create(json) + expect(job.metadata, 'new job').to.have.property('uid') + }) + + describe('Retrieve all available jobs', () => { + expect(kubernetes.list("Job.batch", ns).length, 'total jobs').to.be.at.least(1) + }) + + describe('Retrieve our job by name and namespace', () => { + let fetched = kubernetes.get("Job.batch", name, ns) + expect(job.metadata.uid, 'created and fetched uids').to.equal(fetched.metadata.uid) + }) + + describe('Remove our jobs to cleanup', () => { + kubernetes.delete("Job.batch", name, ns) + }) + }) + + describe('YAML-based resources', () => { + let yamlObject = load(yaml) + const name = yamlObject.metadata.name + const ns = yamlObject.metadata.namespace + + describe('Create our job using the YAML definition', () => { + kubernetes.apply(yaml) + let created = kubernetes.get("Job.batch", name, ns) + expect(created.metadata, 'new job').to.have.property('uid') + }) + }) + +} diff --git a/examples/kill-job.js b/examples/kill-job.js deleted file mode 100644 index bfe379c..0000000 --- a/examples/kill-job.js +++ /dev/null @@ -1,25 +0,0 @@ - -import { sleep } from 'k6'; -import { Kubernetes } from 'k6/x/kubernetes'; - -function getJobNames(nameSpace, kubernetes) { - return kubernetes.jobs.list(nameSpace).map(function(job){ - return job.name - }) -} - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const nameSpace = "default" - const jobName = "new-job" - kubernetes.jobs.kill(jobName, nameSpace) - sleep(1) - let jobsList = getJobNames(nameSpace, kubernetes) - if(jobsList.indexOf(jobName) == -1) { - console.log(jobName + " job has been killed successfully") - } else { - throw jobName + " job was not killed" - } -} diff --git a/examples/list-jobs.js b/examples/list-jobs.js deleted file mode 100644 index 9531cd7..0000000 --- a/examples/list-jobs.js +++ /dev/null @@ -1,14 +0,0 @@ - -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const pods = kubernetes.jobs.list('ingress-nginx') - console.log(`${pods.length} Jobs found:`) - const info = pods.map(function(job){ - return job.name - }) - console.log(JSON.stringify(info, null, 2)) -} From 920de2e51bdcb03cd0fdef7ccce93501475eb8ea Mon Sep 17 00:00:00 2001 From: Paul Balogh Date: Tue, 11 Apr 2023 15:08:04 -0500 Subject: [PATCH 09/15] Adding integration tests for Nodes Signed-off-by: Paul Balogh --- README.md | 6 +++--- examples/list-nodes.js | 21 --------------------- examples/node_operations.js | 19 +++++++++++++++++++ internal/testutils/fake.go | 2 +- 4 files changed, 23 insertions(+), 25 deletions(-) delete mode 100644 examples/list-nodes.js create mode 100644 examples/node_operations.js diff --git a/README.md b/README.md index 349b0df..81525da 100644 --- a/README.md +++ b/README.md @@ -381,9 +381,9 @@ export default function () { ### (Deprecated) `Client.nodes` -| Method | Description | Example | -| ------------ | ------ | ---------------------------------------- | -| list | returns a collection of Nodes comprising the cluster | [list-nodes.js](./examples/list-nodes.js) | +| Method | Description | +| ------------ | ------ | +| list | returns a collection of Nodes comprising the cluster | ```javascript import { Kubernetes } from 'k6/x/kubernetes'; diff --git a/examples/list-nodes.js b/examples/list-nodes.js deleted file mode 100644 index 52ac634..0000000 --- a/examples/list-nodes.js +++ /dev/null @@ -1,21 +0,0 @@ - -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const nodes = kubernetes.nodes.list() - console.log(`${nodes.length} Nodes found:`) - const info = nodes.map(function(node){ - let conditions = {} - node.status.conditions.forEach(function(condition) { - conditions[condition.type] = condition.status - }) - return { - name: node.name, - conditions: conditions - } - }) - console.log(JSON.stringify(info, null, 2)) -} diff --git a/examples/node_operations.js b/examples/node_operations.js new file mode 100644 index 0000000..3445f01 --- /dev/null +++ b/examples/node_operations.js @@ -0,0 +1,19 @@ +import { Kubernetes } from "k6/x/kubernetes"; +import { describe, expect } from "https://jslib.k6.io/k6chaijs/4.3.4.3/index.js"; + +export default function () { + const kubernetes = new Kubernetes(); + + let nodes + + describe('Retrieve all available Nodes', () => { + nodes = kubernetes.list("Node") + expect(nodes.length, 'total nodes').to.be.at.least(1) + }) + + describe('Retrieve our Node by name', () => { + let fetched = kubernetes.get("Node", nodes[0].metadata.name) + expect(nodes[0].metadata.uid, 'fetched uids').to.equal(fetched.metadata.uid) + }) + +} diff --git a/internal/testutils/fake.go b/internal/testutils/fake.go index 4a7863b..e518eb2 100644 --- a/internal/testutils/fake.go +++ b/internal/testutils/fake.go @@ -47,7 +47,7 @@ func (f *FakeRESTMapper) RESTMapping(gk schema.GroupKind, versions ...string) (* return nil, fmt.Errorf("unknown kind: '%s'", gk.Kind) } scope := meta.RESTScopeNamespace - if gk.Kind == "Namespace" { + if gk.Kind == "Namespace" || gk.Kind == "Node" { scope = meta.RESTScopeRoot } From 09f41510351e9d81456c0c062220d2516c8abe9b Mon Sep 17 00:00:00 2001 From: Paul Balogh Date: Tue, 11 Apr 2023 15:30:24 -0500 Subject: [PATCH 10/15] Adding integration tests for Pods Signed-off-by: Paul Balogh --- README.md | 18 ++--- examples/add-ephemeral.js | 43 ------------ examples/create-pod-wait.js | 25 ------- examples/create-pod.js | 32 --------- examples/create_get_list_delete_pod.js | 46 ------------ examples/get-pod.js | 12 ---- examples/kill-pod.js | 25 ------- examples/list-pods.js | 18 ----- examples/pod_operations.js | 97 ++++++++++++++++++++++++++ examples/wait-pod.js | 32 --------- examples/wait_pod_running.js | 38 ---------- 11 files changed, 106 insertions(+), 280 deletions(-) delete mode 100644 examples/add-ephemeral.js delete mode 100644 examples/create-pod-wait.js delete mode 100644 examples/create-pod.js delete mode 100644 examples/create_get_list_delete_pod.js delete mode 100644 examples/get-pod.js delete mode 100644 examples/kill-pod.js delete mode 100644 examples/list-pods.js create mode 100644 examples/pod_operations.js delete mode 100644 examples/wait-pod.js delete mode 100644 examples/wait_pod_running.js diff --git a/README.md b/README.md index 81525da..478fb7a 100644 --- a/README.md +++ b/README.md @@ -440,15 +440,15 @@ export default function () { ### (Deprecated) `Client.pods` -| Method | Description | Example | -| ------------ | ------ | ---------------------------------------- | -| create | runs a pod | [create-pod.js](./examples/create-pod.js), [create-pod-wait.js](./examples/create-pod-wait.js) | -| delete | removes the named Pod | | -| get | returns the named Pod | [get-pod.js](./examples/get-pod.js) | -| list | returns a collection of Pods | [list-pods.js](./examples/list-pods.js) | -| wait | wait for the Pod to be in a given status | [wait-pod.js](./examples/wait-pod.js) | -| exec | executes a non-interactive command | [exec-command.js](./examples/exec-command.js) | -| addEphemeralContainer | adds an ephemeral container to a running pod | [add-ephemeral.js](./examples/add-ephemeral.js) | +| Method | Description | +| ------------ | ------ | +| create | runs a pod | +| delete | removes the named Pod | +| get | returns the named Pod | +| list | returns a collection of Pods | +| wait | wait for the Pod to be in a given status | +| exec | executes a non-interactive command | +| addEphemeralContainer | adds an ephemeral container to a running pod | diff --git a/examples/add-ephemeral.js b/examples/add-ephemeral.js deleted file mode 100644 index a2fe03a..0000000 --- a/examples/add-ephemeral.js +++ /dev/null @@ -1,43 +0,0 @@ -import { sleep } from 'k6'; -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const namespace = "default" - const podName = "new-pod" - const image = "busybox" - const command = ["sh", "-c", "sleep 300"] - const containerName = "ephemeral" - const containerImage = "busybox" - const containerCommand = ["sh", "-c", "sleep 300"] - const containerCapabilities = ["NET_ADMIN","NET_RAW"] - - kubernetes.pods.create({ - namespace: namespace, - name: podName, - image: image, - command: command, - wait: "5s" - }) - - kubernetes.pods.addEphemeralContainer( - podName, - namespace, - { - name: containerName, - image: containerImage, - command: containerCommand, - capabilities: containerCapabilities, - wait: "5s" - } - ) - - let pod = kubernetes.pods.get(podName, namespace) - if (pod.spec.ephemeral_containers[0].name == containerName) { - console.log(containerName + " container successfully created") - } else { - throw containername + " container not created" - } -} diff --git a/examples/create-pod-wait.js b/examples/create-pod-wait.js deleted file mode 100644 index e1c3686..0000000 --- a/examples/create-pod-wait.js +++ /dev/null @@ -1,25 +0,0 @@ - -import { sleep } from 'k6'; -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - }) - const namespace = "default" - const podName = "new-pod" - const image = "busybox" - const command = ["sh", "-c", "/bin/false"] - -try { - kubernetes.pods.create({ - namespace: namespace, - name: podName, - image: image, - command: command, - wait: "5s" - }) - console.log(podName + " has been created") -} catch (err) { - console.log("error creating pod " + podName + ": " + err) -} -} diff --git a/examples/create-pod.js b/examples/create-pod.js deleted file mode 100644 index d8ae5bd..0000000 --- a/examples/create-pod.js +++ /dev/null @@ -1,32 +0,0 @@ - -import { sleep } from 'k6'; -import { Kubernetes } from 'k6/x/kubernetes'; - -function getPodNames(nameSpace, kubernetes) { - return kubernetes.pods.list(nameSpace).map(function(pod){ - return pod.name - }) -} - -export default function () { - const kubernetes = new Kubernetes({ - }) - const namespace = "default" - const podName = "new-pod" - const image = "busybox" - const command = ["sh", "-c", "sleep 300"] - - kubernetes.pods.create({ - namespace: namespace, - name: podName, - image: image, - command: command - }) - sleep(1) - const podsList = getPodNames(namespace, kubernetes) - if(podsList.indexOf(podName) != -1) { - console.log(podName + " pod has been created successfully") - } else { - throw podName + " pod was not created" - } -} diff --git a/examples/create_get_list_delete_pod.js b/examples/create_get_list_delete_pod.js deleted file mode 100644 index 6dfa120..0000000 --- a/examples/create_get_list_delete_pod.js +++ /dev/null @@ -1,46 +0,0 @@ -import { Kubernetes } from 'k6/x/kubernetes' -import { sleep } from 'k6' - -const k8s = new Kubernetes() - -const podSpec = { - apiVersion: "v1", - kind: "Pod", - metadata: { - name: "busybox", - namespace: "default" - }, - spec: { - containers: [ - { - name: "busybox", - image: "busybox", - command: ["sh", "-c", "sleep 30"] - } - ] - } -} - -export default function(){ - var created = k8s.create(podSpec) - console.log("pod '" + created.metadata.name +"' created") - - var pod = k8s.get(podSpec.kind, podSpec.metadata.name, podSpec.metadata.namespace) - if (podSpec.metadata.name != pod.metadata.name) { - throw new Error("fetch by name did not return the Pod. Expected: " + podSpec.metadata.name + " but got: " + fetched.name) - } - - const pods = k8s.list(podSpec.kind, podSpec.metadata.namespace) - if (pods === undefined || pods.length < 1) { - throw new Error("expected listing with 1 Pod") - } - - k8s.delete(podSpec.kind, podSpec.metadata.name, podSpec.metadata.namespace) - - // give time for the pod to be deleted - sleep(5) - - if (k8s.list(podSpec.kind, podSpec.metadata.namespace).length != 0) { - throw new Error("deletion failed to remove pod") - } -} diff --git a/examples/get-pod.js b/examples/get-pod.js deleted file mode 100644 index 4bf6e44..0000000 --- a/examples/get-pod.js +++ /dev/null @@ -1,12 +0,0 @@ - -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const nameSpace = "default" - const name = "pod_name" - const pod = kubernetes.pods.get(name, nameSpace) - console.log(JSON.stringify(pod, null, 2)) -} diff --git a/examples/kill-pod.js b/examples/kill-pod.js deleted file mode 100644 index 7b09346..0000000 --- a/examples/kill-pod.js +++ /dev/null @@ -1,25 +0,0 @@ - -import { sleep } from 'k6'; -import { Kubernetes } from 'k6/x/kubernetes'; - -function getPodNames(nameSpace, kubernetes) { - return kubernetes.pods.list(nameSpace).map(function(pod){ - return pod.name - }) -} - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const nameSpace = "default" - let podsList = getPodNames(nameSpace, kubernetes) - const podName = podsList[0] - kubernetes.pods.kill(podName, nameSpace) - sleep(1) - if (kubernetes.pods.isTerminating(podName, nameSpace)) { - console.log(podName + " pod has been killed successfully") - } else { - throw `${podName} Pod was not killed ${podsList[podName]}` - } -} \ No newline at end of file diff --git a/examples/list-pods.js b/examples/list-pods.js deleted file mode 100644 index da39edf..0000000 --- a/examples/list-pods.js +++ /dev/null @@ -1,18 +0,0 @@ - -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const pods = kubernetes.pods.list() - console.log(`${pods.length} Pods found:`) - const info = pods.map(function(pod){ - return { - namespace: pod.namespace, - name: pod.name, - status: pod.status.phase - } - }) - console.log(JSON.stringify(info, null, 2)) -} diff --git a/examples/pod_operations.js b/examples/pod_operations.js new file mode 100644 index 0000000..85a0ea6 --- /dev/null +++ b/examples/pod_operations.js @@ -0,0 +1,97 @@ +import { Kubernetes } from 'k6/x/kubernetes'; +import { describe, expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.3/index.js'; +import { load, dump } from 'https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs'; + +let json = { + apiVersion: "v1", + kind: "Pod", + metadata: { + name: "json-pod", + namespace: "default" + }, + spec: { + containers: [ + { + name: "busybox", + image: "busybox", + command: ["sh", "-c", "sleep 30"] + } + ] + } +} + +let yaml = ` +apiVersion: v1 +kind: Pod +metadata: + name: yaml-pod + namespace: default +spec: + containers: + - name: busybox + image: busybox + command: ["sh", "-c", "sleep 30"] +` + +export default function () { + const kubernetes = new Kubernetes(); + + describe('JSON-based resources', () => { + const name = json.metadata.name + const ns = json.metadata.namespace + const helpers = kubernetes.helpers(ns) + + let pod + + describe('Create our pod using the JSON definition and wait until running', () => { + pod = kubernetes.create(json) + expect(pod.metadata, 'new pod').to.have.property('uid') + expect(pod.status.phase, 'new pod status').to.equal('Pending') + + helpers.waitPodRunning(name, 10) + + let fetched = kubernetes.get("Pod", name, ns) + expect(fetched.status.phase, 'status after waiting').to.equal('Running') + }) + + describe('Retrieve all available pods', () => { + expect(kubernetes.list("Pod", ns).length, 'total pods').to.be.at.least(1) + }) + + describe('Retrieve our pod by name and namespace', () => { + let fetched = kubernetes.get("Pod", name, ns) + expect(pod.metadata.uid, 'created and fetched uids').to.equal(fetched.metadata.uid) + }) + + describe('Remove our pods to cleanup', () => { + kubernetes.delete("Pod", name, ns) + }) + }) + + describe('YAML-based resources', () => { + let yamlObject = load(yaml) + const name = yamlObject.metadata.name + const ns = yamlObject.metadata.namespace + + describe('Create our pod using the YAML definition', () => { + kubernetes.apply(yaml) + let created = kubernetes.get("Pod", name, ns) + expect(created.metadata, 'new pod').to.have.property('uid') + }) + + describe('Update our Pod with a modified YAML definition', () => { + const newValue = "busybox:1.35.0" + yamlObject.spec.containers[0].image = newValue + let newYaml = dump(yamlObject) + + kubernetes.apply(newYaml) + let updated = kubernetes.get("Pod", name, ns) + expect(updated.spec.containers[0].image, 'changed value').to.be.equal(newValue) + }) + + describe('Remove our pod to cleanup', () => { + kubernetes.delete("Pod", name, ns) + }) + }) + +} diff --git a/examples/wait-pod.js b/examples/wait-pod.js deleted file mode 100644 index a0ce6cc..0000000 --- a/examples/wait-pod.js +++ /dev/null @@ -1,32 +0,0 @@ - -import { sleep } from 'k6'; -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - }) - const namespace = "default" - const podName = "new-pod" - const image = "busybox" - const command = ["sh", "-c", "sleep 5"] - - kubernetes.pods.create({ - namespace: namespace, - name: podName, - image: image, - command: command - }) - - - const options = { - namespace: namespace, - name: podName, - status: "Succeeded", - timeout: "10s" - } - if (kubernetes.pods.wait(options)) { - console.log(podName + " pod completed successfully") - } else { - throw podName + " is not completed" - } -} diff --git a/examples/wait_pod_running.js b/examples/wait_pod_running.js deleted file mode 100644 index daf8ecc..0000000 --- a/examples/wait_pod_running.js +++ /dev/null @@ -1,38 +0,0 @@ -import { Kubernetes } from 'k6/x/kubernetes'; - -let pod = { - apiVersion: "v1", - kind: "Pod", - metadata: { - name: "busybox", - namespace: "default" - }, - spec: { - containers: [ - { - name: "busybox", - image: "busybox", - command: ["sh", "-c", "sleep 30"] - } - ] - } -} - -export default function () { - const kubernetes = new Kubernetes(); - - const ns = "default" - - // create pod in test namespace - pod.metadata.namespace = ns - kubernetes.create(pod) - - // get helpers for test namespace - const helpers = kubernetes.helpers(ns) - - // wait for pod to be running - const timeout = 10 - if (!helpers.waitPodRunning(pod.metadata.name, timeout)) { - console.log(`"pod ${pod.metadata.name} not ready after ${timeout} seconds`) - } -} \ No newline at end of file From 05d53e3196b69b435dd1827fb9bcbe00e2b594ff Mon Sep 17 00:00:00 2001 From: Paul Balogh Date: Wed, 12 Apr 2023 07:32:44 -0500 Subject: [PATCH 11/15] Adding integration tests for Deployments Signed-off-by: Paul Balogh --- README.md | 16 +-- examples/apply-deployment-service-ingress.js | 94 -------------- examples/deployment_operations.js | 126 +++++++++++++++++++ examples/get-deployment.js | 12 -- examples/list-deployments.js | 17 --- 5 files changed, 134 insertions(+), 131 deletions(-) delete mode 100644 examples/apply-deployment-service-ingress.js create mode 100644 examples/deployment_operations.js delete mode 100644 examples/get-deployment.js delete mode 100644 examples/list-deployments.js diff --git a/README.md b/README.md index 478fb7a..29be864 100644 --- a/README.md +++ b/README.md @@ -271,13 +271,13 @@ export default function () { ### (Deprecated) `Client.deployments` -| Method | Description | Example | -| ------------ | ------ | ---------------------------------------- | -| apply | creates the Kubernetes resource given a YAML configuration | [apply-deployment-service-ingress.js](./examples/apply-deployment-service-ingress.js) | -| create | creates the Kubernetes resource given an object configuration | | -| delete | removes the named Deployment | | -| get | returns the named Deployment | [get-configmap.js](./examples/get-deployment.js) | -| list | returns a collection of Deployments | [list-configmaps.js](./examples/list-deployments.js) | +| Method | Description | +| ------------ | ------ | +| apply | creates the Kubernetes resource given a YAML configuration | +| create | creates the Kubernetes resource given an object configuration | +| delete | removes the named Deployment | +| get | returns the named Deployment | +| list | returns a collection of Deployments | @@ -507,7 +507,7 @@ export default function () { | Method | Description | Example | | ------------ | ------ | ---------------------------------------- | -| apply | creates the Kubernetes resource given a YAML configuration | [apply-deployment-service-ingress.js](./examples/apply-deployment-service-ingress.js) | +| apply | creates the Kubernetes resource given a YAML configuration | | | create | creates the Kubernetes resource given an object configuration | | | delete | removes the named service | | | get | returns the named service | [get-service.js](./examples/get-service.js) | diff --git a/examples/apply-deployment-service-ingress.js b/examples/apply-deployment-service-ingress.js deleted file mode 100644 index 2c7e05b..0000000 --- a/examples/apply-deployment-service-ingress.js +++ /dev/null @@ -1,94 +0,0 @@ -import { Kubernetes } from 'k6/x/kubernetes'; -import {check, sleep} from 'k6'; - -function getDeploymentYaml(name, app) { - return `kind: Deployment -apiVersion: apps/v1 -metadata: - name: ` + name + ` -spec: - replicas: 1 - selector: - matchLabels: - app: ` + app +` - - template: - metadata: - labels: - app: ` + app + ` - spec: - containers: - - name: nginx - image: nginx:1.14.2 - ports: - - containerPort: 80 -` -} - -function getServiceYaml(name, app) { - return `apiVersion: v1 -kind: Service -metadata: - name: ` + name + ` -spec: - selector: - app: ` + app + ` - type: ClusterIP - ports: - - protocol: TCP - port: 80 - targetPort: 80 - name: http -` -} - -function getIngressYaml(name, url) { - return `apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: ` + name + ` - annotations: - kuberentes.io/ingress.class: "nginx" -spec: - rules: - - host: ` + url + ` - http: - paths: - - path: / - pathType: ImplementationSpecific - backend: - service: - name: ` + name + ` - port: - name: http -` -} - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const nameSpace = "default"; - const name = "deployment-name"; - const app = 'app-label'; - const url = 'ingress-url.com'; - - kubernetes.deployments.apply(getDeploymentYaml(name, app), nameSpace); - kubernetes.services.apply(getServiceYaml(name, app), nameSpace); - kubernetes.ingresses.apply(getIngressYaml(name, url), nameSpace); - sleep(1); - - const depl_list = kubernetes.deployments.list(nameSpace).map(function(depl){ - return depl.name; - }) - check(depl_list, {'Deployment was created': (d) => d.indexOf(name) != -1}); - const serv_list = kubernetes.services.list(nameSpace).map(function(serv){ - return serv.name; - }) - check(serv_list, {'Service was created': (s) => s.indexOf(name) != -1}); - const ing_list = kubernetes.ingresses.list(nameSpace).map(function(ing){ - return ing.name; - }) - check(ing_list, {'Ingress was created': (i) => i.indexOf(name) != -1}); -} - diff --git a/examples/deployment_operations.js b/examples/deployment_operations.js new file mode 100644 index 0000000..a20e538 --- /dev/null +++ b/examples/deployment_operations.js @@ -0,0 +1,126 @@ +import { Kubernetes } from "k6/x/kubernetes"; +import { describe, expect } from "https://jslib.k6.io/k6chaijs/4.3.4.3/index.js"; +import { load, dump } from "https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs"; + +let json = { + apiVersion: "apps/v1", + kind: "Deployment", + metadata: { + name: "json-deployment", + namespace: "default", + }, + spec: { + replicas: 1, + selector: { + matchLabels: { + app: "json-intg-test" + } + }, + template: { + metadata: { + labels: { + app: "json-intg-test" + } + }, + spec: { + containers: [ + { + name: "nginx", + image: "nginx:1.14.2", + ports: [ + {containerPort: 80} + ] + } + ] + } + } + } +} + +let yaml = ` +apiVersion: apps/v1 +kind: Deployment +metadata: + name: yaml-deployment + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app: yaml-intg-test + template: + metadata: + labels: + app: yaml-intg-test + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 +` + +export default function () { + const kubernetes = new Kubernetes(); + + describe('JSON-based resources', () => { + const name = json.metadata.name + const ns = json.metadata.namespace + + let deployment + + describe('Create our Deployment using the JSON definition', () => { + deployment = kubernetes.create(json) + expect(deployment.metadata, 'new deployment').to.have.property('uid') + }) + + describe('Retrieve all available Deployments', () => { + expect(kubernetes.list("Deployment.apps", ns).length, 'total deployments').to.be.at.least(1) + }) + + describe('Retrieve our Deployment by name and namespace', () => { + let fetched = kubernetes.get("Deployment.apps", name, ns) + expect(deployment.metadata.uid, 'created and fetched uids').to.equal(fetched.metadata.uid) + }) + + describe('Update our Deployment with a modified JSON definition', () => { + const newValue = 2 + json.spec.replicas = newValue + + kubernetes.update(json) + let updated = kubernetes.get("Deployment.apps", name, ns) + expect(updated.spec.replicas, 'changed value').to.be.equal(newValue) + }) + + describe('Remove our Deployment to cleanup', () => { + kubernetes.delete("Deployment.apps", name, ns) + }) + }) + + describe('YAML-based resources', () => { + let yamlObject = load(yaml) + const name = yamlObject.metadata.name + const ns = yamlObject.metadata.namespace + + describe('Create our Deployment using the YAML definition', () => { + kubernetes.apply(yaml) + let created = kubernetes.get("Deployment.apps", name, ns) + expect(created.metadata, 'new deployment').to.have.property('uid') + }) + + describe('Update our Deployment with a modified YAML definition', () => { + const newValue = 2 + yamlObject.spec.replicas = newValue + let newYaml = dump(yamlObject) + + kubernetes.apply(newYaml) + let updated = kubernetes.get("Deployment.apps", name, ns) + expect(updated.spec.replicas, 'changed value').to.be.equal(newValue) + }) + + describe('Remove our Deployment to cleanup', () => { + kubernetes.delete("Deployment.apps", name, ns) + }) + }) + +} diff --git a/examples/get-deployment.js b/examples/get-deployment.js deleted file mode 100644 index 756069d..0000000 --- a/examples/get-deployment.js +++ /dev/null @@ -1,12 +0,0 @@ - -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const nameSpace = "default" - const name = "deploymentname" - const deployment = kubernetes.deployments.get(name, nameSpace) - console.log(JSON.stringify(deployment.object_meta, null, 2)) -} diff --git a/examples/list-deployments.js b/examples/list-deployments.js deleted file mode 100644 index 2d69d14..0000000 --- a/examples/list-deployments.js +++ /dev/null @@ -1,17 +0,0 @@ - -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const deployments = kubernetes.deployments.list() - console.log(`${deployments.length} Deployments found:`) - const info = deployments.map(function (deployment) { - return { - namespace: deployment.namespace, - name: deployment.name, - } - }) - console.log(JSON.stringify(info, null, 2)) -} From 345decf82dadccc6803063ba500e37bfba81d35a Mon Sep 17 00:00:00 2001 From: Paul Balogh Date: Wed, 12 Apr 2023 08:43:58 -0500 Subject: [PATCH 12/15] Adding integration tests for Services Signed-off-by: Paul Balogh --- README.md | 14 ++--- examples/get-service.js | 12 ---- examples/list-services.js | 17 ------ examples/service_operations.js | 108 +++++++++++++++++++++++++++++++++ 4 files changed, 115 insertions(+), 36 deletions(-) delete mode 100644 examples/get-service.js delete mode 100644 examples/list-services.js create mode 100644 examples/service_operations.js diff --git a/README.md b/README.md index 29be864..6eb3efd 100644 --- a/README.md +++ b/README.md @@ -505,13 +505,13 @@ export default function () { ### (Deprecated) `Client.services` -| Method | Description | Example | -| ------------ | ------ | ---------------------------------------- | -| apply | creates the Kubernetes resource given a YAML configuration | | -| create | creates the Kubernetes resource given an object configuration | | -| delete | removes the named service | | -| get | returns the named service | [get-service.js](./examples/get-service.js) | -| list | returns a collection of services | [list-services.js](./examples/list-services.js) | +| Method | Description | +| ------------ | ------ | +| apply | creates the Kubernetes resource given a YAML configuration | +| create | creates the Kubernetes resource given an object configuration | +| delete | removes the named service | +| get | returns the named service | +| list | returns a collection of services | ```javascript diff --git a/examples/get-service.js b/examples/get-service.js deleted file mode 100644 index 256add8..0000000 --- a/examples/get-service.js +++ /dev/null @@ -1,12 +0,0 @@ - -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const nameSpace = "default" - const name = "svc_name" - const svc = kubernetes.services.get(name, nameSpace) - console.log(JSON.stringify(svc, null, 2)) -} diff --git a/examples/list-services.js b/examples/list-services.js deleted file mode 100644 index 73bfd7c..0000000 --- a/examples/list-services.js +++ /dev/null @@ -1,17 +0,0 @@ - -import { Kubernetes } from 'k6/x/kubernetes'; - -export default function () { - const kubernetes = new Kubernetes({ - // config_path: "/path/to/kube/config", ~/.kube/config by default - }) - const svcs = kubernetes.services.list() - console.log(`${svcs.length} Services found:`) - const info = svcs.map(function (svc) { - return { - namespace: svc.namespace, - name: svc.name, - } - }) - console.log(JSON.stringify(info, null, 2)) -} diff --git a/examples/service_operations.js b/examples/service_operations.js new file mode 100644 index 0000000..01efdd5 --- /dev/null +++ b/examples/service_operations.js @@ -0,0 +1,108 @@ +import { Kubernetes } from "k6/x/kubernetes"; +import { describe, expect } from "https://jslib.k6.io/k6chaijs/4.3.4.2/index.js"; +import { load, dump } from "https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs"; + +let json = { + apiVersion: "v1", + kind: "Service", + metadata: { + name: "json-service", + namespace: "default", + }, + spec: { + selector: { + app: "json-intg-test" + }, + type: "ClusterIP", + ports: [ + { + name: "http", + protocol: "TCP", + port: 80, + targetPort: 80, + } + ] + } +} + +let yaml = ` +apiVersion: v1 +kind: Service +metadata: + name: yaml-service + namespace: default +spec: + selector: + app: yaml-intg-test + type: ClusterIP + ports: + - name: http + protocol: TCP + port: 80 + targetPort: 80 +` + +export default function () { + const kubernetes = new Kubernetes(); + + describe('JSON-based resources', () => { + const name = json.metadata.name + const ns = json.metadata.namespace + + let service + + describe('Create our Service using the JSON definition', () => { + service = kubernetes.create(json) + expect(service.metadata, 'new service').to.have.property('uid') + }) + + describe('Retrieve all available Services', () => { + expect(kubernetes.list("Service", ns).length, 'total services').to.be.at.least(1) + }) + + describe('Retrieve our Service by name and namespace', () => { + let fetched = kubernetes.get("Service", name, ns) + expect(service.metadata.uid, 'created and fetched uids').to.equal(fetched.metadata.uid) + }) + + describe('Update our Service with a modified JSON definition', () => { + const newValue = json.spec.selector.app + '-updated' + json.spec.selector.app = newValue + + kubernetes.update(json) + let updated = kubernetes.get("Service", name, ns) + expect(updated.spec.selector.app, 'changed value').to.be.equal(newValue) + }) + + describe('Remove our Service to cleanup', () => { + kubernetes.delete("Service", name, ns) + }) + }) + + describe('YAML-based resources', () => { + let yamlObject = load(yaml) + const name = yamlObject.metadata.name + const ns = yamlObject.metadata.namespace + + describe('Create our Service using the YAML definition', () => { + kubernetes.apply(yaml) + let created = kubernetes.get("Service", name, ns) + expect(created.metadata, 'new service').to.have.property('uid') + }) + + describe('Update our Service with a modified YAML definition', () => { + const newValue = yamlObject.spec.selector.app + '-updated' + yamlObject.spec.selector.app = newValue + let newYaml = dump(yamlObject) + + kubernetes.apply(newYaml) + let updated = kubernetes.get("Service", name, ns) + expect(updated.spec.selector.app, 'changed value').to.be.equal(newValue) + }) + + describe('Remove our Service to cleanup', () => { + kubernetes.delete("Service", name, ns) + }) + }) + +} From dd0a6619775a8d3190579c9d20f387c8704dbd49 Mon Sep 17 00:00:00 2001 From: Paul Balogh Date: Wed, 12 Apr 2023 09:32:06 -0500 Subject: [PATCH 13/15] Minor script cleanup Signed-off-by: Paul Balogh --- examples/configmap_operations.js | 2 +- examples/endpoints_operations.js | 4 ++-- examples/ingress_operations.js | 2 +- examples/job_operations.js | 4 ++-- examples/namespace_operations.js | 2 +- examples/persistentvolume_operations.js | 2 +- examples/persistentvolumeclaim_operations.js | 4 ++-- examples/secret_operations.js | 2 +- examples/service_operations.js | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/configmap_operations.js b/examples/configmap_operations.js index 8acd5c3..4c9c6d3 100644 --- a/examples/configmap_operations.js +++ b/examples/configmap_operations.js @@ -1,5 +1,5 @@ import { Kubernetes } from "k6/x/kubernetes"; -import { describe, expect } from "https://jslib.k6.io/k6chaijs/4.3.4.2/index.js"; +import { describe, expect } from "https://jslib.k6.io/k6chaijs/4.3.4.3/index.js"; import { load, dump } from "https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs"; let json = { diff --git a/examples/endpoints_operations.js b/examples/endpoints_operations.js index b42044c..b4a8436 100644 --- a/examples/endpoints_operations.js +++ b/examples/endpoints_operations.js @@ -1,6 +1,6 @@ import { Kubernetes } from "k6/x/kubernetes"; -import { describe, expect } from "https://jslib.k6.io/k6chaijs/4.3.4.2/index.js"; -import { load, dump } from "https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs"; +import { describe, expect } from "https://jslib.k6.io/k6chaijs/4.3.4.3/index.js"; +import { load } from "https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs"; let json = { apiVersion: "v1", diff --git a/examples/ingress_operations.js b/examples/ingress_operations.js index 15c779f..c8e356c 100644 --- a/examples/ingress_operations.js +++ b/examples/ingress_operations.js @@ -1,5 +1,5 @@ import { Kubernetes } from 'k6/x/kubernetes'; -import { describe, expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.2/index.js'; +import { describe, expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.3/index.js'; import { load, dump } from 'https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs'; let json = { diff --git a/examples/job_operations.js b/examples/job_operations.js index 5f36888..470f072 100644 --- a/examples/job_operations.js +++ b/examples/job_operations.js @@ -1,6 +1,6 @@ import { Kubernetes } from 'k6/x/kubernetes'; -import { describe, expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.2/index.js'; -import { load, dump } from 'https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs'; +import { describe, expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.3/index.js'; +import { load } from 'https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs'; let json = { apiVersion: "batch/v1", diff --git a/examples/namespace_operations.js b/examples/namespace_operations.js index d4b6124..ce7f2b2 100644 --- a/examples/namespace_operations.js +++ b/examples/namespace_operations.js @@ -1,5 +1,5 @@ import { Kubernetes } from 'k6/x/kubernetes'; -import { describe, expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.2/index.js'; +import { describe, expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.3/index.js'; import { load, dump } from 'https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs'; let json = { diff --git a/examples/persistentvolume_operations.js b/examples/persistentvolume_operations.js index 515bb25..f0f2cae 100644 --- a/examples/persistentvolume_operations.js +++ b/examples/persistentvolume_operations.js @@ -1,5 +1,5 @@ import { Kubernetes } from 'k6/x/kubernetes'; -import { describe, expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.2/index.js'; +import { describe, expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.3/index.js'; import { load, dump } from 'https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs'; let json = { diff --git a/examples/persistentvolumeclaim_operations.js b/examples/persistentvolumeclaim_operations.js index b8f28c0..a5faf73 100644 --- a/examples/persistentvolumeclaim_operations.js +++ b/examples/persistentvolumeclaim_operations.js @@ -1,6 +1,6 @@ import { Kubernetes } from 'k6/x/kubernetes'; -import { describe, expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.2/index.js'; -import { load, dump } from 'https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs'; +import { describe, expect } from 'https://jslib.k6.io/k6chaijs/4.3.4.3/index.js'; +import { load } from 'https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs'; let json = { apiVersion: "v1", diff --git a/examples/secret_operations.js b/examples/secret_operations.js index 43990db..f752967 100644 --- a/examples/secret_operations.js +++ b/examples/secret_operations.js @@ -1,5 +1,5 @@ import { Kubernetes } from "k6/x/kubernetes"; -import { describe, expect } from "https://jslib.k6.io/k6chaijs/4.3.4.2/index.js"; +import { describe, expect } from "https://jslib.k6.io/k6chaijs/4.3.4.3/index.js"; import { load, dump } from "https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs"; let json = { diff --git a/examples/service_operations.js b/examples/service_operations.js index 01efdd5..c17ffcb 100644 --- a/examples/service_operations.js +++ b/examples/service_operations.js @@ -1,5 +1,5 @@ import { Kubernetes } from "k6/x/kubernetes"; -import { describe, expect } from "https://jslib.k6.io/k6chaijs/4.3.4.2/index.js"; +import { describe, expect } from "https://jslib.k6.io/k6chaijs/4.3.4.3/index.js"; import { load, dump } from "https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs"; let json = { From d90811582bb38f54ea8ba6d32d6fe235ecfabb82 Mon Sep 17 00:00:00 2001 From: Paul Balogh Date: Wed, 12 Apr 2023 10:01:20 -0500 Subject: [PATCH 14/15] Adding integration tests for StatefulSets Signed-off-by: Paul Balogh --- examples/statefulset_operations.js | 126 +++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 examples/statefulset_operations.js diff --git a/examples/statefulset_operations.js b/examples/statefulset_operations.js new file mode 100644 index 0000000..bfc6824 --- /dev/null +++ b/examples/statefulset_operations.js @@ -0,0 +1,126 @@ +import { Kubernetes } from "k6/x/kubernetes"; +import { describe, expect } from "https://jslib.k6.io/k6chaijs/4.3.4.3/index.js"; +import { load, dump } from "https://cdn.jsdelivr.net/npm/js-yaml@4.1.0/dist/js-yaml.mjs"; + +let json = { + apiVersion: "apps/v1", + kind: "StatefulSet", + metadata: { + name: "json-statefulset", + namespace: "default", + }, + spec: { + replicas: 1, + selector: { + matchLabels: { + app: "json-intg-test" + } + }, + template: { + metadata: { + labels: { + app: "json-intg-test" + } + }, + spec: { + containers: [ + { + name: "nginx", + image: "nginx:1.14.2", + ports: [ + {containerPort: 80} + ] + } + ] + } + } + } +} + +let yaml = ` +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: yaml-statefulset + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app: yaml-intg-test + template: + metadata: + labels: + app: yaml-intg-test + spec: + containers: + - name: nginx + image: nginx:1.14.2 + ports: + - containerPort: 80 +` + +export default function () { + const kubernetes = new Kubernetes(); + + describe('JSON-based resources', () => { + const name = json.metadata.name + const ns = json.metadata.namespace + + let statefulset + + describe('Create our StatefulSet using the JSON definition', () => { + statefulset = kubernetes.create(json) + expect(statefulset.metadata, 'new statefulset').to.have.property('uid') + }) + + describe('Retrieve all available StatefulSets', () => { + expect(kubernetes.list("StatefulSet.apps", ns).length, 'total statefulsets').to.be.at.least(1) + }) + + describe('Retrieve our StatefulSet by name and namespace', () => { + let fetched = kubernetes.get("StatefulSet.apps", name, ns) + expect(statefulset.metadata.uid, 'created and fetched uids').to.equal(fetched.metadata.uid) + }) + + describe('Update our StatefulSet with a modified JSON definition', () => { + const newValue = 2 + json.spec.replicas = newValue + + kubernetes.update(json) + let updated = kubernetes.get("StatefulSet.apps", name, ns) + expect(updated.spec.replicas, 'changed value').to.be.equal(newValue) + }) + + describe('Remove our StatefulSet to cleanup', () => { + kubernetes.delete("StatefulSet.apps", name, ns) + }) + }) + + describe('YAML-based resources', () => { + let yamlObject = load(yaml) + const name = yamlObject.metadata.name + const ns = yamlObject.metadata.namespace + + describe('Create our StatefulSet using the YAML definition', () => { + kubernetes.apply(yaml) + let created = kubernetes.get("StatefulSet.apps", name, ns) + expect(created.metadata, 'new statefulset').to.have.property('uid') + }) + + describe('Update our StatefulSet with a modified YAML definition', () => { + const newValue = 2 + yamlObject.spec.replicas = newValue + let newYaml = dump(yamlObject) + + kubernetes.apply(newYaml) + let updated = kubernetes.get("StatefulSet.apps", name, ns) + expect(updated.spec.replicas, 'changed value').to.be.equal(newValue) + }) + + describe('Remove our StatefulSet to cleanup', () => { + kubernetes.delete("StatefulSet.apps", name, ns) + }) + }) + +} From 1fc2fb9fffb5c89546381a0e6ad2e0086557b995 Mon Sep 17 00:00:00 2001 From: Paul Balogh Date: Wed, 12 Apr 2023 10:07:24 -0500 Subject: [PATCH 15/15] Include links to integration scripts for supported resource types Signed-off-by: Paul Balogh --- README.md | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 6eb3efd..80c24c7 100644 --- a/README.md +++ b/README.md @@ -71,18 +71,18 @@ This API offers methods for creating, retrieving, listing and deleting resources The kinds of resources currently supported are: -* ConfigMap -* Deployment -* Ingress -* Job -* Namespace -* Node -* PersistentVolume -* PersistentVolumeClaim -* Pod -* Secret -* Service -* StatefulSet +* [ConfigMap](examples/configmap_operations.js) +* [Deployment](examples/deployment_operations.js) +* [Ingress](examples/ingress_operations.js) +* [Job](examples/job_operations.js) +* [Namespace](examples/namespace_operations.js) +* [Node](examples/node_operations.js) +* [PersistentVolume](examples/persistentvolume_operations.js) +* [PersistentVolumeClaim](examples/persistentvolumeclaim_operations.js) +* [Pod](examples/pod_operations.js) +* [Secret](examples/secret_operations.js) +* [Service](examples/service_operations.js) +* [StatefulSet](examples/statefulset_operations.js) ### Examples