refactor code in order to support multiple dashboard link formatters

Signed-off-by: Morgan Martinet <morgan.martinet@montreal.ca>
This commit is contained in:
Morgan Martinet
2021-08-29 19:07:34 -04:00
parent c59294d1e5
commit abf7c46404
29 changed files with 757 additions and 144 deletions
+16
View File
@@ -12,6 +12,12 @@ import { KubernetesRequestBody } from '@backstage/plugin-kubernetes-common';
import { OAuthApi } from '@backstage/core-plugin-api';
import { RouteRef } from '@backstage/core-plugin-api';
// Warning: (ae-forgotten-export) The symbol "ClusterLinksFormatter" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "clusterLinksFormatters" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const clusterLinksFormatters: Record<string, ClusterLinksFormatter>;
// Warning: (ae-missing-release-tag) "EntityKubernetesContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@@ -19,6 +25,16 @@ export const EntityKubernetesContent: (_props: {
entity?: Entity | undefined;
}) => JSX.Element;
// Warning: (ae-missing-release-tag) "formatClusterLink" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export function formatClusterLink(options: {
dashboardUrl?: string;
dashboardApp?: string;
object: any;
kind: string;
}): string | undefined;
// Warning: (ae-forgotten-export) The symbol "KubernetesAuthProvidersApi" needs to be exported by the entry point index.d.ts
// Warning: (ae-missing-release-tag) "KubernetesAuthProviders" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
@@ -112,6 +112,7 @@ const KubernetesDrawerContent = <T extends KubernetesDrawerable>({
const cluster = useContext(ClusterContext);
const clusterLink = formatClusterLink({
dashboardUrl: cluster.dashboardUrl,
dashboardApp: cluster.dashboardApp,
object,
kind,
});
+1
View File
@@ -20,3 +20,4 @@ export {
} from './plugin';
export { Router } from './Router';
export * from './kubernetes-auth-provider';
export * from './utils/clusterLinks';
+10
View File
@@ -37,3 +37,13 @@ export interface GroupedResponses extends DeploymentResources {
ingresses: ExtensionsV1beta1Ingress[];
customResources: any[];
}
export interface ClusterLinksFormatterOptions {
dashboardUrl: URL;
object: any;
kind: string;
}
export type ClusterLinksFormatter = (
options: ClusterLinksFormatterOptions,
) => URL;
@@ -1,119 +0,0 @@
/*
* Copyright 2021 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { formatClusterLink } from './clusterLinks';
describe('clusterLinks', () => {
describe('formatClusterLink', () => {
it('should not return an url when there is no dashboard url', () => {
const url = formatClusterLink({ object: {}, kind: 'foo' });
expect(url).toBeUndefined();
});
it('should return an url even when there is no object', () => {
const url = formatClusterLink({
dashboardUrl: 'https://k8s.foo.com',
object: undefined,
kind: 'foo',
});
expect(url).toBe('https://k8s.foo.com');
});
it('should return an url on the workloads when there is a namespace only', () => {
const url = formatClusterLink({
dashboardUrl: 'https://k8s.foo.com',
object: {
metadata: {
namespace: 'bar',
},
},
kind: 'foo',
});
expect(url).toBe('https://k8s.foo.com/#/workloads?namespace=bar');
});
it('should return an url on the workloads when the kind is not recognizeed', () => {
const url = formatClusterLink({
dashboardUrl: 'https://k8s.foo.com',
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'UnknownKind',
});
expect(url).toBe('https://k8s.foo.com/#/workloads?namespace=bar');
});
it('should return an url on the deployment', () => {
const url = formatClusterLink({
dashboardUrl: 'https://k8s.foo.com/',
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'Deployment',
});
expect(url).toBe(
'https://k8s.foo.com/#/deployment/bar/foobar?namespace=bar',
);
});
it('should return an url on the service', () => {
const url = formatClusterLink({
dashboardUrl: 'https://k8s.foo.com/',
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'Service',
});
expect(url).toBe(
'https://k8s.foo.com/#/service/bar/foobar?namespace=bar',
);
});
it('should return an url on the ingress', () => {
const url = formatClusterLink({
dashboardUrl: 'https://k8s.foo.com/',
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'Ingress',
});
expect(url).toBe(
'https://k8s.foo.com/#/ingress/bar/foobar?namespace=bar',
);
});
it('should return an url on the deployment for a hpa', () => {
const url = formatClusterLink({
dashboardUrl: 'https://k8s.foo.com/',
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'HorizontalPodAutoscaler',
});
expect(url).toBe(
'https://k8s.foo.com/#/deployment/bar/foobar?namespace=bar',
);
});
});
});
@@ -0,0 +1,133 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { formatClusterLink } from './formatClusterLink';
describe('clusterLinks', () => {
describe('formatClusterLink', () => {
it('should not return an url when there is no dashboard url', () => {
const url = formatClusterLink({ object: {}, kind: 'foo' });
expect(url).toBeUndefined();
});
it('should return an url even when there is no object', () => {
const url = formatClusterLink({
dashboardUrl: 'https://k8s.foo.com',
object: undefined,
kind: 'foo',
});
expect(url).toBe('https://k8s.foo.com');
});
it('should throw when the app is not recognized', () => {
expect(() =>
formatClusterLink({
dashboardUrl: 'https://k8s.foo.com',
dashboardApp: 'unknownapp',
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'Deployment',
}),
).toThrowError(
"Could not find Kubernetes dashboard app named 'unknownapp'",
);
});
describe('default app', () => {
it('should return an url on the deployment', () => {
const url = formatClusterLink({
dashboardUrl: 'https://k8s.foo.com/',
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'Deployment',
});
expect(url).toBe(
'https://k8s.foo.com/#/deployment/bar/foobar?namespace=bar',
);
});
it('should return an url on the service', () => {
const url = formatClusterLink({
dashboardUrl: 'https://k8s.foo.com/',
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'Service',
});
expect(url).toBe(
'https://k8s.foo.com/#/service/bar/foobar?namespace=bar',
);
});
it('should return an url on the deployment properly url encoded', () => {
const url = formatClusterLink({
dashboardUrl: 'https://k8s.foo.com/',
object: {
metadata: {
name: 'foobar',
namespace: 'bar bar',
},
},
kind: 'Deployment',
});
expect(url).toBe(
'https://k8s.foo.com/#/deployment/bar%20bar/foobar?namespace=bar+bar',
);
});
});
describe('standard app', () => {
it('should return an url on the deployment', () => {
const url = formatClusterLink({
dashboardUrl: 'https://k8s.foo.com/',
dashboardApp: 'standard',
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'Deployment',
});
expect(url).toBe(
'https://k8s.foo.com/#/deployment/bar/foobar?namespace=bar',
);
});
it('should return an url on the service', () => {
const url = formatClusterLink({
dashboardUrl: 'https://k8s.foo.com/',
dashboardApp: 'standard',
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'Service',
});
expect(url).toBe(
'https://k8s.foo.com/#/service/bar/foobar?namespace=bar',
);
});
});
});
});
@@ -0,0 +1,45 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { defaultFormatterName, clusterLinksFormatters } from './formatters';
export function formatClusterLink(options: {
dashboardUrl?: string;
dashboardApp?: string;
object: any;
kind: string;
}) {
if (!options.dashboardUrl) {
return undefined;
}
if (!options.object) {
return options.dashboardUrl;
}
const app = options.dashboardApp || defaultFormatterName;
const formatter = clusterLinksFormatters[app];
if (!formatter) {
throw new Error(`Could not find Kubernetes dashboard app named '${app}'`);
}
const url = formatter({
dashboardUrl: new URL(options.dashboardUrl),
object: options.object,
kind: options.kind,
});
// Note that we can't rely on 'url.href' since it will put the search before the hash
// and this won't be properly recognized by SPAs such as Angular in the standard dashboard.
// Note also that pathname, hash and search will be properly url encoded.
return `${url.origin}${url.pathname}${url.hash}${url.search}`;
}
@@ -0,0 +1,33 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { aksFormatter } from './aks';
describe('clusterLinks - aks formatter', () => {
it('should return an url on the workloads when there is a namespace only', () => {
expect(() =>
aksFormatter({
dashboardUrl: new URL('https://k8s.foo.com'),
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'Deployment',
}),
).toThrowError('AKS formatter is not yet implemented');
});
});
@@ -0,0 +1,20 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ClusterLinksFormatterOptions } from '../../../types/types';
export function aksFormatter(_options: ClusterLinksFormatterOptions): URL {
throw new Error('AKS formatter is not yet implemented');
}
@@ -0,0 +1,33 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { eksFormatter } from './eks';
describe('clusterLinks - aks formatter', () => {
it('should return an url on the workloads when there is a namespace only', () => {
expect(() =>
eksFormatter({
dashboardUrl: new URL('https://k8s.foo.com'),
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'Deployment',
}),
).toThrowError('EKS formatter is not yet implemented');
});
});
@@ -0,0 +1,20 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ClusterLinksFormatterOptions } from '../../../types/types';
export function eksFormatter(_options: ClusterLinksFormatterOptions): URL {
throw new Error('EKS formatter is not yet implemented');
}
@@ -0,0 +1,33 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { gkeFormatter } from './gke';
describe('clusterLinks - aks formatter', () => {
it('should return an url on the workloads when there is a namespace only', () => {
expect(() =>
gkeFormatter({
dashboardUrl: new URL('https://k8s.foo.com'),
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'Deployment',
}),
).toThrowError('GKE formatter is not yet implemented');
});
});
@@ -0,0 +1,20 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ClusterLinksFormatterOptions } from '../../../types/types';
export function gkeFormatter(_options: ClusterLinksFormatterOptions): URL {
throw new Error('GKE formatter is not yet implemented');
}
@@ -0,0 +1,26 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ClusterLinksFormatter } from '../../../types/types';
import { standardFormatter } from './standard';
import { rancherFormatter } from './rancher';
import { openshiftFormatter } from './openshift';
export const clusterLinksFormatters: Record<string, ClusterLinksFormatter> = {
standard: standardFormatter,
rancher: rancherFormatter,
openshift: openshiftFormatter,
};
export const defaultFormatterName = 'standard';
@@ -0,0 +1,33 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { openshiftFormatter } from './openshift';
describe('clusterLinks - aks formatter', () => {
it('should return an url on the workloads when there is a namespace only', () => {
expect(() =>
openshiftFormatter({
dashboardUrl: new URL('https://k8s.foo.com'),
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'Deployment',
}),
).toThrowError('OpenShift formatter is not yet implemented');
});
});
@@ -0,0 +1,22 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ClusterLinksFormatterOptions } from '../../../types/types';
export function openshiftFormatter(
_options: ClusterLinksFormatterOptions,
): URL {
throw new Error('OpenShift formatter is not yet implemented');
}
@@ -0,0 +1,33 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { rancherFormatter } from './rancher';
describe('clusterLinks - aks formatter', () => {
it('should return an url on the workloads when there is a namespace only', () => {
expect(() =>
rancherFormatter({
dashboardUrl: new URL('https://k8s.foo.com'),
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'Deployment',
}),
).toThrowError('Rancher formatter is not yet implemented');
});
});
@@ -0,0 +1,20 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ClusterLinksFormatterOptions } from '../../../types/types';
export function rancherFormatter(_options: ClusterLinksFormatterOptions): URL {
throw new Error('Rancher formatter is not yet implemented');
}
@@ -0,0 +1,115 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { standardFormatter } from './standard';
function formatUrl(url: URL) {
// Note that we can't rely on 'url.href' since it will put the search before the hash
// and this won't be properly recognized by SPAs such as Angular in the standard dashboard.
// Note also that pathname, hash and search will be properly url encoded.
return `${url.origin}${url.pathname}${url.hash}${url.search}`;
}
describe('clusterLinks - standard formatter', () => {
it('should return an url on the workloads when there is a namespace only', () => {
const url = standardFormatter({
dashboardUrl: new URL('https://k8s.foo.com'),
object: {
metadata: {
namespace: 'bar',
},
},
kind: 'foo',
});
expect(formatUrl(url)).toBe(
'https://k8s.foo.com/#/workloads?namespace=bar',
);
});
it('should return an url on the workloads when the kind is not recognizeed', () => {
const url = standardFormatter({
dashboardUrl: new URL('https://k8s.foo.com'),
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'UnknownKind',
});
expect(formatUrl(url)).toBe(
'https://k8s.foo.com/#/workloads?namespace=bar',
);
});
it('should return an url on the deployment', () => {
const url = standardFormatter({
dashboardUrl: new URL('https://k8s.foo.com/'),
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'Deployment',
});
expect(formatUrl(url)).toBe(
'https://k8s.foo.com/#/deployment/bar/foobar?namespace=bar',
);
});
it('should return an url on the service', () => {
const url = standardFormatter({
dashboardUrl: new URL('https://k8s.foo.com/'),
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'Service',
});
expect(formatUrl(url)).toBe(
'https://k8s.foo.com/#/service/bar/foobar?namespace=bar',
);
});
it('should return an url on the ingress', () => {
const url = standardFormatter({
dashboardUrl: new URL('https://k8s.foo.com/'),
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'Ingress',
});
expect(formatUrl(url)).toBe(
'https://k8s.foo.com/#/ingress/bar/foobar?namespace=bar',
);
});
it('should return an url on the deployment for a hpa', () => {
const url = standardFormatter({
dashboardUrl: new URL('https://k8s.foo.com/'),
object: {
metadata: {
name: 'foobar',
namespace: 'bar',
},
},
kind: 'HorizontalPodAutoscaler',
});
expect(formatUrl(url)).toBe(
'https://k8s.foo.com/#/deployment/bar/foobar?namespace=bar',
);
});
});
@@ -13,6 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ClusterLinksFormatterOptions } from '../../../types/types';
const KindMappings: Record<string, string> = {
deployment: 'deployment',
@@ -21,30 +22,18 @@ const KindMappings: Record<string, string> = {
horizontalpodautoscaler: 'deployment',
};
export function formatClusterLink(options: {
dashboardUrl?: string;
object: any;
kind: string;
}) {
if (!options.dashboardUrl) {
return undefined;
}
if (!options.object) {
return options.dashboardUrl;
}
const host = options.dashboardUrl.endsWith('/')
? options.dashboardUrl
: `${options.dashboardUrl}/`;
export function standardFormatter(options: ClusterLinksFormatterOptions) {
const result = new URL(options.dashboardUrl.href);
const name = options.object.metadata?.name;
const namespace = options.object.metadata?.namespace;
const validKind = KindMappings[options.kind.toLocaleLowerCase()];
if (validKind && name && namespace) {
return `${host}#/${encodeURIComponent(validKind)}/${encodeURIComponent(
namespace,
)}/${encodeURIComponent(name)}?namespace=${encodeURIComponent(namespace)}`;
}
if (namespace) {
return `${host}#/workloads?namespace=${encodeURIComponent(namespace)}`;
result.searchParams.set('namespace', namespace);
}
return options.dashboardUrl;
if (validKind && name && namespace) {
result.hash = `/${validKind}/${namespace}/${name}`;
} else if (namespace) {
result.hash = '/workloads';
}
return result;
}
@@ -0,0 +1,18 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { formatClusterLink } from './formatClusterLink';
export { clusterLinksFormatters } from './formatters';
+16
View File
@@ -0,0 +1,16 @@
/*
* Copyright 2020 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './clusterLinks';