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 
✓ Configure Permissions 
✓ Setup an Ingress Gateway 
✓ Checking service topology and metrics 
✓ Configured Traffic Shifting 
✓ Configured Security Controls
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 x status application bookinfo --tenant tetrate -o yaml
apiVersion: api.tsb.tetrate.io/v2
kind: ResourceStatus
metadata:
  name: bookinfo
  organization: tetrate
  tenant: tetrate
spec:
  aggregatedStatus:
    configEvents:
      events:
      - etag: '"ug2aIYaGkkQ="'
        timestamp: "2023-01-10T14:18:21.489344736Z"
        type: TSB_ACCEPTED
  message: Waiting for the configuration to be accepted by MPC
  status: ACCEPTED
This will show that the gateway group for the application has been properly created.
You will see the underlying resources with the ACCEPTED 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, TSB 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 theserverssection 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 x status api bookinfo --application bookinfo --tenant tetrate -o yaml
apiVersion: api.tsb.tetrate.io/v2
kind: ResourceStatus
metadata:
  application: bookinfo
  name: bookinfo
  organization: tetrate
  tenant: tetrate
spec:
  aggregatedStatus:
    children:
      organizations/tetrate/tenants/tetrate/workspaces/bookinfo-ws/gatewaygroups/bookinfo-gw/ingressgateways/bookinfo:
        status: READY
  message: all dependencies are ready
  status: READY
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 (or the hostname in AWS case) of the Application Ingress Gateway that you previously created using the following command.
- Standard
- OpenShift
export GATEWAY_IP=$(kubectl -n bookinfo get service tsb-gateway-bookinfo -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}")
export GATEWAY_IP=$(oc -n bookinfo get service tsb-gateway-bookinfo -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}")
Then execute the following command to send HTTP requests to the Bookinfo application service through the Ingress Gateway.
curl -v http://bookinfo.tetrate.com/api/v1/products \
     --connect-to "bookinfo.tetrate.com:80:$GATEWAY_IP"
> 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."}]