Best Practices How-tos products Tanzu Application Platform

How to Curate and Manage Your APIs in Tanzu Application Platform

The process of building, deploying, and publishing APIs often requires multiple tools and manual steps. Even more effort is necessary to keep customer-facing APIs, a domain-focused abstraction, away from any implementation details. With a public API, it can get difficult to evolve the implementation without disturbing the public contract of the API. 

To solve these problems and to make it simpler for our users, we are introducing API curation as an alpha feature with the latest release of the API auto registration package in Tanzu Application Platform 1.7. With API auto registration, you can curate how your APIs get exposed to external users. Whether it is an existing workload within Tanzu Application Platform already getting auto-registered, an external static API, or an API in the process of getting onboarded into Tanzu Application Platform.

Note: The API curation feature is in alpha and is intended for evaluation and test purposes only. We encourage experimentation and testing, but the API curation feature is not yet ready to be used in a production environment.

Here are some of the benefits of using curated APIs:

  • Multiple APIs can be curated to form a single, cohesive curated API

  • All routing will be automatically generated and managed by the API auto registration controller if a compatible Spring Cloud Gateway instance is present and matched 

  • With the presence of Spring Cloud Gateway comes the many possibilities of Spring Cloud Gateway filters and predicates to enhance the API

Try out API curation

In this section, we will be demonstrating how you can curate an API from multiple sources into one.

Create a new API-producing app

Let’s begin by leveraging the Tanzu Application Platform accelerators. Navigate to the Accelerators tab in Tanzu Developer Portal and choose the Tanzu Java Restful Web App accelerator. Make sure to select the Expose OpenAPI endpoint? checkbox. Modify the rest of the fields to your preference or leave them with the defaults. You have the option to create a new repository to store this generated project now or do it after downloading the project files. Review all the details and generate the project and files. After downloading, you will see a workload.yaml file already generated under the config folder. You can read more about this project and its files inside the README.md file.  

Before deploying the app, we need to make sure to have a PostgreSQL instance ready in the cluster. You can do this by creating a service ClassClaim for your workload:

tanzu service class-claim create customer-database --class postgresql-unmanaged

And you can check the database state and proceed when the claim is in Ready state:

tanzu services class-claims get customer-database

Next, we can apply this workload in the cluster for the pipeline to deploy the app and apply the APIDescriptor in the cluster:

tanzu apps workload apply -f config/workload.yaml

Once the workload is done and the app is ready, you should see an API Descriptor in your configured cluster. This API Descriptor should be in Ready state and the API should already be registered on Tanzu Developer Portal’s API tab.

kubectl get APIDescriptor -A

Connect an existing external API

Next, we will connect an existing API that lives outside of Tanzu Application Platform into the platform using the API Descriptor. For this example, we are using the Petstore API. We add the same details like we did in our workload.yaml for owner, system, type, etc. Additionally, we list the server.url as the location where the external Petstore API is served from. Since the API specification lives under a path within the same URL, we can simply list the apiSpec.path. If in your case, the API spec lives outside of the API, you can configure an apiSpec.url in addition to the apiSpec.path as the full location where the API spec lives.

apiVersion: apis.apps.tanzu.vmware.com/v1alpha1

kind: APIDescriptor

metadata:

  name: pet-store

  namespace: pet

spec:

  type: openapi

  owner: pet-store-department

  system: profile-management

  description: Manage pet store

  location:

    apiSpec:

      path: "/openapi.json"

    server:

      url: https://petstore3.swagger.io/api/v3

Create a file named petstore-api.yaml, add the content above, and apply it your cluster with the following command:

kubectl apply -f path/to/file/petstore-api.yaml

Now you should see two API Descriptors in your cluster, both in Ready state.

kubectl get APIDescriptor -A

Curate the APIs into one

With these two API Descriptors in Ready state, we will now be able to combine the two using the CuratedAPIDescriptor CR and connect them to a Spring Cloud Gateway to generate routing. Before we curate, let’s get the gateway configured and ready. Since Tanzu Application Platform only includes Spring Cloud Gateway as an optionally installed package, you might need to install the package before proceeding.

In your gateway configuration, ensure that the version and groupId used under .spec.api match the same properties in the CuratedAPIDescriptor .spec. It is important to check that the version and groupId are the same for both Spring Cloud Gateway and CuratedAPIDescriptor because it is used internally to find and match the two. Below is the configuration for Spring Cloud Gateway and an Ingress to expose the gateway. Make sure to replace all the instances of <TAP-INGRESS_DOMAIN> with the correct domain for your cluster.

apiVersion: "tanzu.vmware.com/v1"

kind: SpringCloudGateway

metadata:

  name: profile-management

spec:

  api:

    title: Pet Store Profile Management

    description: Pet store Profiles API

    version: 1.2.3

    groupId: profile-management

    serverUrl: http://profile-management.<TAP-INGRESS_DOMAIN>

    cors:

      allowedOrigins:

        - "http://tap-gui.<TAP-INGRESS_DOMAIN>"

        - "http://api-portal.<TAP-INGRESS_DOMAIN>"

      allowedMethods:

        - "GET"

        - "PUT"

        - "POST"

      allowedHeaders:

        - '*'

---

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:<

  name: profile-management

spec:

  ingressClassName: contour

  rules:

    - host: profile-management.<TAP-INGRESS_DOMAIN>

      http:

        paths:

          - path: /

            pathType: Prefix

            backend:

              service:

                name: profile-management

                port:

                  number: 80

Now that gateway is applied in the cluster, let’s proceed with curating our API! There are a few details to call out in the configuration. We configure Spring Cloud Gateway as the route provider using the annotations. Next, we need to match the groupId and version to the ones we configured in the gateway. Finally, we can list all the APIs we want to curate into one. Since we are using Spring Cloud Gateway, each of the API Descriptors with Spring Cloud Gateway–specific filters wherever necessary. For more information on all the available features, you can check out the documentation. In this example, we will be using the RateLimit filter that limits the number of successful requests to 3 per minute. 

apiVersion: apis.apps.tanzu.vmware.com/v1alpha1

kind: CuratedAPIDescriptor

metadata:

  name: profile-management

  annotations:

    "apis.apps.tanzu.vmware.com/route-provider": "spring-cloud-gateway"

spec:

  title: Pet Store

  type: openapi

  groupId: profile-management

  version: 1.2.3

  apiDescriptors:

    - name: customer-profile

      namespace: my-apps

      pathPrefix: /customer

      routeConfig:

        filters: ["RateLimit=3,1m"]

    - name: pet-store

      namespace: curation

      pathPrefix: /pet

After you apply the above curated API into your cluster, you will start seeing SpringCloudGatewayRouteConfig and SpringCloudGatewayMapping objects getting created in your cluster. 

kubectl get scgm -A

NAMESPACE   NAME                          AGE

my-apps     profile-management-92384b18   1m

my-apps     profile-management-9aa58a54   1m


kubectl get scgrc -A


NAMESPACE   NAME                          AGE

my-apps     profile-management-92384b18   1m

my-apps     profile-management-9aa58a54   1m

Once all the resources are created, your curated API will be marked as Ready.

kubectl get curatedapidescriptor -A

NAMESPACE  NAME                 STATUS   CURATED API SPEC URL

my-apps    profile-management   Ready    http://api-auto-registration.<TAP-INGRESS-DOMAIN>/openapi/my-apps/profile-management

Test the curated API

Let’s make API calls directly to test the curation.

First, create a customer profile:

curl -X POST -H 'Content-Type: application/json'
http://profile-management.<TAP_INGRESS_DOMAIN>/customer/api/customer-profiles/ -d '{"firstName": "Joe", "lastName": "Doe", "email": "[email protected]"}'

Now, when you execute the query using curl, you will see the newly created customer: 

curl -X GET
http://profile-management.<TAP_INGRESS_DOMAIN>/customer/api/customer-profiles/

You can also verify that the RateLimit filter is correctly set up by sending more than 3 requests in 1 minute and seeing an HTTP status code of 429. Let’s send the same command a handful of times in quick succession to see the status code:

curl -X GET
http://profile-management.<TAP_INGRESS_DOMAIN>/customer/api/customer-profiles/

Finally, let’s see the whole curated API specification as one. The OpenAPI should be visible under the API Auto Registration controller:

curl -X GET
http://api-auto-registration.<TAP_INGRESS_DOMAIN>/openapi/

In the output, you will see the full curated API’s specification. If you have “API portal for VMware” running, you can also add the above URL as a source URL for a rich interactive view of the API.

More info and links

For more information, see the docs detailing more information

Do you want to learn more about what Spring can offer? Check out Spring Academy.

Broadcom makes no guarantee that services announced in preview, alpha, or beta will become available at a future date. The information in this blog post is for informational purposes only and may not be incorporated into any contract.