Skip to content
You are viewing the latest documentation for Solo Enterprise for kgateway. To access the documentation for older versions, use the version switcher.

For the complete documentation index, see llms.txt. Markdown versions of all docs pages are available by appending .md to any docs URL.

Create ApiProducts

Page as Markdown

Bundle your APIs into versioned ApiProducts and expose them in the portal catalog.

Note

This guide must be completed by a Portal admin.

An ApiProduct is a logical API offering that groups one or more versions of an API. Each version references an HTTPRoute that serves that version’s traffic. The portal controller automatically links the HTTPRoute’s backend services to their ApiDocs and stitches the schemas together into a single generated ApiDoc per version so that they can be rendered in the portal frontend.

You do not reference ApiDocs directly in an ApiProduct. The controller discovers them implicitly through the HTTPRoute’s backend services as shown in this diagram.

    flowchart LR
    APV[ApiProduct Version] -->|targetRefs| HR[HTTPRoute]
    HR -->|backendRefs| Svc[Service]
    AD[ApiDoc] -->|servedBy| Svc
    APV -.->|controller generates| SAD[Stitched ApiDoc]
  
  1. An ApiProduct version references one or more HTTPRoutes via the targetRefs field.
  2. The portal controller examines each HTTPRoute’s backendRefs to find the backend services.
  3. The portal controller finds the ApiDocs that are served by these services by using the servedBy field.
  4. The portal controller stitches the matching schemas together into a single generated ApiDoc per version.

Before you begin

  1. Follow the Get started guide to install Solo Enterprise for kgateway.
  2. Set up a portal.
  3. Create an ApiDoc for your service. The example in this guide uses the petstore app.

Create an ApiProduct

Create an ApiProduct and define one or more versions of your API. Each version references the HTTPRoute that serves that version of the API.

Single API version

Create an ApiProduct with a single version of the petstore API. The ApiProduct references the petstore HTTPRoute that you created before you began.

kubectl apply -f- <<EOF
apiVersion: portal.solo.io/v1alpha1
kind: ApiProduct
metadata:
  name: petstore-api
  namespace: default
spec:
  id: petstore
  displayName: "Petstore API"
  description: "A sample API for managing pets."
  contactEmail: "support@example.com"
  customMetadata:
    category: "Pet Management"
  versions:
  - name: v1
    targetRefs:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      name: petstore-route
    openApiMetadata:
      title: "Petstore API"
      description: "Manage your pets"
      termsOfService: "https://example.com/terms"
      contact: "support@example.com"
      license: "Apache-2.0"
    customMetadata:
      environment: "production"
EOF
SettingDescription
idA URL-safe unique identifier for the ApiProduct (1–128 characters). This ID is used to construct the API URL in the portal API catalog.
displayNameHuman-readable name for that API that is displayed in the portal UI.
descriptionOptional description of the API product (1–1024 characters) displayed in the portal UI.
contactEmailOptional contact email address (max 256 characters) displayed in the portal UI for questions about this API product.
customMetadataOptional arbitrary key-value pairs that are surfaced in the portal UI. You can have a maximum of 16 entries.
versions[].nameThe version identifier, such as v1 or v2.
versions[].targetRefsReference the HTTPRoutes that serve this version.
versions[].customMetadataOptional arbitrary key-value pairs of custom metadata for this specific version, surfaced in the portal UI. You can have a maximum of 16 entries.
versions[].openApiMetadataOptional metadata merged into the stitched OpenAPI schema for this version and displayed in the portal UI when you select this API version.
versions[].openApiMetadata.titleOptional title of the API version (1–256 characters), mapped to info.title in the stitched OpenAPI schema.
versions[].openApiMetadata.descriptionOptional description of the API version (1–1024 characters), mapped to info.description in the stitched OpenAPI schema.
versions[].openApiMetadata.termsOfServiceOptional URL to the terms of service for this API version (1–512 characters), mapped to info.termsOfService in the stitched OpenAPI schema.
versions[].openApiMetadata.contactOptional contact information for this API version (1–256 characters). A value that parses as an email is used as info.contact.email; a value that parses as a URL is used as info.contact.url; any other value is used as info.contact.name.
versions[].openApiMetadata.licenseOptional license name or SPDX identifier for this API version (1–256 characters), such as MIT or Apache-2.0. Mapped to info.license.name in the stitched OpenAPI schema.

Multiple API versions

An ApiProduct can expose multiple API versions simultaneously. Each version references its own HTTPRoute independently. The portal UI displays a version selector for products with multiple versions.

  1. Create a second HTTPRoute for the v2 version of the API. Make sure to use a unique matcher so that requests can be correctly routed to this version. The matcher must be different from the matcher that you use for the v1 version of the API.

    kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: petstore-v2-route
      namespace: default
    spec:
      parentRefs:
      - name: portal-gateway
        namespace: default
      hostnames:
      - "api.example.com"
      rules:
      - matches:
        - path:
            type: PathPrefix
            value: /petstore/v2
        filters:
        - type: URLRewrite
          urlRewrite:
            path:
              type: ReplacePrefixMatch
              replacePrefixMatch: /
        backendRefs:
        - name: petstore
          port: 8080
    EOF
  2. Create the ApiProduct and include both versions of your API.

    kubectl apply -f- <<EOF
    apiVersion: portal.solo.io/v1alpha1
    kind: ApiProduct
    metadata:
      name: petstore-api
      namespace: default
    spec:
      id: petstore
      displayName: "Petstore API"
      versions:
      - name: v1
        targetRefs:
        - group: gateway.networking.k8s.io
          kind: HTTPRoute
          name: petstore-route
        openApiMetadata:
          title: "Petstore API v1"
          description: "Manage your pets"
      - name: v2
        targetRefs:
        - group: gateway.networking.k8s.io
          kind: HTTPRoute
          name: petstore-v2-route
        openApiMetadata:
          title: "Petstore API v2"
          description: "Manage your pets (v2)"
    EOF
  3. Verify that a stichted ApiDoc is generated for each version of the API. Each version gets its own generated ApiDoc named <apiproduct-name>-<version-name>.

    kubectl get apidocs -A 

    Example output:

    NAMESPACE   NAME                  SOURCE     READY   AGE
    default     petstore-api-v1       Stitched   True    1m
    default     petstore-api-v2       Stitched   True    1m
    default     petstore-url-apidoc   Url        True    1m

Add the ApiProduct to the portal

Update the Portal resource to include the ApiProduct in its catalog. The portal controller regenerates the PortalConfig after you update the Portal.

Reference an ApiProduct in the same namespace as the Portal.

kubectl apply -f- <<EOF
apiVersion: portal.solo.io/v1alpha1
kind: Portal
metadata:
  name: my-portal
  namespace: default
spec:
  parametersRef:
    name: portal-params
  visibility:
    public: true
  apiProductRefs:
  - name: petstore-api
  - name: httpbin-api
EOF

Reference an ApiProduct in a different namespace by specifying the namespace field. Cross-namespace references require a ReferenceGrant in the target namespace to authorize the reference.

  1. Create a ReferenceGrant in the namespace where the ApiProduct lives (other-namespace) to allow the Portal in the default namespace to reference it.

    kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: ReferenceGrant
    metadata:
      name: portal-apiproduct-grant
      namespace: other-namespace
    spec:
      from:
      - group: portal.solo.io
        kind: Portal
        namespace: default
      to:
      - group: portal.solo.io
        kind: ApiProduct
    EOF
  2. Create the Portal and reference the ApiProduct in other-namespace.

    kubectl apply -f- <<EOF
    apiVersion: portal.solo.io/v1alpha1
    kind: Portal
    metadata:
      name: my-portal
      namespace: default
    spec:
      parametersRef:
        name: portal-params
      visibility:
        public: true
      apiProductRefs:
      - name: petstore-api
        namespace: other-namespace
      - name: httpbin-api
    EOF

Include all ApiProducts in a specific namespace by using a wildcard for the name field.

kubectl apply -f- <<EOF
apiVersion: portal.solo.io/v1alpha1
kind: Portal
metadata:
  name: my-portal
  namespace: default
spec:
  parametersRef:
    name: portal-params
  visibility:
    public: true
  apiProductRefs:
  - name: "*"
    namespace: default
EOF

Reference a specific ApiProduct across all namespaces by setting namespace: "*". Cross-namespace products still require a ReferenceGrant in each target namespace. Products in namespaces without a grant are silently skipped.

  1. Create a ReferenceGrant in each namespace that the Portal should be allowed to access.

    kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: ReferenceGrant
    metadata:
      name: portal-apiproduct-grant
      namespace: team-a
    spec:
      from:
      - group: portal.solo.io
        kind: Portal
        namespace: default
      to:
      - group: portal.solo.io
        kind: ApiProduct
    EOF
  2. Create the Portal with a namespace wildcard.

    kubectl apply -f- <<EOF
    apiVersion: portal.solo.io/v1alpha1
    kind: Portal
    metadata:
      name: my-portal
      namespace: default
    spec:
      parametersRef:
        name: portal-params
      visibility:
        public: true
      apiProductRefs:
      - name: petstore-api
        namespace: "*"
    EOF
  3. Review the Portal status to monitor which namespaces could not be added to the catalog due to missing ReferenceGrants.

    kubectl describe portal my-portal -n default
  1. Include all ApiProducts across all namespaces by setting both name and namespace to "*". You still need a ReferenceGrant for each namespace. ApiProducts in unauthorized namespaces are silently skipped.

    kubectl apply -f- <<EOF
    apiVersion: portal.solo.io/v1alpha1
    kind: Portal
    metadata:
      name: my-portal
      namespace: default
    spec:
      parametersRef:
        name: portal-params
      visibility:
        public: true
      apiProductRefs:
      - name: "*"
        namespace: "*"
    EOF
  2. Review the Portal status to monitor which namespaces could not be added to the catalog due to missing ReferenceGrants.

    kubectl describe portal my-portal -n default

Verify your ApiProduct

  1. List the ApiProducts and ApiDocs in your namespace. For each ApiProduct version, the controller generates a stitched ApiDoc that is named <apiproduct-name>-<version-name>.

    kubectl get apiproduct,apidoc -n default

    Example output:

    NAME                                     ID         DISPLAY NAME   READY
    apiproduct.portal.solo.io/petstore-api   petstore   Petstore API   True
    
    NAME                                        SOURCE     READY   AGE
    apidoc.portal.solo.io/petstore-api-v1       Stitched   True    24m
    apidoc.portal.solo.io/petstore-api-v2       Stitched   True    7m21s
    apidoc.portal.solo.io/petstore-url-apidoc   Url        True    22h
  2. If an ApiProduct does not show Ready=True, describe the resource to see the error details.

    kubectl describe apiproduct petstore-api -n default
  3. Verify that the PortalConfig was updated with the ApiProduct. The spec.apis field must contain an entry for each ApiProduct version and a reference to the generated stitched ApiDoc resource.

    kubectl get portalconfig my-portal -n default -o yaml

    Example output:

    ...
    spec:
      apis:
      - apiDocRef:
          name: petstore-api-v1
          namespace: default
        apiProductDisplayName: Petstore API
        apiProductId: petstore
        apiProductDescription: A sample API for managing pets.
        contact: support@example.com
        apiVersion: v1
        description: Manage your pets
        title: Petstore API v1
      - apiDocRef:
          name: petstore-api-v2
          namespace: default
        apiProductDisplayName: Petstore API
        apiProductId: petstore
        apiProductDescription: A sample API for managing pets.
        contact: support@example.com
        apiVersion: v2
        description: Manage your pets (v2)
        title: Petstore API v2
      - apiDocRef:
          name: httpbin-api-v1
          namespace: default
        apiProductCustomMetadata:
          category: Utilities
        apiProductDisplayName: HTTPBin API
        apiProductId: httpbin
        apiVersion: v1
        description: A simple HTTP request/response service for testing
        title: HTTPBin API
      portalMetadata:
        name: my-portal
Was this page helpful?