Centralized Swagger Catalog (Microservices)

We often see many services with an extensive OpenAPI catalog, that help integration with the APIs that are being consumed. Many of these services do not follow a microservice architecture and, basically, they just expose all of their Endpoints from the same Java package through the Swagger interface built into the OpenAPI dependencies themselves.

What happens if we have a large number of independent microservices, and we want a single catalog for all of them? This is a question that, once we delve into different information forums and blogs, we’ll see does not have one single answer and there are many possible solutions, each one more convoluted than the last.

That is why the need arises to do this in a more standardized way, without having to resort to creating our own services, coding what is necessary to be able to have a catalog that shows all the APIs we want in a single point. And, the funny thing about it, is that this is really simple, but you have to keep certain things in mind – thing that we will tell you next.

Requirements

You need to take into account the following requirements before tackling the single catalogue:

  1. You need to have the microservices published, with the Swagger documentation exposed: usually they are published in the address: ${SERVICE_URL}/v3/api-docs (if you use version 3), but the configuration allows you to change it.
  2. A correct configuration of CORS is necessary: ​​for the microservices whose documentation is going to be consumed, since otherwise the single swagger interface will not be able to retrieve the information needed for their correct operation.
  3. You have the possibility to use public images from Docker Hub: to be able to consume the one from swagger-ui.

In our local environment

Let’s assume that you have two services published in your local environment, on ports 8080 and 8081, and that you meet the above requirements. You would need to set up a Docker image with the appropriate environment variables, which in this case is just one: URLS.

docker-compose.yml

version: "3.3"
services:
  swagger-ui:
    image: swaggerapi/swagger-ui
    container_name: "swagger-ui"
    ports:
      - "8088:8080"
    environment:
      URLS: "[{name:'Service1',url:'http://localhost:8081/v3/api-docs'},{name:'Service2',url:'http://localhost:8082/v3/api-docs'},]"

This configuration would publish to your port 8088 (http://localhost:8088), which would look for the following:

  • Service1 in the URL: http://localhost:8081/v3/api-docs
  • Service2 in the URL: http://localhost:8082/v3/api-docs

With the service’s name being totally changeable, not dependin on the microservice’s real name.

Publishing it to our cluster

Given how simple it is to use swagger-ui through Docker, one can expect that, with a proper configuration in Kubernetes, it should also be simple – as is the case:

Deployment

kind: Deployment
apiVersion: apps/v1
metadata:
  name: services-swagger-ui
  namespace: services-namespace
  labels:
    app: services-swagger-ui
spec:
  replicas: 1
  selector:
    matchLabels:
      app: services-swagger-ui
  template:
    metadata:
      labels:
        app: services-swagger-ui
    spec:
      containers:
        - name: services-swagger-ui
          image: 'swaggerapi/swagger-ui:v4.10.3'
          ports:
            - name: http
              containerPort: 8080
              protocol: TCP
          env:
            - name: URLS
              value: >-
                [{name:'Service1',url:'https://service1url.com/v3/api-docs'},{name:'Service2',url:'https://service2url.com/v3/api-docs'}]
          resources:
            limits:
              cpu: 50m
              memory: 50Mi
            requests:
              cpu: 5m
              memory: 5Mi
          imagePullPolicy: IfNotPresent
      restartPolicy: Always

In the previous deployment, restricted to the v4.10.3 version of the public image, we would be configuring the documentations that we can find in:

  • https://service1url.com/v3/api-docs
  • https://service2url.com/v3/api-docs

At the resource level, as you can see, the amount of memory and CPU used is quite small, and testing has not even reached one tenth of the limits assigned for this example.

It should be noted that the Docker image is configurable using the many environment variables that you can find in its documentation. There are also Nginx configuration variables, Nginx being the server through which swagger-ui content is published internally within docker. These variables can be seen in their public GitHub. It is worth noting, for example, the BASE_URL environment variable to configure the path, which defaults to ‘/’.

Of course, in order to externally publish the content of this image, we would need the definitions of the Kubernetes services necessary for that (service, ingress, load balancer,… etc), which are more specific to the environment being used.

Header image: 2H Media on Unsplash

Autor

Leave a Reply

Your email address will not be published. Required fields are marked *