Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,6 @@ jobs:
- run: npm run lint
- run: npm audit --audit-level=critical
- run: npm run build-with-tests && npm run test-transpiled
- name: Create k8s Kind Cluster
uses: helm/kind-action@v1
- run: npm run integration-test
5 changes: 3 additions & 2 deletions examples/typescript/patch/patch-example.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { CoreV1Api, KubeConfig, setHeaderOptions, JsonPatch } from '@kubernetes/client-node';
import { CoreV1Api, KubeConfig, setHeaderOptions } from '@kubernetes/client-node';
import { PatchStrategy } from '@kubernetes/client-node/patch';

const kc = new KubeConfig();
kc.loadFromDefault();
Expand Down Expand Up @@ -28,7 +29,7 @@ try {
namespace: 'default',
body: patch,
},
setHeaderOptions('Content-Type', JsonPatch),
setHeaderOptions('Content-Type', PatchStrategy.JsonPatch),
);

console.log('Patched.');
Expand Down
271 changes: 270 additions & 1 deletion package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
"watch": "tsc --watch",
"test": "c8 mocha",
"test-transpiled": "mocha --no-config dist",
"integration-test": "tsx src/test/integration/index.ts",
"prepare": "npm run build && husky",
"prepack": "npm run build",
"docs": "typedoc src/gen"
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export * from './metrics.js';
export * from './object.js';
export * from './health.js';
export * from './middleware.js';
export * from './patch.js';
export { type ConfigOptions, type User, type Cluster, type Context } from './config_types.js';

// Export FetchError so that instanceof checks in user code will definitely use the same instance
Expand Down
34 changes: 18 additions & 16 deletions src/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
import type { RequestContext, ResponseContext, ConfigurationOptions, Middleware } from './gen/index.js';
import { PromiseMiddleware } from './gen/middleware.js';
import type {
RequestContext,
ResponseContext,
ConfigurationOptions,
ObservableMiddleware,
} from './gen/index.js';
import { of } from './gen/rxjsStub.js';

// setHeaderMiddleware returns Middleware[] that sets a header value
export function setHeaderMiddleware(key: string, value: string): Middleware[] {
return [
{
pre: async (c: RequestContext) => {
c.setHeaderParam(key, value);
return c;
},
post: async (c: ResponseContext) => {
return c;
},
export function setHeaderMiddleware(key: string, value: string): ObservableMiddleware {
return {
pre: (request: RequestContext) => {
request.setHeaderParam(key, value);
return of(request);
},
post: (response: ResponseContext) => {
return of(response);
},
];
};
}

// Returns ConfigurationOptions that set a header
export function setHeaderOptions(
key: string,
value: string,
opt?: ConfigurationOptions<PromiseMiddleware>,
): ConfigurationOptions<PromiseMiddleware> {
opt?: ConfigurationOptions<ObservableMiddleware>,
): ConfigurationOptions<ObservableMiddleware> {
const newMiddlware = setHeaderMiddleware(key, value);
const existingMiddlware = opt?.middleware || [];
return {
Expand Down
22 changes: 14 additions & 8 deletions src/middleware_test.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
import { RequestContext, ConfigurationOptions, HttpMethod } from './gen/index.js';
import { RequestContext, ConfigurationOptions, HttpMethod, ObservableMiddleware } from './gen/index.js';
import { deepStrictEqual } from 'node:assert';
import { setHeaderMiddleware, setHeaderOptions } from './middleware.js';
import { PromiseMiddleware } from './gen/middleware.js';

describe('Middleware', async () => {
describe('setHeaderMiddleware', async () => {
it('should set a header when it is blank', async () => {
const reqContext = new RequestContext('http://nowhere.com', HttpMethod.GET);
deepStrictEqual(reqContext.getHeaders(), {});
const headerMiddleware = setHeaderMiddleware('test-key', 'test-value');
const postMiddlewareRequest = await headerMiddleware[0].pre(reqContext);
deepStrictEqual(postMiddlewareRequest.getHeaders(), { 'test-key': 'test-value' });
const postMiddlewareRequest = await headerMiddleware.pre(reqContext);
await postMiddlewareRequest.toPromise().then((request) => {
deepStrictEqual(request.getHeaders(), { 'test-key': 'test-value' });
});
});

it('should replace a header if it is already specified', async () => {
const reqContext = new RequestContext('http://nowhere.com', HttpMethod.GET);
reqContext.setHeaderParam('test-key', 'wrong-value');
deepStrictEqual(reqContext.getHeaders(), { 'test-key': 'wrong-value' });
const headerMiddleware = setHeaderMiddleware('test-key', 'test-value');
const postMiddlewareRequest = await headerMiddleware[0].pre(reqContext);
deepStrictEqual(postMiddlewareRequest.getHeaders(), { 'test-key': 'test-value' });
const postMiddlewareRequest = await headerMiddleware.pre(reqContext);
await postMiddlewareRequest.toPromise().then((request) => {
deepStrictEqual(request.getHeaders(), { 'test-key': 'test-value' });
});
});
});

describe('setHeaderOptions', async () => {
it('should add middleware to set header with no input options arg', async () => {
const reqContext = new RequestContext('http://nowhere.com', HttpMethod.GET);
deepStrictEqual(reqContext.getHeaders(), {});
const testConfigurationOptions: ConfigurationOptions<PromiseMiddleware> = {};
const testConfigurationOptions: ConfigurationOptions<ObservableMiddleware> = {};
const headerConfigurationOptions = setHeaderOptions(
'test-key',
'test-value',
Expand All @@ -40,7 +43,10 @@ describe('Middleware', async () => {
throw new Error('missing middleware in ConfigurationOptions');
}
const postMiddlewareRequest = await headerConfigurationOptions.middleware[0].pre(reqContext);
deepStrictEqual(postMiddlewareRequest.getHeaders(), { 'test-key': 'test-value' });

await postMiddlewareRequest.toPromise().then((request) => {
deepStrictEqual(request.getHeaders(), { 'test-key': 'test-value' });
});
});
});
});
5 changes: 5 additions & 0 deletions src/test/integration/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import patchNamespace from './patchNamespace.js';

console.log('Integration testing');

patchNamespace();
47 changes: 47 additions & 0 deletions src/test/integration/patchNamespace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import assert, { deepEqual } from 'node:assert';
import { PatchStrategy, CoreV1Api, KubeConfig, setHeaderOptions, V1Namespace } from '../../index.js';

export default async function patchNamespace() {
const kc = new KubeConfig();
kc.loadFromDefault();

const coreV1Client = kc.makeApiClient(CoreV1Api);
let newNS = new V1Namespace();
const testNSName = 'integration-test-patch-ns';
newNS.metadata = {
name: testNSName,
labels: {
initialLabel: 'initialValue',
},
};
console.log(`Creating namespace ${testNSName}`);
await coreV1Client.createNamespace({ body: newNS });
newNS = await coreV1Client.readNamespace({ name: testNSName });
assert(newNS.metadata?.name === testNSName);
deepEqual(newNS.metadata?.labels?.initialLabel, 'initialValue');
console.log('Namespace created with initial label.');

const patch = [
{
op: 'replace',
path: '/metadata/labels',
value: {
foo: 'bar',
},
},
];

console.log(`Patching namespace ${testNSName} to replace labels`);
await coreV1Client.patchNamespace(
{
name: testNSName,
body: patch,
},
setHeaderOptions('Content-Type', PatchStrategy.JsonPatch),
);

const patchedNS = await coreV1Client.readNamespace({ name: testNSName });
deepEqual(patchedNS.metadata?.labels?.foo, 'bar');
deepEqual(patchedNS.metadata?.labels?.initialLabel, undefined);
console.log('Namespace patched with new label.');
}