set authProvider and owner to use for gke resources in config

Signed-off-by: Raghunandan Balachandran <raghunandan@spotify.com>
This commit is contained in:
Raghunandan Balachandran
2025-08-11 13:25:56 +02:00
parent 9f36f8f01f
commit 1c42a72179
5 changed files with 147 additions and 2 deletions
@@ -62,4 +62,11 @@ catalog:
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/..."
}
# Optional: Authentication provider for Kubernetes clusters
# Defaults to 'google' if not specified
# Common values: 'google', 'googleServiceAccount'
authProvider: googleServiceAccount
# Optional: Owner of the discovered GKE clusters
# Defaults to 'unknown' if not specified
owner: platform-team
```
+10
View File
@@ -44,6 +44,16 @@ export interface Config {
* @visibility secret
*/
googleServiceAccountCredentials?: string;
/**
* (Optional) Authentication provider to use for Kubernetes clusters
* Defaults to 'google' for backward compatibility
*/
authProvider?: string;
/**
* (Optional) Owner of the discovered clusters
* Defaults to 'unknown' if not specified
*/
owner?: string;
};
};
};
@@ -196,6 +196,54 @@ describe('GkeEntityProvider', () => {
},
);
it('should use configured values for authProvider and owner', async () => {
const customGkeEntityProvider = GkeEntityProvider.fromConfigWithClient({
logger: logger as any,
config: new ConfigReader({
catalog: {
providers: {
gcp: {
gke: {
parents: ['projects/parent1/locations/-'],
authProvider: 'googleServiceAccount',
owner: 'sre',
schedule: {
frequency: {
minutes: 3,
},
timeout: {
minutes: 3,
},
},
},
},
},
},
}),
scheduler: schedulerMock,
clusterManagerClient: clusterManagerClientMock as any,
});
clusterManagerClientMock.listClusters.mockImplementation(() => [
{
clusters: [
{
name: 'some-cluster',
endpoint: '127.0.0.1',
location: 'some-location',
selfLink: 'https://127.0.0.1/some-link',
masterAuth: {
clusterCaCertificate: 'abcdefg',
},
},
],
},
]);
await customGkeEntityProvider.connect(connectionMock);
await customGkeEntityProvider.refresh();
expect(connectionMock.applyMutation).toMatchSnapshot();
});
it('should log GKE API errors', async () => {
clusterManagerClientMock.listClusters.mockRejectedValue(
new Error('some-error'),
@@ -365,5 +413,32 @@ describe('GkeEntityProvider', () => {
expect(MockedClusterManagerClient).toHaveBeenCalledWith();
});
it('should read authProvider and owner from config', () => {
const provider = GkeEntityProvider.fromConfig({
logger: logger as any,
config: new ConfigReader({
catalog: {
providers: {
gcp: {
gke: {
parents: ['projects/test-project/locations/-'],
schedule: {
frequency: { minutes: 30 },
timeout: { minutes: 3 },
},
authProvider: 'googleServiceAccount',
owner: 'platform-team',
},
},
},
},
}),
scheduler: schedulerMock,
});
expect(provider).toBeDefined();
expect(MockedClusterManagerClient).toHaveBeenCalledWith();
});
});
});
@@ -47,6 +47,8 @@ export class GkeEntityProvider implements EntityProvider {
private readonly logger: LoggerService;
private readonly scheduleFn: () => Promise<void>;
private readonly gkeParents: string[];
private readonly gkeAuthProvider: string | undefined;
private readonly gkeOwner: string | undefined;
private readonly clusterManagerClient: container.v1.ClusterManagerClient;
private connection?: EntityProviderConnection;
@@ -54,11 +56,15 @@ export class GkeEntityProvider implements EntityProvider {
logger: LoggerService,
taskRunner: SchedulerServiceTaskRunner,
gkeParents: string[],
gkeAuthProvider: string | undefined,
gkeOwner: string | undefined,
clusterManagerClient: container.v1.ClusterManagerClient,
) {
this.logger = logger;
this.scheduleFn = this.createScheduleFn(taskRunner);
this.gkeParents = gkeParents;
this.gkeAuthProvider = gkeAuthProvider;
this.gkeOwner = gkeOwner;
this.clusterManagerClient = clusterManagerClient;
}
@@ -125,6 +131,8 @@ export class GkeEntityProvider implements EntityProvider {
logger,
scheduler.createScheduledTaskRunner(schedule),
gkeProviderConfig.getStringArray('parents'),
gkeProviderConfig.getOptionalString('authProvider'),
gkeProviderConfig.getOptionalString('owner'),
clusterManagerClient,
);
}
@@ -179,7 +187,8 @@ export class GkeEntityProvider implements EntityProvider {
[ANNOTATION_KUBERNETES_API_SERVER]: `https://${cluster.endpoint}`,
[ANNOTATION_KUBERNETES_API_SERVER_CA]:
cluster.masterAuth?.clusterCaCertificate || '',
[ANNOTATION_KUBERNETES_AUTH_PROVIDER]: 'google',
[ANNOTATION_KUBERNETES_AUTH_PROVIDER]:
this.gkeAuthProvider || 'google',
[ANNOTATION_KUBERNETES_DASHBOARD_APP]: 'gke',
[ANNOTATION_LOCATION]: location,
[ANNOTATION_ORIGIN_LOCATION]: location,
@@ -194,7 +203,7 @@ export class GkeEntityProvider implements EntityProvider {
},
spec: {
type: 'kubernetes-cluster',
owner: 'unknown',
owner: this.gkeOwner || 'unknown',
},
},
};
@@ -67,3 +67,47 @@ exports[`GkeEntityProvider should return clusters as Resources 1`] = `
],
}
`;
exports[`GkeEntityProvider should use configured values for authProvider and owner 1`] = `
[MockFunction] {
"calls": [
[
{
"entities": [
{
"entity": {
"apiVersion": "backstage.io/v1alpha1",
"kind": "Resource",
"metadata": {
"annotations": {
"backstage.io/managed-by-location": "gcp-gke:some-location",
"backstage.io/managed-by-origin-location": "gcp-gke:some-location",
"kubernetes.io/api-server": "https://127.0.0.1",
"kubernetes.io/api-server-certificate-authority": "abcdefg",
"kubernetes.io/auth-provider": "googleServiceAccount",
"kubernetes.io/dashboard-app": "gke",
"kubernetes.io/dashboard-parameters": "{"projectId":"parent1","region":"some-location","clusterName":"some-cluster"}",
},
"name": "some-cluster",
"namespace": "default",
},
"spec": {
"owner": "sre",
"type": "kubernetes-cluster",
},
},
"locationKey": "gcp-gke:some-location",
},
],
"type": "full",
},
],
],
"results": [
{
"type": "return",
"value": undefined,
},
],
}
`;