Kubernetes: add option to fetch additional objectTypes which are not present in DEFAULT_OBJECTS (#28150)
* Fixed lack of secrets Signed-off-by: Florian Fl Bauer <florian.fl.bauer@deutschebahn.com> * add tests Signed-off-by: Florian Fl Bauer <florian.fl.bauer@deutschebahn.com> * remove log Signed-off-by: Florian Fl Bauer <florian.fl.bauer@deutschebahn.com> --------- Signed-off-by: Florian Fl Bauer <florian.fl.bauer@deutschebahn.com>
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@backstage/plugin-kubernetes-backend': patch
|
||||
'@backstage/plugin-kubernetes-common': patch
|
||||
'@backstage/plugin-kubernetes-node': patch
|
||||
---
|
||||
|
||||
Fixed the lack of `secrets` to fetch from the kubernetes api by adding option to specify additional Objects which are not part of Default Objects
|
||||
@@ -592,9 +592,8 @@ Overrides for the Kubernetes object types fetched from the cluster. The default
|
||||
- `statefulsets`
|
||||
- `daemonsets`
|
||||
|
||||
You may use this config to override the default object types if you only want a subset of
|
||||
the default ones. However, it's currently not supported to fetch object types other
|
||||
than the ones specified in the default types.
|
||||
You may use this config to override the default object types if you only want specific ones.
|
||||
However, the only additional object type to fetch at the moment is `secrets`.
|
||||
|
||||
Example:
|
||||
|
||||
@@ -608,6 +607,7 @@ kubernetes:
|
||||
- pods
|
||||
- services
|
||||
- statefulsets
|
||||
- secrets
|
||||
```
|
||||
|
||||
### Role Based Access Control
|
||||
|
||||
@@ -67,6 +67,7 @@ import {
|
||||
ServiceLocatorMethod,
|
||||
} from '../types/types';
|
||||
import {
|
||||
ALL_OBJECTS,
|
||||
DEFAULT_OBJECTS,
|
||||
KubernetesFanOutHandler,
|
||||
} from './KubernetesFanOutHandler';
|
||||
@@ -521,7 +522,7 @@ export class KubernetesBuilder {
|
||||
let objectTypesToFetch;
|
||||
|
||||
if (objectTypesToFetchStrings) {
|
||||
objectTypesToFetch = DEFAULT_OBJECTS.filter(obj =>
|
||||
objectTypesToFetch = ALL_OBJECTS.filter(obj =>
|
||||
objectTypesToFetchStrings.includes(obj.objectType),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,9 +20,13 @@ import {
|
||||
ObjectFetchParams,
|
||||
KubernetesServiceLocator,
|
||||
ServiceLocatorRequestContext,
|
||||
ObjectToFetch,
|
||||
} from '../types/types';
|
||||
import { KubernetesCredential } from '../auth/types';
|
||||
import { KubernetesFanOutHandler } from './KubernetesFanOutHandler';
|
||||
import {
|
||||
KubernetesFanOutHandler,
|
||||
DEFAULT_OBJECTS,
|
||||
} from './KubernetesFanOutHandler';
|
||||
import { KubernetesClientBasedFetcher } from './KubernetesFetcher';
|
||||
import { rest } from 'msw';
|
||||
import { setupServer } from 'msw/node';
|
||||
@@ -190,7 +194,10 @@ describe('KubernetesFanOutHandler', () => {
|
||||
],
|
||||
};
|
||||
|
||||
const getKubernetesFanOutHandler = (customResources: CustomResource[]) => {
|
||||
const getKubernetesFanOutHandler = (
|
||||
customResources: CustomResource[],
|
||||
objectTypesToFetch?: ObjectToFetch[],
|
||||
) => {
|
||||
return new KubernetesFanOutHandler({
|
||||
logger: mockServices.logger.mock(),
|
||||
fetcher: {
|
||||
@@ -201,6 +208,7 @@ describe('KubernetesFanOutHandler', () => {
|
||||
getClustersByEntity,
|
||||
},
|
||||
customResources: customResources,
|
||||
objectTypesToFetch: objectTypesToFetch || DEFAULT_OBJECTS,
|
||||
authStrategy: {
|
||||
getCredential: jest
|
||||
.fn<
|
||||
@@ -451,6 +459,80 @@ describe('KubernetesFanOutHandler', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('fetch objects should be called with secrets', async () => {
|
||||
getClustersByEntity.mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
clusters: [cluster2],
|
||||
}),
|
||||
);
|
||||
|
||||
sut = getKubernetesFanOutHandler(
|
||||
[],
|
||||
[
|
||||
{
|
||||
group: '',
|
||||
apiVersion: 'v1',
|
||||
plural: 'secrets',
|
||||
objectType: 'secrets',
|
||||
},
|
||||
],
|
||||
);
|
||||
|
||||
await sut.getKubernetesObjectsByEntity(
|
||||
{
|
||||
entity,
|
||||
auth: {},
|
||||
},
|
||||
{ credentials: mockCredentials },
|
||||
);
|
||||
|
||||
expect(fetchObjectsForService).toHaveBeenCalledTimes(1);
|
||||
expect(
|
||||
Array.from(fetchObjectsForService.mock.calls[0][0].objectTypesToFetch),
|
||||
).toEqual(
|
||||
expect.arrayContaining([
|
||||
{
|
||||
group: '',
|
||||
apiVersion: 'v1',
|
||||
plural: 'secrets',
|
||||
objectType: 'secrets',
|
||||
},
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it('fetch objects should not be called with secrets', async () => {
|
||||
getClustersByEntity.mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
clusters: [cluster2],
|
||||
}),
|
||||
);
|
||||
|
||||
sut = getKubernetesFanOutHandler([]);
|
||||
|
||||
await sut.getKubernetesObjectsByEntity(
|
||||
{
|
||||
entity,
|
||||
auth: {},
|
||||
},
|
||||
{ credentials: mockCredentials },
|
||||
);
|
||||
|
||||
expect(fetchObjectsForService).toHaveBeenCalledTimes(1);
|
||||
expect(
|
||||
Array.from(fetchObjectsForService.mock.calls[0][0].objectTypesToFetch),
|
||||
).toEqual(
|
||||
expect.not.arrayContaining([
|
||||
{
|
||||
group: '',
|
||||
apiVersion: 'v1',
|
||||
plural: 'secrets',
|
||||
objectType: 'secrets',
|
||||
},
|
||||
]),
|
||||
);
|
||||
});
|
||||
|
||||
it('retrieve objects for two cluster using customResources per cluster', async () => {
|
||||
getClustersByEntity.mockImplementation(() =>
|
||||
Promise.resolve({
|
||||
|
||||
@@ -139,6 +139,16 @@ export const DEFAULT_OBJECTS: ObjectToFetch[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export const ALL_OBJECTS: ObjectToFetch[] = [
|
||||
{
|
||||
group: '',
|
||||
apiVersion: 'v1',
|
||||
plural: 'secrets',
|
||||
objectType: 'secrets',
|
||||
},
|
||||
...DEFAULT_OBJECTS,
|
||||
];
|
||||
|
||||
export interface KubernetesFanOutHandlerOptions
|
||||
extends KubernetesObjectsProviderOptions {
|
||||
authStrategy: AuthenticationStrategy;
|
||||
|
||||
@@ -20,6 +20,7 @@ import { V1LimitRange } from '@kubernetes/client-node';
|
||||
import { V1Pod } from '@kubernetes/client-node';
|
||||
import { V1ReplicaSet } from '@kubernetes/client-node';
|
||||
import { V1ResourceQuota } from '@kubernetes/client-node';
|
||||
import { V1Secret } from '@kubernetes/client-node';
|
||||
import { V1Service } from '@kubernetes/client-node';
|
||||
import { V1StatefulSet } from '@kubernetes/client-node';
|
||||
import { V2HorizontalPodAutoscaler } from '@kubernetes/client-node';
|
||||
@@ -264,7 +265,8 @@ export type FetchResponse =
|
||||
| CustomResourceFetchResponse
|
||||
| StatefulSetsFetchResponse
|
||||
| DaemonSetsFetchResponse
|
||||
| PodStatusFetchResponse;
|
||||
| PodStatusFetchResponse
|
||||
| SecretsFetchResponse;
|
||||
|
||||
// @public (undocumented)
|
||||
export interface GroupedResponses extends DeploymentResources {
|
||||
@@ -432,6 +434,14 @@ export interface ResourceRef {
|
||||
namespace: string;
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface SecretsFetchResponse {
|
||||
// (undocumented)
|
||||
resources: Array<V1Secret>;
|
||||
// (undocumented)
|
||||
type: 'secrets';
|
||||
}
|
||||
|
||||
// @public (undocumented)
|
||||
export interface ServiceFetchResponse {
|
||||
// (undocumented)
|
||||
|
||||
@@ -30,6 +30,7 @@ import {
|
||||
V1ResourceQuota,
|
||||
V1Service,
|
||||
V1StatefulSet,
|
||||
V1Secret,
|
||||
} from '@kubernetes/client-node';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
|
||||
@@ -139,7 +140,8 @@ export type FetchResponse =
|
||||
| CustomResourceFetchResponse
|
||||
| StatefulSetsFetchResponse
|
||||
| DaemonSetsFetchResponse
|
||||
| PodStatusFetchResponse;
|
||||
| PodStatusFetchResponse
|
||||
| SecretsFetchResponse;
|
||||
|
||||
/** @public */
|
||||
export interface PodFetchResponse {
|
||||
@@ -231,6 +233,12 @@ export interface PodStatusFetchResponse {
|
||||
resources: Array<PodStatus>;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface SecretsFetchResponse {
|
||||
type: 'secrets';
|
||||
resources: Array<V1Secret>;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export type KubernetesFetchError = StatusError | RawFetchError;
|
||||
|
||||
|
||||
@@ -191,7 +191,8 @@ export type KubernetesObjectTypes =
|
||||
| 'ingresses'
|
||||
| 'customresources'
|
||||
| 'statefulsets'
|
||||
| 'daemonsets';
|
||||
| 'daemonsets'
|
||||
| 'secrets';
|
||||
|
||||
// @public
|
||||
export interface KubernetesServiceLocator {
|
||||
|
||||
@@ -186,7 +186,8 @@ export type KubernetesObjectTypes =
|
||||
| 'ingresses'
|
||||
| 'customresources'
|
||||
| 'statefulsets'
|
||||
| 'daemonsets';
|
||||
| 'daemonsets'
|
||||
| 'secrets';
|
||||
// If updating this list, also make sure to update
|
||||
// `objectTypes` and `apiVersionOverrides` in config.d.ts on @backstage/plugin-kubernetes-backend!
|
||||
|
||||
|
||||
Reference in New Issue
Block a user