Merge pull request #2424 from SDA-SE/feat/extend-api-model

feat: extend API entity by lifecycle and owner
This commit is contained in:
Oliver Sand
2020-09-17 09:49:13 +02:00
committed by GitHub
6 changed files with 83 additions and 1 deletions
@@ -486,6 +486,8 @@ metadata:
description: Retrieve artist details
spec:
type: openapi
lifecycle: production
owner: artist-relations@example.com
definition: |
openapi: "3.0.0"
info:
@@ -530,6 +532,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(),