Start adding api

Signed-off-by: josh <josh.timmons@hashicorp.com>
This commit is contained in:
josh
2023-05-21 22:40:42 -04:00
parent 77ac78c1da
commit 59102979a5
8 changed files with 214 additions and 6 deletions
+4 -1
View File
@@ -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>
);
};
+91
View File
@@ -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 -1
View File
@@ -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();
});
});
+26
View File
@@ -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,
}),
);
+3
View File
@@ -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