Choosing between RAML and OAS (Swagger)
Everything can get changed in the dynamic world of microservices. You can rewrite every component using another language or another framework or architecture. Only contracts are invariable. They define the way your microservice interacts despite any internal change.
Today we are going to tell you about the problem we faced with selection of contract format definition and share some discovered artifacts.
Microservices. While building the Acronis Cyber Cloud, we realized that we can do nothing without them. But you can’t construct a microservice until you formalize the contract, which represents the interface of the microservice.
When your product contains more than one component and contract writing becomes a regular activity, you should think of some process optimization. It becomes obvious that the interface (contract) and its implementation (microservice) have to correspond with each other, as different components must do the same things similarly. Otherwise, without centralized management, every team will have to spend resources again and again.
Amazon microservices scheme from Werner Vogelis Tweet, СTO Amazon
What is the dilemma? There are two popular approaches to building microservices communication that are the de facto options: HTTP REST and gRPC by Google. We didn’t want to dive into the Google private technologies stack and we have chosen HTTP REST. HTTP REST contract annotations are usually described with one of two possible formats: RAML or OAS (formerly, Swagger).
Every development team has to choose one standard, but we discovered that this choice can be rather difficult.
Why do we need annotations?
The annotation helps an external user to discover what he can do with your service via HTTP interface. Basically, the annotation should contain the list of accessible resources, HTTP-methods, request bodies, parameters, supported and required headers, return codes and answer formats at least. The verbal description is one of the most important annotation elements. It helps answering questions like “What will happen if I add this query parameter to the request?” and “In which cases I will receive the return code 400?”
Moreover, when we speak about a large number of microservices, there’s a possibility to get some additional profit from annotations. For example, using RAML/Swagger annotations you can generate client and server code on different programming languages. You can also automatically produce the documentation for your microservice and upload it to your developer portal. :)
The example of the structured contract description
There is also a rare practice of testing microservices using the contract descriptions. If you have a component and the annotation, you are free to create an autotest to check the service operation with different types of input data. Does the service return the code, unmentioned in the annotation? Can it correctly process initially incorrect data?
The qualitative implementation of contacts and visualization tools simplifies the work with microservices. If an architect has described the contract carefully, designers and developers will be able to integrate the service into other products faster and with less efforts.
To use some additional tools RAML and OAS have the options to add non-standard metadata (example for OAS). So, you have a huge field for creativity on how to use microservices contracts…at least theoretically.
Comparing a ship with a sheep
Acronis Cyber Platform has been the priority product for Acronis developers lately. Acronis Cyber Platform opens new integration areas for Acronis Cyber Cloud with third-party services and agents. Though, while our internal APIs with RAML annotations were convenient for us for a long time, the need to publish API forced us to return to the choice: which annotation standard is better for our job?
Initially it seemed that we have two options – the most popular formats RAML and Swagger (OAS). But in fact, we found not two, but three (and even more) alternatives.
On the one hand, RAML is the powerful and effective language. It has a good support for hierarchy and inheritance. This format is suitable for large companies with tons of annotations. Usually they have more than one product, and their microservices have common contract parts: authentication schemes, data types, error bodies.
But Mulesoft (RAML developer) joined Open API consortium, which promotes Swagger. That’s why RAML stopped its evolution. To realize the meaning of this event, imagine that main Linux component maintainers moved to Microsoft. This kind of the situation forces us to use Swagger, which continues to develop. The third version of Swagger almost matchmatches RAML in terms of flexibility and features.
But there is one problem…
It appeared that not every open-source tool was updated for OAS 3.0. For Go microservices, for example, the most important problem will be the absence of go-swagger adaptation for the last version of the standard. Meanwhile, the difference between Swagger 2 and Swagger 3 is tremendous. For example, in the third version the developers:
- improved the authentication schemes description
- finished implementation of JSON Schema support
- enhanced the opportunity to add examples
So, the situation is curious. Choosing the standard, you have to take into account RAML, Swagger 2 and Swagger 3 as separate options. But only Swagger 2 has a really good ecosystem support, RAML is very flexible…and complicated, while Swagger 3 is poorly supported by the community, so, you will have to develop your own tools or buy rather expensive commercial products for it.
Swagger has a lot of pleasant features, like a ready-to-use editor.swagger.io portal. You can upload your annotation and get a visualization with detailed descriptiondescriptions, links and dependences. More fundamental and less friendly RAML has no such feature. Of course, you can find some tool on GitHub and launch the portal yourself. But you will have to support it, and it’s not so convenient for basic usage or simple testing. In addition Swagger is less formal….: You can generate annotations without comments in the code. The same thing is impossible with any RAML tool, because it breaks the “API first” rule.
Some time ago we started with RAML, as a more flexible language. As a result, we had to do a lot manually a lot. For example, in one of our projectprojects we are using a ramlfications utility for our unit-tests. It supports only RAML v0.8, so we had to do something and force the tool working with RAML v1.0.
Do we really have to choose?
Tired of sorcery and tuning the RAML ecosystem, we concluded that we have to convert RAML to the Swagger 2 format to bring automation, testing and optimization to life. It is a good way to use RAML flexibility and Swagger community support at the same time.
As we discovered, there are two Open Source tools to solve the problem of contracts conversion:
- webapi-parser is the tool by the same company. It pretends to convert everything to any other format. As of today, it declares support for RAML 0.8, RAML 1.0 and Swagger 2.0. But our research discovered that this tool was VERY rough draft and useless for us. They are creating a kind of an IR to add new standards in the future. But today it just doesn’t work.
And it was only part of the difficulties we faced. One of the steps in our pipeline is to check that RAML from repository correctly corresponds to specs. We tried several tools, and all of them were unhappy with our annotations…but in different places, for different reasons, and not always correctly.
Finally, we adopted one now outdated project with its own problems (crashes, has problems with regular expressions and so on). We couldn’t find a free validation and conversion tool, so we started using a commercial solution. In the future, Open Source tools are likely to become more mature and the solution for such a problem will be simpler. But now the efforts for fixing existing Open Source projects appeared to us more expensive than buying a commercial service.
This story is for sharing our experience. Before choosing a contract annotation tool, you should clearly understand what do you want from it and what is your budget for it. Even without Open Source, there already are a lot of services and products for testing, converting and validation. But the price is high – sometimes very high. These expenses are acceptable for a large company, but for a startup it can be a problem.
Also you have to define the spectrum of tools you will use in the future. For example, if you want just to show contracts, Swagger 2 will be the best option with a fancy API, but with RAML you will have to implement and maintain the service yourself.
For more tasks you’ll need more tools. But they are quite different for different platforms. It’s better to inspect available tools and minimize your problems in the future.
We should admit that all the listed ecosystems are not perfect. So if you have RAML fans in the company who are sure that “RAML allows more flexibility” or vice-a-versa, they prefer a more “clear” Swagger, you’d better leave them working in their favorite format. Either way, every of them will force you to fix something manually.
In the next publication we will tell you about static and dynamic annotations tests in Acronis. We will share our RAML-Swagger ecosystem principles and tell you about documentation production and Acronis contracts architecture in general.