feat(kubernetes): update k8s-backend plugin to use label selectors
update plugin to use label selectors when querying backend
This commit is contained in:
committed by
moustafab
parent
da2f4cd41a
commit
e2085293a6
@@ -14,7 +14,12 @@ It is only meant for local development, and the setup for it can be found inside
|
||||
|
||||
## Surfacing your Kubernetes components as part of an entity
|
||||
|
||||
### Adding the entity annotation
|
||||
There are 2 ways to surface your kubernetes components as part of an entity.
|
||||
The label selector takes precedence over the annotation/service id.
|
||||
|
||||
### Common `backstage.io/kubernetes-id` label
|
||||
|
||||
#### Adding the entity annotation
|
||||
|
||||
In order for Backstage to detect that an entity has Kubernetes components,
|
||||
the following annotation should be added to the entity.
|
||||
@@ -24,7 +29,7 @@ annotations:
|
||||
'backstage.io/kubernetes-id': dice-roller
|
||||
```
|
||||
|
||||
### Labeling Kubernetes components
|
||||
#### Labeling Kubernetes components
|
||||
|
||||
In order for Kubernetes components to show up in the service catalog
|
||||
as a part of an entity, Kubernetes components must be labeled with the following label:
|
||||
@@ -32,3 +37,19 @@ as a part of an entity, Kubernetes components must be labeled with the following
|
||||
```yaml
|
||||
'backstage.io/kubernetes-id': <ENTITY_NAME>
|
||||
```
|
||||
|
||||
### Full label selector
|
||||
|
||||
#### Adding the entity label selector to the spec
|
||||
|
||||
In order for Backstage to detect that an entity has kubernetes components the `kubernetes.selector` must have a valid selector. (Currently only matchLabels is supported)
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
kubernetes:
|
||||
selector:
|
||||
matchLabels:
|
||||
someKey: someValue
|
||||
other-key: other-value
|
||||
app.kubernetes.io/name: dice-roller
|
||||
```
|
||||
|
||||
@@ -20,6 +20,7 @@ import {
|
||||
AuthRequestBody,
|
||||
ObjectsByServiceIdResponse,
|
||||
} from '@backstage/plugin-kubernetes-backend';
|
||||
import { V1LabelSelector } from '@kubernetes/client-node';
|
||||
|
||||
export class KubernetesBackendClient implements KubernetesApi {
|
||||
private readonly discoveryApi: DiscoveryApi;
|
||||
@@ -50,10 +51,23 @@ export class KubernetesBackendClient implements KubernetesApi {
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
async getObjectsByServiceId(
|
||||
private parseLabelSelector(params: V1LabelSelector): string {
|
||||
// TODO: figure out how to convert the selector to the full query param from the yaml
|
||||
// (as shown here https://github.com/kubernetes/apimachinery/blob/master/pkg/labels/selector.go)
|
||||
return Object.keys(params.matchLabels)
|
||||
.map(key => `${key}=${params[key]}`)
|
||||
.join(',');
|
||||
}
|
||||
|
||||
async getObjectsByLabelSelector(
|
||||
serviceId: String,
|
||||
labelSelector: V1LabelSelector,
|
||||
requestBody: AuthRequestBody,
|
||||
): Promise<ObjectsByServiceIdResponse> {
|
||||
return await this.getRequired(`/services/${serviceId}`, requestBody);
|
||||
const labelSelectorQueryParams = this.parseLabelSelector(labelSelector);
|
||||
return await this.getRequired(
|
||||
`/services/${serviceId}?labelSelector=${labelSelectorQueryParams}`,
|
||||
requestBody,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
AuthRequestBody,
|
||||
ObjectsByServiceIdResponse,
|
||||
} from '@backstage/plugin-kubernetes-backend';
|
||||
import { V1LabelSelector } from '@kubernetes/client-node';
|
||||
|
||||
export const kubernetesApiRef = createApiRef<KubernetesApi>({
|
||||
id: 'plugin.kubernetes.service',
|
||||
@@ -27,8 +28,9 @@ export const kubernetesApiRef = createApiRef<KubernetesApi>({
|
||||
});
|
||||
|
||||
export interface KubernetesApi {
|
||||
getObjectsByServiceId(
|
||||
getObjectsByLabelSelector(
|
||||
serviceId: String,
|
||||
labelSelector: V1LabelSelector,
|
||||
requestBody: AuthRequestBody,
|
||||
): Promise<ObjectsByServiceIdResponse>;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import {
|
||||
ExtensionsV1beta1Ingress,
|
||||
V1ConfigMap,
|
||||
V1HorizontalPodAutoscaler,
|
||||
V1LabelSelector,
|
||||
V1Service,
|
||||
} from '@kubernetes/client-node';
|
||||
import { Services } from '../Services';
|
||||
@@ -129,9 +130,27 @@ export const KubernetesContent = ({ entity }: KubernetesContentProps) => {
|
||||
);
|
||||
}
|
||||
|
||||
// decide label selector to search by defaulting to this label
|
||||
let labelSelector: V1LabelSelector = {
|
||||
matchLabels: {
|
||||
'backstage.io/kubernetes-id': entity.metadata.name,
|
||||
},
|
||||
};
|
||||
|
||||
if (
|
||||
entity.spec.kubernetes &&
|
||||
(entity.spec.kubernetes.selector as V1LabelSelector)
|
||||
) {
|
||||
labelSelector = entity.spec.kubernetes.selector;
|
||||
}
|
||||
|
||||
// TODO: Add validation on contents/format of requestBody
|
||||
kubernetesApi
|
||||
.getObjectsByServiceId(entity.metadata.name, requestBody)
|
||||
.getObjectsByLabelSelector(
|
||||
entity.metadata.name,
|
||||
labelSelector,
|
||||
requestBody,
|
||||
)
|
||||
.then(result => {
|
||||
setKubernetesObjects(result);
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user