API Definitions
Geralmente os sistema se comunicam através de API, claro que existem outras formas mas esta é a mais comum. Por isso temos uma entidade que trata somente desse assunto. Toda vez que precisamos de comunicação entre uma sistema e outro, principalmente de um terceiros, seja outra equipe ou até mesmo um serviço externo a primeira coisa que precisamos fazer é estudar a API do serviço.
A idéia é centralizar a documentação das APIs por meio do catalog.
Vamos criar a API abaixo no projecto backend-thing-1.
apiVersion: backstage.io/v1alpha1
kind: API
metadata:
name: artist-api
description: Retrieve artist details
spec:
type: openapi
lifecycle: production
owner: artist-relations-team
system: artist-engagement-portal
definition: |
openapi: "3.0.0"
info:
version: 1.0.0
title: Artist API
license:
name: MIT
servers:
- url: http://artist.spotify.net/v1
paths:
/artists:
get:
summary: List all artists
...
Se criarmos na raiz como os outros anteriores o discovery não fará o seu trabalho pois ele procura sempre na pasta backstage que definimos lembra?
Porém se fizermos essa mudança, uma vez que importamos manualmente primeiro, estamos alterando o local das coisas e teremos problemas. Será necessário deletar e deixar que o import seja feito automaticamente.
Já vamos movimentar tudo para a pasta backestage durante a criação para não precisar importar mais nada.
Só para manter tudo funcionando bem, e evitar erros de relacionamento vamos criar o system do projeto exemplo da documentação.
apiVersion: backstage.io/v1alpha1
kind: System
metadata:
name: artist-engagement-portal
description: Handy tools to keep artists in the loop
spec:
owner: artist-relations-team
domain: artists
E aqui temos a ideia do swagger por dentro do backstage.
Porém essa definição que fizemos foi totalmente hardcoded.
definition: |
openapi: "3.0.0"
info:
version: 1.0.0
title: Artist API
license:
name: MIT
servers:
- url: http://artist.spotify.net/v1
paths:
/artists:
get:
summary: List all artists
...
Precisamos de um método que leia isso do arquivo e automatize isso.
Peguei um arquivo de swagger de exemplo só gerar mais documentação, crirei uma pasta no repositório e coloquei lá.
❯ tree
.
├── backstage
│ ├── api.yaml
│ ├── component-website.yaml
│ ├── group.yaml
│ └── system.yaml
└── openapi
└── swagger.json ## Este
Agora vamos editar o api.yaml para:
apiVersion: backstage.io/v1alpha1
kind: API
metadata:
name: artist-api
description: Retrieve artist details
spec:
type: openapi
lifecycle: production
owner: artist-relations-team
system: artist-engagement-portal
definition:
$text: ../openapi/swagger.json
#Também funcionaria usando a url
#$text: https://petstore.swagger.io/v2/swagger.json
$text
: trará o conteúdo do arquivo swagger.json aqui pra dentro.
Claro que não tem muito sentido pois é um json de outro projeto, mas veja como já temos tudo sem muito esforço.
Aproveitando para falar sobre substituições temos:
$text
: Interpreta o conteúdo do arquivo referenciado como texto simples e o incorpora como uma string.$json
: Interpreta o conteúdo do arquivo referenciado como JSON e incorpora a estrutura analisada.$yaml
: Interpreta o conteúdo do arquivo referenciado como YAML e incorpora a estrutura analisada.
Porém, quando colocamos uma url o backstage precisa que você permita a leitura de tal local.
Vamos imaginar que estamos definindo uma API de um serviço externo ao nosso sistema, mas queremos a documentação dela integrada no backstage.
Podemos usar o mesmo exemplo anterior, só mudando alguns nomes.
apiVersion: backstage.io/v1alpha1
kind: API
metadata:
name: petstore-api
description: Petstore API Swagger
spec:
type: openapi
lifecycle: production
owner: artist-relations-team
system: artist-engagement-portal
definition:
$text: https://petstore.swagger.io/v2/swagger.json
O nosso discovery não conseguiu criar automaticamente mas temo o seguinte log.
[backend]: 2024-11-27T19:59:10.396Z catalog warn Processor PlaceholderProcessor threw an error while preprocessing; caused by Error: Placeholder $text could not read location https://petstore.swagger.io/v2/swagger.json, NotAllowedError: Reading from 'https://petstore.swagger.io/v2/swagger.json' is not allowed. You may need to configure an integration for the target host, or add it to the configured list of allowed hosts at 'backend.reading.allow' entity=api:default/petstore-api location=url:https://github.com/davidpuziol/backstage-things-1/tree/main/backstage/apii-external.yaml
Não é permitido a leitura dessa url. Para isso é necessario explicitamente avisar o backend quais os hosts ele pode ler e alterar o app-config.yaml. Documentação sobre isso.
Vamos adicionar a permissão para esse host dentro de app-config.yaml na sessão backend.
backend:
# ...
reading:
allow:
- host: 'petstore.swagger.io'
E também temos ela funcionando.
É sempre interessante somente permitir diretamente hosts conhecidos e sempre referenciar o máximo possível o que tem em casa.
Poderíamos na documentação de um componente ter um link referenciando a API de terceiros, mas o que fizemos aqui foi uma facilidade.
Sempre é bom permitir o próprio domínio da empresa.