feat: extend API entity by lifecycle and owner
This commit is contained in:
@@ -483,6 +483,8 @@ metadata:
|
||||
description: Retrieve artist details
|
||||
spec:
|
||||
type: openapi
|
||||
lifecycle: production
|
||||
owner: artist-relations@example.com
|
||||
definition: |
|
||||
openapi: "3.0.0"
|
||||
info:
|
||||
@@ -527,6 +529,41 @@ The current set of well-known and common values for this field is:
|
||||
[Protocol Buffers](https://developers.google.com/protocol-buffers) to use with
|
||||
[gRPC](https://grpc.io/).
|
||||
|
||||
### `spec.lifecycle` [required]
|
||||
|
||||
The lifecycle state of the API, e.g. `production`. This field is required.
|
||||
|
||||
The software catalog accepts any lifecycle value, but an organization should
|
||||
take great care to establish a proper taxonomy for these.
|
||||
|
||||
The current set of well-known and common values for this field is:
|
||||
|
||||
- `experimental` - an experiment or early, non-production API, signaling that
|
||||
users may not prefer to consume it over other more established APIs, or that
|
||||
there are low or no reliability guarantees
|
||||
- `production` - an established, owned, maintained API
|
||||
- `deprecated` - an API that is at the end of its lifecycle, and may disappear
|
||||
at a later point in time
|
||||
|
||||
### `spec.owner` [required]
|
||||
|
||||
The owner of the API, e.g. `artist-relations@example.com`. This field is
|
||||
required.
|
||||
|
||||
In Backstage, the owner of an API is the singular entity (commonly a team) that
|
||||
bears ultimate responsibility for the API, and has the authority and capability
|
||||
to develop and maintain it. They will be the point of contact if something goes
|
||||
wrong, or if features are to be requested. The main purpose of this field is for
|
||||
display purposes in Backstage, so that people looking at catalog items can get
|
||||
an understanding of to whom this API belongs. It is not to be used by automated
|
||||
processes to for example assign authorization in runtime systems. There may be
|
||||
others that also develop or otherwise touch the API, but there will always be
|
||||
one ultimate owner.
|
||||
|
||||
Apart from being a string, the software catalog leaves the format of this field
|
||||
open to implementers to choose. Most commonly, it is set to the ID or email of a
|
||||
group of people in an organizational structure.
|
||||
|
||||
### `spec.definition` [required]
|
||||
|
||||
The definition of the API, based on the format defined by `spec.type`. This
|
||||
|
||||
@@ -5,6 +5,8 @@ metadata:
|
||||
description: Hello World example for gRPC
|
||||
spec:
|
||||
type: grpc
|
||||
lifecycle: deprecated
|
||||
owner: grpc@example.com
|
||||
definition: |
|
||||
// Copyright 2015 gRPC authors.
|
||||
//
|
||||
|
||||
@@ -3,8 +3,13 @@ kind: API
|
||||
metadata:
|
||||
name: petstore
|
||||
description: The petstore API
|
||||
tags:
|
||||
- store
|
||||
- rest
|
||||
spec:
|
||||
type: openapi
|
||||
lifecycle: experimental
|
||||
owner: pets@example.com
|
||||
definition: |
|
||||
openapi: "3.0.0"
|
||||
info:
|
||||
|
||||
@@ -4,9 +4,11 @@ metadata:
|
||||
name: streetlights
|
||||
description: The Smartylighting Streetlights API allows you to remotely manage the city lights.
|
||||
tags:
|
||||
- unstable
|
||||
- mqtt
|
||||
spec:
|
||||
type: asyncapi
|
||||
lifecycle: production
|
||||
owner: streetlights@example.com
|
||||
definition: |
|
||||
asyncapi: 2.0.0
|
||||
info:
|
||||
|
||||
@@ -33,6 +33,8 @@ describe('ApiV1alpha1Policy', () => {
|
||||
},
|
||||
spec: {
|
||||
type: 'openapi',
|
||||
lifecycle: 'production',
|
||||
owner: 'me',
|
||||
definition: `
|
||||
openapi: "3.0.0"
|
||||
info:
|
||||
@@ -109,6 +111,36 @@ components:
|
||||
await expect(policy.enforce(entity)).rejects.toThrow(/type/);
|
||||
});
|
||||
|
||||
it('rejects missing lifecycle', async () => {
|
||||
delete (entity as any).spec.lifecycle;
|
||||
await expect(policy.enforce(entity)).rejects.toThrow(/lifecycle/);
|
||||
});
|
||||
|
||||
it('rejects wrong lifecycle', async () => {
|
||||
(entity as any).spec.lifecycle = 7;
|
||||
await expect(policy.enforce(entity)).rejects.toThrow(/lifecycle/);
|
||||
});
|
||||
|
||||
it('rejects empty lifecycle', async () => {
|
||||
(entity as any).spec.lifecycle = '';
|
||||
await expect(policy.enforce(entity)).rejects.toThrow(/lifecycle/);
|
||||
});
|
||||
|
||||
it('rejects missing owner', async () => {
|
||||
delete (entity as any).spec.owner;
|
||||
await expect(policy.enforce(entity)).rejects.toThrow(/owner/);
|
||||
});
|
||||
|
||||
it('rejects wrong owner', async () => {
|
||||
(entity as any).spec.owner = 7;
|
||||
await expect(policy.enforce(entity)).rejects.toThrow(/owner/);
|
||||
});
|
||||
|
||||
it('rejects empty owner', async () => {
|
||||
(entity as any).spec.owner = '';
|
||||
await expect(policy.enforce(entity)).rejects.toThrow(/owner/);
|
||||
});
|
||||
|
||||
it('rejects missing definition', async () => {
|
||||
delete (entity as any).spec.definition;
|
||||
await expect(policy.enforce(entity)).rejects.toThrow(/definition/);
|
||||
|
||||
@@ -26,6 +26,8 @@ export interface ApiEntityV1alpha1 extends Entity {
|
||||
kind: typeof KIND;
|
||||
spec: {
|
||||
type: string;
|
||||
lifecycle: string;
|
||||
owner: string;
|
||||
definition: string;
|
||||
};
|
||||
}
|
||||
@@ -40,6 +42,8 @@ export class ApiEntityV1alpha1Policy implements EntityPolicy {
|
||||
spec: yup
|
||||
.object({
|
||||
type: yup.string().required().min(1),
|
||||
lifecycle: yup.string().required().min(1),
|
||||
owner: yup.string().required().min(1),
|
||||
definition: yup.string().required().min(1),
|
||||
})
|
||||
.required(),
|
||||
|
||||
Reference in New Issue
Block a user