So, RAML or OAS (Swagger)?

In the dynamic world of microservices, anything can change — any component can be rewritten in another language, using different frameworks and architecture. The contracts should remain unchanged so that the microservice can be interacted with externally on a consistent basis, regardless of internal metamorphoses. Today we will talk about our dilemma in choosing the format for describing contracts and share the artifacts we found.

So, RAML or OAS (Swagger)?

The post was prepared by Anna Melekhova and Vladimir Lapatin

Microservices. During the development of Acronis Cyber Cloud, we realized that we couldn't escape them. Designing a microservice is impossible without formalizing a contract, which represents the interface of the microservice.

However, when a product contains more than one component, and the development of the contract becomes a regular activity, you inevitably start thinking about optimizing the process. It becomes clear that the interface (contract) and implementation (microservice) should match each other, that different components must do the same things consistently, and that without centralizing all these decisions, each team will have to repeatedly spend time figuring them out.

So, RAML or OAS (Swagger)?
The architecture of Amazon's microservices from a tweet by Werner Vogels, CTO of Amazon
What is the dilemma? De facto, there are two ways for microservices to interact – HTTP Rest and gRPC from Google. Not wanting to get caught up in Google's technology stack, we chose HTTP Rest. Annotations to HTTP REST contracts are most often described in one of two formats: RAML and OAS, previously known as Swagger. Therefore, each development team faces the need to choose one of the standards. But, as it turned out, making this choice can be quite difficult.

Why are annotations needed?

An annotation is needed so that external users can easily understand what can be done with your service through its HTTP interface. At a basic level, the annotation should contain at least a list of available resources, their HTTP methods, request bodies, a list of parameters, and an indication of required and supported headers, as well as return codes and response formats. A critical element of the contract annotation is their verbal description ("What happens if this query parameter is added to the request?", "Under what circumstances will code 400 be returned?")

However, when it comes to developing a large number of microservices, it is desirable to extract additional value from the written annotations. For example, based on RAML/Swagger, you can generate both client and server code in a wide variety of programming languages. Additionally, you can automatically generate documentation for the microservice and upload it to your developer portal :).

So, RAML or OAS (Swagger)?
Example of a structured contract description

The practice of testing microservices based on contract descriptions is less common. If you have written both the annotation and the component, you can create an automated test that checks whether the service works adequately with various types of input data. Does the service return a response code that is not described in the annotation? Will it be able to correctly handle clearly incorrect data?

Moreover, a quality implementation of not just the contracts themselves but also the tools for visualizing annotations can simplify working with the microservice. That is, if the architect has clearly described the contract, based on it, designers and developers can integrate the service into other products without additional time costs.

For the operation of additional tools, both RAML and OAS allow for the addition of metadata not provided for in the standard (for example, this is how it is done in OAS).

In general, there is a vast creative field for applying contracts to microservices... at least theoretically

Comparison of the hedgehog and the snake

Currently, the main focus of development at Acronis is the evolution of the Acronis Cyber Platform. Acronis Cyber Platform serves as new integration touchpoints for third-party services with Acronis Cyber Cloud and the agent component. While our internal APIs, described in RAML, met our needs, the necessity of publishing an API raised the question again: which annotation standard is best suited for our work?

Initially, it seemed there were two solutions — the most widely used developments of RAML and Swagger (or OAS). However, in reality, it turned out that there are at least three or more alternatives.

On one hand, there is RAML — a powerful and efficient language. It implements hierarchy and inheritance well, making this format more suitable for large companies that require many descriptions — meaning not just one product, but numerous microservices with common contract parts — authentication schemas, identical data types, error bodies.

However, the developer of RAML, Mulesoft, joined the Open API consortium, which is focused on development Swagger. As a result, RAML has paused its development. To envision the event format, imagine that the maintainers of essential Linux components went to work at Microsoft. Such a situation creates prerequisites to utilize Swagger, which is evolving dynamically and in its latest — third version — almost catches up with RAML in terms of flexibility and functionality.

If it weren't for one thing...

It turned out that not all open-source utilities have been updated to version OAS 3.0. For microservices on Go, the lack of adaptation of go-swagger to the latest version of the standard will be the most critical. However, the difference between Swagger 2 and Swagger 3 is huge.For instance, in the third version, developers have:

  • improved authentication schema descriptions,
  • completed support for JSON Schema,
  • enhanced the ability to add examples.

The situation is amusing: when choosing a standard, RAML, Swagger 2, and Swagger 3 must be viewed as separate alternatives. Only Swagger 2 has good support from the OpenSource toolkit. RAML is very flexible... and complex, while Swagger 3 is poorly supported by the community, meaning you will have to rely on your own or commercial solutions, which generally tend to be quite expensive.

At the same time, if Swagger offers many nice features, such as a ready-made portal, editor.swagger.io, which allows you to upload an annotation and obtain its visualization with detailed descriptions, links, and relationships, whereas for the more fundamental and less user-friendly RAML, such an opportunity is absent. Yes, you can search for something among projects on GitHub, find a similar one, and set it up yourself. However, in any case, someone needs to maintain the portal, which is not very convenient for basic use or testing needs. Additionally, Swagger is more "principle-free," or liberal—you can generate it from comments in the code, which, of course, contradicts the API-first principle and is not supported by any RAML utilities.

We initially started working with RAML as a more flexible language, and ultimately we had to do a lot ourselves. For instance, in one of the projects, we use the utility ramlfications in unit tests, which only supports RAML 0.8. So we had to add workarounds to make the utility able to "consume" RAML version 1.0.

Do we even need to choose?

After struggling with extending the ecosystem of solutions for RAML, we concluded that we needed to convert RAML into Swagger 2 and conduct all automation, validation, testing, and subsequent optimization within it. This is a good way to utilize both the flexibility of RAML and the community tool support from Swagger.

For this task, there are two OpenSource tools that are supposed to facilitate contract conversion:

  1. oas-raml-converter — a now unsupported utility. During our work with it, we discovered that it has a series of issues with complex RAMLs that are "spread out" across a large number of files. This program is written in JavaScript and performs a recursive traversal of the syntax tree. Due to dynamic typing, understanding this code becomes difficult, so we decided not to waste time on writing patches for a dying utility.
  2. webapi-parser — a tool from the same company that claims to be ready to convert everything and anything, in any direction. As of today, support for RAML 0.8, RAML 1.0, and Swagger 2.0 has been announced. However, at the time of our research, the tool was still EXTREMELY raw and unsuitable for use. The developers are creating a sort of IR, which will allow them to quickly add new standards in the future. But for now, none of this is working.

And this isn’t the only complexity we faced. One step in our pipeline involves checking that the RAML from the repository is correct according to the specification. We tried several utilities. Surprisingly, all of them complained about our annotations in different places and with completely unfounded harsh words. Moreover, not always justifiably :).

Ultimately, we settled on a now-obsolete project that also has a number of issues (it sometimes crashes for no reason and has problems dealing with regular expressions). Thus, we couldn’t find a way to solve the validation and conversion tasks using free tools, and decided to use a commercial utility. In the future, when open-source tools become more advanced, solving this issue may become easier. For now, the time and labor costs of 'finishing' seemed more significant to us than the cost of the commercial service.

Conclusion

After all this, we wanted to share our experience and note that before choosing a tool for describing contracts, you need to clearly determine what you want from it and what budget you are ready to invest. If we forget about open-source, there are already a large number of services and products available that can help with validation and conversion. But they can be quite expensive, and sometimes very expensive. For a large company, these costs are manageable, but for a startup, they can become a significant burden.

Define the set of tools you will use later. For example, if you only need to display a contract, it will be easier to use Swagger 2, which has a nice API, since with RAML you’ll have to set up and maintain the service yourself.
The more tasks you have, the greater your need for tools will be, and they vary for different platforms. It’s better to familiarize yourself with the available versions right away to make a choice that minimizes your future costs.

It must be acknowledged that all ecosystems that exist today are imperfect. Therefore, if the company has fans who love working with RAML because it allows for a more flexible expression of ideas, or conversely prefer Swagger because it is clearer, it is best to let them work in what they are comfortable and want to use, as the tooling of either format requires refinement.

As for our experience, in upcoming posts we will discuss the static and dynamic checks we perform based on our RAML-Swagger architecture, as well as the documentation we generate from contracts and how all of this works.

Only registered users can participate in the survey. Please log in, please.

What language do you use for microservices contract annotations?

  • RAML 0.8

  • RAML 1.0

  • Swagger 2

  • OAS3 (aka )

  • Blueprint

  • Other

  • Not using

100 users voted. 24 users abstained.

Source: habr.com

Buy reliable website hosting with DDoS protection, VPS VDS servers 🔥 Buy reliable website hosting with DDoS protection, VPS VDS servers | ProHoster