API Version
Manage the life cycle of the API, handling multiple versions.
Introduction
API versioning is crucial for managing changes, updates, and improvements to APIs over time. Traefik Hub provides robust support for effectively managing multiple API versions while maintaining backward compatibility and supporting existing clients.
The APIVersion Object
The APIVersion object represents a specific version of an API within Traefik Hub. It allows API owners to effectively manage the lifecycle of their APIs.
When creating a new APIVersion object, you must reference it in its parent API's versions
field.
You can expose an APIVersion using the same mechanism as exposing an API, either through an Ingress or IngressRoute annotation: hub.traefik.io/api-version
.
An API and its APIVersions must be part of the same namespace.
Example
Let's start with an existing API exposed through an Ingress.
- API
- Ingress
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: flight-api
namespace: apps
spec:
openApiSpec:
path: /openapi.json
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: flight-ingress
namespace: apps
annotations:
hub.traefik.io/api: flight-api
spec:
rules:
- http:
paths:
- pathType: Prefix
path: /flight
backend:
service:
name: flight-service
port:
number: 8080
Now, see an example of how you can add two versions to this API, each attached to different Ingresses with the routing mechanism of your choice. Then, the API object only needs to reference its supported versions. Note that the previous API object now references its versions.
- API
- API Version 1
- Ingress 1
- API Version 2
- Ingress 2
apiVersion: hub.traefik.io/v1alpha1
kind: API
metadata:
name: flight-api
namespace: apps
spec:
# Remove the openApiSpec section
versions: # Reference the versions (assumed to be in the same namespace)
- name: flight-api-v1
- name: flight-api-v2
apiVersion: hub.traefik.io/v1alpha1
kind: APIVersion
metadata:
name: flight-api-v1
namespace: apps
spec:
title: "Flight API v1.0.0"
release: v1.0.0
openApiSpec:
path: /openapi.json
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: flight-ingress
namespace: apps
annotations:
hub.traefik.io/api-version: flight-api-v1
spec:
rules:
- http:
paths:
- pathType: Prefix
path: /flight
backend:
service:
name: flight-service
port:
number: 8080
apiVersion: hub.traefik.io/v1alpha1
kind: APIVersion
metadata:
name: flight-api-v2
namespace: apps
spec:
title: "Flight API v2.0.0"
release: v2.0.0
openApiSpec:
path: /openapi.json
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: flight-ingress
namespace: apps
annotations:
hub.traefik.io/api-version: flight-api-v2
spec:
rules:
- http:
paths:
- pathType: Prefix
path: /flight/v2
backend:
service:
name: flight-v2-service
port:
number: 8080
And that's it!
Operation Filtering
Operation filtering allows you to restrict user groups to specific OpenAPI operations.
Here's how it works:
- Define OperationSets: OperationSets are named collections of OpenAPI operations. For example, you might create an operationSet called "admin" that includes operations to delete customers and retrieve customer statistics, and another called "support" that includes operations to retrieve a list of all customers.
- Configure APIAccess: Once you've defined your
operationSets
, you can reference them in your APIAccess configurations. For instance, you might grant access to the "admin" operationSet to members of the "admin" group and access to the "support" operationSet to members of the "support" group.
OperationSets
An operationSet
is composed of:
- A name, which will be referenced in the APIAccess.
- A matcher to select the API operation(s) to be included in the
operationSet
.
Here are examples of how to define operationSets using different matchers:
- Path
- Path Prefix
- Path Regex
- Only HTTP Method(s)
# Example of versioning an API using `path` for URI path.
apiVersion: hub.traefik.io/v1alpha1
kind: APIVersion
metadata:
name: my-flights-api-v2
namespace: apps
spec:
release: v2.0.0
title: "An awesome title for this release, like a cheese name"
openApiSpec:
path: /api/v2/openapi.json
operationSets:
- name: flight-operations
matchers:
- path: /flights
# Example of versioning an API using `pathPrefix` for URI path.
apiVersion: hub.traefik.io/v1alpha1
kind: APIVersion
metadata:
name: my-flights-api-v2
namespace: apps
spec:
release: v2.0.0
title: "An awesome title for this release, like a cheese name"
openApiSpec:
path: /api/v2/openapi.json
operationSets:
- name: flight-operations
matchers:
- pathPrefix: /flights
# Example of versioning an API using `pathRegex` for URI path.
apiVersion: hub.traefik.io/v1alpha1
kind: APIVersion
metadata:
name: my-flights-api-v2
namespace: apps
spec:
release: v2.0.0
title: "An awesome title for this release, like a cheese name"
openApiSpec:
path: /api/v2/openapi.json
operationSets:
- name: flight-operations
matchers:
- pathRegex: /flights/.*/number
apiVersion: hub.traefik.io/v1alpha1
kind: APIVersion
metadata:
name: my-flights-api-v2
namespace: apps
spec:
release: v2.0.0
title: "An awesome title for this release, like a cheese name"
openApiSpec:
path: /api/v2/openapi.json
operationSets:
- name: flight-operations
matchers:
methods:
- GET
- POST
- Only one of the following path settings is allowed:
path
,pathPrefix
, orpathRegex
. - You can use the
methods
option without specifying a path setting (path
,pathPrefix
, orpathRegex
). - You can combine a path setting with the
methods
option. - The
pathRegex
must match both the OpenAPI specification and the request. For example, the request to/flights/:id
shouldn't be expressed by/flights/[0-9]+
but by/flights/.+
to satisfy both/flights/{flightID}
in the OAS specification and/flights/2
in the actual user request.
Please note the subtle difference between configuring one matcher with multiple options and configuring multiple matchers. The examples below illustrate the difference in the syntax.
- One Matcher
- Two Matchers
operationSets:
- name: read-pets
matchers:
- pathPrefix: /pets
methods:
- GET
operationSets:
- name: read-or-path
matchers:
- pathPrefix: /pets
- methods:
- GET
Without a Defined HTTP Method
The following example shows an API CRD using an operation matcher with pathPrefix
, without any HTTP method defined.
This would allow all HTTP methods matching the /flights
path prefix.
For example, GET /flights
, GET /flights/{id}
, POST /flights
, PUT /flights/{id}
.
# Example of versioning an API using `pathPrefix` for URI path.
apiVersion: hub.traefik.io/v1alpha1
kind: APIVersion
metadata:
name: my-flights-api-v2
namespace: apps
spec:
release: v2.0.0
title: "An awesome title for this release, like a cheese name"
openApiSpec:
path: /api/v2/openapi.json
operationSets:
- name: flight-operations
matchers:
- pathPrefix: /flights
Every Matcher Option Must Align
The next example shows an API CRD using one matcher
with two options.
One doing path prefix filtering and one doing method filtering.
Both options must be fulfilled.
Setting two options, one with pathPrefix
and the other with methods
(act as a logical AND).
This allows GET
for all operations matching the /flights
path prefix.
For example, GET /flights
, GET /flights/{id}
, GET /flights/findByStatus
.
apiVersion: hub.traefik.io/v1alpha1
kind: APIVersion
metadata:
name: my-flights-api-v2
namespace: apps
spec:
release: v2.0.0
title: "An awesome title for this release, like a cheese name"
openApiSpec:
path: /api/v2/openapi.json
operationSets:
- name: read-flights
matchers:
- pathPrefix: /flights
methods:
- GET
One of the Two Matchers Must Match
The next example shows an API CRD using a combination of two matchers
.
One doing path prefix filtering and the other doing method filtering.
One of the matchers must fulfil.
Setting two matchers, one with pathPrefix
and the other with methods
(act as a logical OR).
This allows all operations matching the /flights
path prefix.
This allows GET
operations on all endpoints of the API
For example, POST /flights
, GET /airports/{id}
.
apiVersion: hub.traefik.io/v1alpha1
kind: APIVersion
metadata:
name: my-flights-api-v2
namespace: apps
spec:
release: v2.0.0
title: "An awesome title for this release, like a cheese name"
openApiSpec:
path: /api/v2/openapi.json
operationSets:
- name: read-flights
matchers:
- pathPrefix: /flights
- methods:
- GET