Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7ccedea
expanding externalCerts to support configMaps
Gazza7205 Mar 30, 2026
273c04f
added support for policy/service aliases, sampleMessages and policyBa…
Gazza7205 Apr 8, 2026
7b12e1f
added retry scenario for failed applies where a new commit is detected
Gazza7205 Apr 9, 2026
37a6fdb
updated ingress and service reconcile
Gazza7205 Apr 10, 2026
d56a59f
added graphman constraint to listenPorts for management connection
Gazza7205 Apr 10, 2026
86b2410
added additional checks and logs for repositories
Gazza7205 Apr 10, 2026
59e4bf5
updated logs, refactored temp paths
Gazza7205 Apr 13, 2026
b53525c
added checks for init configuration where an empty repository is used
Gazza7205 Apr 15, 2026
f92c43b
updated handling for root level bundles in repositories that have no …
Gazza7205 Apr 15, 2026
8d73b46
added additional checks for commits
Gazza7205 Apr 16, 2026
f2ec943
updated statestore repository handling
Gazza7205 Apr 17, 2026
ef90490
removed redundant repository conditions
Gazza7205 Apr 20, 2026
9b9dff4
added additional checks and validation for invalid repository bundles…
Gazza7205 Apr 21, 2026
4269978
added additional logging for invalid entities
Gazza7205 Apr 22, 2026
40dc1c9
added gateway startup probe
Gazza7205 Apr 22, 2026
8a02415
added merge condition for serviceResolutionConfigs
Gazza7205 Apr 22, 2026
4748e6e
fix tests
Gazza7205 Apr 22, 2026
081ed58
updated dependencies, set gateway version to 11.2.1
Gazza7205 Apr 22, 2026
fd3ae33
rebuilt config
Gazza7205 Apr 22, 2026
6bc4946
updated redis connection handling
Gazza7205 Apr 23, 2026
3a2752d
updated examples - gateway v11.2.1, graphman-static-init 1.0.5, opera…
Gazza7205 Apr 23, 2026
1587dd8
updated dual mode otk examples, removed unused otk schema
Gazza7205 Apr 24, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "~1.24.13"
go-version: "~1.26.1"
- name: Setup kind
env:
KIND_VERSION: "0.30.0"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/integration_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: "~1.24.13"
go-version: "~1.26.1"
- name: Configure Git
run: |
git config user.name "$GITHUB_ACTOR"
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ docker-secret.yaml
tenant_info.json
example/repositories/local-tests
example/gateway/local-tests
example/state-store/local-tests
example/base/resources/configmaps/cassandra
.vscode

Expand Down
4 changes: 2 additions & 2 deletions Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ pipeline {
agent { label "default" }
environment {
ARTIFACTORY_DOCKER_IMS_IMAGE_REG = "ims-base-images-docker-release-local.usw1.packages.broadcom.com"
ARTIFACTORY_DOCKER_IMS_IMAGE = "ims-distro-debian13-static:202510"
ARTIFACTORY_DOCKER_IMS_IMAGE = "ims-distro-debian13-static:202603"
ARTIFACTORY_DOCKER_GO_IMAGE_REG = "docker-hub.usw1.packages.broadcom.com"
ARTIFACTORY_DOCKER_DEV_LOCAL_REG_HOST = "apim-docker-dev-local.usw1.packages.broadcom.com"
ARTIFACT_HOST = "${ARTIFACTORY_DOCKER_DEV_LOCAL_REG_HOST}"
Expand Down Expand Up @@ -63,7 +63,7 @@ pipeline {
docker login ${ARTIFACTORY_DOCKER_IMS_IMAGE_REG} -u ${ARTIFACTORY_DEV_LOCAL_USERNAME} -p ${ARTIFACTORY_DEV_LOCAL_APIKEY}
docker login ${ARTIFACTORY_DOCKER_GO_IMAGE_REG} -u ${ARTIFACTORY_DEV_LOCAL_USERNAME} -p ${ARTIFACTORY_DEV_LOCAL_APIKEY}
DISTROLESS_IMG=${ARTIFACTORY_DOCKER_IMS_IMAGE_REG}/${ARTIFACTORY_DOCKER_IMS_IMAGE}
GO_BUILD_IMG=${ARTIFACTORY_DOCKER_GO_IMAGE_REG}/golang:1.24
GO_BUILD_IMG=${ARTIFACTORY_DOCKER_GO_IMAGE_REG}/golang:1.26
cat Dockerfile | sed -e "s~DISTROLESS_IMG~${DISTROLESS_IMG}~g" | sed -e "s~GO_BUILD_IMG~${GO_BUILD_IMG}~g" > operator.Dockerfile
docker buildx build -f operator.Dockerfile -t ${ARTIFACTORY_DOCKER_DEV_LOCAL_REG_HOST}/${IMAGE_TAG_BASE}:${RELEASE_VERSION} --builder "${DOCKER_BUILDER_NAME}" --platform="${TARGET_PLATFORMS}" --build-arg TITLE="${IMAGE_NAME}" --build-arg COPYRIGHT="${COPYRIGHT}" --build-arg VERSION="${RELEASE_VERSION}" --build-arg CREATED="${CREATED}" --build-arg GOPROXY="${GOPROXY}" . --push
'''
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ START_KIND_CLUSTER ?= true
KUBE_VERSION ?= 1.34
KIND_CONFIG ?= kind-$(KUBE_VERSION).yaml

GATEWAY_IMG ?= docker.io/caapim/gateway:11.1.3
GO_BUILD_IMG ?= golang:1.24
GATEWAY_IMG ?= docker.io/caapim/gateway:11.2.1
GO_BUILD_IMG ?= golang:1.26
DISTROLESS_IMG ?= gcr.io/distroless/static:nonroot
GO_PROXY ?= ""

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Layer7 Gateway Operator
The Layer7 Gateway Operator, built using the [Operator SDK](https://github.com/operator-framework/operator-sdk) covers all aspects of deploying, maintaining and upgrading API Gateways in Kubernetes.

##### Note: The Operator examples currently use ***Gateway 11.1.3*** as a base.
##### Note: The Operator examples currently use ***Gateway 11.2.1*** as a base.

## [Getting Started](https://github.com/CAAPIM/layer7-operator/wiki/Getting-Started)
## [Additional Documentation](https://github.com/CAAPIM/layer7-operator/wiki)
Expand Down
25 changes: 9 additions & 16 deletions api/v1/gateway_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,7 @@ type App struct {
ExternalSecrets []ExternalSecret `json:"externalSecrets,omitempty"`
ExternalKeys []ExternalKey `json:"externalKeys,omitempty"`
ExternalCerts []ExternalCert `json:"externalCerts,omitempty"`
StartupProbe corev1.Probe `json:"startupProbe,omitempty"`
LivenessProbe corev1.Probe `json:"livenessProbe,omitempty"`
ReadinessProbe corev1.Probe `json:"readinessProbe,omitempty"`
CustomConfig CustomConfig `json:"customConfig,omitempty"`
Expand Down Expand Up @@ -344,9 +345,6 @@ type PortalReference struct {
type Otk struct {
// Enable or disable the OTK initContainer
Enabled bool `json:"enabled,omitempty"`
// ManageCrossNamespace allows a cluster-wide layer7 operator to manage internal/dmz gateways across namespaces
// this is limited to a single kubernetes cluster.
ManageCrossNamespace bool `json:"manageCrossNamespace,omitempty"`
// InitContainerImage for the initContainer
InitContainerImage string `json:"initContainerImage,omitempty"`
// InitContainerImagePullPolicy
Expand Down Expand Up @@ -392,16 +390,9 @@ type OtkMaintenanceTasks struct {
}

type GatewayReference struct {
// Name of the gateway
// if managing otk gateways across namespaces this must match the referenced gateway CR
Name string `json:"name,omitempty"`
// Namespace of the referenced gateway if managing gateways cross namespace (optional)
Namespace string `json:"namespace,omitempty"`
// Url of the target gateway
// used for post-installation gateway policy configuration
Url string `json:"url,omitempty"`
// Port of the target gateway
Port int `json:"port,omitempty"`
}

type OtkOverrides struct {
Expand Down Expand Up @@ -720,7 +711,7 @@ type Graphman struct {
// Service
type Service struct {
// Enabled or disabled
Enabled bool ` json:"enabled,omitempty"`
Enabled bool `json:"enabled,omitempty"`
// Annotations for the service
Annotations map[string]string `json:"annotations,omitempty"`
// Type ClusterIP, NodePort, LoadBalancer
Expand Down Expand Up @@ -885,15 +876,17 @@ const (
RevocationCheckPolicyTypeSpecified RevocationCheckPolicyType = "SPECIFIED"
)

// ExternalCert is a reference to an existing TLS or Opaque Secret in Kubernetes
// The Layer7 Operator will attempt to convert this secret to a Graphman bundle that can be applied
// ExternalCert is a reference to an existing TLS or Opaque Secret or ConfigMap in Kubernetes
// The Layer7 Operator will attempt to convert this to a Graphman bundle that can be applied
// dynamically keeping any referenced trusted certs up-to-date.
// You can bring in external secrets using tools like cert-manager
// You can bring in external certs using tools like cert-manager
type ExternalCert struct {
// Enabled or disabled
Enabled bool `json:"enabled,omitempty"`
// Name of the Secret which already exists in Kubernetes
Name string `json:"name,omitempty"`
// Name of the Secret or ConfigMap which already exists in Kubernetes
Name string `json:"name,omitempty"`
// Type of the referenced resource: "secret" (default) or "configmap"
Type string `json:"type,omitempty"`
VerifyHostname bool `json:"verifyHostname,omitempty"`
TrustedFor []TrustedFor `json:"trustedFor,omitempty"`
TrustAnchor bool `json:"trustAnchor,omitempty"`
Expand Down
42 changes: 14 additions & 28 deletions api/v1/gateway_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"strings"

v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/intstr"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
Expand All @@ -34,52 +33,39 @@ import (
//var gatewaylog = logf.Log.WithName("gateway-resource")

func (r *Gateway) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
return ctrl.NewWebhookManagedBy(mgr, r).
WithDefaulter(r).
WithValidator(r).
Complete()
}

//+kubebuilder:webhook:path=/mutate-security-brcmlabs-com-v1-gateway,mutating=true,failurePolicy=fail,sideEffects=None,groups=security.brcmlabs.com,resources=gateways,verbs=create;update,versions=v1,name=mgateway.kb.io,admissionReviewVersions=v1

var _ admission.CustomDefaulter = &Gateway{}
var _ admission.Defaulter[*Gateway] = &Gateway{}

// Default implements webhook.Defaulter so a webhook will be registered for the type
func (r *Gateway) Default(ctx context.Context, obj runtime.Object) error {
// Default implements admission.Defaulter for *Gateway.
func (r *Gateway) Default(ctx context.Context, obj *Gateway) error {
return nil
}

//+kubebuilder:webhook:path=/validate-security-brcmlabs-com-v1-gateway,mutating=false,failurePolicy=fail,sideEffects=None,groups=security.brcmlabs.com,resources=gateways,verbs=create;update,versions=v1,name=vgateway.kb.io,admissionReviewVersions=v1

var _ admission.CustomValidator = &Gateway{}
var _ admission.Validator[*Gateway] = &Gateway{}

// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (r *Gateway) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
gateway, ok := obj.(*Gateway)
if !ok {
return nil, fmt.Errorf("expected a Gateway, received %T", obj)
}
return validateGateway(gateway)
// ValidateCreate implements admission.Validator for *Gateway.
func (r *Gateway) ValidateCreate(ctx context.Context, obj *Gateway) (admission.Warnings, error) {
return validateGateway(obj)
}

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (r *Gateway) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
_, ok := oldObj.(*Gateway)
if !ok {
return nil, fmt.Errorf("expected a Gateway for oldObj, received %T", oldObj)
}
gateway, ok := newObj.(*Gateway)
if !ok {
return nil, fmt.Errorf("expected a Gateway for newObj, received %T", newObj)
}
return validateGateway(gateway)
// ValidateUpdate implements admission.Validator for *Gateway.
func (r *Gateway) ValidateUpdate(ctx context.Context, oldObj, newObj *Gateway) (admission.Warnings, error) {
return validateGateway(newObj)
}

// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (r *Gateway) ValidateDelete(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
// ValidateDelete implements admission.Validator for *Gateway.
func (r *Gateway) ValidateDelete(ctx context.Context, obj *Gateway) (admission.Warnings, error) {
//gatewaylog.Info("validate delete", "name", r.Name)
return []string{}, nil
return nil, nil
}

func validateGateway(r *Gateway) (admission.Warnings, error) {
Expand Down
42 changes: 14 additions & 28 deletions api/v1/repository_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,58 +23,44 @@ import (
"fmt"
"strings"

"k8s.io/apimachinery/pkg/runtime"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

func (r *Repository) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
return ctrl.NewWebhookManagedBy(mgr, r).
WithDefaulter(r).
WithValidator(r).
Complete()
}

//+kubebuilder:webhook:path=/mutate-security-brcmlabs-com-v1-repository,mutating=true,failurePolicy=fail,sideEffects=None,groups=security.brcmlabs.com,resources=repositories,verbs=create;update,versions=v1,name=mrepository.kb.io,admissionReviewVersions=v1

var _ admission.CustomDefaulter = &Repository{}
var _ admission.Defaulter[*Repository] = &Repository{}

// Default implements webhook.Defaulter so a webhook will be registered for the type
func (r *Repository) Default(ctx context.Context, obj runtime.Object) error {
// Default implements admission.Defaulter for *Repository.
func (r *Repository) Default(ctx context.Context, obj *Repository) error {
return nil
}

//+kubebuilder:webhook:path=/validate-security-brcmlabs-com-v1-repository,mutating=false,failurePolicy=fail,sideEffects=None,groups=security.brcmlabs.com,resources=repositories,verbs=create;update,versions=v1,name=vrepository.kb.io,admissionReviewVersions=v1

var _ admission.CustomValidator = &Repository{}
var _ admission.Validator[*Repository] = &Repository{}

// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
func (r *Repository) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
repository, ok := obj.(*Repository)
if !ok {
return nil, fmt.Errorf("expected a Repository, received %T", obj)
}
return validateRepository(repository)
// ValidateCreate implements admission.Validator for *Repository.
func (r *Repository) ValidateCreate(ctx context.Context, obj *Repository) (admission.Warnings, error) {
return validateRepository(obj)
}

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
func (r *Repository) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
_, ok := oldObj.(*Repository)
if !ok {
return nil, fmt.Errorf("expected a Repository for oldObj, received %T", oldObj)
}
repository, ok := newObj.(*Repository)
if !ok {
return nil, fmt.Errorf("expected a Repository for newObj, received %T", newObj)
}
return validateRepository(repository)
// ValidateUpdate implements admission.Validator for *Repository.
func (r *Repository) ValidateUpdate(ctx context.Context, oldObj, newObj *Repository) (admission.Warnings, error) {
return validateRepository(newObj)
}

// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
func (r *Repository) ValidateDelete(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
// ValidateDelete implements admission.Validator for *Repository.
func (r *Repository) ValidateDelete(ctx context.Context, obj *Repository) (admission.Warnings, error) {
// Could extend to checking which gateways reference this before deletion.
return []string{}, nil
return nil, nil
}

func validateRepository(r *Repository) (admission.Warnings, error) {
Expand Down
3 changes: 2 additions & 1 deletion api/v1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ metadata:
},
"spec": {
"app": {
"image": "docker.io/caapim/gateway:11.1.3",
"image": "docker.io/caapim/gateway:11.2.1",
"management": {
"cluster": {
"hostname": "gateway.brcmlabs.com",
Expand Down
Loading
Loading