From d22c1dd193d2888da850f5c06a2742de8d4b8430 Mon Sep 17 00:00:00 2001 From: Tomas Dabasinskas Date: Thu, 9 Feb 2023 20:10:08 +0200 Subject: [PATCH] Add tab for resources Signed-off-by: Tomas Dabasinskas --- .../app/src/components/catalog/EntityPage.tsx | 31 ++++++ plugins/puppetdb/dev/index.tsx | 27 ----- .../ExampleComponent.test.tsx | 42 ------- .../ExampleComponent/ExampleComponent.tsx | 53 --------- .../ExampleFetchComponent.test.tsx | 40 ------- .../ExampleFetchComponent.tsx | 105 ------------------ .../components/PuppetDbTab/PuppetDbTab.tsx | 42 +++++++ .../index.ts | 4 +- .../index.ts => constants.ts} | 8 +- plugins/puppetdb/src/index.ts | 2 +- plugins/puppetdb/src/plugin.ts | 23 +++- 11 files changed, 104 insertions(+), 273 deletions(-) delete mode 100644 plugins/puppetdb/dev/index.tsx delete mode 100644 plugins/puppetdb/src/components/ExampleComponent/ExampleComponent.test.tsx delete mode 100644 plugins/puppetdb/src/components/ExampleComponent/ExampleComponent.tsx delete mode 100644 plugins/puppetdb/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx delete mode 100644 plugins/puppetdb/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx create mode 100644 plugins/puppetdb/src/components/PuppetDbTab/PuppetDbTab.tsx rename plugins/puppetdb/src/components/{ExampleComponent => PuppetDbTab}/index.ts (85%) rename plugins/puppetdb/src/{components/ExampleFetchComponent/index.ts => constants.ts} (79%) diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx index d07870194b..362b49cadb 100644 --- a/packages/app/src/components/catalog/EntityPage.tsx +++ b/packages/app/src/components/catalog/EntityPage.tsx @@ -116,6 +116,7 @@ import { EntityRollbarContent, isRollbarAvailable, } from '@backstage/plugin-rollbar'; +import { PuppetDbTab, isPuppetDbAvailable } from '@backstage/plugin-puppetdb'; import { EntitySentryContent } from '@backstage/plugin-sentry'; import { EntityTechdocsContent } from '@backstage/plugin-techdocs'; import { EntityTechInsightsScorecardCard } from '@backstage/plugin-tech-insights'; @@ -836,6 +837,35 @@ const domainPage = ( ); +const resourcePage = ( + + + + {entityWarningContent} + + + + + + + + + + + + + + + + + + +); + export const entityPage = ( @@ -844,6 +874,7 @@ export const entityPage = ( + {defaultEntityPage} diff --git a/plugins/puppetdb/dev/index.tsx b/plugins/puppetdb/dev/index.tsx deleted file mode 100644 index 6535e015ae..0000000000 --- a/plugins/puppetdb/dev/index.tsx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2023 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 React from 'react'; -import { createDevApp } from '@backstage/dev-utils'; -import { puppetdbPlugin, PuppetdbPage } from '../src/plugin'; - -createDevApp() - .registerPlugin(puppetdbPlugin) - .addPage({ - element: , - title: 'Root Page', - path: '/puppetdb', - }) - .render(); diff --git a/plugins/puppetdb/src/components/ExampleComponent/ExampleComponent.test.tsx b/plugins/puppetdb/src/components/ExampleComponent/ExampleComponent.test.tsx deleted file mode 100644 index 4de00c8385..0000000000 --- a/plugins/puppetdb/src/components/ExampleComponent/ExampleComponent.test.tsx +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2023 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 React from 'react'; -import { ExampleComponent } from './ExampleComponent'; -import { rest } from 'msw'; -import { setupServer } from 'msw/node'; -import { screen } from '@testing-library/react'; -import { - setupRequestMockHandlers, - renderInTestApp, -} from '@backstage/test-utils'; - -describe('ExampleComponent', () => { - const server = setupServer(); - // Enable sane handlers for network requests - setupRequestMockHandlers(server); - - // setup mock response - beforeEach(() => { - server.use( - rest.get('/*', (_, res, ctx) => res(ctx.status(200), ctx.json({}))), - ); - }); - - it('should render', async () => { - await renderInTestApp(); - expect(screen.getByText('Welcome to puppetdb!')).toBeInTheDocument(); - }); -}); diff --git a/plugins/puppetdb/src/components/ExampleComponent/ExampleComponent.tsx b/plugins/puppetdb/src/components/ExampleComponent/ExampleComponent.tsx deleted file mode 100644 index af1c72aabb..0000000000 --- a/plugins/puppetdb/src/components/ExampleComponent/ExampleComponent.tsx +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2023 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 React from 'react'; -import { Typography, Grid } from '@material-ui/core'; -import { - InfoCard, - Header, - Page, - Content, - ContentHeader, - HeaderLabel, - SupportButton, -} from '@backstage/core-components'; -import { ExampleFetchComponent } from '../ExampleFetchComponent'; - -export const ExampleComponent = () => ( - -
- - -
- - - A description of your plugin goes here. - - - - - - All content should be wrapped in a card like this. - - - - - - - - -
-); diff --git a/plugins/puppetdb/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx b/plugins/puppetdb/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx deleted file mode 100644 index a714f640da..0000000000 --- a/plugins/puppetdb/src/components/ExampleFetchComponent/ExampleFetchComponent.test.tsx +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2023 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 React from 'react'; -import { render, screen } from '@testing-library/react'; -import { ExampleFetchComponent } from './ExampleFetchComponent'; -import { rest } from 'msw'; -import { setupServer } from 'msw/node'; -import { setupRequestMockHandlers } from '@backstage/test-utils'; - -describe('ExampleFetchComponent', () => { - const server = setupServer(); - // Enable sane handlers for network requests - setupRequestMockHandlers(server); - - // setup mock response - beforeEach(() => { - server.use( - rest.get('https://randomuser.me/*', (_, res, ctx) => - res(ctx.status(200), ctx.delay(2000), ctx.json({})), - ), - ); - }); - it('should render', async () => { - await render(); - expect(await screen.findByTestId('progress')).toBeInTheDocument(); - }); -}); diff --git a/plugins/puppetdb/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx b/plugins/puppetdb/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx deleted file mode 100644 index e379cd0b60..0000000000 --- a/plugins/puppetdb/src/components/ExampleFetchComponent/ExampleFetchComponent.tsx +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2023 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 React from 'react'; -import { makeStyles } from '@material-ui/core/styles'; -import { Table, TableColumn, Progress } from '@backstage/core-components'; -import Alert from '@material-ui/lab/Alert'; -import useAsync from 'react-use/lib/useAsync'; - -const useStyles = makeStyles({ - avatar: { - height: 32, - width: 32, - borderRadius: '50%', - }, -}); - -type User = { - gender: string; // "male" - name: { - title: string; // "Mr", - first: string; // "Duane", - last: string; // "Reed" - }; - location: object; // {street: {number: 5060, name: "Hickory Creek Dr"}, city: "Albany", state: "New South Wales",…} - email: string; // "duane.reed@example.com" - login: object; // {uuid: "4b785022-9a23-4ab9-8a23-cb3fb43969a9", username: "blackdog796", password: "patch",…} - dob: object; // {date: "1983-06-22T12:30:23.016Z", age: 37} - registered: object; // {date: "2006-06-13T18:48:28.037Z", age: 14} - phone: string; // "07-2154-5651" - cell: string; // "0405-592-879" - id: { - name: string; // "TFN", - value: string; // "796260432" - }; - picture: { medium: string }; // {medium: "https://randomuser.me/api/portraits/men/95.jpg",…} - nat: string; // "AU" -}; - -type DenseTableProps = { - users: User[]; -}; - -export const DenseTable = ({ users }: DenseTableProps) => { - const classes = useStyles(); - - const columns: TableColumn[] = [ - { title: 'Avatar', field: 'avatar' }, - { title: 'Name', field: 'name' }, - { title: 'Email', field: 'email' }, - { title: 'Nationality', field: 'nationality' }, - ]; - - const data = users.map(user => { - return { - avatar: ( - {user.name.first} - ), - name: `${user.name.first} ${user.name.last}`, - email: user.email, - nationality: user.nat, - }; - }); - - return ( - - ); -}; - -export const ExampleFetchComponent = () => { - const { value, loading, error } = useAsync(async (): Promise => { - const response = await fetch('https://randomuser.me/api/?results=20'); - const data = await response.json(); - return data.results; - }, []); - - if (loading) { - return ; - } else if (error) { - return {error.message}; - } - - return ; -}; diff --git a/plugins/puppetdb/src/components/PuppetDbTab/PuppetDbTab.tsx b/plugins/puppetdb/src/components/PuppetDbTab/PuppetDbTab.tsx new file mode 100644 index 0000000000..9f143fd5e6 --- /dev/null +++ b/plugins/puppetdb/src/components/PuppetDbTab/PuppetDbTab.tsx @@ -0,0 +1,42 @@ +/* + * Copyright 2022 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 React from 'react'; +import { + Page, + Content, + MissingAnnotationEmptyState, +} from '@backstage/core-components'; +import { useEntity } from '@backstage/plugin-catalog-react'; +import { isPuppetDbAvailable } from '../../plugin'; +import { ANNOTATION_PUPPET_CERTNAME } from '../../constants'; + +export const PuppetDbTab = () => { + const { entity } = useEntity(); + + if (!isPuppetDbAvailable(entity)) { + return ( + + ); + } + + return ( + + + TODO: Implement PuppetDB plugin + + + ); +}; diff --git a/plugins/puppetdb/src/components/ExampleComponent/index.ts b/plugins/puppetdb/src/components/PuppetDbTab/index.ts similarity index 85% rename from plugins/puppetdb/src/components/ExampleComponent/index.ts rename to plugins/puppetdb/src/components/PuppetDbTab/index.ts index 7e520a7ab8..4b96137c54 100644 --- a/plugins/puppetdb/src/components/ExampleComponent/index.ts +++ b/plugins/puppetdb/src/components/PuppetDbTab/index.ts @@ -1,5 +1,5 @@ /* - * Copyright 2023 The Backstage Authors + * Copyright 2022 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. @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { ExampleComponent } from './ExampleComponent'; +export { PuppetDbTab } from './PuppetDbTab'; diff --git a/plugins/puppetdb/src/components/ExampleFetchComponent/index.ts b/plugins/puppetdb/src/constants.ts similarity index 79% rename from plugins/puppetdb/src/components/ExampleFetchComponent/index.ts rename to plugins/puppetdb/src/constants.ts index 9644c904ea..57fb4373f4 100644 --- a/plugins/puppetdb/src/components/ExampleFetchComponent/index.ts +++ b/plugins/puppetdb/src/constants.ts @@ -13,4 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { ExampleFetchComponent } from './ExampleFetchComponent'; + +/** + * Annotation for specifying the certificate name of a node in PuppetDB. + * + * @public + */ +export const ANNOTATION_PUPPET_CERTNAME = 'puppet.com/certname'; diff --git a/plugins/puppetdb/src/index.ts b/plugins/puppetdb/src/index.ts index b0a6326a99..091ae1a467 100644 --- a/plugins/puppetdb/src/index.ts +++ b/plugins/puppetdb/src/index.ts @@ -13,4 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { puppetdbPlugin, PuppetdbPage } from './plugin'; +export { puppetdbPlugin, PuppetDbTab, isPuppetDbAvailable } from './plugin'; diff --git a/plugins/puppetdb/src/plugin.ts b/plugins/puppetdb/src/plugin.ts index fd0ee267d3..131ec5a449 100644 --- a/plugins/puppetdb/src/plugin.ts +++ b/plugins/puppetdb/src/plugin.ts @@ -19,7 +19,13 @@ import { } from '@backstage/core-plugin-api'; import { rootRouteRef } from './routes'; +import { Entity } from '@backstage/catalog-model'; +import { ANNOTATION_PUPPET_CERTNAME } from './constants'; +/** + * Create the PuppetDB frontend plugin. + * @public + */ export const puppetdbPlugin = createPlugin({ id: 'puppetdb', routes: { @@ -27,11 +33,24 @@ export const puppetdbPlugin = createPlugin({ }, }); -export const PuppetdbPage = puppetdbPlugin.provide( +/** + * Checks if the entity has a puppet certname annotation. + * @public + * @param entity - The entity to check for the puppet cername annotation. + */ +export const isPuppetDbAvailable = (entity: Entity) => + // TODO(tdabasinskas): Remove the `|| true` once testing is done. + Boolean(entity.metadata.annotations?.[ANNOTATION_PUPPET_CERTNAME]) || true; + +/** + * Creates a routable extension for the PuppetDB plugin tab. + * @public + */ +export const PuppetDbTab = puppetdbPlugin.provide( createRoutableExtension({ name: 'PuppetdbPage', component: () => - import('./components/ExampleComponent').then(m => m.ExampleComponent), + import('./components/PuppetDbTab').then(m => m.PuppetDbTab), mountPoint: rootRouteRef, }), );