@@ -23,8 +23,10 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@backstage/catalog-model": "workspace:^",
|
||||
"@backstage/config": "workspace:^",
|
||||
"@backstage/core-components": "workspace:^",
|
||||
"@backstage/core-plugin-api": "workspace:^",
|
||||
"@backstage/plugin-catalog-react": "workspace:^",
|
||||
"@backstage/theme": "workspace:^",
|
||||
"@material-ui/core": "^4.9.13",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
@@ -32,7 +34,8 @@
|
||||
"react-use": "^17.2.4"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.13.1 || ^17.0.0"
|
||||
"react": "^16.13.1 || ^17.0.0",
|
||||
"react-router-dom": "*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@backstage/cli": "workspace:^",
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
|
||||
/** @public */
|
||||
export const NOMAD_JOB_ANNOTATION = 'nomad.io/job';
|
||||
import { useEntity } from '@backstage/plugin-catalog-react';
|
||||
import { MissingAnnotationEmptyState } from '@backstage/core-components';
|
||||
import { Route, Routes } from 'react-router-dom';
|
||||
import { GroupListForEntity } from './components/GroupList/GroupListForEntity';
|
||||
|
||||
/** @public */
|
||||
export const NOMAD_GROUP_ANNOTATION = 'nomad.io/group';
|
||||
@@ -27,6 +29,20 @@ export const NOMAD_TASK_ANNOTATION = 'nomad.io/task';
|
||||
|
||||
/** @public */
|
||||
export const isNomadAvailable = (entity: Entity) =>
|
||||
Boolean(entity.metadata.annotations?.[NOMAD_JOB_ANNOTATION]) ||
|
||||
Boolean(entity.metadata.annotations?.[NOMAD_GROUP_ANNOTATION]) ||
|
||||
Boolean(entity.metadata.annotations?.[NOMAD_TASK_ANNOTATION]);
|
||||
|
||||
/** @public */
|
||||
export const EmbeddedRouter = () => {
|
||||
const { entity } = useEntity();
|
||||
|
||||
if (!isNomadAvailable(entity)) {
|
||||
return <MissingAnnotationEmptyState annotation={NOMAD_GROUP_ANNOTATION} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Routes>
|
||||
<Route path="/" element={<GroupListForEntity />} />
|
||||
</Routes>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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 { Config } from '@backstage/config';
|
||||
import { createApiRef } from '@backstage/core-plugin-api';
|
||||
|
||||
/** @public */
|
||||
export const nomadApiRef = createApiRef<NomadApi>({
|
||||
id: 'plugin.nomad.service',
|
||||
});
|
||||
|
||||
/** @public */
|
||||
export type NomadApi = {
|
||||
/**
|
||||
* listAllocations is for listing all allocations matching some part of 'prefix'.
|
||||
*
|
||||
* See: https://developer.hashicorp.com/nomad/api-docs/allocations#list-allocations
|
||||
*/
|
||||
listAllocations: (
|
||||
options: ListAllocationsRequest,
|
||||
) => Promise<ListAllocationsResponse>;
|
||||
};
|
||||
|
||||
/** @public */
|
||||
export interface ListAllocationsRequest {
|
||||
namespace?: string;
|
||||
filter?: string;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface ListAllocationsResponse {
|
||||
allocations: Allocation[];
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface Allocation {
|
||||
id: string;
|
||||
clientStatus: string;
|
||||
createTime: number;
|
||||
namespace: string;
|
||||
name: string;
|
||||
modifyTime: number;
|
||||
nodeID: string;
|
||||
taskGroup: string;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export interface DeploymentStatus {
|
||||
healthy: boolean;
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export class NomadHttpApi implements NomadApi {
|
||||
static fromConfig(config: Config) {
|
||||
return new NomadHttpApi(
|
||||
config.getOptionalString('nomad.nomadAddr'),
|
||||
config.getOptionalString('nomad.nomadRegion'),
|
||||
config.getOptionalString('nomad.nomadNamespace'),
|
||||
config.getOptionalString('nomad.nomadToken'),
|
||||
);
|
||||
}
|
||||
|
||||
constructor(
|
||||
private nomadAddr?: string,
|
||||
private nomadRegion?: string,
|
||||
private nomadNamespace?: string,
|
||||
private nomadToken?: string,
|
||||
) {}
|
||||
|
||||
async listAllocations(
|
||||
options: ListAllocationsRequest,
|
||||
): Promise<ListAllocationsResponse> {
|
||||
return Promise.resolve({
|
||||
allocations: [],
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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 { Table } from '@backstage/core-components';
|
||||
import React from 'react';
|
||||
|
||||
export const GroupListForEntity = () => {
|
||||
return (
|
||||
<Table
|
||||
options={{
|
||||
paging: false,
|
||||
toolbar: false,
|
||||
}}
|
||||
columns={[]}
|
||||
data={[]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -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 { useEntity } from '@backstage/plugin-catalog-react';
|
||||
import { NOMAD_GROUP_ANNOTATION } from '../Router';
|
||||
|
||||
/**
|
||||
* Get the entity's group and query it from the Nomad API.
|
||||
*/
|
||||
export const useGroupForEntity = () => {
|
||||
const { entity } = useEntity();
|
||||
const group = entity.metadata.annotations?.[NOMAD_GROUP_ANNOTATION] ?? '';
|
||||
};
|
||||
@@ -13,10 +13,22 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { nomadPlugin } from './plugin';
|
||||
import {
|
||||
nomadPlugin,
|
||||
entityContentRouteRef,
|
||||
EntityNomadContent,
|
||||
} from './plugin';
|
||||
|
||||
describe('nomad', () => {
|
||||
it('should export plugin', () => {
|
||||
expect(nomadPlugin).toBeDefined();
|
||||
});
|
||||
|
||||
it('should export Nomad entity ref', () => {
|
||||
expect(entityContentRouteRef).toBeDefined();
|
||||
});
|
||||
|
||||
it('should export Nomad entity', () => {
|
||||
expect(EntityNomadContent).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,19 +14,36 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import {
|
||||
configApiRef,
|
||||
createApiFactory,
|
||||
createPlugin,
|
||||
createRoutableExtension,
|
||||
createRouteRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
import { rootRouteRef } from './routes';
|
||||
import { NomadHttpApi, nomadApiRef } from './api';
|
||||
|
||||
export const entityContentRouteRef = createRouteRef({
|
||||
id: 'nomad:entity-content',
|
||||
});
|
||||
|
||||
export const nomadPlugin = createPlugin({
|
||||
id: 'nomad',
|
||||
apis: [
|
||||
createApiFactory({
|
||||
api: nomadApiRef,
|
||||
deps: { configApi: configApiRef },
|
||||
factory: ({ configApi }) => NomadHttpApi.fromConfig(configApi),
|
||||
}),
|
||||
],
|
||||
routes: {
|
||||
root: rootRouteRef,
|
||||
entityContent: entityContentRouteRef,
|
||||
},
|
||||
});
|
||||
|
||||
/** @public */
|
||||
export const NomadPage = nomadPlugin.provide(
|
||||
createRoutableExtension({
|
||||
name: 'NomadPage',
|
||||
@@ -35,3 +52,12 @@ export const NomadPage = nomadPlugin.provide(
|
||||
mountPoint: rootRouteRef,
|
||||
}),
|
||||
);
|
||||
|
||||
/** @public */
|
||||
export const EntityNomadContent = nomadPlugin.provide(
|
||||
createRoutableExtension({
|
||||
name: 'EntityNomadContent',
|
||||
component: () => import('./Router').then(m => m.EmbeddedRouter),
|
||||
mountPoint: entityContentRouteRef,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -7932,10 +7932,12 @@ __metadata:
|
||||
dependencies:
|
||||
"@backstage/catalog-model": "workspace:^"
|
||||
"@backstage/cli": "workspace:^"
|
||||
"@backstage/config": "workspace:^"
|
||||
"@backstage/core-app-api": "workspace:^"
|
||||
"@backstage/core-components": "workspace:^"
|
||||
"@backstage/core-plugin-api": "workspace:^"
|
||||
"@backstage/dev-utils": "workspace:^"
|
||||
"@backstage/plugin-catalog-react": "workspace:^"
|
||||
"@backstage/test-utils": "workspace:^"
|
||||
"@backstage/theme": "workspace:^"
|
||||
"@material-ui/core": ^4.9.13
|
||||
@@ -7950,6 +7952,7 @@ __metadata:
|
||||
react-use: ^17.2.4
|
||||
peerDependencies:
|
||||
react: ^16.13.1 || ^17.0.0
|
||||
react-router-dom: "*"
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
|
||||
Reference in New Issue
Block a user