To identify the OpenAPI spec for all of the API services in your environment, Gloo uses an ApiDoc custom resource.

Before you begin

For example steps, see the Set up Gloo Portal tutorial.

  1. Install Gloo Portal.
  2. Deploy REST API services that conform to the OpenAPI specification (OAS), v2 or v3.

Options to create ApiDocs

To create ApiDocs, choose from the options in the following table.

MethodApiDoc creationHow to trigger updates to ApiDocDescription
Kubernetes service annotationsAutomaticUpdate the Kubernetes serviceAdd annotations to your apps’ services so that Gloo automatically discovers their REST APIs.
ApiDocManualUpdate the ApiDoc manuallyManually create a Gloo ApiDoc custom resource to describe your REST API services. Typically, you choose this option if you use external services for apps that run outside your cluster environment, such as in a virtual machine (VM).

Automatically discover REST API services

Annotate your Kubernetes services so that Gloo automatically discovers their REST API services and creates the ApiDoc resource for you. Any time that you redeploy your workloads, Gloo refetches the OpenAPI spec to update the ApiDoc for you.

To annotate your services:

  1. Review or update the gloo.solo.io annotations that Gloo used to automatically discover and create an ApiDoc for each service.

    Review the following table to understand this configuration.

    SettingRequired?Description
    /scrape-openapi-sourceYesAdd the relative path where your service exposes its OpenAPI v2 or v3 specification in YAML or JSON format. Common paths include /api/v3/openapi.json or /swagger.json. You might also provide a publicly accessible URL to the spec, such as Istio’s bookinfo example: https://raw.githubusercontent.com/istio/istio/master/samples/bookinfo/swagger.yaml.
    /scrape-openapi-schemeNoEnter http or https for the protocol scheme to use when accessing the OpenAPI schema, such as if it differs from the source endpoint. The default value is http.
    /scrape-openapi-portNoEnter the port to use when accessing the OpenAPI schema, such as if it differs from the source endpoint.
    /scrape-usage-pull-attempts, /scrape-usage-retry-delay, /scrape-usage-use-backoffNoYou can configure these annotations for increased resiliency. For example, if your workload’s container takes some time to spin up, you might adjust the retry delay or the number of pull attempts.
  2. Verify that your ApiDocs are created.

Manually create an ApiDoc resource

If you don’t want Gloo to automatically discover and create ApiDocs for your apps, you can manually create the ApiDoc resource. You might choose this option if you use external services for apps that run outside your cluster environment, such as in a virtual machine (VM).

  1. Deploy your apps with REST API services that conform to the OpenAPI specification (OAS).

  2. Get the OpenAPI schema for the apps that you deployed.

  3. Create the ApiDoc custom resource to describe the OpenAPI schema of your app.

      kubectl apply -f - << EOF
    apiVersion: apimanagement.gloo.solo.io/v2
    kind: ApiDoc
    metadata:
      annotations:
        cluster.solo.io/cluster: ""
      name: customers-api-schema
      namespace: default
    spec:
      openapi:
        # The YAML- or JSON-formatted OpenAPI v2 or v3 schema string to use for your API. 
        inlineString: '{"components":"customer"}'
      servedBy:
      - destinationSelector:
          port:
            number: 8080
          selector:
            cluster: $CLUSTER_NAME
            name: app
            namespace: app
    EOF
      

    Review the following table to understand this configuration. For more information, see the API docs.

    SettingDescription
    openapi.inlineStringThe YAML- or JSON-formatted OpenAPI v2 or v3 schema string to use for your API. Replace this value with your schema, such as '{ "info": { "title": "Gloo Portal API", "version": "1.0.0", "description": "Review the following reference documentation for the Gloo Portal APIs. Use these endpoints to manage user access to both the developer portal and the API resources exposed by the portal." }, "openapi": "3.0.0", "servers": [ { "url": "https://api.gloo-platform-portal.com/v1" } ], "paths": { "/login": { "get": { "description": "Logs user into the developer portal. This is the path that should be used as the callbackPath in the ExtAuthPolicy's OIDC configuration.", "operationId": "login", "security": [ { "identityToken": [ ] } ], "responses": { "200": { "description": "Successfully logged in" } }, "summary": "Logs user into the developer portal", "tags": [ "User" ] } }'
    servedBy.destinationSelectorSpecify the backing destination for your app, by label or by name. This destination matches the destinations that you later route to. Supported destinations are Kubernetes services or Gloo virtual destinations.
  4. Verify that your ApiDocs are created.

Verify that your ApiDocs are created

Verify that your apps are running and that Gloo has the ApiDocs that describe their OpenAPI specs.

  1. Check that your apps are running.

      kubectl get pods -A
      
  2. Automatic discovery: Enable port-forwarding for one of your apps and check that the OpenAPI spec exists on the path that you included in the gloo.solo.io/scrape-openapi-source annotation on the service. The following example checks the Tracks app.

      kubectl -n tracks port-forward services/tracks-rest-api 5000:5000
      

    In your browser, open http://localhost:5000/swagger.json and verify that the OpenAPI spec exists:

      {
     "swagger": "2.0",
     "info": {
       "description": "REST API for Catstronauts to retrieve data for tracks, authors and modules.",
       "version": "1.0.0",
       "title": "Catstronauts REST API"
     },
     ...
      
  3. List the ApiDocs in each app’s namespace.

      kubectl get apidocs -A
      
  4. Optional: If an app does not have an ApiDoc, try recreating the service. Or, you can manually create an ApiDoc such as with the following example.

      kubectl apply -n tracks -f - << EOF
    apiVersion: apimanagement.gloo.solo.io/v2
    kind: ApiDoc
    metadata:
      annotations:
        cluster.solo.io/cluster: ""
      name: tracks-rest-api-service
      namespace: tracks
    spec:
      openapi:
        # The YAML- or JSON-formatted OpenAPI v2 or v3 schema string to use for your API. 
        inlineString: '{"openapi":"3.0.3","info":{"title":"Catstronauts REST API","description":"REST API for Catstronauts to retrieve data for tracks, authors and modules.","version":"1.1.0"},"servers":[{"url":"/"}],"tags":[{"name":"Tracks","description":"A track is a collection of modules around a topic for catstronauts to learn about."},{"name":"Authors"},{"name":"Modules"}],"paths":{"/tracks":{"get":{"tags":["Tracks"],"summary":"Retrieves a list of tracks","responses":{"200":{"description":"Successful. Returns an array of Track objects.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Track"}},"examples":{"test-1":{"value":[{"id":"c_0","thumbnail":"https://res.cloudinary.com/dety84pbu/image/upload/v1598465568/nebula_cat_djkt9r.jpg","topic":"Cat-stronomy","authorId":"cat-1","title":"Cat-stronomy, an introduction","description":"Curious to learn what Cat-stronomy is all about? Explore the planetary and celestial alignments and how they have affected our space missions.","numberOfViews":163,"createdAt":"2018-09-10T07:13:53.020Z","length":2377,"modulesCount":10,"modules":["l_0","l_1","l_2","l_3","l_4","l_5","l_6","l_7","l_8","l_9"]},{"id":"c_1","thumbnail":"https://res.cloudinary.com/dety84pbu/image/upload/v1598474100/famous_cats_epuqcr.jpg","topic":"Famous Catstronauts","authorId":"cat-2","title":"Famous Catstronauts","description":"Be inspired by famous catstronauts who have made their names legend from across the galaxies. Special guest appearance included, so hold on to your boots!","numberOfViews":86,"createdAt":"2017-12-06T23:03:08.815Z","length":1916,"modulesCount":5,"modules":["l_10","l_11","l_12","l_13","l_14"]}]},"test-2":{"value":[{"id":"c_2","thumbnail":"https://res.cloudinary.com/dety84pbu/image/upload/v1598457117/spaceSuite_knkmu8.jpg","topic":"Kitty space suit","authorId":"cat-3","title":"Kitty space suit, all you need to know","description":"# Fidem dum accipit officio tactaeque extis caecaeque \n ## Caelo scilicet protulit \n Lorem markdownum et naides sumpserat nasci est vulnere mille comitesque \n praeterque crus, cur ruere, per nemus tanta dextra? Dente fluit adspeximus \n dempto, faciem, minimo parentali locorum! Unda an ergo equidem regia hac se est \n ira pugnantem. \n > Invenerit Solem agmine; aut voce melioris Lesbi. Lacrimas ad et, pendens quem, \n > ater venatrixque quis. Sed cacumina tulisti occasus, trisulcis multum, quid. \n > Quam Mercurium tergusque modo ubi, captis reddidit quae posse, rata popularis \n > inferni. \n ## Spatiosumque nigris \n Praemia qua simul fallitur cum et iuppiter inquit adversaque cutem, at dextera, \n alias. Scelus utque dolor, iuncta quamvis, hunc auceps celebrare coetu excussum \n deiectam. Videres nectar utque catenas una Granico corpore, verba Iovis \n intellectumque templum, domum dat et quod. Pedum quod cultusque versus magnorum \n ira ratis coepi conplexibus et armento summa non Dianae, dare ardor adire. \n Carens peperisse; omnem tenus, me sine. \n - Dare prior \n - Est incessit ille mirantum facta fiunt \n - Sed modo deprendit inpediunt sublime quiete \n ## Aeacus carpit hanc vestes senectus pocula \n Et novos esset genetrix glacies; inluxisse protecta, est ante consumptis, \n manumque, Phylius genitore caelarat herbosaque. Phoebus vulnera, clade debita, \n satiantur nefando. \n > Deprensi de velum alas Circaea quies perterrita si mota quam terres, sic si \n > res gerebam viros esse. Medullas ut tenax mandata classe amores vastius siqua, \n > sanabilis sed fiducia Leucon, capaci Orithyiae. Lumen terris digitis ac modo \n > sequentis Cereri te tulerit inspicitur! Subit veneno equi videt genua in \n > aetasque qui sanguisque, mihi flexit vivunt hamadryadas. \n ## At pater gestamina gravi forma \n Nec inter est adopertam nec, supernum et tecta: tapetibus? Genetrix sustinet \n heres pugnae usquam erectos in erant Achilles! \n Fuerat harenae me hiems Pholus tempus Phoebe. Geminis mihi vimen, in vidi \n pigetque in mole cruore, fugat dissuadet!","numberOfViews":61,"createdAt":"2020-04-20T13:59:10.470Z","length":1823,"modulesCount":5,"modules":["l_15","l_16","l_17","l_18","l_19"]}]}}}}}}}},"/tracks/{id}":{"get":{"tags":["Tracks"],"summary":"Find track by ID","description":"Returns a single track","parameters":[{"name":"id","in":"path","description":"Track ID","required":true,"schema":{"type":"string"},"examples":{"c_0":{"value":"c_0"}}}],"responses":{"200":{"description":"Successful. Returns a single track.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Track"},"examples":{"c_0":{"value":{"thumbnail":"https://res.cloudinary.com/dety84pbu/image/upload/v1598465568/nebula_cat_djkt9r.jpg","topic":"Cat-stronomy","authorId":"cat-1","title":"Cat-stronomy, an introduction","description":"Curious to learn what Cat-stronomy is all about? Explore the planetary and celestial alignments and how they have affected our space missions.","numberOfViews":163,"createdAt":"2018-09-10T07:13:53.020Z","length":2377,"modulesCount":10,"modules":["l_0","l_1","l_2","l_3","l_4","l_5","l_6","l_7","l_8","l_9"]}}}}}},"404":{"description":"Track not found.","content":{}}}}},"/tracks/{id}/modules":{"get":{"tags":["Tracks"],"summary":"Retrieves the list of modules for a given track","parameters":[{"name":"id","in":"path","description":"Track ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful. Returns the list of modules for a given track.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Module"}}}}},"404":{"description":"Track not found.","content":{}}}}},"/tracks/{id}/numberOfViews":{"patch":{"tags":["Tracks"],"summary":"Updates the number of views for a track","parameters":[{"name":"id","in":"path","description":"Track ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful. Returns the updated Track object.","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Track"}}}}},"404":{"description":"Track not found.","content":{}}}}},"/author/{id}":{"get":{"tags":["Authors"],"summary":"Find author by ID","description":"Returns a single author","parameters":[{"name":"id","in":"path","description":"Author ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful. Returns a single author.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Author"}}}},"404":{"description":"Author not found.","content":{}}}}},"/module/{id}":{"get":{"tags":["Modules"],"summary":"Find module by ID","description":"Returns a single module","parameters":[{"name":"id","in":"path","description":"Module ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Successful. Returns a single module.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Module"}}}},"404":{"description":"Module not found.","content":{}}}}}},"components":{"schemas":{"Track":{"type":"object","properties":{"id":{"type":"string"},"thumbnail":{"type":"string"},"topic":{"type":"string"},"authorId":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"numberOfViews":{"type":"integer"},"createdAt":{"type":"string"},"length":{"type":"integer"},"modulesCount":{"type":"integer"},"modules":{"type":"array","items":{"type":"string"}}}},"Author":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"photo":{"type":"string"}}},"Module":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"trackId":{"type":"string"},"authorId":{"type":"string"},"topic":{"type":"string"},"length":{"type":"integer"},"content":{"type":"string"},"videoUrl":{"type":"string"}}}}}}'
      servedBy:
      - destinationSelector:
        port:
          number: 5000
        selector:
          name: tracks-rest-api
          namespace: tracks
    EOF
      
  5. Describe one of the ApiDocs, and verify that the ApiDoc has the OpenAPI spec for the service.

      kubectl describe apidocs -n tracks
      

    Example output:

      ...
    Spec:
      Openapi:
        Inline String:  {"components":{"schemas":{"Author":{"properties":{"id":{"type":"string"},"name":{"type":"string"},"photo":{"type":"string"}},"type":"object"},"Module":{"properties":{"authorId":{"type":"string"},"content":{"type":"string"}