--- title: Generating OpenAPI Specification with Ent author: MasseElch authorURL: "https://github.com/masseelch" authorImageURL: "https://avatars.githubusercontent.com/u/12862103?v=4" --- In a [previous blogpost](https://entgo.io/blog/2021/07/29/generate-a-fully-working-go-crud-http-api-with-ent), we presented to you [`elk`](https://github.com/masseelch/elk) - an [extension](https://entgo.io/docs/extensions) to Ent enabling you to generate a fully-working Go CRUD HTTP API from your schema. In the today's post I'd like to introduce to you a shiny new feature that recently made it into `elk`: a fully compliant [OpenAPI Specification (OAS)](https://swagger.io/resources/open-api/) generator. OAS (formerly known as Swagger Specification) is a technical specification defining a standard, language-agnostic interface description for REST APIs. This allows both humans and automated tools to understand the described service without the actual source code or additional documentation. Combined with the [Swagger Tooling](https://swagger.io/) you can generate both server and client boilerplate code for more than 20 languages, just by passing in the OAS file. ### Getting Started The first step is to add the `elk` package to your project: ```shell go install github.com/masseelch/elk ``` `elk` uses the Ent [Extension API](https://entgo.io/docs/extensions) to integrate with Ent’s code-generation. This requires that we use the `entc` (ent codegen) package as described [here](https://entgo.io/docs/code-gen#use-entc-as-a-package) to generate code for our project. Follow the next two steps to enable it and to configure Ent to work with the `elk` extension: 1\. Create a new Go file named `ent/entc.go` and paste the following content: ```go // +build ignore package main import ( "log" "entgo.io/ent/entc" "entgo.io/ent/entc/gen" "github.com/masseelch/elk" ) func main() { ex, err := elk.NewExtension( elk.GenerateSpec("openapi.json"), ) if err != nil { log.Fatalf("creating elk extension: %v", err) } err = entc.Generate("./schema", &gen.Config{}, entc.Extensions(ex)) if err != nil { log.Fatalf("running ent codegen: %v", err) } } ``` 2\. Edit the `ent/generate.go` file to execute the `ent/entc.go` file: ```go package ent //go:generate go run -mod=mod entc.go ``` With these steps complete, all is set up for generating an OAS file from your schema! If you are new to Ent and want to learn more about it, how to connect to different types of databases, run migrations or work with entities, then head over to the [Setup Tutorial](https://entgo.io/docs/tutorial-setup/). ### Generate an OAS file The first step on our way to the OAS file is to create an Ent schema graph: ```shell go run -mod=mod entgo.io/ent/cmd/ent init Fridge Compartment Item ``` To demonstrate `elk`'s OAS generation capabilities, we will build together an example application. Suppose I have multiple fridges with multiple compartments, and my significant-other and I want to know its contents at all times. To supply ourselves with this incredibly useful information we will create a Go server with a RESTful API. To ease the creation of client applications that can communicate with our server, we will create an OpenAPI Specification file describing its API. Once we have that, we can build a frontend to manage fridges and contents in a language of our choice by using the Swagger Codegen! You can find an example that uses docker to generate a client [here](https://github.com/masseelch/elk/blob/master/internal/openapi/ent/generate.go). Let's create our schema: ```go title="ent/fridge.go" package schema import ( "entgo.io/ent" "entgo.io/ent/schema/edge" "entgo.io/ent/schema/field" ) // Fridge holds the schema definition for the Fridge entity. type Fridge struct { ent.Schema } // Fields of the Fridge. func (Fridge) Fields() []ent.Field { return []ent.Field{ field.String("title"), } } // Edges of the Fridge. func (Fridge) Edges() []ent.Edge { return []ent.Edge{ edge.To("compartments", Compartment.Type), } } ``` ```go title="ent/compartment.go" package schema import ( "entgo.io/ent" "entgo.io/ent/schema/edge" "entgo.io/ent/schema/field" ) // Compartment holds the schema definition for the Compartment entity. type Compartment struct { ent.Schema } // Fields of the Compartment. func (Compartment) Fields() []ent.Field { return []ent.Field{ field.String("name"), } } // Edges of the Compartment. func (Compartment) Edges() []ent.Edge { return []ent.Edge{ edge.From("fridge", Fridge.Type). Ref("compartments"). Unique(), edge.To("contents", Item.Type), } } ``` ```go title="ent/item.go" package schema import ( "entgo.io/ent" "entgo.io/ent/schema/edge" "entgo.io/ent/schema/field" ) // Item holds the schema definition for the Item entity. type Item struct { ent.Schema } // Fields of the Item. func (Item) Fields() []ent.Field { return []ent.Field{ field.String("name"), } } // Edges of the Item. func (Item) Edges() []ent.Edge { return []ent.Edge{ edge.From("compartment", Compartment.Type). Ref("contents"). Unique(), } } ``` Now, let's generate the Ent code and the OAS file. ```shell go generate ./... ``` In addition to the files Ent normally generates, another file named `openapi.json` has been created. Copy its contents and paste them into the [Swagger Editor](https://editor.swagger.io/). You should see three groups: **Compartment**, ** Item** and **Fridge**.
Swagger Editor Example
POST operation on Fridge
Updated API Info
DELETE operation is gone