Create a portal
Create the backend and frontend of your developer portal.
Previously, you bundled your apps into ApiProducts. Now, you configure the backend and frontend of your developer portal to serve the ApiProducts to your end users.
Before you begin
Complete the API product tutorial.
Create the backend portal
Create a Portal that configures the host domain on which you want to expose your ApiProducts to end users.
Step 1: Create the portal
Create a Portal custom resource. You create the Portal in the same namespace as the ApiProducts. This way, you do not need to create a Kubernetes ReferenceGrant to let the Portal refer to the ApiProducts.
kubectl apply -n gloo-system -f- <<EOF apiVersion: portal.gloo.solo.io/v1 kind: Portal metadata: name: portal-developer namespace: gloo-system spec: visibility: public: true apiProducts: - name: tracks-svc-api-product namespace: gloo-system - name: petstore-svc-api-product namespace: gloo-system EOF
Review the following table to understand this configuration.
Field Description metadata Note that the Portal is created in the same namespace as the portal server and ApiProducts, gloo-system
. If your Portal is in a different namespace, you must create a Kubernetes ReferenceGrant to let the Portal refer to the portal server’s Service and the ApiProducts.visibility Decide whether the ApiProducts in the portal are visible to all users (public APIs) or if the ApiProducts are hidden until the user successfully authenticates (private APIs). The default value is false
to set up private APIs. The example sets the value totrue
so that any user can view the ApiProductsapiProducts Select the ApiProducts to include in the portal. Check the status of your ApiProducts. Notice that the ApiProducts are now
ACCEPTED
because you created a portal that selects them.kubectl get apiproducts -n gloo-system -o yaml | grep status -A5
Example output:
status: state: State: approval: ACCEPTED message: SUCCESS observedGeneration: 2 -- status: state: State: approval: ACCEPTED message: SUCCESS observedGeneration: 1
Check the ApiDocs again. Notice that Gloo automatically generated an ApiDoc that includes the stitched schema of all the paths that are exposed by each matcher of the HTTPRoutes for each ApiProduct in the same
gloo-system
namespace as the Portal. For example, you have one stitched schema for the 3 services that are part of the Petstore ApiProduct.kubectl get apidocs -A
Example output:
NAMESPACE NAME AGE gloo-system store-route-gloo-system-stitched-openapi 10s gloo-system tracks-route-gloo-system-stitched-openapi 10s pets pets-rest-api-service 26m store store-rest-api-service 26m tracks tracks-rest-api-service 26m users users-rest-api-service 26m
Check that Gloo automatically generated a PortalConfig resource. The PortalConfig is an internal resource that Gloo uses to combine the stitched schema of the ApiDoc, the portal metadata of each ApiProduct, and the other details such as visibility and host domain for your Portal.
kubectl describe portalconfigs -n gloo-system
Example output:
Name: portal-developer-gloo-system Namespace: gloo-system Labels: portal.gloo.solo.io/gc_label=gloo-system Annotations: <none> API Version: internal.gloo.solo.io/v2 Kind: PortalConfig Spec: Apis: API Id: petstore-v1 API Product Display Name: Pet Store API Product Id: petstore API Schema: Name: pets-route-gloo-system-stitched-openapi Namespace: gloo-system API Version: v1 Contact: support@example.com Custom Metadata: Compatibility: None Description: Totally awesome API for all things pets! License: License info, such as MIT Lifecycle: Supported Terms Of Service: You must authenticate to use this API! And other Terms of Service. Title: Pet Store REST API API Id: tracks-v1 API Product Display Name: Catstronauts Course Tracks API Product Id: tracks API Schema: Name: tracks-route-gloo-system-stitched-openapi Namespace: gloo-system API Version: v1 Contact: support@example.com Custom Metadata: Compatibility: None Description: REST API for Catstronauts to retrieve data for tracks, authors and modules. License: License info, such as MIT Lifecycle: Supported Terms Of Service: You must authenticate to use this API! And other Terms of Service. Title: Catstronauts REST API Domains: developer.example.com Portal Ref: Name: portal-developer Namespace: gloo-system Public: true Status: Common: State: Approval: ACCEPTED Message: SUCCESS
Step 2: Create a route to the portal
Create an HTTPRoute for the backend portal. The HTTPRoute maps your Kubernetes Gateway with the backend portal server and the host domain that you want your backend portal to be available on. You create the HTTPRoute in the same namespace as the portal server. This way, you do not need to create a Kubernetes ReferenceGrant to let the HTTPRoute refer to the portal server’s Service.
kubectl apply -n gloo-system -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: portal-backend-route namespace: gloo-system spec: parentRefs: - name: http namespace: gloo-system hostnames: - developer.example.com rules: - backendRefs: - name: gateway-portal-web-server namespace: gloo-system port: 8080 EOF
Confirm that the route references are resolved.
kubectl get httproutes -n gloo-system portal-backend-route -o yaml
Example output:
[...] - lastTransitionTime: "2024-04-17T18:54:53Z" message: "" observedGeneration: 2 reason: ResolvedRefs status: "True" type: ResolvedRefs
Good job! You set up the backend of your developer portal. The backend means that your ApiProducts are exposed on a backend-facing host, developer.example.com
, that your internal services use to route and protect requests to the backing API services.
Next, you can set up a frontend portal.
Create the frontend portal
The frontend portal is the web user interface (UI) application that your end users access. In the portal, your end users can discover and authenticate to use your ApiProducts.
Gloo provides a sample React app that you can use as a starting point to develop your own frontend application. This frontend app displays the information that your Portal resource pulls together: the API products and usage plans that you want to expose, along with additional metadata. Because this information is controlled by the Portal resource, you don’t have to update the frontend app as often after the initial setup.
Deploy the
dev-portal-starter
sample React app. For more information, see the GitHub project. Notice that the portal server URL environment variable is set with thedeveloper.example.com
route that you previously created for the backend portal.kubectl apply -n gloo-system -f- <<EOF apiVersion: v1 kind: ServiceAccount metadata: name: portal-frontend namespace: gloo-system --- apiVersion: v1 kind: Service metadata: name: portal-frontend namespace: gloo-system labels: app: portal-frontend service: portal-frontend spec: ports: - name: http port: 4000 targetPort: 4000 selector: app: portal-frontend --- apiVersion: apps/v1 kind: Deployment metadata: name: portal-frontend namespace: gloo-system spec: replicas: 1 selector: matchLabels: app: portal-frontend template: metadata: labels: app: portal-frontend spec: serviceAccountName: portal-frontend containers: - image: gcr.io/solo-public/docs/portal-frontend:latest imagePullPolicy: Always name: portal-frontend args: ["--host", "0.0.0.0"] ports: - containerPort: 4000 env: - name: VITE_PORTAL_SERVER_URL value: http://developer.example.com:8080/v1 # The URL that the backend Portal is exposed on via an HTTPRoute. EOF
Verify that the frontend app is running.
kubectl get all -n gloo-system -l app=portal-frontend
Create a RouteOption for a CORS filter. Notice that the RouteOption is in the same namespace as the HTTPRoute for the backend portal server. This way, the frontend portal app can communicate with the backend portal server. The CORS filter allows origin from your local host for development purposes along with the URL that you want the frontend portal to be available on,
portal.example.com
.kubectl apply -n gloo-system -f- <<EOF apiVersion: gateway.solo.io/v1 kind: RouteOption metadata: name: portal-cors namespace: gloo-system spec: options: cors: allowOrigin: - http://localhost:4000 - http://127.0.0.1:4000 - http://portal.example.com - http://portal.example.com:8080 allowHeaders: - "Content-Type" - "Authorization" - "Access-Control-Allow-Origin" allowMethods: - GET - POST - PUT - DELETE - OPTIONS allowCredentials: true EOF
Update the HTTPRoute of the backend portal server to apply the RouteOption with the CORS filter.
kubectl apply -n gloo-system -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: portal-backend-route namespace: gloo-system spec: parentRefs: - name: http namespace: gloo-system hostnames: - developer.example.com rules: - backendRefs: - name: gateway-portal-web-server namespace: gloo-system port: 8080 filters: - type: ExtensionRef extensionRef: group: gateway.solo.io kind: RouteOption name: portal-cors EOF
Create an HTTPRoute for the frontend portal app. The route matches the same route that the CORS filter allows originating traffic from,
portal.example.com
. Your end users can access the frontend portal app on this route. You create the HTTPRoute in the same namespace as the frontend portal app. This way, you do not need to create a Kubernetes ReferenceGrant to let the HTTPRoute refer to the frontend portal app’s Service.kubectl apply -n gloo-system -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: portal-frontend-route namespace: gloo-system spec: parentRefs: - name: http namespace: gloo-system hostnames: - portal.example.com rules: - backendRefs: - name: portal-frontend namespace: gloo-system port: 4000 EOF
Verify that the frontend route is created. In the status section, check for
Accepted
andResolvedRefs
in the reason output.kubectl get httproute portal-frontend-route -n gloo-system -o yaml | grep "status" -A15
You are almost there! You have all the pieces for a basic developer portal set up. Now, you can check out the portal as an end user.
Explore the portal
Explore how your end users can use the developer portal to discover, access, and use your API products. Because you set the portal visibility to public and did not enforce authentication, you can review all the pages that are available in the web UI.
To have the routing for the frontend portal work on your local machine, update your
/etc/hosts
to map the IP address of the Kubernetes Gateway to the routes that you created for your APIs, portal backend, and portal frontend. If you are using an actual domain that you own to serve the frontend app, you can skip this step.sudo nano /etc/hosts
Replace
18.xxx.xxx.xx
with the value of the IP address of your gateway.- For gateways with an IP address such as in GCP, get the
EXTERNAL-IP
of the service by runningkubectl get svc -n gloo-system gloo-proxy-http
. - For gateways that use a load balancer host address such as in AWS, get the
EXTERNAL-IP
of the service by runningkubectl get svc -n gloo-system gloo-proxy-http
. Then, get the backing IP address of the load balancer by runningdig <loadbalancer-external-IP-host-address>
.
18.xxx.xxx.xx portal.example.com 18.xxx.xxx.xx developer.example.com 18.xxx.xxx.xx api.petstore.com 18.xxx.xxx.xx api.tracks.com
- For gateways with an IP address such as in GCP, get the
In your browser, open the web UI of the frontend portal app, http://portal.example.com:8080/.
When you open the web UI, you might see the following message:no healthy upstream
. The portal frontend app is probably still in process. View the logs until you see a message that indicates that the portal frontend app is available. The process can take a few minutes. To view the logs, runkubectl logs -n gloo-system deploy/portal-frontend
.open http://portal.example.com:8080/
From the menu bar, click the APIs tab. You find the two ApiProducts that you created in this tutorial. Note that the portal metadata that you configured is shown for the description, version, tags, and other information.
Click the Pet Store REST API. You can review the OpenAPI spec for each route in the ApiProduct, for
pet
,store
, anduser
. To get a JSON file of the OpenAPI spec from either view, click Download.Click Swagger View to toggle the view from Redocly to Swagger.
Good job! You set up and explored the developer portal.