Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bump openapi version to support for k8s media types #1341

Merged
Show file tree
Hide file tree
Changes from 6 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
33 changes: 31 additions & 2 deletions examples/patch-example.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// in a real program use require('@kubernetes/client-node')
const k8s = require('../dist/index');
const { createConfiguration, ServerConfiguration } = require('../dist');
const { PromiseMiddlewareWrapper } = require('../dist/gen/middleware');

const kc = new k8s.KubeConfig();
kc.loadFromDefault();
Expand All @@ -19,9 +21,36 @@ k8sApi.listNamespacedPod({ namespace }).then((res) => {
},
];
// TODO this method of passing the content type will change when we figure out a way to properly do this
const options = { headers: { 'Content-type': k8s.PatchUtils.PATCH_FORMAT_JSON_PATCH } };
const headerPatchMiddleware = new PromiseMiddlewareWrapper({
pre: async (requestContext) => {
requestContext.setHeaderParam('Content-type', 'application/json-patch+json');
return requestContext;
},
post: async (responseContext) => responseContext,
});
let currentContext = kc.getCurrentContext();
let currentCluster = kc.getCluster(currentContext);
if (currentCluster === undefined || currentCluster === null) {
throw new Error('Cluster is undefined');
}
let server = currentCluster.server;
if (server === undefined) {
throw new Error('Server is undefined');
}

const baseServerConfig = new ServerConfiguration(server, {});
const configuration = createConfiguration({
middleware: [headerPatchMiddleware],
baseServer: baseServerConfig,
authMethods: {
default: kc,
},
});
k8sApi
.patchNamespacedPod({ name: res?.items?.[0].metadata?.name ?? '', namespace, body: patch }, options)
.patchNamespacedPod(
{ name: res?.items?.[0].metadata?.name ?? '', namespace, body: patch },
configuration,
)
.then(() => {
console.log('Patched.');
})
Expand Down
83 changes: 83 additions & 0 deletions examples/typescript/patch/patch-example.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import {
CoreV1Api,
RequestContext,
ResponseContext,
KubeConfig,
createConfiguration,
Configuration,
ServerConfiguration,
} from '../../../dist';
import { PromiseMiddlewareWrapper } from '../../../dist/gen/middleware';

// const k8s = require('@kubernetes/client-node');
davidgamero marked this conversation as resolved.
Show resolved Hide resolved

const kc = new KubeConfig();
kc.loadFromDefault();

const k8sApi = kc.makeApiClient(CoreV1Api);

k8sApi
.listNamespacedPod({
namespace: 'default',
})
.then((res) => {
const patch = [
{
op: 'replace',
path: '/metadata/labels',
value: {
foo: 'bar',
},
},
];
const options = { headers: { 'Content-type': 'application/json-patch+json' } };
const headerPatchMiddleware = new PromiseMiddlewareWrapper({
pre: async (requestContext: RequestContext) => {
requestContext.setHeaderParam('Content-type', 'application/json-patch+json');
return requestContext;
},
post: async (responseContext: ResponseContext) => responseContext,
Copy link
Member

@mstruebing mstruebing Oct 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, one question:
is it required to define both pre as well as post even if you do not do anything else than return the arguments like in your example with post?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i can try removing them right now and let you know, but I had them to satisfy the typescript typings and show what was possible, not necessarily because they are needed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i don't see any default implementations of the pre/post methods, so they are most likely required for now, but we could easily add a wrapper that does default them or even a wrapper that makes middleware/configuration from a desired MIME media type since that's most of what we're after here

Copy link
Contributor Author

@davidgamero davidgamero Oct 17, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update: you can skip the middleware altogether if you want to use the first supported content type which is application/json-patch+json, but for any other types you'll have to add it, but this is just a workaround for now, and the ergonomics will be greatly improved with config merging in the future :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for explaining. I was just asking because I was curious :)
This is fine, especially as a workaround! 👍

});
const currentContext = kc.getCurrentContext();
const currentCluster = kc.getCluster(currentContext);
if (currentCluster === undefined || currentCluster === null) {
throw new Error('Cluster is undefined');
}
const server = currentCluster.server;
if (server === undefined) {
throw new Error('Server is undefined');
}

const baseServerConfig: ServerConfiguration<{}> = new ServerConfiguration<{}>(server, {});
const configuration: Configuration = createConfiguration({
middleware: [headerPatchMiddleware],
baseServer: baseServerConfig,
authMethods: {
default: kc,
},
});

const podName = res.items[0].metadata?.name;
if (podName === undefined) {
throw new Error('Pod name is undefined');
}
k8sApi
.patchNamespacedPod(
{
name: podName,
namespace: 'default',
body: patch,
},
configuration,
)
.then(() => {
// tslint:disable-next-line:no-console
console.log('Patched.');
})
.catch((err) => {
// tslint:disable-next-line:no-console
console.log('Error: ');
// tslint:disable-next-line:no-console
console.log(err);
davidgamero marked this conversation as resolved.
Show resolved Hide resolved
});
});
43 changes: 23 additions & 20 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
"prettier": "^3.0.0",
"source-map-support": "^0.5.9",
"ts-mockito": "^2.3.1",
"ts-node": "^8.2.0",
"ts-node": "^8.10.2",
"tslint": "^6.1.3",
"typedoc": "^0.25.0",
"typescript": "~5.2.2"
Expand Down
2 changes: 1 addition & 1 deletion settings
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@ export CLIENT_VERSION="0.8-SNAPSHOT"
# Name of the release package
export PACKAGE_NAME="@kubernetes/node-client"

export OPENAPI_GENERATOR_COMMIT=5555137b7926de2f501e091718ff72429b808220
export OPENAPI_GENERATOR_COMMIT=ba367e60e85392a7fd58cdb374c35c3aaaece872
davidgamero marked this conversation as resolved.
Show resolved Hide resolved
4 changes: 2 additions & 2 deletions src/gen/.openapi-generator/COMMIT
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
Requested Commit: 5555137b7926de2f501e091718ff72429b808220
Actual Commit: 5555137b7926de2f501e091718ff72429b808220
Requested Commit: ba367e60e85392a7fd58cdb374c35c3aaaece872
Actual Commit: ba367e60e85392a7fd58cdb374c35c3aaaece872
2 changes: 1 addition & 1 deletion src/gen/.openapi-generator/VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
7.0.0-SNAPSHOT
7.1.0-SNAPSHOT
8 changes: 4 additions & 4 deletions src/gen/apis/AdmissionregistrationApi.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// TODO: better import syntax?
import {BaseAPIRequestFactory, RequiredError, COLLECTION_FORMATS} from './baseapi';
import {Configuration} from '../configuration';
import {RequestContext, HttpMethod, ResponseContext, HttpFile} from '../http/http';
import {RequestContext, HttpMethod, ResponseContext, HttpFile, HttpInfo} from '../http/http';
import FormData from "form-data";
import { URLSearchParams } from 'url';
import {ObjectSerializer} from '../models/ObjectSerializer';
Expand Down Expand Up @@ -57,14 +57,14 @@ export class AdmissionregistrationApiResponseProcessor {
* @params response Response returned by the server for a request to getAPIGroup
* @throws ApiException if the response code was not in [200, 299]
*/
public async getAPIGroup(response: ResponseContext): Promise<V1APIGroup > {
public async getAPIGroupWithHttpInfo(response: ResponseContext): Promise<HttpInfo<V1APIGroup >> {
const contentType = ObjectSerializer.normalizeMediaType(response.headers["content-type"]);
if (isCodeInRange("200", response.httpStatusCode)) {
const body: V1APIGroup = ObjectSerializer.deserialize(
ObjectSerializer.parse(await response.body.text(), contentType),
"V1APIGroup", ""
) as V1APIGroup;
return body;
return new HttpInfo(response.httpStatusCode, response.headers, response.body, body);
}
if (isCodeInRange("401", response.httpStatusCode)) {
throw new ApiException<undefined>(response.httpStatusCode, "Unauthorized", undefined, response.headers);
Expand All @@ -76,7 +76,7 @@ export class AdmissionregistrationApiResponseProcessor {
ObjectSerializer.parse(await response.body.text(), contentType),
"V1APIGroup", ""
) as V1APIGroup;
return body;
return new HttpInfo(response.httpStatusCode, response.headers, response.body, body);
}

throw new ApiException<string | Buffer | undefined>(response.httpStatusCode, "Unknown API Status Code!", await response.getBodyAsAny(), response.headers);
Expand Down
Loading
Loading