REST ❤ Swagger, 2 minutes to create an API SDK ⏱ – Codegen Demo – Part 1

Overview

On March 30th, I presented a webinar to the French VMUG community on the REST API subject and in particular on the way to generate API SDK clients without writing any code.

Slide deck is published (only in french, sorry) here: vupti.me/rls.

As said in the slide deck, this presentation was greatly inspired by a VMworld session: {CODE2216E} The art of code that writes code (Kyle Ruddy @ VMware Inc.). I cannot encourage you enough to see the replay if you did not do it yet.

The only part I did not pulished yet, was the demo part (even if, curious people may have found it in the repository).

I was planning to find a way to host the Jupyter Notebook online but as some commands rely on docker commands... I could not fount a hoster that enable it. So, let's re-write it in 2 blog posts.

Target of this post

So this post aims to demonstrate how you can create API SDK clients with Swagger Codegen:

  • Based on API documentation (both OpenAPI OASv3 and Swagger v2 are supported)
  • In the language of your choice (see below for the list)
  • Whitout writing any single line of code yourself (except for usage of the generated SDK)
  • In minutes !

Impossible? Let's see.

Next post

In a second post, I will demonstrate how to build/use SDK for VMware products: vCenter and vCloud Director.

Prerequisites

Docker

First, we need a docker setup (in order to avoid installing locally, the codegen software). I won't explain how to install and configure a docker host, this is not the point of the post.

We get the docker image of Swagger Codegen:

1docker pull swaggerapi/swagger-codegen-cli

If you prefer a local installation of Codegen, it is possible but you will need to modify some of the following commands.

Folders structure

For the tests, we will create 2 folders, for input files and output ones within a codegen folder:

1mkdir -p codegen/in/ codegen/out/
2ls codegen/ # should output "in out"

Python

We will create some python modules for test. I suggest to use a virtualenv if you want to proceed the same tests and to install some dependencies:

1wget https://github.com/lrivallain/rest-loves-swagger/raw/master/demo/requirements.txt
2wget https://github.com/lrivallain/rest-loves-swagger/raw/master/demo/utils.py
3pip install -r requirements.txt

Warning: I strongly suggest that you review the content of all the files you download on your computer before using them!

Go

A part of this post will provide a Go module. Install Go runtime to be able to test it.

Available languages

Codegen supports tons of output languages. To demonstrate it, we can use the following command:

(The sed part is only to prettify the ouput)

1docker run --rm swaggerapi/swagger-codegen-cli langs | sed 's/,/\n    /g'

The output of the command will be something like:

 1Available languages: [ada
 2     ada-server
 3     akka-scala
 4     android
 5     apache2
 6     apex
 7     aspnetcore
 8     bash
 9     csharp
10     clojure
11     cwiki
12     cpprest
13     csharp-dotnet2
14     dart
15     dart-jaguar
16     elixir
17     elm
18     eiffel
19     erlang-client
20     erlang-server
21     finch
22     flash
23     python-flask
24     go
25     go-server
26     groovy
27     haskell-http-client
28     haskell
29     jmeter
30     jaxrs-cxf-client
31     jaxrs-cxf
32     java
33     inflector
34     jaxrs-cxf-cdi
35     jaxrs-spec
36     jaxrs
37     msf4j
38     java-pkmst
39     java-play-framework
40     jaxrs-resteasy-eap
41     jaxrs-resteasy
42     javascript
43     javascript-closure-angular
44     java-vertx
45     kotlin
46     lua
47     lumen
48     nancyfx
49     nodejs-server
50     objc
51     perl
52     php
53     powershell
54     pistache-server
55     python
56     qt5cpp
57     r
58     rails5
59     restbed
60     ruby
61     rust
62     rust-server
63     scala
64     scala-gatling
65     scala-lagom-server
66     scalatra
67     scalaz
68     php-silex
69     sinatra
70     slim
71     spring
72     dynamic-html
73     html2
74     html
75     swagger
76     swagger-yaml
77     swift5
78     swift4
79     swift3
80     swift
81     php-symfony
82     tizen
83     typescript-aurelia
84     typescript-angular
85     typescript-inversify
86     typescript-angularjs
87     typescript-fetch
88     typescript-jquery
89     typescript-node
90     undertow
91     ze-ph
92     kotlin-server]

Pick the one you need !

Chuck Norris

We will use a sample API (api.chucknorris.io) for a first test.

Here is our plan:

  1. Get API documentation (from api.chucknorris.io/documentation)
  2. Pretify with | python -m json.tool
  3. Store the result in a file
  4. Display the first lines
1curl -s https://api.chucknorris.io/documentation | python -m json.tool > codegen/in/chucknorris.json
2head -n 25 codegen/in/chucknorris.json

You should see the content of a swagger file, with the API description.

Package configuration

We will create a Codegen configuration file for a python module, with some information about naming and versioning.

1echo '{
2  "packageName":"chucknorris_client",
3  "projectName":"chucknorris-client",
4  "packageVersion":"1.0.0"
5}' > codegen/in/config_chucknorris_client.json

SDK generation

Now we specify to Codegen, to use both API documentation file and package configuration one to create a new python based client SDK:

1docker run --rm -v ${PWD}/codegen:/local \
2  swaggerapi/swagger-codegen-cli generate \
3    -i /local/in/chucknorris.json \
4    -o /local/out/python-chucknorris \
5    -c /local/in/config_chucknorris_client.json \
6    -l python

We now have a new python module:

1ls codegen/out/python-chucknorris/

Output:

1README.md	    git_push.sh       test
2chucknorris_client  requirements.txt  test-requirements.txt
3docs		    setup.py	      tox.ini

And we can pip install this module:

1pip install codegen/out/python-chucknorris/

Use our new module

We create and run the following python file to use our new module:

 1import chucknorris_client
 2from chucknorris_client.rest import ApiException
 3
 4from utils import *
 5logger = logging.getLogger("DEMO_CHUCKNORRIS")
 6
 7# Configure API
 8logger.debug("Create an API client")
 9client = chucknorris_client.ApiClient(chucknorris_client.Configuration())
10
11logger.debug("Target the Joke Controller")
12api_instance = chucknorris_client.JokeControllerApi(client)
13
14try:
15    logger.debug("Get a random joke:")
16    api_response = api_instance.get_random_joke_value_using_get()
17    logger.info(api_response)
18except ApiException as e:
19    logger.error(
20        "Exception when calling JokeControllerApi->get_random_joke_value_using_get: %s\n" % e
21    )

You can now run it and get the following result:

1DEMO_CHUCKNORRIS 	Create an API client
2DEMO_CHUCKNORRIS 	Target the Joke Controller
3DEMO_CHUCKNORRIS 	Get a random joke:
4DEMO_CHUCKNORRIS 	Chuck Norris was worshipped as a god by the Eskimos. That is why they had igloos modelled after his signature move.

Please consider that most of the python code we used is about the logger and not the complexity of getting a random Chuck Norris fact. If you don't, Chuck Norris may come to you for an explaination.

Same with Go ?

Lets do the same, with Go:

1docker run --rm -v ${PWD}/codegen:/local \
2  swaggerapi/swagger-codegen-cli generate \
3    -i /local/in/chucknorris.json \
4    -o /local/out/gochucknorris \
5    -DpackageName=gochucknorris \
6    -l go

The Go test file (for example: codegen/chuck.go):

 1package main
 2
 3import (
 4    "log"
 5    cn "out/gochucknorris"
 6    "golang.org/x/net/context"
 7)
 8
 9func main() {
10    log.Print("New API client with empty configuration")
11    client := cn.NewAPIClient(cn.NewConfiguration())
12    log.Print("Get random joke")
13    joke, r, err := client.JokeControllerApi.GetRandomJokeValueUsingGET(context.Background(), nil)
14    // Test error
15    if err != nil {
16        log.Print("Error:", err)
17    }
18    // Test HTTP Response code
19    if r.StatusCode == 200 {
20        log.Print(joke.Value)
21    }
22}

And the result of a go run codegen/chuck.go:

12020/04/01 17:28:11 New API client with empty configuration
22020/04/01 17:28:11 Get random joke
32020/04/01 17:28:12 Chuck Norris can levitate birds.

Conclusion

How long to get this new API SDK client in a new language? Less than a minute !

In the next post, we will apply this process to two VMware products:

  • vCenter (6.7 only sorry!)
  • vCloud Director