Version your APIs

Many times, you might have multiple versions of an API that you want to expose to end users. With Gloo Platform's flexibile approach to portal metadata, you can provide support phases, compatibility, usage plans, terms of service, licensing, and other lifecycle management information for each API version. Then, you can bundle multiple API versions into a single API product.

Before you begin

  1. Make sure that your cluster name is set as an environment variable.

    echo $CLUSTER_NAME
    
  2. Get the external address of the ingress gateway. If you deployed your ingress gateway in a different namespace or with a different version, update the command.

    export INGRESS_GW_IP=$(kubectl get svc -n gloo-mesh-gateways istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    echo $INGRESS_GW_IP
    
    export INGRESS_GW_IP=$(kubectl get svc -n gloo-mesh-gateways istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
    echo $INGRESS_GW_IP
    

    Note: Depending on your environment, you might see <pending> instead of an external IP address. For example, if you are testing locally in kind or minikube, or if you have insufficent permissions in your cloud platform, you can instead port-forward the service port of the ingress gateway:

    kubectl -n gloo-mesh-gateways port-forward deploy/istio-ingressgateway-1-20 8081
    

Step 1: Deploy two versions of your API

The following example application has two versions. In one version, the app returns the color blue. In the other version, the app returns the color green. Each app has its own workload and service.

  1. Create the Blue app. To review the service and deployment, see the GitHub source file.

    kubectl apply -f https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/main/policy-demo/color-app-blue.yaml
    
  2. Create the Green app. To review the service and deployment, see the GitHub source file.

    kubectl apply -f https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/main/policy-demo/color-app-green.yaml
    
  3. Verify that your color apps are running.

    kubectl get all -l app=color
    
  4. Create an ApiDoc resource for each app. An ApiDoc is a simple way to add an OpenAPI schema to your app. If your app has a path such as swagger.json or a remote URL to fetch the OpenAPI schema from, you could use automatic discovery instead. For more information, see Create your APIs

    kubectl apply -f - << EOF
    apiVersion: apimanagement.gloo.solo.io/v2
    kind: ApiDoc
    metadata:
      annotations:
        cluster.solo.io/cluster: ""
      name: color-blue
      namespace: default
      labels:
       app: color
       color: blue
    spec:
      openapi:
        # The YAML- or JSON-formatted OpenAPI v2 or v3 schema string to use for your API. 
        inlineString: '{"openapi":"3.0.0","info":{"title":"Blue Endpoint API","version":"1.0.0","description":"API for the /blue endpoint that returns the color of the serving pod."},"paths":{"/blue":{"get":{"summary":"Get the color of the serving pod","description":"Returns the color of the serving pod.","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"color":{"type":"string","description":"The color of the serving pod. This value is dynamically generated by the server."}}}}}}}}}}}'
      servedBy:
      - destinationSelector:
          port:
            number: 10000
          selector:
            cluster: $CLUSTER_NAME
            name: color-blue
            namespace: default
    EOF
    
    kubectl apply -f - << EOF
    apiVersion: apimanagement.gloo.solo.io/v2
    kind: ApiDoc
    metadata:
      annotations:
        cluster.solo.io/cluster: ""
      name: color-green
      namespace: default
      labels:
       app: color
       color: green
    spec:
      openapi:
        # The YAML- or JSON-formatted OpenAPI v2 or v3 schema string to use for your API. 
        inlineString: '{"openapi":"3.0.0","info":{"title":"Green Endpoint API","version":"1.0.0","description":"API for the /green endpoint that returns the color green."},"paths":{"/green":{"get":{"summary":"Get the color green","description":"Returns the color green as the response.","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"color":{"type":"string","example":"green","description":"The color green is returned as the response."}}}}}}}}}}}'
      servedBy:
      - destinationSelector:
          port:
            number: 10000
          selector:
            cluster: $CLUSTER_NAME
            name: color-green
            namespace: default
    EOF
    

  5. Verify that the ApiDocs are created with an OpenAPI spec for each of your color apps.

    kubectl get apidocs -o=jsonpath='{range .items[*]}[{.metadata.name}, {.spec.openapi.inlineString}]{"\n"}{end}' 
    

    Example output:

    [color-blue, {"openapi":"3.0.0","info":{"title":"Blue Endpoint API","version":"1.0.0","description":"API for the /blue endpoint that returns the color of the serving pod."},"paths":{"/blue":{"get":{"summary":"Get the color of the serving pod","description":"Returns the color of the serving pod.","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"color":{"type":"string","description":"The color of the serving pod. This value is dynamically generated by the server."}}}}}}}}}}}]
       
    [color-green, {"openapi":"3.0.0","info":{"title":"Green Endpoint API","version":"1.0.0","description":"API for the /green endpoint that returns the color green."},"paths":{"/green":{"get":{"summary":"Get the color green","description":"Returns the color green as the response.","responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{"color":{"type":"string","example":"green","description":"The color green is returned as the response."}}}}}}}}}}}]
    

Step 2: Set up portal routing to your APIs

You have two versions of your color app, blue and green. You can group these versions together into a single API product with lifecycle management details for your end users.

  1. Create a route table to represent each API version of your color apps.

    kubectl apply -f - << EOF
    apiVersion: networking.gloo.solo.io/v2
    kind: RouteTable
    metadata:
      name: color-blue
      namespace: gloo-mesh-gateways
      labels:
         portal: dev-portal
         app: color
         color: blue
    spec:
      http:
      - name: color-blue
        labels:
          usagePlans: dev-portal
          app: color
          color: blue
        matchers:
        - uri:
            prefix: /blue
        forwardTo:
          destinations:
          - ref:
              name: color-blue
              namespace: default
              cluster: $CLUSTER_NAME
            port:
              number: 10000
      portalMetadata:
        apiProductId: "color"
        apiProductDisplayName: "Colors API Product"
        apiVersion: "v1"
        title: "Color API v1"
        description: "The Color API tells you what color it is. The v1 version is blue."
        termsOfService: "Information about your Terms of Service."
        contact: "support@colors.com"
        license: "License info, such as MIT"
        lifecycle: "Deprecated"
        customMetadata:
          compatibility: "Forwards"
    EOF
    
    kubectl apply -f - << EOF
    apiVersion: networking.gloo.solo.io/v2
    kind: RouteTable
    metadata:
      name: color-green
      namespace: gloo-mesh-gateways
      labels:
         portal: dev-portal
         app: color
         color: green
    spec:
      http:
      - name: color-green
        labels:
          usagePlans: dev-portal
          app: color
          color: green
        matchers:
        - uri:
            prefix: /green
        forwardTo:
          destinations:
          - ref:
              name: color-green
              namespace: default
              cluster: $CLUSTER_NAME
            port:
              number: 10000
      portalMetadata:
        apiProductId: "color"
        apiProductDisplayName: "Colors API Product"
        apiVersion: "v2"
        title: "Color API v2"
        description: "The Color API tells you what color it is. The v2 version is green."
        termsOfService: "Information about your Terms of Service."
        contact: "support@colors.com"
        license: "License info, such as MIT"
        lifecycle: "Supported"
        customMetadata:
          compatibility: "Backwards"
    EOF
    

    Review the following table to understand this configuration. For more information, see the API docs.

    Setting Description
    Namespace Create the route table in the same namespace, or import it into the same Gloo workspace as the ingress gateway. In this example, the route table is in the same namespace as the ingress gateway, gloo-mesh-gateways.
    Labels Include labels to help select this route table with other portal resources later. This example has two labels. The portal: dev-portal label can be used to associate this route table as part of the dev-portal collection of Gloo resources, while the app: color labels can be used to associate this route table more specifically with the different Color APIs.
    HTTP name and labels Name your route and add a label that you can use to apply the policies of your usage plan to the route later. In this example, the Reviews routes have three labels: usagePlans: dev-portal, app: color, and a color label unique to each version.
    HTTP matchers and forwardTo for the route For each app that you want to expose APIs for, define the route matchers that you want the APIs to be available on. This example defines the /blue or /green route for each version. Then, these routes are available on the matching host, such as colors.com/blue or colors.com/green.
    Portal metadata A set of key-value pairs that describe your API, which you put together in the previous step. At a minimum, each route table for an API version must have a unique apiVersion but the same apiProductId to group the versions together. You can also include other portal metadata, as shown in the following example. Later, your developer portal displays this information in the end-user facing API documentation. For more information about each setting, see the API docs.
  2. Create a route table for the domain that you want your API products to be exposed on. This route table delegates the routing rules for matching HTTP routes to the route tables that you previously created. Note that the following example does not set any portal metadata, because that information is set per API product in the delegated route tables.

    kubectl apply -f - << EOF
    apiVersion: networking.gloo.solo.io/v2
    kind: RouteTable
    metadata:
      name: colors-com-rt
      namespace: gloo-mesh-gateways
    spec:
      hosts:
      - colors.com
      virtualGateways:
      - name: color-ingressgateway
        namespace: gloo-mesh-gateways
        cluster: $CLUSTER_NAME
      http:
      - matchers:
        - uri:
            prefix: /       
        delegate:
          routeTables:
            - labels:
                app: color
    EOF
    

    Review the following table to understand this configuration. For more information, see the API docs.

    Setting Description
    Namespace Create the route table in the same namespace or import it into the same Gloo workspace as the ingress gateway. In this example, the route table is in the same namespace as the ingress gateway, gloo-mesh-gateways.
    Hosts Add the host domains that you want the API products to be exposed on, such as colors.com.
    Virtual gateway Select the virtual gateway with the host that you want to use to expose your apps’ APIs. In this example, you select a virtual gateway that you create in the next step.
    HTTP matchers and delegations For each API product that you want to expose on the host domain, set up matchers and delegated route tables. In this example, requests that match / are delegated to the app: color route tables.
  3. Create a virtual gateway for the host domain that you want to expose your API products on. The following example configures a simple HTTP gateway. For more examples such as HTTPS/TLS, see Configure gateway listeners.

    kubectl apply -f - << EOF
    apiVersion: networking.gloo.solo.io/v2
    kind: VirtualGateway
    metadata:
      name: color-ingressgateway
      namespace: gloo-mesh-gateways
    spec:
      listeners:
        - port:
            number: 80
          http: {}
          allowedRouteTables:
            - host: colors.com
      workloads:
      - selector:
          labels:
            istio: ingressgateway
          cluster: $CLUSTER_NAME
    EOF
    

    Review the following table to understand this configuration. For more information, see the API docs.

    Setting Description
    Listener's allowed route tables Add the host domain that matches the route table for the API products that you want to expose. In this example, the colors.com matches the host in the domain-level route table that you created to expose together your Reviews API product.
  4. Verify that you can reach both versions of your color app. The following example sends a curl request to each of the API versions that you set up. Note that the routes are not yet secured. You secure the routes with rate limiting and external auth policies later as part of your portal's usage plan.

    • colors.com is the host that you set in both the domain-level route table and the virtual gateway.
    • /blue is the prefix that the domain-level route table delegates to the Blue route table.
    curl -v --resolve colors.com:80:${INGRESS_GW_IP} http://colors.com/blue
    

    Example output:

    < HTTP/1.1 200 OK
    ...
    "blue-pod"
    
    • colors.com is the host that you set in both the domain-level route table and the virtual gateway.
    • /green is the prefix that the domain-level route table delegates to the Green route table.
    curl -v --resolve colors.com:80:${INGRESS_GW_IP} http://colors.com/green
    

    Example output:

    < HTTP/1.1 200 OK
    ...
    "green-pod"
    

Step 3: Verify your API product in the frontend portal

Now, you have multiple versions of your API product. Your end users can review each API version's metadata, such as lifecycle management, as part of the API product in your frontend portal.

  1. Create a frontend developer portal.
  2. Interact with the developer portal as an end user to discover your API products.
  3. Verify that the Colors API Product has both API versions for blue and green.

Color API products in the frontend developer portal

Cleanup

You can optionally remove the resources that you set up as part of this guide.
  1. Delete your color apps.
    kubectl delete all -l app=color
    
  2. Delete the domain-level colors.com route table along with the delegated routes tables for the versions of your color apps.
    kubectl delete rt -n gloo-mesh-gateways colors-com-rt
    kubectl delete rt -n gloo-mesh-gateways color-blue
    kubectl delete rt -n gloo-mesh-gateways color-green
    
  3. Delete the virtual gateway for your colors.com domain.
    kubectl delete vg -n gloo-mesh-gateways color-ingressgateway