Skip to content

Commit b8382b6

Browse files
authored
Merge pull request #772 from schrodit/add-list-method
Add list method to generic KubernetesObjectApi
2 parents fae1e5b + 07737cb commit b8382b6

File tree

2 files changed

+198
-3
lines changed

2 files changed

+198
-3
lines changed

src/object.ts

+93-3
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ type KubernetesObjectResponseBody =
2020
| V1APIResourceList;
2121

2222
/** Kubernetes API verbs. */
23-
type KubernetesApiAction = 'create' | 'delete' | 'patch' | 'read' | 'replace';
23+
type KubernetesApiAction = 'create' | 'delete' | 'patch' | 'read' | 'list' | 'replace';
2424

2525
/**
2626
* Valid Content-Type header values for patch operations. See
@@ -315,6 +315,96 @@ export class KubernetesObjectApi extends ApisApi {
315315
return this.requestPromise(localVarRequestOptions);
316316
}
317317

318+
/**
319+
* List any Kubernetes resources.
320+
* @param apiVersion api group and version of the form <apiGroup>/<version>
321+
* @param kind Kubernetes resource kind
322+
* @param namespace list resources in this namespace
323+
* @param pretty If \&#39;true\&#39;, then the output is pretty printed.
324+
* @param exact Should the export be exact. Exact export maintains cluster-specific fields like
325+
* \&#39;Namespace\&#39;. Deprecated. Planned for removal in 1.18.
326+
* @param exportt Should this value be exported. Export strips fields that a user can not
327+
* specify. Deprecated. Planned for removal in 1.18.
328+
* @param fieldSelector A selector to restrict the list of returned objects by their fields. Defaults to everything.
329+
* @param labelSelector A selector to restrict the list of returned objects by their labels. Defaults to everything.
330+
* @param limit Number of returned resources.
331+
* @param options Optional headers to use in the request.
332+
* @return Promise containing the request response and [[KubernetesListObject<KubernetesObject>]].
333+
*/
334+
public async list(
335+
apiVersion: string,
336+
kind: string,
337+
namespace?: string,
338+
pretty?: string,
339+
exact?: boolean,
340+
exportt?: boolean,
341+
fieldSelector?: string,
342+
labelSelector?: string,
343+
limit?: number,
344+
continueToken?: string,
345+
options: { headers: { [name: string]: string } } = { headers: {} },
346+
): Promise<{ body: KubernetesListObject<KubernetesObject>; response: http.IncomingMessage }> {
347+
// verify required parameters 'apiVersion', 'kind' is not null or undefined
348+
if (apiVersion === null || apiVersion === undefined) {
349+
throw new Error('Required parameter apiVersion was null or undefined when calling list.');
350+
}
351+
if (kind === null || kind === undefined) {
352+
throw new Error('Required parameter kind was null or undefined when calling list.');
353+
}
354+
355+
const localVarPath = await this.specUriPath(
356+
{
357+
apiVersion,
358+
kind,
359+
metadata: {
360+
namespace,
361+
},
362+
},
363+
'list',
364+
);
365+
const localVarQueryParameters: any = {};
366+
const localVarHeaderParams = this.generateHeaders(options.headers);
367+
368+
if (pretty !== undefined) {
369+
localVarQueryParameters.pretty = ObjectSerializer.serialize(pretty, 'string');
370+
}
371+
372+
if (exact !== undefined) {
373+
localVarQueryParameters.exact = ObjectSerializer.serialize(exact, 'boolean');
374+
}
375+
376+
if (exportt !== undefined) {
377+
localVarQueryParameters.export = ObjectSerializer.serialize(exportt, 'boolean');
378+
}
379+
380+
if (fieldSelector !== undefined) {
381+
localVarQueryParameters.fieldSelector = ObjectSerializer.serialize(fieldSelector, 'string');
382+
}
383+
384+
if (labelSelector !== undefined) {
385+
localVarQueryParameters.labelSelector = ObjectSerializer.serialize(labelSelector, 'string');
386+
}
387+
388+
if (limit !== undefined) {
389+
localVarQueryParameters.limit = ObjectSerializer.serialize(limit, 'number');
390+
}
391+
392+
if (continueToken !== undefined) {
393+
localVarQueryParameters.continue = ObjectSerializer.serialize(continueToken, 'string');
394+
}
395+
396+
const localVarRequestOptions: request.Options = {
397+
method: 'GET',
398+
qs: localVarQueryParameters,
399+
headers: localVarHeaderParams,
400+
uri: localVarPath,
401+
useQuerystring: this._useQuerystring,
402+
json: true,
403+
};
404+
405+
return this.requestPromise(localVarRequestOptions);
406+
}
407+
318408
/**
319409
* Replace any Kubernetes resource.
320410
* @param spec Kubernetes resource spec
@@ -403,15 +493,15 @@ export class KubernetesObjectApi extends ApisApi {
403493
if (!resource) {
404494
throw new Error(`Unrecognized API version and kind: ${spec.apiVersion} ${spec.kind}`);
405495
}
406-
if (resource.namespaced && !spec.metadata.namespace) {
496+
if (resource.namespaced && !spec.metadata.namespace && action !== 'list') {
407497
spec.metadata.namespace = this.defaultNamespace;
408498
}
409499
const parts = [this.apiVersionPath(spec.apiVersion)];
410500
if (resource.namespaced && spec.metadata.namespace) {
411501
parts.push('namespaces', encodeURIComponent(String(spec.metadata.namespace)));
412502
}
413503
parts.push(resource.name);
414-
if (action !== 'create') {
504+
if (action !== 'create' && action !== 'list') {
415505
if (!spec.metadata.name) {
416506
throw new Error('Required spec property name is not set');
417507
}

src/object_test.ts

+105
Original file line numberDiff line numberDiff line change
@@ -1747,6 +1747,85 @@ describe('KubernetesObject', () => {
17471747
await client.delete(s, undefined, undefined, 7, undefined, 'Foreground');
17481748
scope.done();
17491749
});
1750+
1751+
it('should list resources in a namespace', async () => {
1752+
const scope = nock('https://d.i.y')
1753+
.get(
1754+
'/api/v1/namespaces/default/secrets?fieldSelector=metadata.name%3Dtest-secret1&labelSelector=app%3Dmy-app&limit=5&continue=abc',
1755+
)
1756+
.reply(200, {
1757+
apiVersion: 'v1',
1758+
kind: 'SecretList',
1759+
items: [
1760+
{
1761+
apiVersion: 'v1',
1762+
kind: 'Secret',
1763+
metadata: {
1764+
name: 'test-secret-1',
1765+
uid: 'a4fd7a65-2af5-4ef1-a0bc-cb34a308b821',
1766+
},
1767+
},
1768+
],
1769+
metadata: {
1770+
resourceVersion: '216532459',
1771+
continue: 'abc',
1772+
},
1773+
});
1774+
const lr = await client.list(
1775+
'v1',
1776+
'Secret',
1777+
'default',
1778+
undefined,
1779+
undefined,
1780+
undefined,
1781+
'metadata.name=test-secret1',
1782+
'app=my-app',
1783+
5,
1784+
'abc',
1785+
);
1786+
const items = lr.body.items;
1787+
expect(items).to.have.length(1);
1788+
scope.done();
1789+
});
1790+
1791+
it('should list resources in all namespaces', async () => {
1792+
const scope = nock('https://d.i.y')
1793+
.get(
1794+
'/api/v1/secrets?fieldSelector=metadata.name%3Dtest-secret1&labelSelector=app%3Dmy-app&limit=5',
1795+
)
1796+
.reply(200, {
1797+
apiVersion: 'v1',
1798+
kind: 'SecretList',
1799+
items: [
1800+
{
1801+
apiVersion: 'v1',
1802+
kind: 'Secret',
1803+
metadata: {
1804+
name: 'test-secret-1',
1805+
uid: 'a4fd7a65-2af5-4ef1-a0bc-cb34a308b821',
1806+
},
1807+
},
1808+
],
1809+
metadata: {
1810+
resourceVersion: '216532459',
1811+
continue: 'abc',
1812+
},
1813+
});
1814+
const lr = await client.list(
1815+
'v1',
1816+
'Secret',
1817+
undefined,
1818+
undefined,
1819+
undefined,
1820+
undefined,
1821+
'metadata.name=test-secret1',
1822+
'app=my-app',
1823+
5,
1824+
);
1825+
const items = lr.body.items;
1826+
expect(items).to.have.length(1);
1827+
scope.done();
1828+
});
17501829
});
17511830

17521831
describe('errors', () => {
@@ -1921,5 +2000,31 @@ describe('KubernetesObject', () => {
19212000
expect(thrown).to.be.true;
19222001
scope.done();
19232002
});
2003+
2004+
it('should throw error if no apiVersion', async () => {
2005+
let thrown = false;
2006+
try {
2007+
await (client.list as any)(undefined, undefined);
2008+
expect.fail('should have thrown an error');
2009+
} catch (e) {
2010+
thrown = true;
2011+
expect(e.message).to.contain(
2012+
'Required parameter apiVersion was null or undefined when calling ',
2013+
);
2014+
}
2015+
expect(thrown).to.be.true;
2016+
});
2017+
2018+
it('should throw error if no kind', async () => {
2019+
let thrown = false;
2020+
try {
2021+
await (client.list as any)('', undefined);
2022+
expect.fail('should have thrown an error');
2023+
} catch (e) {
2024+
thrown = true;
2025+
expect(e.message).to.contain('Required parameter kind was null or undefined when calling ');
2026+
}
2027+
expect(thrown).to.be.true;
2028+
});
19242029
});
19252030
});

0 commit comments

Comments
 (0)