Part 1 - Create an API Product

The first part of the guide demonstrates publishing a simple API as an API Product to which HTTP requests can be routed.

In this guide, we’ll:

  1. Create an API Document from an OpenAPI Schema.
  2. Create an API Product from our API Document.
  3. Connect to our API through the Istio or Gloo Gateway.

You can find more information about terms like API Document and API Product in our Concepts section of the docs.

Prerequisites

For this guide, we’ll need the following:

Install API Backend

In this guide we’ll be using the OpenAPI Example Pet Store as the backend for our API Product.

To install the Pet Store to Kubernetes:

kubectl apply -n default -f \
  https://raw.githubusercontent.com/solo-io/gloo/v1.3.7/example/petstore/petstore.yaml
kubectl -n default rollout status deployment petstore

Then verify that then installation completed successfully:

deployment "petstore" successfully rolled out

Create an API Document

The next step in our process is to create an API Document based on the OpenAPI Schema defined by the Pet Store application. An API Document includes only the schema, and does not include any details on where the service is published or how to route to it.

The Pet Store application serves its Swagger File (OpenAPI Schema) via HTTP GET /swagger.json. Let’s register this schema with the Dev Portal operator by creating an APIDoc:

cat <<EOF | kubectl apply -f -
apiVersion: devportal.solo.io/v1alpha1
kind: APIDoc
metadata:
  name: petstore-schema
  namespace: default
spec:
  ## specify the type of schema provided in this APIDoc.
  ## can be either gRPC or openAPI  
  openApi:
    content:
      # we use a fetchUrl here to tell the dev portal
      # to fetch the schema contents directly from the petstore service.
      # 
      # configmaps and inline strings are also supported.
      fetchUrl: http://petstore.default:8080/swagger.json

EOF

Once the API Doc has been created, we can verify that the Dev Portal has processed it by checking its status:

kubectl get apidoc -n default petstore-schema -oyaml
apiVersion: devportal.solo.io/v1alpha1
kind: APIDoc
# ...truncated for brevity
status:
  description: A sample API that uses a petstore as an example to demonstrate features
    in the swagger-2.0 specification
  displayName: Swagger Petstore
  observedGeneration: "2"
  openApi:
    operations:
    - operationId: addPet
      path: /api/pets
      verb: POST
    - operationId: deletePet
      path: /api/pets/{id}
      verb: DELETE
    - operationId: findPetById
      path: /api/pets/{id}
      verb: GET
    - operationId: findPets
      path: /api/pets
      verb: GET
  state: Succeeded
  version: 1.0.0

When we see the Doc in a Succeeded state, it means its API operations can now be published as an API Product. You can also create an API Doc by using the Admin Dashboard.

Publish an API Product

Let’s create a simple API Product. API Products provide the means of bundling and publishing APIs with a given set of policies (defined as Usage Plans). An API Product can be selective about which operations in an API Document are exposed by the product.

The API Product we’ll be creating here has no Usage Plans defined, which means it will expose our API to unauthenticated traffic.

API Products also define the route(s) to a service that is serving the operations defined in the API Document. Routes can be specified on a per operation basis, or through a default route associated with the API Product.

The API Product we’ll be creating does not define any specific operations from the apiDoc, so all operations will be included.

Apply the API Product to the cluster:

cat << EOF | kubectl apply -f -
apiVersion: devportal.solo.io/v1alpha1
kind: APIProduct
metadata:
  name: petstore-product
  namespace: default

spec:

  apis:
  # Specify the API Doc(s) that will be included in the Product
  # each specifier can include a list of individual operations
  # to import from the API Doc.
  #
  # If none are listed, all the 
  # operations will be imported from the doc. 
  - apiDoc:
      name: petstore-schema
      namespace: default
  
  # Each imported operation must have a 'route' associated with it.
  # Routes can be specified on each imported operation, in the API Doc itself.
  # The Default Route provided here will be used for any operations which do not have a route defined.
  # A route must be provided for every Operation to enable routing for an API Product.  
  defaultRoute:
    inlineRoute:
      backends:
      - kube:
          name: petstore
          namespace: default
          port: 8080

  # To connect to this API Product, send HTTP requests to the Istio Gateway
  # with the Host header set to this domain.
  # This API Product will be served on the `api.example.com` domain.
  domains:
  - api.example.com

  displayInfo: 
    description: Petstore Product
    title: Petstore Product

EOF

You may receive the message bash: api.example.com: command not found after running the above command. This is expected and can be ignored.

We can verify that our product was accepted into the system by checking its status.state:

kubectl get apiproducts.devportal.solo.io -n default petstore-product -ojsonpath='{.status.state}'

The command should result in an output of Succeeded once the product has been created.

The complete status of an API Product gives detailed information, including the translated API Schema and parsed routing configurations rendered by the Dev Portal operator.

You can view the complete status by running:

kubectl get apiproducts.devportal.solo.io -n default petstore-product -oyaml

We can also confirm the Virtual Service which corresponds to our API Product:

kubectl get virtualservices.networking.istio.io -n default
NAME               GATEWAYS                              HOSTS                    AGE
petstore-product   [istio-system/istio-ingressgateway]   [api.example.com]        110m
kubectl get virtualservices.gateway.solo.io -n default
NAME               AGE
petstore-product   81m

You can also create an API Product by using the Admin Dashboard.

Test our API using cURL

Now that we have exposed our API Product for routing, we should be able to make client requests to the product APIs.

Let’s get the address of the Gateway. Choose the option corresponding to your Ingress Service Type:

export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}')
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
export INGRESS_HOST=$(kubectl -n gloo-system get service gateway-proxy -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
export INGRESS_PORT=$(kubectl -n gloo-system get service gateway-proxy -o jsonpath='{.spec.ports[?(@.name=="http")].port}')
export INGRESS_HOST=$(kubectl get po -l gloo=gateway-proxy -n gloo-system -o jsonpath='{.items[0].status.hostIP}')
export INGRESS_PORT=$(kubectl -n gloo-system get service gateway-proxy -o jsonpath='{.spec.ports[?(@.name=="http")].nodePort}')

With the Ingress address, we can now try to call one of our published operations:

curl "http://${INGRESS_HOST}:${INGRESS_PORT}/api/pets" -H "Host: api.example.com"

We should see the output:

[{"id":1,"name":"Dog","status":"available"},{"id":2,"name":"Cat","status":"pending"}]

Great! We’ve just seen how the Developer Portal can publish an API on Istio and Gloo Gateways without you needing to directly configure those resources. Let’s now see how to expose our APIs to developers using the Portal resource.

Next steps

Continue on to part 2 of the Getting Started guide to see how the Developer Portal can generate and publish a developer-facing website with documentation and tooling for interacting with these APIs.

Questions

For any questions using the Developer Portal, please visit the Solo.io slack channel at https://slack.solo.io.

If you’d like to report an issue or bug, please see the Dev Portal Issues Repository on GitHub.