refactor(k8s-plugin): update to use annotation based label selector
add changeset
This commit is contained in:
@@ -42,7 +42,7 @@ kubernetes:
|
||||
Mac copy to clipboard:
|
||||
|
||||
```
|
||||
kubectl get secret $(kubectl get sa dice-roller -o=json | jq -r .secrets[0].name) -o=json | jq -r '.data["token"]' | base64 --decode | pbcopy
|
||||
kubectl get secret $(kubectl get sa dice-roller -o=json | jq -r '.secrets[0].name') -o=json | jq -r '.data["token"]' | base64 --decode | pbcopy
|
||||
```
|
||||
|
||||
Paste into `app-config.local.yaml` `kubernetes.clusters[0].serviceAccountToken`
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Config, ConfigReader } from '../../../../packages/config/src';
|
||||
import { Config, ConfigReader } from '@backstage/config';
|
||||
import { getCombinedClusterDetails } from './index';
|
||||
|
||||
describe('getCombinedClusterDetails', () => {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
|
||||
import { ClusterDetails, ClusterLocatorMethod } from '..';
|
||||
import { Config } from '../../../../packages/config/src';
|
||||
import { Config } from '@backstage/config';
|
||||
import { ConfigClusterLocator } from './ConfigClusterLocator';
|
||||
|
||||
export { ConfigClusterLocator } from './ConfigClusterLocator';
|
||||
|
||||
+34
-23
@@ -16,7 +16,6 @@
|
||||
|
||||
import { handleGetKubernetesObjectsForService } from './getKubernetesObjectsForServiceHandler';
|
||||
import { getVoidLogger } from '@backstage/backend-common';
|
||||
import { ComponentEntityV1alpha1 } from '@backstage/catalog-model';
|
||||
import { ObjectFetchParams } from '..';
|
||||
|
||||
const TEST_SERVICE_ID = 'my-service';
|
||||
@@ -25,26 +24,6 @@ const fetchObjectsForService = jest.fn();
|
||||
|
||||
const getClustersByServiceId = jest.fn();
|
||||
|
||||
const goodEntity: ComponentEntityV1alpha1 = {
|
||||
apiVersion: 'backstage.io/v1beta1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'test-component',
|
||||
},
|
||||
spec: {
|
||||
type: 'service',
|
||||
lifecycle: 'production',
|
||||
owner: 'joe',
|
||||
kubernetes: {
|
||||
selector: {
|
||||
matchLabels: {
|
||||
'backstage.io/test-label': 'test-component',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const mockFetch = (mock: jest.Mock) => {
|
||||
mock.mockImplementation((params: ObjectFetchParams) =>
|
||||
Promise.resolve({
|
||||
@@ -111,7 +90,24 @@ describe('handleGetKubernetesObjectsForService', () => {
|
||||
getClustersByServiceId,
|
||||
},
|
||||
getVoidLogger(),
|
||||
{ entity: goodEntity },
|
||||
{
|
||||
entity: {
|
||||
apiVersion: 'backstage.io/v1beta1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'test-component',
|
||||
annotations: {
|
||||
'backstage.io/kubernetes-labels-selector':
|
||||
'backstage.io/test-label=test-component',
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
type: 'service',
|
||||
lifecycle: 'production',
|
||||
owner: 'joe',
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
expect(getClustersByServiceId.mock.calls.length).toBe(1);
|
||||
@@ -186,10 +182,25 @@ describe('handleGetKubernetesObjectsForService', () => {
|
||||
},
|
||||
getVoidLogger(),
|
||||
{
|
||||
entity: goodEntity,
|
||||
auth: {
|
||||
google: 'google_token_123',
|
||||
},
|
||||
entity: {
|
||||
apiVersion: 'backstage.io/v1beta1',
|
||||
kind: 'Component',
|
||||
metadata: {
|
||||
name: 'test-component',
|
||||
annotations: {
|
||||
'backstage.io/kubernetes-labels-selector':
|
||||
'backstage.io/test-label=test-component',
|
||||
},
|
||||
},
|
||||
spec: {
|
||||
type: 'service',
|
||||
lifecycle: 'production',
|
||||
owner: 'joe',
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
|
||||
import { Logger } from 'winston';
|
||||
import { ComponentEntityV1alpha1 } from '@backstage/catalog-model';
|
||||
import {
|
||||
KubernetesRequestBody,
|
||||
ClusterDetails,
|
||||
@@ -47,18 +46,6 @@ const DEFAULT_OBJECTS = new Set<KubernetesObjectTypes>([
|
||||
'ingresses',
|
||||
]);
|
||||
|
||||
function parseLabelSelector(entity: ComponentEntityV1alpha1): string {
|
||||
const matchLabels = entity?.spec?.kubernetes?.selector?.matchLabels;
|
||||
if (matchLabels) {
|
||||
// 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(matchLabels)
|
||||
.map(key => `${key}=${matchLabels[key.toString()]}`)
|
||||
.join(',');
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
// Fans out the request to all clusters that the service lives in, aggregates their responses together
|
||||
export const handleGetKubernetesObjectsForService: GetKubernetesObjectsForServiceHandler = async (
|
||||
serviceId,
|
||||
@@ -92,7 +79,10 @@ export const handleGetKubernetesObjectsForService: GetKubernetesObjectsForServic
|
||||
.join(', ')}]`,
|
||||
);
|
||||
|
||||
const labelSelector = parseLabelSelector(requestBody.entity);
|
||||
const labelSelector: string =
|
||||
requestBody.entity?.metadata?.annotations?.[
|
||||
'backstage.io/kubernetes-label-selector'
|
||||
] || `backstage.io/kubernetes-id=${requestBody.entity.metadata.name}`;
|
||||
|
||||
return Promise.all(
|
||||
clusterDetailsDecoratedForAuth.map(clusterDetails => {
|
||||
|
||||
@@ -23,7 +23,7 @@ import {
|
||||
V1ReplicaSet,
|
||||
V1Service,
|
||||
} from '@kubernetes/client-node';
|
||||
import { ComponentEntityV1alpha1 } from '@backstage/catalog-model';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
|
||||
export interface ClusterDetails {
|
||||
name: string;
|
||||
@@ -36,7 +36,7 @@ export interface KubernetesRequestBody {
|
||||
auth?: {
|
||||
google?: string;
|
||||
};
|
||||
entity: ComponentEntityV1alpha1;
|
||||
entity: Entity;
|
||||
}
|
||||
|
||||
export interface ClusterObjects {
|
||||
|
||||
Reference in New Issue
Block a user