From 669e73b87bdcedc1e712b129f556f0e8baba6ca9 Mon Sep 17 00:00:00 2001 From: Morgan Martinet Date: Mon, 27 Dec 2021 22:40:46 -0500 Subject: [PATCH] change dashboardParameters signature after code review Signed-off-by: Morgan Martinet --- docs/features/kubernetes/configuration.md | 1 + plugins/kubernetes-backend/api-report.md | 3 +- .../ConfigClusterLocator.test.ts | 72 +++++++++++++++++++ .../cluster-locator/ConfigClusterLocator.ts | 5 +- plugins/kubernetes-backend/src/types/types.ts | 3 +- plugins/kubernetes-common/api-report.md | 3 +- plugins/kubernetes-common/src/types.ts | 3 +- plugins/kubernetes/api-report.md | 1 + plugins/kubernetes/src/types/types.ts | 3 +- .../clusterLinks/formatClusterLink.test.ts | 42 +++++++++++ .../utils/clusterLinks/formatClusterLink.ts | 3 +- .../utils/clusterLinks/formatters/gke.test.ts | 6 +- .../src/utils/clusterLinks/formatters/gke.ts | 12 ++-- 13 files changed, 139 insertions(+), 18 deletions(-) diff --git a/docs/features/kubernetes/configuration.md b/docs/features/kubernetes/configuration.md index f06a72ca4e..492cd86022 100644 --- a/docs/features/kubernetes/configuration.md +++ b/docs/features/kubernetes/configuration.md @@ -39,6 +39,7 @@ kubernetes: region: 'europe-west1' skipTLSVerify: true skipMetricsLookup: true + exposeDashboard: true ``` ### `serviceLocatorMethod` diff --git a/plugins/kubernetes-backend/api-report.md b/plugins/kubernetes-backend/api-report.md index 63d0dfceb9..9b181c8514 100644 --- a/plugins/kubernetes-backend/api-report.md +++ b/plugins/kubernetes-backend/api-report.md @@ -6,6 +6,7 @@ import { Config } from '@backstage/config'; import express from 'express'; import type { FetchResponse } from '@backstage/plugin-kubernetes-common'; +import type { JsonObject } from '@backstage/types'; import type { KubernetesFetchError } from '@backstage/plugin-kubernetes-common'; import type { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; import { Logger as Logger_2 } from 'winston'; @@ -31,7 +32,7 @@ export interface ClusterDetails { // (undocumented) caData?: string | undefined; dashboardApp?: string; - dashboardParameters?: any; + dashboardParameters?: JsonObject; dashboardUrl?: string; name: string; // (undocumented) diff --git a/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.test.ts b/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.test.ts index f5d6b56893..6ece380f28 100644 --- a/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.test.ts +++ b/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.test.ts @@ -176,4 +176,76 @@ describe('ConfigClusterLocator', () => { }, ]); }); + + it('one cluster with dashboardParameters', async () => { + const config: Config = new ConfigReader({ + clusters: [ + { + name: 'cluster1', + url: 'http://localhost:8080', + authProvider: 'serviceAccount', + dashboardApp: 'gke', + dashboardParameters: { + projectId: 'some-project', + region: 'some-region', + clusterName: 'cluster1', + }, + }, + ], + }); + + const sut = ConfigClusterLocator.fromConfig(config); + + const result = await sut.getClusters(); + + expect(result).toStrictEqual([ + { + name: 'cluster1', + serviceAccountToken: undefined, + url: 'http://localhost:8080', + authProvider: 'serviceAccount', + skipMetricsLookup: false, + skipTLSVerify: false, + caData: undefined, + dashboardApp: 'gke', + dashboardParameters: { + projectId: 'some-project', + region: 'some-region', + clusterName: 'cluster1', + }, + }, + ]); + }); + + it('one cluster with dashboardUrl', async () => { + const config: Config = new ConfigReader({ + clusters: [ + { + name: 'cluster1', + url: 'http://localhost:8080', + authProvider: 'serviceAccount', + dashboardApp: 'standard', + dashboardUrl: 'http://someurl', + }, + ], + }); + + const sut = ConfigClusterLocator.fromConfig(config); + + const result = await sut.getClusters(); + + expect(result).toStrictEqual([ + { + name: 'cluster1', + serviceAccountToken: undefined, + url: 'http://localhost:8080', + authProvider: 'serviceAccount', + skipMetricsLookup: false, + skipTLSVerify: false, + caData: undefined, + dashboardApp: 'standard', + dashboardUrl: 'http://someurl', + }, + ]); + }); }); diff --git a/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.ts b/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.ts index 50ddb906a9..d8436b6c24 100644 --- a/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.ts +++ b/plugins/kubernetes-backend/src/cluster-locator/ConfigClusterLocator.ts @@ -47,9 +47,8 @@ export class ConfigClusterLocator implements KubernetesClustersSupplier { if (dashboardApp) { clusterDetails.dashboardApp = dashboardApp; } - const dashboardParameters = c.getOptionalString('dashboardParameters'); - if (dashboardParameters) { - clusterDetails.dashboardParameters = dashboardParameters; + if (c.has('dashboardParameters')) { + clusterDetails.dashboardParameters = c.get('dashboardParameters'); } switch (authProvider) { diff --git a/plugins/kubernetes-backend/src/types/types.ts b/plugins/kubernetes-backend/src/types/types.ts index 6be205e4e8..4f25805063 100644 --- a/plugins/kubernetes-backend/src/types/types.ts +++ b/plugins/kubernetes-backend/src/types/types.ts @@ -15,6 +15,7 @@ */ import { Logger } from 'winston'; +import type { JsonObject } from '@backstage/types'; import type { FetchResponse, KubernetesFetchError, @@ -135,7 +136,7 @@ export interface ClusterDetails { * This is used by the GKE formatter which requires the project, region and cluster name. * @see dashboardApp */ - dashboardParameters?: any; + dashboardParameters?: JsonObject; } export interface GKEClusterDetails extends ClusterDetails {} diff --git a/plugins/kubernetes-common/api-report.md b/plugins/kubernetes-common/api-report.md index c6ef21592b..15019d71c3 100644 --- a/plugins/kubernetes-common/api-report.md +++ b/plugins/kubernetes-common/api-report.md @@ -4,6 +4,7 @@ ```ts import { Entity } from '@backstage/catalog-model'; +import type { JsonObject } from '@backstage/types'; import { V1ConfigMap } from '@kubernetes/client-node'; import { V1CronJob } from '@kubernetes/client-node'; import { V1Deployment } from '@kubernetes/client-node'; @@ -62,7 +63,7 @@ export interface ClientPodStatus { // @public (undocumented) export interface ClusterAttributes { dashboardApp?: string; - dashboardParameters?: any; + dashboardParameters?: JsonObject; dashboardUrl?: string; name: string; } diff --git a/plugins/kubernetes-common/src/types.ts b/plugins/kubernetes-common/src/types.ts index ff40ee5119..afda9b5299 100644 --- a/plugins/kubernetes-common/src/types.ts +++ b/plugins/kubernetes-common/src/types.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import type { JsonObject } from '@backstage/types'; import { V1ConfigMap, V1CronJob, @@ -69,7 +70,7 @@ export interface ClusterAttributes { * Specifies specific parameters used by some dashboard URL formatters. * This is used by the GKE formatter which requires the project, region and cluster name. */ - dashboardParameters?: any; + dashboardParameters?: JsonObject; } export interface ClusterObjects { diff --git a/plugins/kubernetes/api-report.md b/plugins/kubernetes/api-report.md index 33ac98fb76..8dc0114738 100644 --- a/plugins/kubernetes/api-report.md +++ b/plugins/kubernetes/api-report.md @@ -10,6 +10,7 @@ import { BackstagePlugin } from '@backstage/core-plugin-api'; import { DiscoveryApi } from '@backstage/core-plugin-api'; import { Entity } from '@backstage/catalog-model'; import { IdentityApi } from '@backstage/core-plugin-api'; +import type { JsonObject } from '@backstage/types'; import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common'; import { OAuthApi } from '@backstage/core-plugin-api'; import { ObjectsByEntityResponse } from '@backstage/plugin-kubernetes-common'; diff --git a/plugins/kubernetes/src/types/types.ts b/plugins/kubernetes/src/types/types.ts index 92e06e2e04..1bdfa181d9 100644 --- a/plugins/kubernetes/src/types/types.ts +++ b/plugins/kubernetes/src/types/types.ts @@ -14,6 +14,7 @@ * limitations under the License. */ +import type { JsonObject } from '@backstage/types'; import { V1Deployment, V1Pod, @@ -44,7 +45,7 @@ export interface GroupedResponses extends DeploymentResources { export interface ClusterLinksFormatterOptions { dashboardUrl?: URL; - dashboardParameters?: any; + dashboardParameters?: JsonObject; object: any; kind: string; } diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.test.ts b/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.test.ts index 31e07a0f14..b767d496a2 100644 --- a/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.test.ts +++ b/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.test.ts @@ -114,5 +114,47 @@ describe('clusterLinks', () => { ); }); }); + describe('GKE app', () => { + it('should return an url on the deployment', () => { + const url = formatClusterLink({ + dashboardApp: 'gke', + dashboardParameters: { + projectId: 'foobar-333614', + region: 'us-east1-c', + clusterName: 'cluster-1', + }, + object: { + metadata: { + name: 'foobar', + namespace: 'bar', + }, + }, + kind: 'Deployment', + }); + expect(url).toBe( + 'https://console.cloud.google.com/kubernetes/deployment/us-east1-c/cluster-1/bar/foobar/overview?project=foobar-333614', + ); + }); + it('should return an url on the service', () => { + const url = formatClusterLink({ + dashboardApp: 'gke', + dashboardParameters: { + projectId: 'foobar-333614', + region: 'us-east1-c', + clusterName: 'cluster-1', + }, + object: { + metadata: { + name: 'foobar', + namespace: 'bar', + }, + }, + kind: 'Service', + }); + expect(url).toBe( + 'https://console.cloud.google.com/kubernetes/service/us-east1-c/cluster-1/bar/foobar/overview?project=foobar-333614', + ); + }); + }); }); }); diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.ts b/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.ts index 90fd616737..6a998bbce2 100644 --- a/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.ts +++ b/plugins/kubernetes/src/utils/clusterLinks/formatClusterLink.ts @@ -14,12 +14,13 @@ * limitations under the License. */ +import type { JsonObject } from '@backstage/types'; import { defaultFormatterName, clusterLinksFormatters } from './formatters'; export type FormatClusterLinkOptions = { dashboardUrl?: string; dashboardApp?: string; - dashboardParameters?: any; + dashboardParameters?: JsonObject; object: any; kind: string; }; diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/gke.test.ts b/plugins/kubernetes/src/utils/clusterLinks/formatters/gke.test.ts index 7560c9e353..20541f216d 100644 --- a/plugins/kubernetes/src/utils/clusterLinks/formatters/gke.test.ts +++ b/plugins/kubernetes/src/utils/clusterLinks/formatters/gke.test.ts @@ -45,7 +45,7 @@ describe('clusterLinks - GKE formatter', () => { kind: 'Deployment', }), ).toThrowError( - 'GKE dashboard requires a "projectId" in the dashboardParameters option', + 'GKE dashboard requires a "projectId" of type string in the dashboardParameters option', ); }); it('should provide a region in the dashboardParameters options', () => { @@ -64,7 +64,7 @@ describe('clusterLinks - GKE formatter', () => { kind: 'Deployment', }), ).toThrowError( - 'GKE dashboard requires a "region" in the dashboardParameters option', + 'GKE dashboard requires a "region" of type string in the dashboardParameters option', ); }); it('should provide a clusterName in the dashboardParameters options', () => { @@ -83,7 +83,7 @@ describe('clusterLinks - GKE formatter', () => { kind: 'Deployment', }), ).toThrowError( - 'GKE dashboard requires a "clusterName" in the dashboardParameters option', + 'GKE dashboard requires a "clusterName" of type string in the dashboardParameters option', ); }); it('should return an url on the cluster when there is a namespace only', () => { diff --git a/plugins/kubernetes/src/utils/clusterLinks/formatters/gke.ts b/plugins/kubernetes/src/utils/clusterLinks/formatters/gke.ts index bbd60bd568..1dbeb2872e 100644 --- a/plugins/kubernetes/src/utils/clusterLinks/formatters/gke.ts +++ b/plugins/kubernetes/src/utils/clusterLinks/formatters/gke.ts @@ -28,19 +28,19 @@ export function gkeFormatter(options: ClusterLinksFormatterOptions): URL { throw new Error('GKE dashboard requires a dashboardParameters option'); } const args = options.dashboardParameters; - if (!args.projectId) { + if (typeof args.projectId !== 'string') { throw new Error( - 'GKE dashboard requires a "projectId" in the dashboardParameters option', + 'GKE dashboard requires a "projectId" of type string in the dashboardParameters option', ); } - if (!args.region) { + if (typeof args.region !== 'string') { throw new Error( - 'GKE dashboard requires a "region" in the dashboardParameters option', + 'GKE dashboard requires a "region" of type string in the dashboardParameters option', ); } - if (!args.clusterName) { + if (typeof args.clusterName !== 'string') { throw new Error( - 'GKE dashboard requires a "clusterName" in the dashboardParameters option', + 'GKE dashboard requires a "clusterName" of type string in the dashboardParameters option', ); } const basePath = new URL('https://console.cloud.google.com/');