Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(argocd): create a new plugin for argocd #1360

Merged
merged 1 commit into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions plugins/argocd/.eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module.exports = require('@backstage/cli/config/eslint-factory')(__dirname);
6 changes: 6 additions & 0 deletions plugins/argocd/OWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
approvers:
- karthikjeeyar
- rohitkrai03
reviewers:
- karthikjeeyar
- rohitkrai03
54 changes: 54 additions & 0 deletions plugins/argocd/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# argocd

Welcome to the argocd 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 [/argocd](http://localhost:3000/argocd).

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.

## Loading as Dynamic Plugin

This plugin can be loaded in backstage showcase application as a dynamic plugin.

Follow the below steps -

- Export dynamic plugin assets. This will build and create the static assets for the plugin and put it inside dist-scalprum folder.

```sh
yarn export-dynamic
```

- Package and copy dist-scalprum folder assets to dynamic-plugins-root folder in showcase application.

```sh
pkg=../plugins/argocd
archive=$(npm pack $pkg)
tar -xzf "$archive" && rm "$archive"
mv package $(echo $archive | sed -e 's:\.tgz$::')
```

- Add the extension point inside the app-config.yaml or app-config.local.yaml file.

```yaml
dynamicPlugins:
frontend:
janus-idp.backstage-plugin-argocd:
mountPoints:
- mountPoint: entity.page.cd/cards
importName: ArgocdPage
config:
layout:
gridColumn: '1 / -1'
if:
anyOf:
- hasAnnotation: backstage.io/kubernetes-id
- hasAnnotation: backstage.io/kubernetes-namespace
Comment on lines +50 to +51
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just curious, does this depends on k8s backend or just same annotations

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't depend on k8s backend but i still expect these annotations on the resources. This is a temporary condition anyway, we'll tweak it once we start using the argocd backend API.

```

For more detailed explanation on dynamic plugins follow this [doc](https://github.com/janus-idp/backstage-showcase/blob/main/showcase-docs/dynamic-plugins.md).
13 changes: 13 additions & 0 deletions plugins/argocd/app-config.janus-idp.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
dynamicPlugins:
frontend:
janus-idp.backstage-plugin-argocd:
mountPoints:
- mountPoint: entity.page.cd/cards
importName: ArgocdPage
config:
layout:
gridColumn: '1 / -1'
if:
anyOf:
- hasAnnotation: backstage.io/kubernetes-id
- hasAnnotation: backstage.io/kubernetes-namespace
1 change: 1 addition & 0 deletions plugins/argocd/config.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export interface Config {}
14 changes: 14 additions & 0 deletions plugins/argocd/dev/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import React from 'react';

import { createDevApp } from '@backstage/dev-utils';

import { ArgocdPage, argocdPlugin } from '../src/plugin';

createDevApp()
.registerPlugin(argocdPlugin)
.addPage({
element: <ArgocdPage />,
title: 'Root Page',
path: '/argocd',
})
.render();
76 changes: 76 additions & 0 deletions plugins/argocd/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
{
"name": "@janus-idp/backstage-plugin-argocd",
Copy link
Member

@nickboldt nickboldt Mar 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I notice this is different from the existing roadie plugin backstage-plugin-argo-cd (note extra dash in argo-cd) and I like that it's different as it will allow us to differentiate one from the other in dependabot configuration.

"version": "0.1.0",
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
"private": true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this intentional?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we can make this public once we add the actual argocd feature. I don't want to publish an npm package with example components.

"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
"types": "dist/index.d.ts"
},
"backstage": {
"role": "frontend-plugin"
},
"sideEffects": false,
"scripts": {
"build": "backstage-cli package build",
"clean": "backstage-cli package clean",
"export-dynamic": "janus-cli package export-dynamic-plugin",
"lint": "backstage-cli package lint",
"postpack": "backstage-cli package postpack",
"postversion": "yarn run export-dynamic",
"prepack": "backstage-cli package prepack",
"start": "backstage-cli package start",
"test": "backstage-cli package test --passWithNoTests --coverage",
"tsc": "tsc"
},
"dependencies": {
"@backstage/core-components": "^0.14.0",
"@backstage/core-plugin-api": "^1.9.0",
"@backstage/theme": "^0.5.1",
"@material-ui/core": "^4.9.13",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "^4.0.0-alpha.61",
"react-use": "^17.2.4"
},
"peerDependencies": {
"react": "16.13.1 || ^17.0.0 || ^18.0.0"
},
"devDependencies": {
"@backstage/cli": "0.25.2",
"@backstage/core-app-api": "1.12.0",
"@backstage/dev-utils": "1.0.27",
"@backstage/test-utils": "1.5.0",
"@janus-idp/cli": "1.7.5",
"@testing-library/jest-dom": "6.0.0",
"@testing-library/react": "14.0.0",
"@testing-library/user-event": "14.0.0",
"msw": "1.0.0"
},
"files": [
"dist",
"config.d.ts",
"dist-scalprum",
"app-config.janus-idp.yaml"
],
"scalprum": {
"name": "janus-idp.backstage-plugin-argocd",
"exposedModules": {
"PluginRoot": "./src/index.ts"
}
},
"configSchema": "config.d.ts",
"repository": {
"type": "git",
"url": "https://github.com/janus-idp/backstage-plugins",
"directory": "plugins/argocd"
},
"keywords": [
"backstage",
"plugin"
],
"homepage": "https://janus-idp.io/",
"bugs": "https://github.com/janus-idp/backstage-plugins/issues"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';

import {
renderInTestApp,
setupRequestMockHandlers,
} from '@backstage/test-utils';

import { screen } from '@testing-library/react';
import { rest } from 'msw';
import { setupServer } from 'msw/node';

import { ExampleComponent } from './ExampleComponent';

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(<ExampleComponent />);
expect(screen.getByText('Welcome to ArgoCD!')).toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react';

import {
Content,
ContentHeader,
Header,
HeaderLabel,
InfoCard,
Page,
SupportButton,
} from '@backstage/core-components';

import { Grid, Typography } from '@material-ui/core';

import { ExampleFetchComponent } from '../ExampleFetchComponent';

export const ExampleComponent = () => (
<Page themeId="tool">
<Header
title="Welcome to ArgoCD!"
subtitle="Official ArgoCD plugin from Red Hat"
>
<HeaderLabel label="Owner" value="RHTAP" />
<HeaderLabel label="Lifecycle" value="Alpha" />
</Header>
<Content>
<ContentHeader title="ArgoCD Plugin">
<SupportButton>
This is the official ArgoCD plugin from Red Hat.
</SupportButton>
</ContentHeader>
<Grid container spacing={3} direction="column">
<Grid item>
<InfoCard title="Information card">
<Typography variant="body1">
All content should be wrapped in a card like this.
</Typography>
</InfoCard>
</Grid>
<Grid item>
<ExampleFetchComponent />
</Grid>
</Grid>
</Content>
</Page>
);
1 change: 1 addition & 0 deletions plugins/argocd/src/components/ExampleComponent/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { ExampleComponent } from './ExampleComponent';
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import React from 'react';

import { render, screen } from '@testing-library/react';

import { ExampleFetchComponent } from './ExampleFetchComponent';

describe('ExampleFetchComponent', () => {
it('renders the user table', async () => {
render(<ExampleFetchComponent />);

// Wait for the table to render
const table = await screen.findByRole('table');
const nationality = screen.getAllByText('GB');
// Assert that the table contains the expected user data
expect(table).toBeInTheDocument();
expect(screen.getByAltText('Carolyn')).toBeInTheDocument();
expect(screen.getByText('Carolyn Moore')).toBeInTheDocument();
expect(screen.getByText('[email protected]')).toBeInTheDocument();
expect(nationality[0]).toBeInTheDocument();
});
});
Loading
Loading