Merge branch 'master' into HACKATHON_SB_1/scaffolder_docs

Signed-off-by: Steven Billington <39339008+green2jello@users.noreply.github.com>
This commit is contained in:
Steven Billington
2024-05-31 14:28:44 -04:00
committed by GitHub
1452 changed files with 56584 additions and 20495 deletions
@@ -86,12 +86,17 @@ contains more information about the required fields.
Once we have a `template.yaml` ready, we can then add it to the software catalog
for use by the scaffolder.
> Note: When you add or modify a template, you will need to refresh the location entity.
> Otherwise, Backstage won't display the template in the available templates,
> or it will keep showing the old template. You can refresh the location instance by
> going into `Catalog` web page, choosing `Locations` instead of `Components`, and selecting the correct location entity.
> From there, you can click on the refresh icon representing "Scheduled entity refresh" action.
> Afterwards, you should see your template updated.
:::note Note
When you add or modify a template, you will need to refresh the location entity.
Otherwise, Backstage won't display the template in the available templates,
or it will keep showing the old template. You can refresh the location instance by
going into `Catalog` web page, choosing `Locations` instead of `Components`, and selecting the correct
location entity.
From there, you can click on the refresh icon representing "Scheduled entity refresh" action.
Afterwards, you should see your template updated.
:::
You can add the template files to the catalog through
[static location configuration](../software-catalog/configuration.md#static-location-configuration),
@@ -1,10 +1,10 @@
---
id: authorizing-parameters-steps-and-actions
title: 'Authorizing parameters, steps and actions'
description: How to authorize part of a template
id: authorizing-scaffolder-template-details
title: 'Authorizing scaffolder tasks, parameters, steps, and actions'
description: How to authorize parts of a template and authorize scaffolder task access
---
The scaffolder plugin integrates with the Backstage [permission framework](../../permissions/overview.md), which allows you to control access to certain parameters and steps in your templates based on the user executing the template.
The scaffolder plugin integrates with the Backstage [permission framework](../../permissions/overview.md), which allows you to control access to certain parameters and steps in your templates based on the user executing the template. It also allows you to control access to scaffolder tasks.
### Authorizing parameters and steps
@@ -174,7 +174,64 @@ class ExamplePermissionPolicy implements PermissionPolicy {
}
```
Although the rules exported by the scaffolder are simple, combining them can help you achieve more complex cases.
### Authorizing scaffolder tasks
The scaffolder plugin also exposes permissions that can restrict access to tasks, task logs, task creation, and task cancellation. This can be useful if you want to control who has access to these areas of the scaffolder.
```ts title="packages/src/backend/plugins/permissions.ts"
/* highlight-add-start */
import {
taskCancelPermission,
taskCreatePermission,
taskReadPermission,
} from '@backstage/plugin-scaffolder-common/alpha';
/* highlight-add-end */
class ExamplePermissionPolicy implements PermissionPolicy {
async handle(
request: PolicyQuery,
user?: BackstageIdentityResponse,
): Promise<PolicyDecision> {
/* highlight-add-start */
if (isPermission(request.permission, taskCreatePermission)) {
if (user?.identity.userEntityRef === 'user:default/spiderman') {
return {
result: AuthorizeResult.ALLOW,
};
}
}
if (isPermission(request.permission, taskCancelPermission)) {
if (user?.identity.userEntityRef === 'user:default/spiderman') {
return {
result: AuthorizeResult.ALLOW,
};
}
}
if (isPermission(request.permission, taskReadPermission)) {
if (user?.identity.userEntityRef === 'user:default/spiderman') {
return {
result: AuthorizeResult.ALLOW,
};
}
}
/* highlight-add-end */
return {
result: AuthorizeResult.DENY,
};
}
}
```
In the provided example permission policy, we only grant the `spiderman` user permissions to perform/access the following actions/resources:
- Read all scaffolder tasks and their associated events/logs.
- Cancel any ongoing scaffolder tasks.
- Trigger software templates, which effectively creates new scaffolder tasks.
Any other user would be denied access to these actions/resources.
Although the rules exported by the scaffolder are simple, combining them can help you achieve more complex use cases.
### Authorizing in the New Backend System
@@ -229,4 +286,8 @@ backend.add(customPermissionBackendModule);
/* highlight-add-end */
```
> Note: the `ExamplePermissionPolicy` here could be the one from the [Authorizing parameters and steps](#authorizing-parameters-and-steps) example or from the [Authorizing actions](#authorizing-actions) example. It would work the same way for both of them.
:::note Note
The `ExamplePermissionPolicy` here could be the one from the [Authorizing parameters and steps](#authorizing-parameters-and-steps) example or from the [Authorizing actions](#authorizing-actions) example. It would work the same way for both of them.
:::
@@ -57,7 +57,11 @@ backend.add(import('@backstage/plugin-scaffolder-backend-module-github'));
backend.start();
```
> Note: This is a simplified example of what your backend may look like, you may have more code in here then this.
:::note Note
This is a simplified example of what your backend may look like, you may have more code in here then this.
:::
## Listing Actions
@@ -12,7 +12,11 @@ This is done in your `app-config.yaml` by adding
[Backstage integrations](https://backstage.io/docs/integrations/) for the
appropriate source code repository for your organization.
> Note: Integrations may already be set up as part of your `app-config.yaml`.
:::note Note
Integrations may already be set up as part of your `app-config.yaml`.
:::
The next step is to [add templates](http://backstage.io/docs/features/software-templates/adding-templates)
to your Backstage app.
+22 -4
View File
@@ -20,10 +20,14 @@ locations like GitHub or GitLab.
> Be sure to have covered
> [Getting Started with Backstage](../../getting-started) before proceeding.
> Note: if you're running Backstage with Node 20 or later, you'll need to pass the flag `--no-node-snapshot` to Node in order to
> use the templates feature.
> One way to do this is to specify the `NODE_OPTIONS` environment variable before starting Backstage:
> `export NODE_OPTIONS=--no-node-snapshot`
:::note Note
If you're running Backstage with Node 20 or later, you'll need to pass the flag `--no-node-snapshot` to Node in order to
use the templates feature.
One way to do this is to specify the `NODE_OPTIONS` environment variable before starting Backstage:
`export NODE_OPTIONS=--no-node-snapshot`
:::
The Software Templates are available under `/create`. For local development you
should be able to reach them at `http://localhost:3000/create`.
@@ -103,3 +107,17 @@ from `backstage/packages/app/src/App.tsx`:
```
After the change, you should no longer see the button.
## Previewing and Executing Previous Template Tasks
Each execution of a template is treated as a unique task, identifiable by its own unique ID. To view a list of previously executed template tasks, navigate to the "Create" page and access the "Task List" from the context menu (represented by the vertical ellipsis, or 'kebab menu', icon in the upper right corner).
![Template Task List](../../assets/software-templates/template-task-list.png)
If you wish to re-run a previously executed template, navigate to the template tasks page. Locate the desired task and select the "Start Over" option from the context menu.
![Template Start Over](../../assets/software-templates/template-start-over.png)
This action will initiate a new execution of the selected template, pre-populated with the same parameters as the previous run, but these parameters can be edited before re-execution.
In the event of a failed template execution, the "Start Over" option can be used to re-execute the template. The parameters from the original run will be pre-filled, but they can be adjusted as needed before retrying the template.
@@ -5,7 +5,11 @@ title: 'Migrating to react-jsonschema-form@v5'
description: Docs on migrating to `react-jsonschema-form`@v5 and the new designs
---
> Note: If you were previously using the `/alpha` imports to test out the `scaffolder/next` work, those imports have been promoted to the default exports from the respective packages. You should just have to remove the `/alpha` from the import path, and remove the `Next` from the import name. `NextScaffolderPage` -> `ScaffolderPage`, `createNextScaffolderFieldExtension` -> `createScaffolderFieldExtension` etc.
:::note Note
If you were previously using the `/alpha` imports to test out the `scaffolder/next` work, those imports have been promoted to the default exports from the respective packages. You should just have to remove the `/alpha` from the import path, and remove the `Next` from the import name. `NextScaffolderPage` -> `ScaffolderPage`, `createNextScaffolderFieldExtension` -> `createScaffolderFieldExtension` etc.
:::
## What's `react-jsonschema-form`?
@@ -8,10 +8,14 @@ If you want to extend the functionality of the Scaffolder, you can do so
by writing custom actions which can be used alongside our
[built-in actions](./builtin-actions.md).
> Note: When adding custom actions, the actions array will **replace the
> built-in actions too**. Meaning, you will no longer be able to use them.
> If you want to continue using the builtin actions, include them in the actions
> array when registering your custom actions, as seen below.
:::note Note
When adding custom actions, the actions array will **replace the
built-in actions too**. Meaning, you will no longer be able to use them.
If you want to continue using the builtin actions, include them in the actions
array when registering your custom actions, as seen below.
:::
## Writing your Custom Action
@@ -681,6 +681,8 @@ how to use them in the Scaffolder templates. It's important to mention that Back
native filters from the Nunjucks library. For a complete list of these native filters and their usage,
refer to the [Nunjucks documentation](https://mozilla.github.io/nunjucks/templating.html#builtin-filters).
To create your own custom filters, look to the section [Custom Filters](#custom-filters) hereafter.
### parseRepoUrl
The `parseRepoUrl` filter parse a repository URL into
@@ -765,3 +767,150 @@ The `projectSlug` filter generates a project slug from a repository URL
- **Input**: `github.com?repo=backstage&org=backstage`
- **Output**: `backstage/backstage`
## Custom Filters
Whenever it is needed to extend the built-in filters with yours `${{ parameters.name | my-filter1 | my-filter2 | etc }}`, then you can add them
using the property `additionalTemplateFilters`.
The `additionalTemplateFilters` property accepts as type a `Record`
```ts title="plugins/scaffolder-backend/src/service/Router.ts"
additionalTemplateFilters?: Record<string, TemplateFilter>;
```
where the first parameter is the name of the filter and the second receives a list of `JSON value` arguments. The `templateFilter()` function must return a JsonValue which is either a Json array, object or primitive.
```ts title="plugins/scaffolder-node/src/types.ts"
export type TemplateFilter = (...args: JsonValue[]) => JsonValue | undefined;
```
From a practical coding point of view, you will translate that into the following snippet code handling 2 filters:
```ts"
...
additionalTemplateFilters: {
base64: (...args: JsonValue[]) => btoa(args.join("")),
betterFilter: (...args: JsonValue[]) => { return `This is a much better string than "${args}", don't you think?` }
}
```
And within your template, you will be able to use the filters using a parameter and the filter passed using the pipe symbol
```yaml
apiVersion: scaffolder.backstage.io/v1beta3
kind: Template
metadata:
name: test
title: Test
spec:
owner: user:guest
type: service
parameters:
- title: Test custom filters
properties:
userName:
title: Name of the user
type: string
steps:
- id: debug
name: debug
action: debug:log
input:
message: ${{ parameters.userName | betterFilter | base64 }}
```
Next, you will have to register the property `addTemplateFilters` using the `scaffolderTemplatingExtensionPoint` of a new `BackendModule` [created](../../backend-system/architecture/06-modules.md).
Here is a very simplified example of how to do that:
```ts title="packages/backend-next/src/index.ts"
/* highlight-add-start */
import { scaffolderTemplatingExtensionPoint } from '@backstage/plugin-scaffolder-node/alpha';
import { createBackendModule } from '@backstage/backend-plugin-api';
/* highlight-add-end */
/* highlight-add-start */
const scaffolderModuleCustomFilters = createBackendModule({
pluginId: 'scaffolder', // name of the plugin that the module is targeting
moduleId: 'custom-filters',
register(env) {
env.registerInit({
deps: {
scaffolder: scaffolderTemplatingExtensionPoint,
// ... and other dependencies as needed
},
async init({ scaffolder /* ..., other dependencies */ }) {
scaffolder.addTemplateFilters({
base64: (...args: JsonValue[]) => btoa(args.join('')),
betterFilter: (...args: JsonValue[]) => {
return `This is a much better string than "${args}", don't you think?`;
},
});
},
});
},
});
/* highlight-add-end */
const backend = createBackend();
backend.add(import('@backstage/plugin-scaffolder-backend/alpha'));
/* highlight-add-next-line */
backend.add(scaffolderModuleCustomFilters());
```
If you still use the legacy backend system, then you will use the `createRouter()` function of the `Scaffolder plugin`
```ts title="packages/backend/src/plugins/scaffolder.ts"
export default async function createPlugin({
logger,
config,
}: PluginEnvironment): Promise<Router> {
...
return await createRouter({
logger,
config,
additionalTemplateFilters: {
<YOUR_FILTERS>
}
});
```
## Template Editor
Writing template is most of the times an iterative process. You will need to test your template to make sure it has a good user experience and that it works as expected. To help on this process the scaffolder comes with a build in template editor that allows you to test your template in a real environment for querying data and execute the actions on dry-run mode to see the results of those one.
To access to the template editor you can go to the templates page and select "Template Editor" from the context menu or navigate to the `{scaffolder-path}/edit` url. (i.e. the default route would be `/create/edit`)
![Context menu](../../assets/software-templates/context-menu.png)
The template editor has 3 main sections:
1. **Load Template Directory**: Load a local template directory, allowing you to both edit and try executing your own template.
2. **Edit Template Form**: Preview and edit a template form, either using a sample template or by loading a template from the catalog.
3. **Custom Field Explorer**: View and play around with available installed custom field extensions.
### Load Template Directory
Allow to load a directory on your local file system that contains a template and editing the files in it while previewing the form and executing the template.
![template editor load dir](../../assets/software-templates/template-editor-load-dir.png)
If you complete the form in the right side and click on `Create` button, the template will be executed in dry-run mode and the result will be shown in the `Dry-run result` drawer that will pop-up at the bottom of the screen.
Here we could find all the file system results of the template execution as well as the logs of each action that was executed.
![dry run drawer example](../../assets/software-templates/template-editor-dry-run.png)
### Edit Template Form
This is a reduced version of the template editor that allows you to select any template from the catalog and do some modifications on the form presented to the user to test some changes.
Have in mind that changes in this form will not be saved on the template and is meant to test out changes to replicate them manually on the template file after.
### Custom Field Explorer
The custom filed explorer allows you to select any custom field loaded on the backstage instance and test different values and configurations.