Merge branch 'master' of github.com:spotify/backstage into mob/register-unregister-components
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
# ADR005: Catalog Core Entities
|
||||
|
||||
| Created | Status |
|
||||
| ---------- | ------ |
|
||||
| 2020-05-29 | Open |
|
||||
|
||||
## Context
|
||||
|
||||
We want to standardize on a few core entities that we are tracking in the Backstage catalog. This allows us to build specific plugins around them.
|
||||
|
||||
## Decision
|
||||
|
||||
Backstage should eventually support the following core entities:
|
||||
|
||||
- **Components** are individual pieces of software
|
||||
- **APIs** are the boundaries between different components
|
||||
- **Resources** are physical or virtual infrastructure needed to operate a component
|
||||
|
||||

|
||||
|
||||
For now, we'll start by only implementing support for the Component entity in the Backstage catalog. This can later be extended to APIs, Resources and other potentially useful entities.
|
||||
|
||||
### Component
|
||||
|
||||
A component is a piece of software, for example a mobile application feature, web site, backend service or data pipeline (list not exhaustive). A component can be tracked in source control, or use some existing open source or commercial software. It can implement APIs for other components to consume. In turn it might depend on APIs implemented by other components, or resources that are attached to it at runtime.
|
||||
|
||||
Component entities are typically defined in YAML descriptor files next to the code of the component, and could look like this (actual schema will evolve):
|
||||
|
||||
```yaml
|
||||
apiVersion: backstage.io/v1beta1
|
||||
kind: Component
|
||||
metadata:
|
||||
name: my-component-name
|
||||
spec:
|
||||
type: service
|
||||
```
|
||||
|
||||
### API
|
||||
|
||||
APIs form an abstraction that allows large software ecosystems to scale. Thus, APIs are a first class citizen in the Backstage model and the primary way to discover existing functionality in the ecosystem.
|
||||
|
||||
APIs are implemented by components and make their boundaries explicit. They might be defined using an RPC IDL (e.g. in Protobuf, GraphQL or similar), a data schema (e.g. in Avro, TFRecord or similar), or as code interfaces (e.g. framework APIs in Swift, Kotlin, Java, C++, Typescript etc). In any case, APIs exposed by components need to be in a known machine-readable format so we can build further tooling and analysis on top.
|
||||
|
||||
APIs are typically indexed from existing definitions in source control and thus wouldn't need their own descriptor files, but would be stored in the catalog somewhat like this (actual schema will evolve):
|
||||
|
||||
```yaml
|
||||
apiVersion: backstage.io/v1beta1
|
||||
kind: API
|
||||
metadata:
|
||||
name: my-component-api
|
||||
spec:
|
||||
type: grpc
|
||||
definition: >
|
||||
service HelloService {
|
||||
rpc SayHello (HelloRequest) returns (HelloResponse);
|
||||
}
|
||||
message HelloRequest {
|
||||
string greeting = 1;
|
||||
}
|
||||
message HelloResponse {
|
||||
string reply = 1;
|
||||
}
|
||||
```
|
||||
|
||||
### Resource
|
||||
|
||||
Resources are the infrastructure your software needs to operate at runtime like Bigtable databases, Pub/Sub topics, S3 buckets or CDNs. Modelling them together with components and APIs will allow us to visualize and create tooling around them in Backstage.
|
||||
|
||||
Resources are typically indexed from declarative definitions (e.g. Terraform, GCP Config Connector, AWS Cloud Formation) and/or inventories from cloud providers (e.g. GCP Asset Inventory) and thus wouldn't need their own descriptor files, but would be stored in the catalog somewhat like this (actual schema will evolve):
|
||||
|
||||
```yaml
|
||||
apiVersion: backstage.io/v1beta1
|
||||
kind: Resource
|
||||
metadata:
|
||||
name: my-component-db
|
||||
spec:
|
||||
type: gcp-spanner
|
||||
url: spanner.googleapis.com/projects/prj/instances/my-component-db/databases/my-db
|
||||
```
|
||||
|
||||
## Consequences
|
||||
|
||||
We will continue fleshing out support for the Component entity in the Backstage catalog.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
@@ -39,14 +39,19 @@ Each plugin is responsible for registering its components to corresponding route
|
||||
The app will call the `createPlugin` method on each plugin, passing in a `router` object with a set
|
||||
of methods on it.
|
||||
|
||||
```typescript
|
||||
import { createPlugin } from '@backstage/core';
|
||||
```jsx
|
||||
import { createPlugin, createRouteRef } from '@backstage/core';
|
||||
import ExampleComponent from './components/ExampleComponent';
|
||||
|
||||
export default createPlugin({
|
||||
id: 'my-plugin',
|
||||
export const rootRouteRef = createRouteRef({
|
||||
path: '/new-plugin',
|
||||
title: 'New plugin',
|
||||
});
|
||||
|
||||
export const plugin = createPlugin({
|
||||
id: 'new-plugin',
|
||||
register({ router }) {
|
||||
router.registerRoute('/my-plugin', ExampleComponent);
|
||||
router.addRoute(rootRouteRef, ExampleComponent);
|
||||
},
|
||||
});
|
||||
```
|
||||
@@ -54,17 +59,18 @@ export default createPlugin({
|
||||
#### `router` API
|
||||
|
||||
```typescript
|
||||
type RouterHooks = {
|
||||
registerRoute(
|
||||
path: RoutePath,
|
||||
Component: ComponentType<any>,
|
||||
options?: RouteOptions,
|
||||
): void;
|
||||
addRoute(
|
||||
target: RouteRef,
|
||||
Component: ComponentType<any>,
|
||||
options?: RouteOptions,
|
||||
): void;
|
||||
|
||||
registerRedirect(
|
||||
path: RoutePath,
|
||||
target: RoutePath,
|
||||
options?: RouteOptions,
|
||||
): void;
|
||||
};
|
||||
/**
|
||||
* @deprecated See the `addRoute` method
|
||||
*/
|
||||
registerRoute(
|
||||
path: RoutePath,
|
||||
Component: ComponentType<any>,
|
||||
options?: RouteOptions,
|
||||
): void;
|
||||
```
|
||||
|
||||
@@ -1,16 +1,28 @@
|
||||
# Development Environment
|
||||
|
||||
This section describes how to get set up for doing development on the Backstage repository.
|
||||
|
||||
## Cloning the Repository
|
||||
|
||||
After you have cloned the Backstage repository, you should run the following commands
|
||||
once to set things up for development:
|
||||
|
||||
```bash
|
||||
$ yarn install # fetch dependency packages - may take a while
|
||||
|
||||
$ yarn tsc # does a first run of type generation and checks
|
||||
```
|
||||
|
||||
## Serving the Example App
|
||||
|
||||
Open a terminal window and start the web app using the following commands from the project root:
|
||||
Open a terminal window and start the web app by using the following command from the project root.
|
||||
Make sure you have run the above mentioned commands first.
|
||||
|
||||
```bash
|
||||
$ yarn install # may take a while
|
||||
|
||||
$ yarn start
|
||||
```
|
||||
|
||||
The final `yarn start` command should open a local instance of Backstage in your browser, otherwise open one of the URLs printed in the terminal.
|
||||
This should open a local instance of Backstage in your browser, otherwise open one of the URLs printed in the terminal.
|
||||
|
||||
By default, backstage will start on port 3000, however you can override this by setting an environment variable `PORT` on your local machine. e.g. `export PORT=8080` then running `yarn start`. Or `PORT=8080 yarn start`.
|
||||
|
||||
|
||||
@@ -43,13 +43,18 @@ In the root folder you have some configuration for typescript and jest, the test
|
||||
In the `src` folder we get to the interesting bits. Check out the `plugin.ts`:
|
||||
|
||||
```jsx
|
||||
import { createPlugin } from '@backstage/core';
|
||||
import { createPlugin, createRouteRef } from '@backstage/core';
|
||||
import ExampleComponent from './components/ExampleComponent';
|
||||
|
||||
export default createPlugin({
|
||||
export const rootRouteRef = createRouteRef({
|
||||
path: '/new-plugin',
|
||||
title: 'New plugin',
|
||||
});
|
||||
|
||||
export const plugin = createPlugin({
|
||||
id: 'new-plugin',
|
||||
register({ router }) {
|
||||
router.registerRoute('/new-plugin', ExampleComponent);
|
||||
router.addRoute(rootRouteRef, ExampleComponent);
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
@@ -1,21 +1,36 @@
|
||||
# createPlugin - router
|
||||
|
||||
The router that is passed to the `register` function includes makes it possible for plugins to hook into routing of the Backstage app and provide the end users with new views to navigate to.
|
||||
The router that is passed to the `register` function makes it possible for plugins to hook into routing of the Backstage app and provide the end users with new views to navigate to.
|
||||
This is done by utilising the following methods on the `router`:
|
||||
|
||||
```typescript
|
||||
type RouterHooks = {
|
||||
registerRoute(
|
||||
path: RoutePath,
|
||||
Component: ComponentType<any>,
|
||||
options?: RouteOptions,
|
||||
): void;
|
||||
addRoute(
|
||||
target: RouteRef,
|
||||
Component: ComponentType<any>,
|
||||
options?: RouteOptions,
|
||||
): void;
|
||||
|
||||
registerRedirect(
|
||||
path: RoutePath,
|
||||
target: RoutePath,
|
||||
options?: RouteOptions,
|
||||
): void;
|
||||
};
|
||||
/**
|
||||
* @deprecated See the `addRoute` method
|
||||
*/
|
||||
registerRoute(
|
||||
path: RoutePath,
|
||||
Component: ComponentType<any>,
|
||||
options?: RouteOptions,
|
||||
): void;
|
||||
```
|
||||
|
||||
## RouteRef
|
||||
|
||||
`addRoute` method is using mutable RouteRefs, which can be created as following:
|
||||
|
||||
```ts
|
||||
import { createRouteRef } from '@backstage/core';
|
||||
|
||||
const myPluginRouteRef = createRouteRef({
|
||||
path: '/my-plugin',
|
||||
title: 'My Plugin',
|
||||
});
|
||||
```
|
||||
|
||||
[Back to References](README.md)
|
||||
|
||||
Reference in New Issue
Block a user