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:
- Create an API Document from an OpenAPI Schema.
- Create an API Product from our API Document.
- Create an Environment to expose our API Product
- Connect to our API through the Istio or Gloo Edge.
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:
curl
kubectl
- A compatible Kubernetes cluster setup (1.16 or higher), to which you can connect via
kubectl
- One of the following Gateway technologies installed to your cluster, either:
- Gloo Edge Enterprise 1.9 or higher;
- Istio 1.15 or higher;
- The Gloo Portal installed to your cluster. Please refer to the setup guide for detailed installation instructions.
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.9.0-beta8/example/petstore/petstore.yaml
kubectl -n default rollout status deployment petstore
Then verify that the 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 Gloo Portal operator by creating an APIDoc:
cat <<EOF | kubectl apply -f -
apiVersion: portal.gloo.solo.io/v1beta1
kind: APIDoc
metadata:
name: petstore-schema
namespace: default
spec:
## specify the type of schema provided in this APIDoc.
## openApi is only option at this time.
openApi:
content:
# we use a fetchUrl here to tell the Gloo 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 Gloo Portal has processed it by checking its status
:
kubectl get apidoc -n default petstore-schema -oyaml
apiVersion: portal.gloo.solo.io/v1beta1
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 included in an API Product.
You can also create an API Doc by using the Admin Dashboard.
Gloo Portal requires the operationId
field on all of the operations
in an OpenAPI document. While this field is
optional in the OpenAPI specification, Gloo Portal uses it to assign API Documents to API Products.
An operation without an operationId will cause the API Document to enter the Invalid
state.
Create an API Product
Let's create a simple API Product. API Products provide the means of bundling APIs into a Version. Each Version in an API Product can be selective about which operations in an API Document are exposed by the product version.
The API Product we'll be creating here will have a single version called v1
and it will include all operations from the Pet Store API Doc we just created.
API Product versions 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 version.
The route configuration depends on the type of gateway technology we are using.
For Gloo Edge Enterprise, the preferred way of configuring a routing destination is to use an
Upstream.
If you have Upstream Discovery
configured in Gloo Edge, then you should already have an Upstream
for the petstore
service.
If not, we can easily create one:
cat << EOF | kubectl apply -f -
apiVersion: gloo.solo.io/v1
kind: Upstream
metadata:
name: default-petstore-8080
namespace: gloo-system
spec:
kube:
serviceName: petstore
serviceNamespace: default
servicePort: 8080
EOF
This assumes that you have installed Gloo Edge Enterprise to the gloo-system
namespace, or that the namespace is
watched by Gloo Edge. You should adapt the above configuration if that is not the case.
Now we can create our APIProduct
and use the Upstream
as a backend for out route:
cat << EOF | kubectl apply -f -
apiVersion: portal.gloo.solo.io/v1beta1
kind: APIProduct
metadata:
name: petstore-product
namespace: default
labels:
app: petstore
spec:
displayInfo:
description: Petstore Product
title: Petstore Product
# Specify one or more version objects that will each include a list
# of APIs that compose the version and routing for the version
versions:
- name: v1
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.
# Here we define a route that will be used by default for all the selected APIProduct version operations.
# You can also set overrides for this route on each individual operation.
# A route must be provided for every Operation to enable routing for an API Product.
gatewayConfig:
route:
inlineRoute:
backends:
- upstream:
name: default-petstore-8080
namespace: gloo-system
# You can add arbitrary tags to an APIProduct version.
# Users will be able to search for APIs based on the available tags when they log into a portal application.
tags:
stable: {}
EOF
If you are integrating Gloo Portal with Istio directly, the simplest way of configuring a route is to just reference the Kubernetes service you want to send traffic to.
cat << EOF | kubectl apply -f -
apiVersion: portal.gloo.solo.io/v1beta1
kind: APIProduct
metadata:
name: petstore-product
namespace: default
labels:
app: petstore
spec:
displayInfo:
description: Petstore Product
title: Petstore Product
# Specify one or more version objects that will each include a list
# of APIs that compose the version and routing for the version
versions:
- name: v1
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.
# Here we define a route that will be used by default for all the selected APIProduct version operations.
# You can also set overrides for this route on each individual operation.
# A route must be provided for every Operation to enable routing for an API Product.
gatewayConfig:
route:
inlineRoute:
backends:
- kube:
name: petstore
namespace: default
port: 8080
# You can add arbitrary tags to an APIProduct version.
# Users will be able to search for APIs based on the available tags when they log into a portal application.
tags:
stable: {}
EOF
We can verify that our product was accepted into the system by checking its status.state
:
kubectl get apiproducts.portal.gloo.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.
You can view the complete status by running:
kubectl get apiproducts.portal.gloo.solo.io -n default petstore-product -oyaml
You can also create an API Product by using the Admin Dashboard.
Create an Environment
The final piece of the puzzle is to create an Environment that will expose our API Product version. The Environment resource defines domains on which to expose the API Products, the versions of an API Product to expose, and a Usage Plan for each API Product. The Usage Plan includes authentication and rate limiting. We will not be defining a Usage Plan for our Pet Store API Product, so unauthenticated access will be allowed.
We are going to create an Environment named dev
using the domain api.example.com
and expose v1
of our Pet Store API Product.
cat << EOF | kubectl apply -f -
apiVersion: portal.gloo.solo.io/v1beta1
kind: Environment
metadata:
name: dev
namespace: default
spec:
domains:
# If you are using Gloo Edge and the Gateway is listening on a port other than 80,
# you need to include a domain in this format: <DOMAIN>:<PORT>.
- api.example.com
displayInfo:
description: This environment is meant for developers to deploy and test their APIs.
displayName: Development
# This field will determine which APIProduct versions are published in this Environment.
# Each entry represents a selector which contains criteria to match the desired API product versions.
# Here we use a single selector that will match all APIProducts with the 'app: petstore' label in all namespaces;
# Additionally, we want to select only version of these APIProducts that contain the 'stable' tag.
apiProducts:
- namespaces:
- "*"
labels:
- key: app
operator: Equals
values:
- petstore
versions:
tags:
- stable
EOF
We can check on the status of our Environment by running the following:
kubectl get environment -n default dev -ojsonpath='{.status.state}'
The command should result in an output of Succeeded
once the Environment has been created.
The complete status of an Environment gives detailed information, including the translated API Schema and parsed routing configurations rendered by the Gloo Portal operator.
You can view the complete status by running:
kubectl get environments.portal.gloo.solo.io -n default dev -oyaml
We can also confirm the Virtual Service which corresponds to our Environment:
kubectl get virtualservices.gateway.solo.io -n default
NAME AGE
dev 81m
kubectl get virtualservices.networking.istio.io -n default
NAME GATEWAYS HOSTS AGE
dev ["istio-system/istio-ingressgateway"] ["api.example.com"] 3m25s
You can also create an Environment 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:
- Gloo Edge - External Load Balancer
- Gloo Edge - Docker for Desktop / Node port
- Gloo Edge - Kind Cluster with Node Port
- Istio - External Load Balancer
- Istio - Docker for Desktop / Node port
- Istio - Kind Cluster with Node Port
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}')
export INGRESS_HOST=127.0.0.1
export INGRESS_PORT=$(kubectl -n gloo-system get service gateway-proxy -o jsonpath='{.spec.ports[?(@.name=="http")].nodePort}')
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}')
For more help on getting the Ingress address, see https://istio.io/docs/tasks/traffic-management/ingress/ingress-control/#determining-the-ingress-ip-and-ports
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}')
For more help on getting the Ingress address, see https://istio.io/docs/tasks/traffic-management/ingress/ingress-control/#determining-the-ingress-ip-and-ports
export INGRESS_HOST=127.0.0.1
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
For more help on getting the Ingress address, see https://istio.io/docs/tasks/traffic-management/ingress/ingress-control/#determining-the-ingress-ip-and-ports
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 Gloo Portal can publish an API on Istio and Gloo Edge 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 Gloo Portal can generate and publish a developer-facing website with documentation and tooling for interacting with these APIs.
Questions
For any questions using the Gloo 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 Gloo Portal Issues Repository on GitHub.