diff --git a/packages/app/package.json b/packages/app/package.json
index cb61e1ed8c..1262c954cc 100644
--- a/packages/app/package.json
+++ b/packages/app/package.json
@@ -16,6 +16,7 @@
"@backstage/plugin-gitops-profiles": "^0.1.1-alpha.22",
"@backstage/plugin-graphiql": "^0.1.1-alpha.22",
"@backstage/plugin-jenkins": "^0.1.1-alpha.22",
+ "@backstage/plugin-kubernetes": "^0.1.1-alpha.22",
"@backstage/plugin-lighthouse": "^0.1.1-alpha.22",
"@backstage/plugin-newrelic": "^0.1.1-alpha.22",
"@backstage/plugin-register-component": "^0.1.1-alpha.22",
diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx
index c382abc3a8..d96fe9841f 100644
--- a/packages/app/src/components/catalog/EntityPage.tsx
+++ b/packages/app/src/components/catalog/EntityPage.tsx
@@ -29,6 +29,7 @@ import {
import { Router as ApiDocsRouter } from '@backstage/plugin-api-docs';
import { Router as SentryRouter } from '@backstage/plugin-sentry';
import { EmbeddedDocsRouter as DocsRouter } from '@backstage/plugin-techdocs';
+import { Router as KubernetesRouter } from '@backstage/plugin-kubernetes';
import React from 'react';
import {
AboutCard,
@@ -99,6 +100,11 @@ const ServiceEntityPage = ({ entity }: { entity: Entity }) => (
title="Docs"
element={}
/>
+ }
+ />
);
@@ -124,6 +130,11 @@ const WebsiteEntityPage = ({ entity }: { entity: Entity }) => (
title="Docs"
element={}
/>
+ }
+ />
);
const DefaultEntityPage = ({ entity }: { entity: Entity }) => (
diff --git a/packages/app/src/plugins.ts b/packages/app/src/plugins.ts
index b36d0323e0..aa68bc5fad 100644
--- a/packages/app/src/plugins.ts
+++ b/packages/app/src/plugins.ts
@@ -33,3 +33,4 @@ export { plugin as Jenkins } from '@backstage/plugin-jenkins';
export { plugin as ApiDocs } from '@backstage/plugin-api-docs';
export { plugin as GithubPullRequests } from '@roadiehq/backstage-plugin-github-pull-requests';
export { plugin as GcpProjects } from '@backstage/plugin-gcp-projects';
+export { plugin as Kubernetes } from '@backstage/plugin-kubernetes';
diff --git a/packages/backend/package.json b/packages/backend/package.json
index aa6f0ad0bf..147ea630c2 100644
--- a/packages/backend/package.json
+++ b/packages/backend/package.json
@@ -26,6 +26,7 @@
"@backstage/plugin-catalog-backend": "^0.1.1-alpha.22",
"@backstage/plugin-graphql-backend": "^0.1.1-alpha.22",
"@backstage/plugin-identity-backend": "^0.1.1-alpha.22",
+ "@backstage/plugin-kubernetes-backend": "^0.1.1-alpha.22",
"@backstage/plugin-proxy-backend": "^0.1.1-alpha.22",
"@backstage/plugin-rollbar-backend": "^0.1.1-alpha.22",
"@backstage/plugin-scaffolder-backend": "^0.1.1-alpha.22",
diff --git a/packages/backend/src/index.ts b/packages/backend/src/index.ts
index ab32822769..7c52175d76 100644
--- a/packages/backend/src/index.ts
+++ b/packages/backend/src/index.ts
@@ -34,6 +34,7 @@ import healthcheck from './plugins/healthcheck';
import auth from './plugins/auth';
import catalog from './plugins/catalog';
import identity from './plugins/identity';
+import kubernetes from './plugins/kubernetes';
import rollbar from './plugins/rollbar';
import scaffolder from './plugins/scaffolder';
import sentry from './plugins/sentry';
@@ -73,6 +74,7 @@ async function main() {
const rollbarEnv = useHotMemoize(module, () => createEnv('rollbar'));
const sentryEnv = useHotMemoize(module, () => createEnv('sentry'));
const techdocsEnv = useHotMemoize(module, () => createEnv('techdocs'));
+ const kubernetesEnv = useHotMemoize(module, () => createEnv('kubernetes'));
const graphqlEnv = useHotMemoize(module, () => createEnv('graphql'));
const appEnv = useHotMemoize(module, () => createEnv('app'));
@@ -86,6 +88,7 @@ async function main() {
.addRouter('/auth', await auth(authEnv))
.addRouter('/identity', await identity(identityEnv))
.addRouter('/techdocs', await techdocs(techdocsEnv))
+ .addRouter('/kubernetes', await kubernetes(kubernetesEnv))
.addRouter('/proxy', await proxy(proxyEnv, '/proxy'))
.addRouter('/graphql', await graphql(graphqlEnv))
.addRouter('', await app(appEnv));
diff --git a/packages/backend/src/plugins/kubernetes.ts b/packages/backend/src/plugins/kubernetes.ts
new file mode 100644
index 0000000000..42b7722ff6
--- /dev/null
+++ b/packages/backend/src/plugins/kubernetes.ts
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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 { createRouter } from '@backstage/plugin-kubernetes-backend';
+import { PluginEnvironment } from '../types';
+
+export default async function createPlugin({ logger }: PluginEnvironment) {
+ return await createRouter({ logger });
+}
diff --git a/plugins/kubernetes-backend/.eslintrc.js b/plugins/kubernetes-backend/.eslintrc.js
new file mode 100644
index 0000000000..16a033dbc6
--- /dev/null
+++ b/plugins/kubernetes-backend/.eslintrc.js
@@ -0,0 +1,3 @@
+module.exports = {
+ extends: [require.resolve('@backstage/cli/config/eslint.backend')],
+};
diff --git a/plugins/kubernetes-backend/README.md b/plugins/kubernetes-backend/README.md
new file mode 100644
index 0000000000..0246da24ed
--- /dev/null
+++ b/plugins/kubernetes-backend/README.md
@@ -0,0 +1,11 @@
+# Kubernetes Backend
+
+WORK IN PROGRESS
+
+This is the backend part of the Kubernetes plugin.
+
+It responds to Kubernetes requests from the frontend.
+
+## Links
+
+- [The Backstage homepage](https://backstage.io)
diff --git a/plugins/kubernetes-backend/package.json b/plugins/kubernetes-backend/package.json
new file mode 100644
index 0000000000..2e59aaeec0
--- /dev/null
+++ b/plugins/kubernetes-backend/package.json
@@ -0,0 +1,42 @@
+{
+ "name": "@backstage/plugin-kubernetes-backend",
+ "version": "0.1.1-alpha.22",
+ "main": "src/index.ts",
+ "types": "src/index.ts",
+ "license": "Apache-2.0",
+ "private": false,
+ "publishConfig": {
+ "access": "public",
+ "main": "dist/index.cjs.js",
+ "types": "dist/index.d.ts"
+ },
+ "scripts": {
+ "start": "backstage-cli backend:dev",
+ "build": "backstage-cli backend:build",
+ "lint": "backstage-cli lint",
+ "test": "backstage-cli test",
+ "prepack": "backstage-cli prepack",
+ "postpack": "backstage-cli postpack",
+ "clean": "backstage-cli clean"
+ },
+ "dependencies": {
+ "@backstage/backend-common": "^0.1.1-alpha.22",
+ "@types/express": "^4.17.6",
+ "compression": "^1.7.4",
+ "cors": "^2.8.5",
+ "express": "^4.17.1",
+ "express-promise-router": "^3.0.3",
+ "fs-extra": "^9.0.0",
+ "helmet": "^4.0.0",
+ "morgan": "^1.10.0",
+ "winston": "^3.2.1",
+ "yn": "^4.0.0"
+ },
+ "devDependencies": {
+ "@backstage/cli": "^0.1.1-alpha.22",
+ "jest-fetch-mock": "^3.0.3"
+ },
+ "files": [
+ "dist"
+ ]
+}
diff --git a/plugins/kubernetes-backend/src/index.test.ts b/plugins/kubernetes-backend/src/index.test.ts
new file mode 100644
index 0000000000..4fca4ca746
--- /dev/null
+++ b/plugins/kubernetes-backend/src/index.test.ts
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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 '@backstage/backend-common';
+
+describe('test', () => {
+ it('unbreaks the test runner', () => {
+ expect(true).toBeTruthy();
+ });
+});
diff --git a/plugins/kubernetes-backend/src/index.ts b/plugins/kubernetes-backend/src/index.ts
new file mode 100644
index 0000000000..7612c392a2
--- /dev/null
+++ b/plugins/kubernetes-backend/src/index.ts
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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 './service/router';
diff --git a/plugins/kubernetes-backend/src/run.ts b/plugins/kubernetes-backend/src/run.ts
new file mode 100644
index 0000000000..995adaff10
--- /dev/null
+++ b/plugins/kubernetes-backend/src/run.ts
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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 yn from 'yn';
+import { getRootLogger } from '@backstage/backend-common';
+import { startStandaloneServer } from './service/standaloneServer';
+
+const port = process.env.PLUGIN_PORT ? Number(process.env.PLUGIN_PORT) : 3004;
+const enableCors = yn(process.env.PLUGIN_CORS, { default: false });
+const logger = getRootLogger();
+
+startStandaloneServer({ port, enableCors, logger }).catch(err => {
+ logger.error(err);
+ process.exit(1);
+});
+
+process.on('SIGINT', () => {
+ logger.info('CTRL+C pressed; exiting.');
+ process.exit(0);
+});
diff --git a/plugins/kubernetes-backend/src/service/router.ts b/plugins/kubernetes-backend/src/service/router.ts
new file mode 100644
index 0000000000..b200896887
--- /dev/null
+++ b/plugins/kubernetes-backend/src/service/router.ts
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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 express from 'express';
+import Router from 'express-promise-router';
+import { Logger } from 'winston';
+
+export interface RouterOptions {
+ logger: Logger;
+}
+
+const makeRouter = (logger: Logger): express.Router => {
+ const router = Router();
+ router.use(express.json());
+
+ router.get('/services/:serviceId', async (req, res) => {
+ const serviceId = req.params.serviceId;
+ logger.info(`HERE ${serviceId}`);
+ res.send({ serviceId });
+ });
+
+ return router;
+};
+
+export async function createRouter(
+ options: RouterOptions,
+): Promise {
+ const logger = options.logger;
+
+ logger.info('Initializing Kubernetes backend');
+ return makeRouter(logger);
+}
diff --git a/plugins/kubernetes-backend/src/service/standaloneApplication.ts b/plugins/kubernetes-backend/src/service/standaloneApplication.ts
new file mode 100644
index 0000000000..5eea4fb8f5
--- /dev/null
+++ b/plugins/kubernetes-backend/src/service/standaloneApplication.ts
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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 {
+ errorHandler,
+ notFoundHandler,
+ requestLoggingHandler,
+} from '@backstage/backend-common';
+import compression from 'compression';
+import cors from 'cors';
+import express from 'express';
+import helmet from 'helmet';
+import { Logger } from 'winston';
+import { createRouter } from './router';
+
+export interface ApplicationOptions {
+ enableCors: boolean;
+ logger: Logger;
+}
+
+export async function createStandaloneApplication(
+ options: ApplicationOptions,
+): Promise {
+ const { enableCors, logger } = options;
+ const app = express();
+
+ app.use(helmet());
+ if (enableCors) {
+ app.use(cors());
+ }
+ app.use(compression());
+ app.use(express.json());
+ app.use(requestLoggingHandler());
+ app.use('/', await createRouter({ logger }));
+ app.use(notFoundHandler());
+ app.use(errorHandler());
+
+ return app;
+}
diff --git a/plugins/kubernetes-backend/src/service/standaloneServer.ts b/plugins/kubernetes-backend/src/service/standaloneServer.ts
new file mode 100644
index 0000000000..9831bc986b
--- /dev/null
+++ b/plugins/kubernetes-backend/src/service/standaloneServer.ts
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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 { Server } from 'http';
+import { Logger } from 'winston';
+import { createStandaloneApplication } from './standaloneApplication';
+
+export interface ServerOptions {
+ port: number;
+ enableCors: boolean;
+ logger: Logger;
+}
+
+export async function startStandaloneServer(
+ options: ServerOptions,
+): Promise {
+ const logger = options.logger.child({ service: 'kubernetes-backend' });
+
+ logger.debug('Creating application...');
+ const app = await createStandaloneApplication({
+ enableCors: options.enableCors,
+ logger,
+ });
+
+ logger.debug('Starting application server...');
+ return await new Promise((resolve, reject) => {
+ const server = app.listen(options.port, (err?: Error) => {
+ if (err) {
+ reject(err);
+ return;
+ }
+
+ logger.info(`Listening on port ${options.port}`);
+ resolve(server);
+ });
+ });
+}
diff --git a/plugins/kubernetes-backend/src/setupTests.ts b/plugins/kubernetes-backend/src/setupTests.ts
new file mode 100644
index 0000000000..f7b6ca962d
--- /dev/null
+++ b/plugins/kubernetes-backend/src/setupTests.ts
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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.
+ */
+
+require('jest-fetch-mock').enableMocks();
+
+export {};
diff --git a/plugins/kubernetes/.eslintrc.js b/plugins/kubernetes/.eslintrc.js
new file mode 100644
index 0000000000..13573efa9c
--- /dev/null
+++ b/plugins/kubernetes/.eslintrc.js
@@ -0,0 +1,3 @@
+module.exports = {
+ extends: [require.resolve('@backstage/cli/config/eslint')],
+};
diff --git a/plugins/kubernetes/README.md b/plugins/kubernetes/README.md
new file mode 100644
index 0000000000..678c9a96a6
--- /dev/null
+++ b/plugins/kubernetes/README.md
@@ -0,0 +1,13 @@
+# kubernetes
+
+Welcome to the kubernetes plugin!
+
+_This plugin was created through the Backstage CLI_
+
+## Getting started
+
+Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn start` in the root directory, and then navigating to [/kubernetes](http://localhost:3000/kubernetes).
+
+You can also serve the plugin in isolation by running `yarn start` in the plugin directory.
+This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads.
+It is only meant for local development, and the setup for it can be found inside the [/dev](./dev) directory.
diff --git a/plugins/kubernetes/dev/index.tsx b/plugins/kubernetes/dev/index.tsx
new file mode 100644
index 0000000000..f352fb9c34
--- /dev/null
+++ b/plugins/kubernetes/dev/index.tsx
@@ -0,0 +1,19 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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 { createDevApp } from '@backstage/dev-utils';
+import { plugin } from '../src';
+
+createDevApp().registerPlugin(plugin).render();
diff --git a/plugins/kubernetes/package.json b/plugins/kubernetes/package.json
new file mode 100644
index 0000000000..aa8a7f61e4
--- /dev/null
+++ b/plugins/kubernetes/package.json
@@ -0,0 +1,47 @@
+{
+ "name": "@backstage/plugin-kubernetes",
+ "version": "0.1.1-alpha.22",
+ "main": "src/index.ts",
+ "types": "src/index.ts",
+ "license": "Apache-2.0",
+ "publishConfig": {
+ "access": "public",
+ "main": "dist/index.esm.js",
+ "types": "dist/index.d.ts"
+ },
+ "scripts": {
+ "build": "backstage-cli plugin:build",
+ "start": "backstage-cli plugin:serve",
+ "lint": "backstage-cli lint",
+ "test": "backstage-cli test",
+ "diff": "backstage-cli plugin:diff",
+ "prepack": "backstage-cli prepack",
+ "postpack": "backstage-cli postpack",
+ "clean": "backstage-cli clean"
+ },
+ "dependencies": {
+ "@backstage/catalog-model": "^0.1.1-alpha.22",
+ "@backstage/core": "^0.1.1-alpha.22",
+ "@backstage/theme": "^0.1.1-alpha.22",
+ "@material-ui/core": "^4.11.0",
+ "@material-ui/icons": "^4.9.1",
+ "@material-ui/lab": "4.0.0-alpha.45",
+ "react": "^16.13.1",
+ "react-router-dom": "6.0.0-beta.0",
+ "react-dom": "^16.13.1",
+ "react-use": "^15.3.3"
+ },
+ "devDependencies": {
+ "@backstage/cli": "^0.1.1-alpha.22",
+ "@backstage/dev-utils": "^0.1.1-alpha.22",
+ "@testing-library/jest-dom": "^5.10.1",
+ "@testing-library/react": "^10.4.1",
+ "@testing-library/user-event": "^12.0.7",
+ "@types/jest": "^26.0.7",
+ "@types/node": "^12.0.0",
+ "jest-fetch-mock": "^3.0.3"
+ },
+ "files": [
+ "dist"
+ ]
+}
diff --git a/plugins/kubernetes/src/Router.tsx b/plugins/kubernetes/src/Router.tsx
new file mode 100644
index 0000000000..994788bf72
--- /dev/null
+++ b/plugins/kubernetes/src/Router.tsx
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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 React from 'react';
+import { Entity } from '@backstage/catalog-model';
+import { Route, Routes } from 'react-router-dom';
+
+import { rootCatalogKubernetesRouteRef } from './plugin';
+import { KubernetesContent } from './components/KubernetesContent';
+import { WarningPanel } from '@backstage/core';
+
+const KUBERNETES_ANNOTATION = 'backstage.io/kubernetes';
+
+export const Router = ({ entity }: { entity: Entity }) => {
+ const kubernetesAnnotationValue =
+ entity.metadata.annotations?.[KUBERNETES_ANNOTATION];
+
+ if (!kubernetesAnnotationValue) {
+ return (
+
+
{KUBERNETES_ANNOTATION}
annotation is missing on the entity.
+
+ );
+ }
+
+ return (
+
+ }
+ />
+
+ );
+};
diff --git a/plugins/kubernetes/src/api/KubernetesBackendClient.ts b/plugins/kubernetes/src/api/KubernetesBackendClient.ts
new file mode 100644
index 0000000000..fed3cd2ed0
--- /dev/null
+++ b/plugins/kubernetes/src/api/KubernetesBackendClient.ts
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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 { DiscoveryApi } from '@backstage/core';
+import { KubernetesApi } from './types';
+
+export class KubernetesBackendClient implements KubernetesApi {
+ private readonly discoveryApi: DiscoveryApi;
+
+ constructor(options: { discoveryApi: DiscoveryApi }) {
+ this.discoveryApi = options.discoveryApi;
+ }
+
+ private async getRequired(path: string): Promise {
+ const url = `${await this.discoveryApi.getBaseUrl('kubernetes')}${path}`;
+ const response = await fetch(url);
+
+ if (!response.ok) {
+ const payload = await response.text();
+ const message = `Request failed with ${response.status} ${response.statusText}, ${payload}`;
+ throw new Error(message);
+ }
+
+ return await response.json();
+ }
+
+ async getObjectsByServiceId(serviceId: String): Promise<{}> {
+ return await this.getRequired(`/services/${serviceId}`);
+ }
+}
diff --git a/plugins/kubernetes/src/api/types.ts b/plugins/kubernetes/src/api/types.ts
new file mode 100644
index 0000000000..2ad6e567f9
--- /dev/null
+++ b/plugins/kubernetes/src/api/types.ts
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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 { createApiRef } from '@backstage/core';
+
+export const kubernetesApiRef = createApiRef({
+ id: 'plugin.kubernetes.service',
+ description:
+ 'Used by the Kubernetes plugin to make requests to accompanying backend',
+});
+
+export interface KubernetesApi {
+ getObjectsByServiceId(serviceId: String): Promise<{}>;
+}
diff --git a/plugins/kubernetes/src/components/KubernetesContent/KubernetesContent.tsx b/plugins/kubernetes/src/components/KubernetesContent/KubernetesContent.tsx
new file mode 100644
index 0000000000..d79454a5d1
--- /dev/null
+++ b/plugins/kubernetes/src/components/KubernetesContent/KubernetesContent.tsx
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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 React, { FC, useEffect, useState } from 'react';
+import { Typography, Grid } from '@material-ui/core';
+import {
+ InfoCard,
+ Page,
+ pageTheme,
+ Content,
+ ContentHeader,
+ useApi,
+} from '@backstage/core';
+import { Entity } from '@backstage/catalog-model';
+import { kubernetesApiRef } from '../../api/types';
+
+// TODO this is a temporary component used to construct the Kubernetes plugin boilerplate
+
+export const KubernetesContent: FC<{ entity: Entity }> = ({ entity }) => {
+ const kubernetesApi = useApi(kubernetesApiRef);
+ const [kubernetesObjects, setKubernetesObjects] = useState<{} | undefined>(
+ undefined,
+ );
+ const [error, setError] = useState(undefined);
+
+ useEffect(() => {
+ kubernetesApi
+ .getObjectsByServiceId(entity.metadata.name)
+ .then(result => {
+ setKubernetesObjects(result);
+ })
+ .catch(e => {
+ setError(e.message);
+ });
+ }, [entity.metadata.name, kubernetesApi]);
+
+ return (
+
+
+
+
+
+
+
+ {kubernetesObjects === undefined &&
+ )}
+
+
+
+
+
+
+ );
+};
diff --git a/plugins/kubernetes/src/components/KubernetesContent/index.ts b/plugins/kubernetes/src/components/KubernetesContent/index.ts
new file mode 100644
index 0000000000..dc10b08927
--- /dev/null
+++ b/plugins/kubernetes/src/components/KubernetesContent/index.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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 { KubernetesContent } from './KubernetesContent';
diff --git a/plugins/kubernetes/src/index.ts b/plugins/kubernetes/src/index.ts
new file mode 100644
index 0000000000..8b5969666c
--- /dev/null
+++ b/plugins/kubernetes/src/index.ts
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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 { plugin } from './plugin';
+export { Router } from './Router';
diff --git a/plugins/kubernetes/src/plugin.test.ts b/plugins/kubernetes/src/plugin.test.ts
new file mode 100644
index 0000000000..20c50a813a
--- /dev/null
+++ b/plugins/kubernetes/src/plugin.test.ts
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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 { plugin } from './plugin';
+
+describe('kubernetes', () => {
+ it('should export plugin', () => {
+ expect(plugin).toBeDefined();
+ });
+});
diff --git a/plugins/kubernetes/src/plugin.ts b/plugins/kubernetes/src/plugin.ts
new file mode 100644
index 0000000000..b7ad9615f5
--- /dev/null
+++ b/plugins/kubernetes/src/plugin.ts
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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 {
+ createApiFactory,
+ createPlugin,
+ createRouteRef,
+ discoveryApiRef,
+} from '@backstage/core';
+import { KubernetesBackendClient } from './api/KubernetesBackendClient';
+import { kubernetesApiRef } from './api/types';
+
+export const rootCatalogKubernetesRouteRef = createRouteRef({
+ path: '*',
+ title: 'Kubernetes',
+});
+
+export const plugin = createPlugin({
+ id: 'kubernetes',
+ apis: [
+ createApiFactory({
+ api: kubernetesApiRef,
+ deps: { discoveryApi: discoveryApiRef },
+ factory: ({ discoveryApi }) =>
+ new KubernetesBackendClient({ discoveryApi }),
+ }),
+ ],
+});
diff --git a/plugins/kubernetes/src/setupTests.ts b/plugins/kubernetes/src/setupTests.ts
new file mode 100644
index 0000000000..4b4cdbdaaf
--- /dev/null
+++ b/plugins/kubernetes/src/setupTests.ts
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2020 Spotify AB
+ *
+ * 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 '@testing-library/jest-dom';
+
+require('jest-fetch-mock').enableMocks();