Create Applications and APIs
In this section, you're going to create an Application
called bookinfo
and attach an API to it. The API will configure the application ingress
based on the contents of an OpenAPI spec.
Applications in TSB are logical groupings of Services that expose the different
features and use cases for the application. For example, the Bookinfo application
is composed by the productpage
, reviews
, ratings
and details
services, and
their different features can be accessed through the productpage
HTTP endpoints.
Applications belong to a Tenant and can be used to observe the
behavior of the services as well as to configure how those services and their APIs can be consumed.
They do this by exposing a set of API objects that define what is
available in the Application and the conditions that need to be met to consume those features.
OpenAPI is a widely adopted standard to define and describe HTTP APIs. It allows defining metadata for the APIs, describe the endpoints, how they behave and how users should interact with them. TSB leverages this information to automatically configure the Application Ingress Gateway and expose the hostnames defined in the OpenAPI spec and configure routes for all the endpoints.
In this tutorial we'll see the basics for Application and API creation. Once these concepts are clear, you will be able to create your own Applications and APIs and apply more sophisticated configuration such Authentication, rate-limiting, etc. The Application Gateway provides an in-depth example of such configurations.
Before you get started, make sure you:
✓ Familiarize yourself with TSB concepts
✓ Install the TSB demo environment
✓ Deploy the Istio Bookinfo sample app
✓ Create a Tenant
✓ Create a Workspace
✓ Setup an Ingress Gateway
Creating the Application
Create the following application.yaml
:
apiversion: application.tsb.tetrate.io/v2
kind: Application
metadata:
organization: tetrate
tenant: tetrate
name: bookinfo
spec:
displayName: Bookinfo
description: Bookinfo application
workspace: organizations/tetrate/tenants/tetrate/workspaces/bookinfo-ws
gatewayGroup: organizations/tetrate/tenants/tetrate/workspaces/bookinfo-ws/gatewaygroups/bookinfo-gw
Apply with tctl
:
tctl apply -f application.yaml
This will create the bookinfo
Application and link it to the given workspace and
use existing Gateway Group bookinfo-gw
that you have created previously to create
Ingress Gateway resources for your APIs. More details over the created resources can be configured as
explained in the Application reference.
You can verify the application has been created properly with:
tctl get applicationstatus bookinfo --tenant tetrate -o yaml
apiVersion: application.tsb.tetrate.io/v2
kind: ApplicationStatus
metadata:
name: bookinfo
organization: tetrate
tenant: tetrate
spec:
resources:
- resource:
fqn: organizations/tetrate/tenants/tetrate/workspaces/bookinfo-ws
status: CONFIGURED
- resource:
exclusivelyOwned: true
fqn: organizations/tetrate/tenants/tetrate/workspaces/bookinfo-ws/gatewaygroups/bookinfo
status: CONFIGURED
status: CONFIGURED
This will show that the gateway group for the application has been properly created.
You will see the underlying resources with the CONFIGURED
status, confirming they have
been properly created. If there were some issues, the status would reflect that accordingly.
Attaching an OpenAPI spec
Once the Application object has been defined you can start attaching OpenAPI specs to expose different APIs in the application's Ingress Gateway. At this point, the Ingress Gateway has been deployed to the cluster but no configuration has been applied to it. In this step we'll be configuring it with an OpenAPI spec.
Create the following bookinfo-api.yaml
:
apiversion: application.tsb.tetrate.io/v2
kind: API
metadata:
organization: tetrate
tenant: tetrate
application: bookinfo
name: bookinfo
spec:
displayName: Bookinfo API
description: Bookinfo API
workloadSelector:
namespace: bookinfo
labels:
app: tsb-gateway-bookinfo
openapi: |
openapi: 3.0.0
info:
description: This is the API of the Istio BookInfo sample application.
version: 1.0.0
title: BookInfo API
termsOfService: https://istio.io/
license:
name: Apache 2.0
url: http://www.apache.org/licenses/LICENSE-2.0.html
x-tsb-service: productpage.bookinfo
servers:
- url: http://bookinfo.tetrate.com/api/v1
tags:
- name: product
description: Information about a product (in this case a book)
- name: review
description: Review information for a product
- name: rating
description: Rating information for a product
externalDocs:
description: Learn more about the Istio BookInfo application
url: https://istio.io/docs/samples/bookinfo.html
paths:
/products:
get:
tags:
- product
summary: List all products
description: List all products available in the application with a minimum amount of
information.
operationId: getProducts
responses:
"200":
description: successful operation
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Product"
"/products/{id}":
get:
tags:
- product
summary: Get individual product
description: Get detailed information about an individual product with the given id.
operationId: getProduct
parameters:
- name: id
in: path
description: Product id
required: true
schema:
type: integer
format: int32
responses:
"200":
description: successful operation
content:
application/json:
schema:
$ref: "#/components/schemas/ProductDetails"
"400":
description: Invalid product id
"/products/{id}/reviews":
get:
tags:
- review
summary: Get reviews for a product
description: Get reviews for a product, including review text and possibly ratings
information.
operationId: getProductReviews
parameters:
- name: id
in: path
description: Product id
required: true
schema:
type: integer
format: int32
responses:
"200":
description: successful operation
content:
application/json:
schema:
$ref: "#/components/schemas/ProductReviews"
"400":
description: Invalid product id
"/products/{id}/ratings":
get:
tags:
- rating
summary: Get ratings for a product
description: Get ratings for a product, including stars and their color.
operationId: getProductRatings
parameters:
- name: id
in: path
description: Product id
required: true
schema:
type: integer
format: int32
responses:
"200":
description: successful operation
content:
application/json:
schema:
$ref: "#/components/schemas/ProductRatings"
"400":
description: Invalid product id
components:
schemas:
Product:
type: object
description: Basic information about a product
properties:
id:
type: integer
format: int32
description: Product id
title:
type: string
description: Title of the book
descriptionHtml:
type: string
description: Description of the book - may contain HTML tags
required:
- id
- title
- descriptionHtml
ProductDetails:
type: object
description: Detailed information about a product
properties:
id:
type: integer
format: int32
description: Product id
publisher:
type: string
description: Publisher of the book
language:
type: string
description: Language of the book
author:
type: string
description: Author of the book
ISBN-10:
type: string
description: ISBN-10 of the book
ISBN-13:
type: string
description: ISBN-13 of the book
year:
type: integer
format: int32
description: Year the book was first published in
type:
type: string
enum:
- paperback
- hardcover
description: Type of the book
pages:
type: integer
format: int32
description: Number of pages of the book
required:
- id
- publisher
- language
- author
- ISBN-10
- ISBN-13
- year
- type
- pages
ProductReviews:
type: object
description: Object containing reviews for a product
properties:
id:
type: integer
format: int32
description: Product id
reviews:
type: array
description: List of reviews
items:
$ref: "#/components/schemas/Review"
required:
- id
- reviews
Review:
type: object
description: Review of a product
properties:
reviewer:
type: string
description: Name of the reviewer
text:
type: string
description: Review text
rating:
$ref: "#/components/schemas/Rating"
required:
- reviewer
- text
Rating:
type: object
description: Rating of a product
properties:
stars:
type: integer
format: int32
minimum: 1
maximum: 5
description: Number of stars
color:
type: string
enum:
- red
- black
description: Color in which stars should be displayed
required:
- stars
- color
ProductRatings:
type: object
description: Object containing ratings of a product
properties:
id:
type: integer
format: int32
description: Product id
ratings:
type: object
description: A hashmap where keys are reviewer names, values are number of stars
additionalProperties:
type: string
required:
- id
- ratings
Apply with tctl
:
tctl apply -f bookinfo-api.yaml
This will generate an Ingress Gateway configuration for the application's ingress based on the contents of the OpenAPI spec. It will use the hostnames defined in the spec to expose them in the ingress as well as the information of the endpoints to configure the sources for the different services.
Additionally, TBS provides a set of OpenAPI extensions to further customize the Ingress Gateway and add TLS settings, rate limiting, authentication, and more.
In this case, the Ingress Gateway will be configured as follows:
- The API will be exposed at
http://bookinfo.tetrate.com/api/v1
, as defined in theservers
section of the OpenAPI spec. - The following endpoints will be configured in the Ingress Gateway and routed to the
service defined in the x-tsb-service
extension.
GET /products
GET /products/{id}
GET /products/{id}/reviews
GET /products/{id}/ratings
As you can see, TSB allows you to configure a fully-functional Application Ingress Gateway by merely
defining a small application and its OpenAPI spec. The OpenAPI spec itself required one small
extension (x-tsb-service
) to describe the routing configuration that should be performed by TSB.
The value of the x-tsb-service
annotation, productpage.bookinfo
in our example, corresponds
to the name of the service in the Service Registry.
This allows users to configure APIs for logical services without having to worry about where those
services are running. TSB will figure out routing and multi-cluster configuration automatically.
To verify that all resources have been created, you can run the following command:
tctl get apistatus bookinfo --tenant tetrate --application bookinfo -o yaml
apiVersion: application.tsb.tetrate.io/v2
kind: APIStatus
metadata:
application: bookinfo
name: bookinfo
organization: tetrate
tenant: tetrate
spec:
resources:
- resource:
exclusivelyOwned: true
expectedEtag: '"Tll5vTzdQ2U="'
fqn: organizations/tetrate/tenants/tetrate/workspaces/bookinfo-ws/gatewaygroups/bookinfo/ingressgateways/bookinfo
status: CONFIGURED
status: CONFIGURED
This will show the status of all the resources that have been implicitly created by TSB to configure the Ingress Gateway.
At this point, the Ingress Gateway is configured and serving the API described in the OpenAPI spec.
Testing
Let's try making an HTTP request to one of the endpoints exposed by the API. In the following example, since you do not
control bookinfo.tetrate.com
, you will have to trick curl
into thinking that bookinfo.tetrate.com
resolves to the IP
address of the Application Ingress Gateway.
Obtain the IP address of the Application Ingress Gateway that you previously created using the following command.
kubectl -n bookinfo get service tsb-gateway-bookinfo -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
Then execute the following command to send HTTP requests to the Bookinfo application service through the Ingress Gateway.
Replace the gateway-ip
with the value you obtained in the previous step.
curl -v http://bookinfo.tetrate.com/api/v1/products \
--resolve "bookinfo.tetrate.com:80:<gateway-ip>" \
-H "X-B3-Sampled: 1"
> GET /api/v1/products HTTP/1.1
> Host: bookinfo.tetrate.com
> User-Agent: curl/7.77.0
> Accept: */*
>
< HTTP/1.1 200 OK
< content-type: application/json
< content-length: 395
< server: istio-envoy
< date: Tue, 16 Nov 2021 13:17:43 GMT
< x-envoy-upstream-service-time: 4
<
[{"id": 0, "title": "The Comedy of Errors", "descriptionHtml": "<a href=\"https://en.wikipedia.org/wiki/The_Comedy_of_Errors\">Wikipedia Summary</a>: The Comedy of Errors is one of <b>William Shakespeare's</b> early plays. It is his shortest and one of his most farcical comedies, with a major part of the humour coming from slapstick and mistaken identity, in addition to puns and word play."}]