diff --git a/.github/check_image_tags.sh b/.github/check_image_tags.sh
deleted file mode 100755
index e39b5e8c..00000000
--- a/.github/check_image_tags.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-## Determine if image tags already exist
-## Do not allow overwrites
-function tag_exists() {
- IMAGE_TAG_BASE=${1#*/}
- curl -s -f -lSL https://hub.docker.com/v2/repositories/${IMAGE_TAG_BASE}/tags/$2 &> /dev/null
-}
-
-if tag_exists $1 $2; then
- echo tag $2 already exists on $1, exiting.
- exit 1
-fi
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
deleted file mode 100644
index 7a6c4940..00000000
--- a/.github/workflows/ci.yaml
+++ /dev/null
@@ -1,38 +0,0 @@
-name: Build Images
-on:
- push:
- branches:
- - main
- - develop
- - experimental
-jobs:
- build-and-push-images:
- name: Build and Push Images
- runs-on: ubuntu-latest
- env:
- VERSION: ${{ github.ref_name }}
- IMAGE_TAG_BASE: docker.io/layer7api/layer7-operator
- steps:
- - name: Checkout repo
- uses: actions/checkout@v4
- with:
- fetch-depth: 0
- - name: Configure Git
- run: |
- git config user.name "$GITHUB_ACTOR"
- git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
- - name: Login to Docker Hub
- uses: docker/login-action@v3
- with:
- username: ${{ secrets.DOCKERHUB_USERNAME }}
- password: ${{ secrets.DOCKERHUB_TOKEN }}
- - name: Prepare Bases
- run: make version
- - name: Build and push Operator
- run: make docker-build docker-push
- - name: Build and push Operator Bundle
- run: make bundle-build bundle-push
\ No newline at end of file
diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml
deleted file mode 100644
index 8f52953b..00000000
--- a/.github/workflows/pr.yaml
+++ /dev/null
@@ -1,38 +0,0 @@
-name: Build PR Images
-on:
- pull_request:
- branches:
- - main
- - develop
- - experimental
-jobs:
- build-and-push-images:
- name: Build and Push Images
- runs-on: ubuntu-latest
- env:
- VERSION: ${GITHUB_HEAD_REF}
- IMAGE_TAG_BASE: docker.io/layer7api/layer7-operator
- steps:
- - name: Checkout repo
- uses: actions/checkout@v4
- with:
- fetch-depth: 0
- - name: Configure Git
- run: |
- git config user.name "$GITHUB_ACTOR"
- git config user.email "$GITHUB_ACTOR@users.noreply.github.com"
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v3
- - name: Login to Docker Hub
- uses: docker/login-action@v3
- with:
- username: ${{ secrets.DOCKERHUB_USERNAME }}
- password: ${{ secrets.DOCKERHUB_TOKEN }}
- - name: Prepare Bases
- run: make version
- - name: Build and push Operator
- run: make docker-build docker-push
- - name: Build and push Operator Bundle
- run: make bundle-build bundle-push
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 04fd8906..6e1c8336 100644
--- a/Makefile
+++ b/Makefile
@@ -222,7 +222,7 @@ run: manifests generate fmt vet ## Run a controller from your host.
.PHONY: docker-build
docker-build: dockerfile #test ## Build docker image with the manager.
- $(CONTAINER_TOOL) build -f operator.Dockerfile -t ${IMG} .
+ $(CONTAINER_TOOL) build -t ${IMG} -f operator.Dockerfile --build-arg COPYRIGHT="${COPYRIGHT}" --build-arg AUTHOR="layer7" --build-arg TITLE="layer7-operator" --build-arg VERSION="${IMAGE_TAG}" --build-arg CREATED="${CREATED}" .
.PHONY: docker-push
docker-push: ## Push docker image with the manager.
diff --git a/api/v1/gateway_types.go b/api/v1/gateway_types.go
index 41fcad93..d3434fd6 100644
--- a/api/v1/gateway_types.go
+++ b/api/v1/gateway_types.go
@@ -117,6 +117,8 @@ type GatewayStatus struct {
LastAppliedExternalSecrets map[string][]string `json:"lastAppliedExternalSecrets,omitempty"`
// LastAppliedExternalCerts
LastAppliedExternalCerts map[string][]string `json:"lastAppliedExternalCerts,omitempty"`
+ // LastAppliedOtkFipsCerts tracks which OTK FIPS user certificates have been applied
+ LastAppliedOtkFipsCerts map[string][]string `json:"lastAppliedOtkFipsCerts,omitempty"`
}
// GatewayState tracks the status of Gateway Resources
@@ -342,6 +344,9 @@ 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
@@ -356,21 +361,27 @@ type Otk struct {
Overrides OtkOverrides `json:"overrides,omitempty"`
// A list of subSolutionKitNames - all,internal or dmz cover the primary use cases for the OTK. Only use if directed by support
SubSolutionKitNames []string `json:"subSolutionKitNames,omitempty"`
- // InternalOtkGatewayReference to an Operator managed Gateway deployment that is configured with otk.type: internal
- // This configures a relationship between DMZ and Internal Gateways.
- InternalOtkGatewayReference string `json:"internalGatewayReference,omitempty"`
- // InternalGatewayPort defaults to 9443 or graphmanDynamicSync port
- InternalGatewayPort int `json:"internalGatewayPort,omitempty"`
- // OTKPort is used in Single mode - sets the otk.port cluster-wide property and in Dual-Mode
- // sets host_oauth2_auth_server port in #OTK Client Context Variables
- // TODO: Make this an array for many dmz deployments to one internal
- DmzOtkGatewayReference string `json:"dmzGatewayReference,omitempty"`
// OTKPort defaults to 8443
OTKPort int `json:"port,omitempty"`
// MaintenanceTasks for the OTK database are disabled by default
MaintenanceTasks OtkMaintenanceTasks `json:"maintenanceTasks,omitempty"`
- // RuntimeSyncIntervalSeconds how often OTK Gateways should be updated in internal/dmz mode
- RuntimeSyncIntervalSeconds int `json:"runtimeSyncIntervalSeconds,omitempty"`
+ //InternalOTKGateway reference if type is dmz
+ InternalOTKGateway GatewayReference `json:"internalGateway,omitempty"`
+ //DmzOTKGateway reference if type is internal
+ DmzOTKGateway GatewayReference `json:"dmzGateway,omitempty"`
+ // FipsCertificates is a list of certificate references for FIPS user management
+ // on Internal gateways. Each entry references a Secret or ConfigMap containing
+ // leaf certificates for DMZ gateway mTLS client authentication.
+ FipsCertificates []OtkFipsCertificate `json:"fipsCertificates,omitempty"`
+}
+
+type OtkFipsCertificate struct {
+ // Enabled or disabled
+ Enabled bool `json:"enabled,omitempty"`
+ // Name of the Secret or ConfigMap
+ Name string `json:"name,omitempty"`
+ // Type of the referenced resource: "secret" or "configmap"
+ Type string `json:"type,omitempty"`
}
// OtkMaintenanceTasks are included in the install bundle as disabled scheduled tasks
@@ -380,6 +391,19 @@ type OtkMaintenanceTasks struct {
Enabled bool `json:"enabled,omitempty"`
}
+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 {
// Enable or disable otk overrides
Enabled bool `json:"enabled,omitempty"`
@@ -893,6 +917,8 @@ type ExternalKey struct {
// only one key usage type is allowed
// SSL | CA | AUDIT_SIGNING | AUDIT_VIEWER
KeyUsageType KeyUsageType `json:"keyUsageType,omitempty"`
+ // Otk indicates that this key usage was specific for OTK
+ //Otk bool `json:"otk,omitempty"`
}
type KeyUsageType string
diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go
index 3fec98ec..372d0911 100644
--- a/api/v1/zz_generated.deepcopy.go
+++ b/api/v1/zz_generated.deepcopy.go
@@ -570,6 +570,21 @@ func (in *GatewayList) DeepCopyObject() runtime.Object {
return nil
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *GatewayReference) DeepCopyInto(out *GatewayReference) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayReference.
+func (in *GatewayReference) DeepCopy() *GatewayReference {
+ if in == nil {
+ return nil
+ }
+ out := new(GatewayReference)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *GatewayRepositoryStatus) DeepCopyInto(out *GatewayRepositoryStatus) {
*out = *in
@@ -706,6 +721,22 @@ func (in *GatewayStatus) DeepCopyInto(out *GatewayStatus) {
(*out)[key] = outVal
}
}
+ if in.LastAppliedOtkFipsCerts != nil {
+ in, out := &in.LastAppliedOtkFipsCerts, &out.LastAppliedOtkFipsCerts
+ *out = make(map[string][]string, len(*in))
+ for key, val := range *in {
+ var outVal []string
+ if val == nil {
+ (*out)[key] = nil
+ } else {
+ inVal := (*in)[key]
+ in, out := &inVal, &outVal
+ *out = make([]string, len(*in))
+ copy(*out, *in)
+ }
+ (*out)[key] = outVal
+ }
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayStatus.
@@ -1035,6 +1066,13 @@ func (in *Otk) DeepCopyInto(out *Otk) {
copy(*out, *in)
}
out.MaintenanceTasks = in.MaintenanceTasks
+ out.InternalOTKGateway = in.InternalOTKGateway
+ out.DmzOTKGateway = in.DmzOTKGateway
+ if in.FipsCertificates != nil {
+ in, out := &in.FipsCertificates, &out.FipsCertificates
+ *out = make([]OtkFipsCertificate, len(*in))
+ copy(*out, *in)
+ }
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Otk.
@@ -1123,6 +1161,21 @@ func (in *OtkDatabaseAuthCredentials) DeepCopy() *OtkDatabaseAuthCredentials {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *OtkFipsCertificate) DeepCopyInto(out *OtkFipsCertificate) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OtkFipsCertificate.
+func (in *OtkFipsCertificate) DeepCopy() *OtkFipsCertificate {
+ if in == nil {
+ return nil
+ }
+ out := new(OtkFipsCertificate)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *OtkMaintenanceTasks) DeepCopyInto(out *OtkMaintenanceTasks) {
*out = *in
diff --git a/config/crd/bases/security.brcmlabs.com_gateways.yaml b/config/crd/bases/security.brcmlabs.com_gateways.yaml
index a473a499..10347579 100644
--- a/config/crd/bases/security.brcmlabs.com_gateways.yaml
+++ b/config/crd/bases/security.brcmlabs.com_gateways.yaml
@@ -4003,12 +4003,47 @@ spec:
description: Type of OTK Database
type: string
type: object
- dmzGatewayReference:
- description: OTKPort is used in Single mode - sets the otk.
- type: string
+ dmzGateway:
+ description: DmzOTKGateway reference if type is internal
+ properties:
+ name:
+ description: |-
+ Name of the gateway
+ if managing otk gateways across namespaces this must...
+ type: string
+ namespace:
+ description: Namespace of the referenced gateway if managing
+ gateways cross namespace...
+ type: string
+ port:
+ description: Port of the target gateway
+ type: integer
+ url:
+ description: |-
+ Url of the target gateway
+ used for post-installation gateway policy...
+ type: string
+ type: object
enabled:
description: Enable or disable the OTK initContainer
type: boolean
+ fipsCertificates:
+ description: FipsCertificates is a list of certificate references
+ for FIPS user...
+ items:
+ properties:
+ enabled:
+ description: Enabled or disabled
+ type: boolean
+ name:
+ description: Name of the Secret or ConfigMap
+ type: string
+ type:
+ description: 'Type of the referenced resource: "secret"
+ or "configmap"'
+ type: string
+ type: object
+ type: array
initContainerImage:
description: InitContainerImage for the initContainer
type: string
@@ -4142,14 +4177,27 @@ spec:
type: string
type: object
type: object
- internalGatewayPort:
- description: InternalGatewayPort defaults to 9443 or graphmanDynamicSync
- port
- type: integer
- internalGatewayReference:
- description: InternalOtkGatewayReference to an Operator managed
- Gateway deployment that...
- type: string
+ internalGateway:
+ description: InternalOTKGateway reference if type is dmz
+ properties:
+ name:
+ description: |-
+ Name of the gateway
+ if managing otk gateways across namespaces this must...
+ type: string
+ namespace:
+ description: Namespace of the referenced gateway if managing
+ gateways cross namespace...
+ type: string
+ port:
+ description: Port of the target gateway
+ type: integer
+ url:
+ description: |-
+ Url of the target gateway
+ used for post-installation gateway policy...
+ type: string
+ type: object
maintenanceTasks:
description: MaintenanceTasks for the OTK database are disabled
by default
@@ -4158,6 +4206,10 @@ spec:
description: Enable or disable database maintenance tasks
type: boolean
type: object
+ manageCrossNamespace:
+ description: ManageCrossNamespace allows a cluster-wide layer7
+ operator to manage...
+ type: boolean
overrides:
description: Overrides default OTK install functionality
properties:
@@ -4192,10 +4244,6 @@ spec:
port:
description: OTKPort defaults to 8443
type: integer
- runtimeSyncIntervalSeconds:
- description: RuntimeSyncIntervalSeconds how often OTK Gateways
- should be updated in...
- type: integer
subSolutionKitNames:
description: A list of subSolutionKitNames - all,internal
or dmz cover the primary use...
@@ -6479,6 +6527,14 @@ spec:
items:
type: string
type: array
+ lastAppliedOtkFipsCerts:
+ additionalProperties:
+ items:
+ type: string
+ type: array
+ description: LastAppliedOtkFipsCerts tracks which OTK FIPS user certificates
+ have been...
+ type: object
managementPod:
description: Management Pod is a Gateway with a special annotation
is used as a...
diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml
index 80400590..3b94dc9a 100644
--- a/deploy/bundle.yaml
+++ b/deploy/bundle.yaml
@@ -4002,12 +4002,47 @@ spec:
description: Type of OTK Database
type: string
type: object
- dmzGatewayReference:
- description: OTKPort is used in Single mode - sets the otk.
- type: string
+ dmzGateway:
+ description: DmzOTKGateway reference if type is internal
+ properties:
+ name:
+ description: |-
+ Name of the gateway
+ if managing otk gateways across namespaces this must...
+ type: string
+ namespace:
+ description: Namespace of the referenced gateway if managing
+ gateways cross namespace...
+ type: string
+ port:
+ description: Port of the target gateway
+ type: integer
+ url:
+ description: |-
+ Url of the target gateway
+ used for post-installation gateway policy...
+ type: string
+ type: object
enabled:
description: Enable or disable the OTK initContainer
type: boolean
+ fipsCertificates:
+ description: FipsCertificates is a list of certificate references
+ for FIPS user...
+ items:
+ properties:
+ enabled:
+ description: Enabled or disabled
+ type: boolean
+ name:
+ description: Name of the Secret or ConfigMap
+ type: string
+ type:
+ description: 'Type of the referenced resource: "secret"
+ or "configmap"'
+ type: string
+ type: object
+ type: array
initContainerImage:
description: InitContainerImage for the initContainer
type: string
@@ -4141,14 +4176,27 @@ spec:
type: string
type: object
type: object
- internalGatewayPort:
- description: InternalGatewayPort defaults to 9443 or graphmanDynamicSync
- port
- type: integer
- internalGatewayReference:
- description: InternalOtkGatewayReference to an Operator managed
- Gateway deployment that...
- type: string
+ internalGateway:
+ description: InternalOTKGateway reference if type is dmz
+ properties:
+ name:
+ description: |-
+ Name of the gateway
+ if managing otk gateways across namespaces this must...
+ type: string
+ namespace:
+ description: Namespace of the referenced gateway if managing
+ gateways cross namespace...
+ type: string
+ port:
+ description: Port of the target gateway
+ type: integer
+ url:
+ description: |-
+ Url of the target gateway
+ used for post-installation gateway policy...
+ type: string
+ type: object
maintenanceTasks:
description: MaintenanceTasks for the OTK database are disabled
by default
@@ -4157,6 +4205,10 @@ spec:
description: Enable or disable database maintenance tasks
type: boolean
type: object
+ manageCrossNamespace:
+ description: ManageCrossNamespace allows a cluster-wide layer7
+ operator to manage...
+ type: boolean
overrides:
description: Overrides default OTK install functionality
properties:
@@ -4191,10 +4243,6 @@ spec:
port:
description: OTKPort defaults to 8443
type: integer
- runtimeSyncIntervalSeconds:
- description: RuntimeSyncIntervalSeconds how often OTK Gateways
- should be updated in...
- type: integer
subSolutionKitNames:
description: A list of subSolutionKitNames - all,internal
or dmz cover the primary use...
@@ -6478,6 +6526,14 @@ spec:
items:
type: string
type: array
+ lastAppliedOtkFipsCerts:
+ additionalProperties:
+ items:
+ type: string
+ type: array
+ description: LastAppliedOtkFipsCerts tracks which OTK FIPS user certificates
+ have been...
+ type: object
managementPod:
description: Management Pod is a Gateway with a special annotation
is used as a...
diff --git a/deploy/crd.yaml b/deploy/crd.yaml
index 0596a22c..179219a0 100644
--- a/deploy/crd.yaml
+++ b/deploy/crd.yaml
@@ -4002,12 +4002,47 @@ spec:
description: Type of OTK Database
type: string
type: object
- dmzGatewayReference:
- description: OTKPort is used in Single mode - sets the otk.
- type: string
+ dmzGateway:
+ description: DmzOTKGateway reference if type is internal
+ properties:
+ name:
+ description: |-
+ Name of the gateway
+ if managing otk gateways across namespaces this must...
+ type: string
+ namespace:
+ description: Namespace of the referenced gateway if managing
+ gateways cross namespace...
+ type: string
+ port:
+ description: Port of the target gateway
+ type: integer
+ url:
+ description: |-
+ Url of the target gateway
+ used for post-installation gateway policy...
+ type: string
+ type: object
enabled:
description: Enable or disable the OTK initContainer
type: boolean
+ fipsCertificates:
+ description: FipsCertificates is a list of certificate references
+ for FIPS user...
+ items:
+ properties:
+ enabled:
+ description: Enabled or disabled
+ type: boolean
+ name:
+ description: Name of the Secret or ConfigMap
+ type: string
+ type:
+ description: 'Type of the referenced resource: "secret"
+ or "configmap"'
+ type: string
+ type: object
+ type: array
initContainerImage:
description: InitContainerImage for the initContainer
type: string
@@ -4141,14 +4176,27 @@ spec:
type: string
type: object
type: object
- internalGatewayPort:
- description: InternalGatewayPort defaults to 9443 or graphmanDynamicSync
- port
- type: integer
- internalGatewayReference:
- description: InternalOtkGatewayReference to an Operator managed
- Gateway deployment that...
- type: string
+ internalGateway:
+ description: InternalOTKGateway reference if type is dmz
+ properties:
+ name:
+ description: |-
+ Name of the gateway
+ if managing otk gateways across namespaces this must...
+ type: string
+ namespace:
+ description: Namespace of the referenced gateway if managing
+ gateways cross namespace...
+ type: string
+ port:
+ description: Port of the target gateway
+ type: integer
+ url:
+ description: |-
+ Url of the target gateway
+ used for post-installation gateway policy...
+ type: string
+ type: object
maintenanceTasks:
description: MaintenanceTasks for the OTK database are disabled
by default
@@ -4157,6 +4205,10 @@ spec:
description: Enable or disable database maintenance tasks
type: boolean
type: object
+ manageCrossNamespace:
+ description: ManageCrossNamespace allows a cluster-wide layer7
+ operator to manage...
+ type: boolean
overrides:
description: Overrides default OTK install functionality
properties:
@@ -4191,10 +4243,6 @@ spec:
port:
description: OTKPort defaults to 8443
type: integer
- runtimeSyncIntervalSeconds:
- description: RuntimeSyncIntervalSeconds how often OTK Gateways
- should be updated in...
- type: integer
subSolutionKitNames:
description: A list of subSolutionKitNames - all,internal
or dmz cover the primary use...
@@ -6478,6 +6526,14 @@ spec:
items:
type: string
type: array
+ lastAppliedOtkFipsCerts:
+ additionalProperties:
+ items:
+ type: string
+ type: array
+ description: LastAppliedOtkFipsCerts tracks which OTK FIPS user certificates
+ have been...
+ type: object
managementPod:
description: Management Pod is a Gateway with a special annotation
is used as a...
diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml
index 1be27732..fd2d446d 100644
--- a/deploy/cw-bundle.yaml
+++ b/deploy/cw-bundle.yaml
@@ -4011,12 +4011,47 @@ spec:
description: Type of OTK Database
type: string
type: object
- dmzGatewayReference:
- description: OTKPort is used in Single mode - sets the otk.
- type: string
+ dmzGateway:
+ description: DmzOTKGateway reference if type is internal
+ properties:
+ name:
+ description: |-
+ Name of the gateway
+ if managing otk gateways across namespaces this must...
+ type: string
+ namespace:
+ description: Namespace of the referenced gateway if managing
+ gateways cross namespace...
+ type: string
+ port:
+ description: Port of the target gateway
+ type: integer
+ url:
+ description: |-
+ Url of the target gateway
+ used for post-installation gateway policy...
+ type: string
+ type: object
enabled:
description: Enable or disable the OTK initContainer
type: boolean
+ fipsCertificates:
+ description: FipsCertificates is a list of certificate references
+ for FIPS user...
+ items:
+ properties:
+ enabled:
+ description: Enabled or disabled
+ type: boolean
+ name:
+ description: Name of the Secret or ConfigMap
+ type: string
+ type:
+ description: 'Type of the referenced resource: "secret"
+ or "configmap"'
+ type: string
+ type: object
+ type: array
initContainerImage:
description: InitContainerImage for the initContainer
type: string
@@ -4150,14 +4185,27 @@ spec:
type: string
type: object
type: object
- internalGatewayPort:
- description: InternalGatewayPort defaults to 9443 or graphmanDynamicSync
- port
- type: integer
- internalGatewayReference:
- description: InternalOtkGatewayReference to an Operator managed
- Gateway deployment that...
- type: string
+ internalGateway:
+ description: InternalOTKGateway reference if type is dmz
+ properties:
+ name:
+ description: |-
+ Name of the gateway
+ if managing otk gateways across namespaces this must...
+ type: string
+ namespace:
+ description: Namespace of the referenced gateway if managing
+ gateways cross namespace...
+ type: string
+ port:
+ description: Port of the target gateway
+ type: integer
+ url:
+ description: |-
+ Url of the target gateway
+ used for post-installation gateway policy...
+ type: string
+ type: object
maintenanceTasks:
description: MaintenanceTasks for the OTK database are disabled
by default
@@ -4166,6 +4214,10 @@ spec:
description: Enable or disable database maintenance tasks
type: boolean
type: object
+ manageCrossNamespace:
+ description: ManageCrossNamespace allows a cluster-wide layer7
+ operator to manage...
+ type: boolean
overrides:
description: Overrides default OTK install functionality
properties:
@@ -4200,10 +4252,6 @@ spec:
port:
description: OTKPort defaults to 8443
type: integer
- runtimeSyncIntervalSeconds:
- description: RuntimeSyncIntervalSeconds how often OTK Gateways
- should be updated in...
- type: integer
subSolutionKitNames:
description: A list of subSolutionKitNames - all,internal
or dmz cover the primary use...
@@ -6487,6 +6535,14 @@ spec:
items:
type: string
type: array
+ lastAppliedOtkFipsCerts:
+ additionalProperties:
+ items:
+ type: string
+ type: array
+ description: LastAppliedOtkFipsCerts tracks which OTK FIPS user certificates
+ have been...
+ type: object
managementPod:
description: Management Pod is a Gateway with a special annotation
is used as a...
diff --git a/docs/gateway.md b/docs/gateway.md
index cd245c6b..9c7f619c 100644
--- a/docs/gateway.md
+++ b/docs/gateway.md
@@ -10634,11 +10634,10 @@ This can be further extended with custom attributes using the additionalResource
false |
- | dmzGatewayReference |
- string |
+ dmzGateway |
+ object |
- OTKPort is used in Single mode - sets the otk.port cluster-wide property and in Dual-Mode
-sets host_oauth2_auth_server port in #OTK Client Context Variables
+ DmzOTKGateway reference if type is internal
|
false |
@@ -10648,6 +10647,15 @@ sets host_oauth2_auth_server port in #OTK Client Context Variables
Enable or disable the OTK initContainer
false |
+
+ | fipsCertificates |
+ []object |
+
+ FipsCertificates is a list of certificate references for FIPS user management
+on Internal gateways. Each entry references a Secret or ConfigMap containing
+leaf certificates for DMZ gateway mTLS client authentication.
+ |
+ false |
| initContainerImage |
string |
@@ -10670,25 +10678,25 @@ sets host_oauth2_auth_server port in #OTK Client Context Variables
false |
- | internalGatewayPort |
- integer |
+ internalGateway |
+ object |
- InternalGatewayPort defaults to 9443 or graphmanDynamicSync port
+ InternalOTKGateway reference if type is dmz
|
false |
- | internalGatewayReference |
- string |
+ maintenanceTasks |
+ object |
- InternalOtkGatewayReference to an Operator managed Gateway deployment that is configured with otk.type: internal
-This configures a relationship between DMZ and Internal Gateways.
+ MaintenanceTasks for the OTK database are disabled by default
|
false |
- | maintenanceTasks |
- object |
+ manageCrossNamespace |
+ boolean |
- MaintenanceTasks for the OTK database are disabled by default
+ ManageCrossNamespace allows a cluster-wide layer7 operator to manage internal/dmz gateways across namespaces
+this is limited to a single kubernetes cluster.
|
false |
@@ -10705,13 +10713,6 @@ This configures a relationship between DMZ and Internal Gateways.
OTKPort defaults to 8443
false |
-
- | runtimeSyncIntervalSeconds |
- integer |
-
- RuntimeSyncIntervalSeconds how often OTK Gateways should be updated in internal/dmz mode
- |
- false |
| subSolutionKitNames |
[]string |
@@ -11313,6 +11314,97 @@ only supports MySQL and Oracle
+### Gateway.spec.app.otk.dmzGateway
+[↩ Parent](#gatewayspecappotk)
+
+
+
+DmzOTKGateway reference if type is internal
+
+
+
+
+ | Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ | name |
+ string |
+
+ Name of the gateway
+if managing otk gateways across namespaces this must match the referenced gateway CR
+ |
+ false |
+
+ | namespace |
+ string |
+
+ Namespace of the referenced gateway if managing gateways cross namespace (optional)
+ |
+ false |
+
+ | port |
+ integer |
+
+ Port of the target gateway
+ |
+ false |
+
+ | url |
+ string |
+
+ Url of the target gateway
+used for post-installation gateway policy configuration
+ |
+ false |
+
+
+
+
+### Gateway.spec.app.otk.fipsCertificates[index]
+[↩ Parent](#gatewayspecappotk)
+
+
+
+
+
+
+
+
+ | Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ | enabled |
+ boolean |
+
+ Enabled or disabled
+ |
+ false |
+
+ | name |
+ string |
+
+ Name of the Secret or ConfigMap
+ |
+ false |
+
+ | type |
+ string |
+
+ Type of the referenced resource: "secret" or "configmap"
+ |
+ false |
+
+
+
+
### Gateway.spec.app.otk.initContainerSecurityContext
[↩ Parent](#gatewayspecappotk)
@@ -11698,6 +11790,56 @@ PodSecurityContext, the value specified in SecurityContext takes precedence.
+### Gateway.spec.app.otk.internalGateway
+[↩ Parent](#gatewayspecappotk)
+
+
+
+InternalOTKGateway reference if type is dmz
+
+
+
+
+ | Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ | name |
+ string |
+
+ Name of the gateway
+if managing otk gateways across namespaces this must match the referenced gateway CR
+ |
+ false |
+
+ | namespace |
+ string |
+
+ Namespace of the referenced gateway if managing gateways cross namespace (optional)
+ |
+ false |
+
+ | port |
+ integer |
+
+ Port of the target gateway
+ |
+ false |
+
+ | url |
+ string |
+
+ Url of the target gateway
+used for post-installation gateway policy configuration
+ |
+ false |
+
+
+
+
### Gateway.spec.app.otk.maintenanceTasks
[↩ Parent](#gatewayspecappotk)
@@ -17951,6 +18093,13 @@ GatewayStatus defines the observed state of Gateways
LastAppliedClusterProperties
false |
+
+ | lastAppliedOtkFipsCerts |
+ map[string][]string |
+
+ LastAppliedOtkFipsCerts tracks which OTK FIPS user certificates have been applied
+ |
+ false |
| managementPod |
string |
diff --git a/example/Makefile b/example/Makefile
index 9548e996..f29739fa 100644
--- a/example/Makefile
+++ b/example/Makefile
@@ -32,7 +32,7 @@ basic:
@$(MAKE) --silent t=10 wait
kubectl apply -f ./gateway/basic-gateway.yaml
-advanced: default-redis
+advanced:
kubectl apply -k ./repositories
@$(MAKE) --silent t=10 wait
kubectl apply -f ./gateway/advanced-gateway.yaml
@@ -61,9 +61,8 @@ portal-example: redis
@echo "####################################################################################################################################"
./portal-integration/create-tenant.sh -d ./portal-integration/enroll-payload.json -n ${NAMESPACE}
-# add nginx ip for portal domains so the agent can resolve them
g2c-agent:
- sed -e 's/ip:.*/ip: "$(shell kubectl get svc ingress-nginx-controller -n ingress-nginx -ojsonpath="{.spec.clusterIP}")"/g' ./portal-integration/g2c-agent/deployment-template.yaml > ./portal-integration/g2c-agent/deployment.yaml
+#sed -e 's/ip:.*/ip: "$(shell kubectl get svc ingress-nginx-controller -n ingress-nginx -ojsonpath="{.spec.clusterIP}")"/g' ./portal-integration/g2c-agent/deployment-template.yaml > ./portal-integration/g2c-agent/deployment.yaml
kubectl apply -k ./portal-integration/g2c-agent
echo "deploy g2cagent"
@@ -77,18 +76,15 @@ default-redis:
helm upgrade -i standalone -f ./portal-integration/redis/redis-values.yaml oci://registry-1.docker.io/bitnamicharts/redis
@$(MAKE) --silent t=15 wait
kubectl wait --for=condition=ready --timeout=600s pod -l app.kubernetes.io/name=redis
-
-configure-nginx-ssl-passthrough:
- kubectl -n ingress-nginx get deployment ingress-nginx-controller -oyaml | sed -e "s/env:/\- \-\-enable\-ssl\-passthrough\n env\:/g" | kubectl -n ingress-nginx apply -f -
grafana-stack:
- helm repo add grafana https://grafana.github.io/helm-charts
+ helm repo add grafana https://grafana-community.github.io/helm-charts
helm upgrade --install --values ./otel-lgtm/grafana-stack/loki-overrides.yaml loki grafana/loki -n grafana-loki --create-namespace
helm upgrade --install --values ./otel-lgtm/grafana-stack/promtail-overrides.yaml promtail grafana/promtail -n grafana-loki
helm upgrade --install --values ./otel-lgtm/grafana-stack/tempo-overrides.yaml tempo grafana/tempo -n grafana-loki
helm upgrade --install --values ./otel-lgtm/grafana-stack/mimir-distributed-overrides.yaml mimir grafana/mimir-distributed -n grafana-loki
-otel-lgtm-example-kind: install cert-manager prometheus-lgtm open-telemetry grafana-stack nginx-kind
+otel-lgtm-example-kind: install cert-manager prometheus-lgtm open-telemetry grafana-stack contour-kind
kubectl apply -f ./otel-lgtm/collector.yaml
kubectl apply -f ./otel-lgtm/instrumentation.yaml
kubectl apply -k ./repositories
@@ -103,27 +99,27 @@ otel-lgtm-example: install cert-manager prometheus-lgtm open-telemetry grafana-s
@$(MAKE) --silent t=10 wait
kubectl apply -f ./gateway/otel-lgtm-gateway.yaml
-otel-prometheus-example-kind: install cert-manager prometheus open-telemetry jaeger nginx-kind
- kubectl apply -f ./otel-prometheus/servicemonitor.yaml
- kubectl apply -f ./otel-prometheus/collector.yaml
- kubectl apply -f ./otel-prometheus/instrumentation.yaml
- kubectl apply -f ./otel-prometheus/observability/jaeger/jaeger.yaml
- kubectl apply -f ./otel-prometheus/observability/jaeger/ingress.yaml
- kubectl apply -k ./repositories
- @$(MAKE) --silent t=10 wait
- kubectl apply -f ./gateway/otel-prometheus-gateway.yaml
-
-otel-prometheus-example: install cert-manager prometheus open-telemetry jaeger
- kubectl apply -f ./otel-prometheus/servicemonitor.yaml
- kubectl apply -f ./otel-prometheus/collector.yaml
- kubectl apply -f ./otel-prometheus/instrumentation.yaml
- kubectl apply -f ./otel-prometheus/observability/jaeger/jaeger.yaml
- kubectl apply -f ./otel-prometheus/observability/jaeger/ingress.yaml
- kubectl apply -k ./repositories
- @$(MAKE) --silent t=10 wait
- kubectl apply -f ./gateway/otel-prometheus-gateway.yaml
-
-otel-elastic-example-kind: install cert-manager open-telemetry elastic nginx-kind
+# otel-prometheus-example-kind: install cert-manager prometheus open-telemetry jaeger contour-kind
+# kubectl apply -f ./otel-prometheus/servicemonitor.yaml
+# kubectl apply -f ./otel-prometheus/collector.yaml
+# kubectl apply -f ./otel-prometheus/instrumentation.yaml
+# kubectl apply -f ./otel-prometheus/observability/jaeger/jaeger.yaml
+# kubectl apply -f ./otel-prometheus/observability/jaeger/ingress.yaml
+# kubectl apply -k ./repositories
+# @$(MAKE) --silent t=10 wait
+# kubectl apply -f ./gateway/otel-prometheus-gateway.yaml
+
+# otel-prometheus-example: install cert-manager prometheus open-telemetry jaeger
+# kubectl apply -f ./otel-prometheus/servicemonitor.yaml
+# kubectl apply -f ./otel-prometheus/collector.yaml
+# kubectl apply -f ./otel-prometheus/instrumentation.yaml
+# kubectl apply -f ./otel-prometheus/observability/jaeger/jaeger.yaml
+# kubectl apply -f ./otel-prometheus/observability/jaeger/ingress.yaml
+# kubectl apply -k ./repositories
+# @$(MAKE) --silent t=10 wait
+# kubectl apply -f ./gateway/otel-prometheus-gateway.yaml
+
+otel-elastic-example-kind: install cert-manager open-telemetry elastic contour-kind
@$(MAKE) --silent t=$(shell kubectl get secret/apm-server-quickstart-apm-token -o go-template='{{index .data "secret-token" | base64decode}}') create-collector
kubectl apply -f ./otel-elastic/instrumentation.yaml
@$(MAKE) --silent t=10 wait
@@ -150,15 +146,15 @@ otel-elastic-example: install cert-manager open-telemetry elastic
@echo "#####################################################\n"
cert-manager:
- kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.5/cert-manager.yaml
+ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.20.0/cert-manager.yaml
@$(MAKE) --silent t=10 wait
kubectl wait --for=condition=ready --timeout=600s pod -l app=cert-manager -n cert-manager
kubectl wait --for=condition=ready --timeout=600s pod -l app=cainjector -n cert-manager
kubectl wait --for=condition=ready --timeout=600s pod -l app=webhook -n cert-manager
elastic:
- kubectl create -f https://download.elastic.co/downloads/eck/2.8.0/crds.yaml
- kubectl apply -f https://download.elastic.co/downloads/eck/2.8.0/operator.yaml
+ kubectl create -f https://download.elastic.co/downloads/eck/3.3.1/crds.yaml
+ kubectl apply -f https://download.elastic.co/downloads/eck/3.3.1/operator.yaml
@$(MAKE) --silent t=10 wait
kubectl wait --for=condition=ready --timeout=600s pod -l control-plane=elastic-operator -n elastic-system
kubectl apply -f ./otel-elastic/components
@@ -174,40 +170,97 @@ metrics-server:
kubectl apply -f ./metrics-server/metrics-server-0-6-3.yaml
open-telemetry:
- kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/download/v0.97.1/opentelemetry-operator.yaml
+ kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/download/v0.146.0/opentelemetry-operator.yaml
@$(MAKE) --silent t=10 wait
kubectl wait --for=condition=ready --timeout=600s pod -l app.kubernetes.io/name=opentelemetry-operator -n opentelemetry-operator-system
-prometheus:
- helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
- helm repo update
- -kubectl create ns monitoring
- kubectl apply -k ./otel-prometheus/monitoring/grafana/
- helm upgrade -i prometheus -f ./otel-prometheus/monitoring/prometheus/prometheus-values.yaml prometheus-community/kube-prometheus-stack -n monitoring
+# prometheus:
+# helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
+# helm repo update
+# -kubectl create ns monitoring
+# kubectl apply -k ./otel-prometheus/monitoring/grafana/
+# helm upgrade -i prometheus -f ./otel-prometheus/monitoring/prometheus/prometheus-values.yaml prometheus-community/kube-prometheus-stack -n monitoring
prometheus-lgtm:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
-kubectl create ns monitoring
kubectl apply -k ./otel-lgtm/prometheus/grafana-dashboard/
+ @$(MAKE) NAMESPACE=monitoring pki
helm upgrade -i prometheus -f ./otel-lgtm/prometheus/prometheus-values.yaml prometheus-community/kube-prometheus-stack -n monitoring
-
jaeger:
-kubectl create namespace observability
- kubectl apply -f https://github.com/jaegertracing/jaeger-operator/releases/download/v1.44.0/jaeger-operator.yaml -n observability
+ kubectl apply -f https://github.com/jaegertracing/jaeger-operator/releases/download/v1.65.0/jaeger-operator.yaml -n observability
@$(MAKE) --silent t=10 wait
kubectl wait --for=condition=ready --timeout=600s pod -l name=jaeger-operator -n observability
-nginx-kind:
- kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
+contour: pki
+ helm repo add contour https://projectcontour.github.io/helm-charts/
+ helm upgrade --install contour contour/contour --namespace projectcontour --create-namespace
@$(MAKE) --silent t=10 wait
- kubectl wait --for=condition=ready --timeout=600s pod -l app.kubernetes.io/name=ingress-nginx,app.kubernetes.io/component=controller -n ingress-nginx
+ kubectl wait --for=condition=ready --timeout=600s pod -l app.kubernetes.io/name=contour,app.kubernetes.io/component=contour -n projectcontour
+ kubectl wait --for=condition=ready --timeout=600s pod -l app.kubernetes.io/name=contour,app.kubernetes.io/component=envoy -n projectcontour
-nginx:
- kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
+contour-kind: pki
+ helm repo add contour https://projectcontour.github.io/helm-charts/
+ helm upgrade --install contour contour/contour --namespace projectcontour --set envoy.useHostPort.http=true --set envoy.useHostPort.https=true --create-namespace
@$(MAKE) --silent t=10 wait
- kubectl wait --for=condition=ready --timeout=600s pod -l app.kubernetes.io/name=ingress-nginx,app.kubernetes.io/component=controller -n ingress-nginx
+ kubectl wait --for=condition=ready --timeout=600s pod -l app.kubernetes.io/name=contour,app.kubernetes.io/component=contour -n projectcontour
+ kubectl wait --for=condition=ready --timeout=600s pod -l app.kubernetes.io/name=contour,app.kubernetes.io/component=envoy -n projectcontour
+
+uninstall-contour:
+ helm uninstall contour -n projectcontour
+
+pki:
+ -openssl req -x509 -newkey rsa:2048 -nodes -days 365 -subj "/CN=*.brcmlabs.com" \
+ -addext "subjectAltName=DNS:*.brcmlabs.com,DNS:brcmlabs.com" \
+ -keyout /tmp/tls.key -out /tmp/tls.crt
+ -kubectl create secret tls brcmlabs \
+ --cert=/tmp/tls.crt --key=/tmp/tls.key \
+ -n $(NAMESPACE) --dry-run=client -o yaml | kubectl apply -f -
+
+pki-otk:
+ @test -f /tmp/otk-internal-tls.crt || \
+ openssl req -x509 -newkey rsa:2048 -nodes -days 365 \
+ -subj "/CN=gateway-internal-otk.brcmlabs.com" \
+ -addext "subjectAltName=DNS:gateway-internal-otk.brcmlabs.com,DNS:gateway-internal-otk-pm.brcmlabs.com" \
+ -keyout /tmp/otk-internal-tls.key -out /tmp/otk-internal-tls.crt
+ @test -f /tmp/otk-dmz-tls.crt || \
+ openssl req -x509 -newkey rsa:2048 -nodes -days 365 \
+ -subj "/CN=gateway-dmz-otk.brcmlabs.com" \
+ -addext "subjectAltName=DNS:gateway-dmz-otk.brcmlabs.com,DNS:gateway-dmz-otk-pm.brcmlabs.com" \
+ -keyout /tmp/otk-dmz-tls.key -out /tmp/otk-dmz-tls.crt
+ @test -f /tmp/otk-dmz-mtls.crt || { \
+ openssl req -x509 -newkey rsa:2048 -nodes -days 365 \
+ -subj "/CN=otk-dmz-mtls-ca" \
+ -keyout /tmp/otk-dmz-mtls-ca.key -out /tmp/otk-dmz-mtls-ca.crt && \
+ openssl req -newkey rsa:2048 -nodes \
+ -subj "/CN=dmz-gateway" \
+ -keyout /tmp/otk-dmz-mtls.key -out /tmp/otk-dmz-mtls.csr && \
+ openssl x509 -req -in /tmp/otk-dmz-mtls.csr \
+ -CA /tmp/otk-dmz-mtls-ca.crt -CAkey /tmp/otk-dmz-mtls-ca.key \
+ -CAcreateserial -days 365 -out /tmp/otk-dmz-mtls.crt; \
+ }
+
+pki-otk-dmz: pki-otk
+ -kubectl create secret tls otk-dmz-secret \
+ --cert=/tmp/otk-dmz-tls.crt --key=/tmp/otk-dmz-tls.key \
+ -n $(NAMESPACE) --dry-run=client -o yaml | kubectl apply -f -
+ -kubectl create secret tls otk-dmz-mtls-secret \
+ --cert=/tmp/otk-dmz-mtls.crt --key=/tmp/otk-dmz-mtls.key \
+ -n $(NAMESPACE) --dry-run=client -o yaml | kubectl apply -f -
+ -kubectl create secret generic otk-internal-ca-cert \
+ --from-file=ca.crt=/tmp/otk-internal-tls.crt \
+ -n $(NAMESPACE) --dry-run=client -o yaml | kubectl apply -f -
+
+pki-otk-internal: pki-otk
+ -kubectl create secret tls otk-internal-secret \
+ --cert=/tmp/otk-internal-tls.crt --key=/tmp/otk-internal-tls.key \
+ -n $(NAMESPACE) --dry-run=client -o yaml | kubectl apply -f -
+ -kubectl create secret generic otk-dmz-mtls-public-cert \
+ --from-file=dmz-gateway.crt=/tmp/otk-dmz-mtls.crt \
+ -n $(NAMESPACE) --dry-run=client -o yaml | kubectl apply -f -
cassandra:
helm upgrade --install cassandra -f ./otk/database/cassandra/cassandra-values.yaml oci://registry-1.docker.io/bitnamicharts/cassandra
@@ -228,18 +281,17 @@ uninstall:
-kubectl delete -f ./otel-prometheus/instrumentation.yaml
-kubectl delete -f ./otel-elastic/instrumentation.yaml
-kubectl delete -f ./otel-prometheus/observability/jaeger
- -kubectl delete -f https://github.com/open-telemetry/opentelemetry-operator/releases/download/v0.97.1/opentelemetry-operator.yaml
+ -kubectl delete -f https://github.com/open-telemetry/opentelemetry-operator/releases/download/v0.146.0/opentelemetry-operator.yaml
-helm uninstall prometheus -n monitoring
-kubectl delete -k ./otel-prometheus/monitoring/grafana/
- -kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.5/cert-manager.yaml
- -kubectl delete -f https://github.com/jaegertracing/jaeger-operator/releases/download/v1.44.0/jaeger-operator.yaml -n observability
- -kubectl delete -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
- -kubectl delete -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
+ -kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.20.0/cert-manager.yaml
+ -kubectl delete -f https://github.com/jaegertracing/jaeger-operator/releases/download/v1.65.0/jaeger-operator.yaml -n observability
-kubectl delete ns observability
-kubectl delete ns monitoring
-kubectl delete -f https://github.com/CAAPIM/layer7-operator/releases/download/v1.2.2/bundle.yaml
-helm uninstall mysql
-helm uninstall cassandra
+ -helm uninstall contour -n projectcontour
uninstall-kind:
kind delete cluster --name layer7
diff --git a/example/README.md b/example/README.md
index 2bf54ad0..ec73a911 100644
--- a/example/README.md
+++ b/example/README.md
@@ -35,7 +35,6 @@ Portal Integration Example
Other examples
- [Elastic Stack](./otel-elastic)
-- [Prometheus](./otel-prometheus)
Repositories (used in most of the examples)
- [Repositories](./repositories/)
\ No newline at end of file
diff --git a/example/advanced/README.md b/example/advanced/README.md
index d3b77961..7cd05ccc 100644
--- a/example/advanced/README.md
+++ b/example/advanced/README.md
@@ -13,15 +13,15 @@ By the end of this example you should have a better understanding of the Layer7
```
3. If you would like to create a TLS secret for your ingress controller then add tls.crt and tls.key to [base/resources/secrets/tls](../base/resources/secrets/tls)
- these will be referenced later on.
-4. You will need an ingress controller like nginx
+4. You will need an ingress controller like [contour](https://projectcontour.io/)
- if you do not have one installed already you can use the makefile in the example directory to deploy one
- ```cd example```
- Generic Kubernetes
- - ```make nginx```
+ - ```make contour```
- Kind (Kubernetes in Docker)
- follow the steps in Quickstart
or
- - ```make nginx-kind```
+ - ```make contour-kind```
- return to the previous folder
- ```cd ..```
@@ -38,11 +38,11 @@ cd example
```
make kind-cluster
```
-3. Deploy Nginx (based on your environment)
+3. Deploy Contour (based on your environment)
```
-make nginx
+make contour
or
-make nginx-kind
+make contour-kind
```
4. Deploy the example
```
@@ -353,8 +353,8 @@ version: 11.1.3
```
kubectl get ingress
-NAME CLASS HOSTS ADDRESS PORTS AGE
-ssg nginx gateway.brcmlabs.com or localhost 80, 443 54m
+NAME CLASS HOSTS ADDRESS PORTS AGE
+ssg contour gateway.brcmlabs.com or localhost 80, 443 54m
```
Add the following to your hosts file for DNS resolution
diff --git a/example/basic/README.md b/example/basic/README.md
index abe2ae75..15a758a3 100644
--- a/example/basic/README.md
+++ b/example/basic/README.md
@@ -170,8 +170,8 @@ You will see an init container starting with graphman-static-init.
Init Containers:
graphman-static-init-c1b58adb6d:
Container ID: containerd://21924ae85d25437d3634ea5da1415c9bb58d678600f9fd67d4f0b0360857d7c5
- Image: docker.io/layer7api/graphman-static-init:1.0.0
- Image ID: docker.io/layer7api/graphman-static-init@sha256:24189a432c0283845664c6fd54c3e8d9f86ad9d35ef12714bb3a18b7aba85aa4
+ Image: docker.io/caapim/graphman-static-init:1.0.4
+ Image ID: docker.io/caapim/graphman-static-init@sha256:8cb1035035b18fa9dc2c95e2b584c758e78909b3f615ee5f49dce166e8aae213
Port:
Host Port:
State: Terminated
diff --git a/example/gateway/advanced-gateway.yaml b/example/gateway/advanced-gateway.yaml
index 59c054ca..1a110910 100644
--- a/example/gateway/advanced-gateway.yaml
+++ b/example/gateway/advanced-gateway.yaml
@@ -140,8 +140,7 @@ spec:
# Management port requires a separate service.
service:
enabled: false
- #annotations:
- # cloud.google.com/load-balancer-type: "Internal"
+ annotations: {}
type: ClusterIP
ports:
- name: management
@@ -159,7 +158,8 @@ spec:
enabled: false # this runs the gateway in dbbacked/ephemeral mode
# jdbcUrl: "jdbc:mysql://cluster1-haproxy.pxc.svc.cluster.local:3306/ssg"
service:
- # annotations:
+ annotations:
+ projectcontour.io/upstream-protocol.tls: "8443,9443"
type: LoadBalancer
ports:
- name: https
@@ -172,10 +172,8 @@ spec:
protocol: TCP
ingress:
enabled: true
- ingressClassName: nginx
- annotations:
- nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
- # nginx.ingress.kubernetes.io/ssl-passthrough: "true"
+ ingressClassName: contour
+ annotations: {}
tls:
- hosts:
- gateway.brcmlabs.com
diff --git a/example/gateway/openshift-gateway.yaml b/example/gateway/openshift-gateway.yaml
index d3b44509..faa449f6 100644
--- a/example/gateway/openshift-gateway.yaml
+++ b/example/gateway/openshift-gateway.yaml
@@ -142,13 +142,11 @@ spec:
protocol: TCP
ingress:
enabled: false
- ingressClassName: nginx
+ ingressClassName: contour
type: route
route:
host: gateway.brcmlabs.com
- annotations:
- # nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
- # nginx.ingress.kubernetes.io/ssl-passthrough: "true"
+ annotations: {}
tls:
- hosts:
- gateway.brcmlabs.coms
diff --git a/example/gateway/otel-elastic-gateway.yaml b/example/gateway/otel-elastic-gateway.yaml
index d2e97d1e..ce8aef44 100644
--- a/example/gateway/otel-elastic-gateway.yaml
+++ b/example/gateway/otel-elastic-gateway.yaml
@@ -94,9 +94,8 @@ spec:
secretName: gateway-secret
service:
enabled: true
- #annotations:
- # cloud.google.com/load-balancer-type: "Internal"
- type: LoadBalancer
+ annotations: {}
+ type: ClusterIP
ports:
- name: management
port: 9443
@@ -127,7 +126,7 @@ spec:
- -Dcom.l7tech.server.pkix.useDefaultTrustAnchors=true
- -Dcom.l7tech.security.ssl.hostAllowWildcard=true
listenPorts:
- harden: true
+ harden: false
custom:
enabled: true
ports:
@@ -253,9 +252,9 @@ spec:
- name: otel.traceEnabled
value: "true"
- name: otel.attributePrefix
- value: l7_
+ value: layer7_
- name: otel.metricPrefix
- value: l7_
+ value: layer7_
- name: otel.traceConfig
value: |
{
@@ -286,23 +285,18 @@ spec:
otel.java.global-autoconfigure.enabled=true
# Additional properties go here
service:
- # annotations:
- type: LoadBalancer
+ annotations:
+ projectcontour.io/upstream-protocol.tls: "8443"
+ type: ClusterIP
ports:
- name: https
port: 8443
targetPort: 8443
protocol: TCP
- - name: monitoring
- port: 8889
- targetPort: 8889
- protocol: TCP
ingress:
enabled: true
- ingressClassName: nginx
- annotations:
- nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
- # nginx.ingress.kubernetes.io/ssl-passthrough: "true"
+ ingressClassName: contour
+ annotations: {}
tls:
- hosts:
- gateway.brcmlabs.com
diff --git a/example/gateway/otel-lgtm-gateway.yaml b/example/gateway/otel-lgtm-gateway.yaml
index 1ee781df..116786c5 100644
--- a/example/gateway/otel-lgtm-gateway.yaml
+++ b/example/gateway/otel-lgtm-gateway.yaml
@@ -91,8 +91,8 @@ spec:
secretName: gateway-secret
service:
enabled: true
- #annotations:
- # cloud.google.com/load-balancer-type: "Internal"
+ annotations:
+ projectcontour.io/upstream-protocol.tls: "9443"
type: LoadBalancer
ports:
- name: management
@@ -250,9 +250,9 @@ spec:
- name: otel.traceEnabled
value: "true"
- name: otel.attributePrefix
- value: l7_
+ value: layer7_
- name: otel.metricPrefix
- value: l7_
+ value: layer7_
- name: otel.traceConfig
value: |
{
@@ -283,7 +283,8 @@ spec:
otel.java.global-autoconfigure.enabled=true
# Additional properties go here
service:
- # annotations:
+ annotations:
+ projectcontour.io/upstream-protocol.tls: "8443"
type: LoadBalancer
ports:
- name: https
@@ -292,10 +293,8 @@ spec:
protocol: TCP
ingress:
enabled: true
- ingressClassName: nginx
- annotations:
- nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
- # nginx.ingress.kubernetes.io/ssl-passthrough: "true"
+ ingressClassName: contour
+ annotations: {}
tls:
- hosts:
- gateway.brcmlabs.com
diff --git a/example/gateway/otel-lgtm-sdk-only-gateway.yaml b/example/gateway/otel-lgtm-sdk-only-gateway.yaml
index e41b7e1c..1acb9a87 100644
--- a/example/gateway/otel-lgtm-sdk-only-gateway.yaml
+++ b/example/gateway/otel-lgtm-sdk-only-gateway.yaml
@@ -89,8 +89,8 @@ spec:
secretName: gateway-secret
service:
enabled: true
- #annotations:
- # cloud.google.com/load-balancer-type: "Internal"
+ annotations:
+ projectcontour.io/upstream-protocol.tls: "9443"
type: LoadBalancer
ports:
- name: management
@@ -248,9 +248,9 @@ spec:
- name: otel.traceEnabled
value: "true"
- name: otel.attributePrefix
- value: l7_
+ value: layer7_
- name: otel.metricPrefix
- value: l7_
+ value: layer7_
- name: otel.traceConfig
value: |
{
@@ -281,7 +281,8 @@ spec:
otel.java.global-autoconfigure.enabled=true
# Additional properties go here
service:
- # annotations:
+ annotations:
+ projectcontour.io/upstream-protocol.tls: "8443"
type: LoadBalancer
ports:
- name: https
@@ -290,10 +291,8 @@ spec:
protocol: TCP
ingress:
enabled: true
- ingressClassName: nginx
- annotations:
- nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
- # nginx.ingress.kubernetes.io/ssl-passthrough: "true"
+ ingressClassName: contour
+ annotations: {}
tls:
- hosts:
- gateway.brcmlabs.com
diff --git a/example/gateway/otk/otk-dmz.yaml b/example/gateway/otk/otk-dmz.yaml
index d87d8c52..c4abe46d 100644
--- a/example/gateway/otk/otk-dmz.yaml
+++ b/example/gateway/otk/otk-dmz.yaml
@@ -84,8 +84,8 @@ spec:
# Management port requires a separate service...
service:
enabled: true
- #annotations:
- # cloud.google.com/load-balancer-type: "Internal"
+ annotations:
+ projectcontour.io/upstream-protocol.tls: "9443"
type: LoadBalancer
ports:
- name: management
@@ -155,7 +155,8 @@ spec:
com.l7tech.server.clusterStaleNodeCleanupTimeoutSeconds=86400
# Additional properties go here
service:
- # annotations:
+ annotations:
+ projectcontour.io/upstream-protocol.tls: "8443"
type: ClusterIP
ports:
- name: https
@@ -164,10 +165,8 @@ spec:
protocol: TCP
ingress:
enabled: true
- ingressClassName: nginx
- annotations:
- nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
- # nginx.ingress.kubernetes.io/ssl-passthrough: "true"
+ ingressClassName: contour
+ annotations: {}
tls:
- hosts:
- gateway-dmz.brcmlabs.com
diff --git a/example/gateway/otk/otk-internal.yaml b/example/gateway/otk/otk-internal.yaml
index d70af7e9..698e5350 100644
--- a/example/gateway/otk/otk-internal.yaml
+++ b/example/gateway/otk/otk-internal.yaml
@@ -149,7 +149,8 @@ spec:
com.l7tech.server.clusterStaleNodeCleanupTimeoutSeconds=86400
# Additional properties go here
service:
- # annotations:
+ annotations:
+ projectcontour.io/upstream-protocol.tls: "8443,9443"
type: ClusterIP
ports:
- name: https
@@ -162,10 +163,8 @@ spec:
protocol: TCP
ingress:
enabled: true
- ingressClassName: nginx
- annotations:
- nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
- # nginx.ingress.kubernetes.io/ssl-passthrough: "true"
+ ingressClassName: contour
+ annotations: {}
tls:
- hosts:
- gateway.brcmlabs.com
diff --git a/example/gateway/otk/otk-single.yaml b/example/gateway/otk/otk-single.yaml
index 641592fd..62dfcb04 100644
--- a/example/gateway/otk/otk-single.yaml
+++ b/example/gateway/otk/otk-single.yaml
@@ -77,33 +77,6 @@ spec:
databaseWaitTimeout: 60
singletonExtraction: true
- # livenessProbe:
- # httpGet:
- # port: https
- # scheme: HTTPS
- # path: /auth/oauth/health
- # httpHeaders:
- # - name: Host
- # value: 127.0.0.1
- # failureThreshold: 25
- # initialDelaySeconds: 15
- # periodSeconds: 10
- # successThreshold: 1
- # timeoutSeconds: 1
- # readinessProbe:
- # httpGet:
- # port: https
- # scheme: HTTPS
- # path: /auth/oauth/health
- # httpHeaders:
- # - name: Host
- # value: 127.0.0.1
- # failureThreshold: 25
- # initialDelaySeconds: 15
- # periodSeconds: 10
- # successThreshold: 1
- # timeoutSeconds: 1
-
bundle:
- type: restman
source: secret
@@ -155,6 +128,8 @@ spec:
secretName: gateway-secret
service:
enabled: true
+ annotations:
+ projectcontour.io/upstream-protocol.tls: "9443"
type: ClusterIP
ports:
- name: management
@@ -172,7 +147,8 @@ spec:
database:
enabled: false
service:
- # annotations:
+ annotations:
+ projectcontour.io/upstream-protocol.tls: "8443"
type: LoadBalancer
ports:
- name: https
@@ -191,9 +167,8 @@ spec:
# - host: gateway-otk-management.brcmlabs.com
# port:
# targetPort: management
- ingressClassName: nginx
- annotations:
- nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
+ ingressClassName: contour
+ annotations: {}
tls:
- hosts:
- gateway.brcmlabs.com
diff --git a/example/gateway/otk/otk-ssg-dmz.yaml b/example/gateway/otk/otk-ssg-dmz.yaml
new file mode 100644
index 00000000..3015705d
--- /dev/null
+++ b/example/gateway/otk/otk-ssg-dmz.yaml
@@ -0,0 +1,235 @@
+apiVersion: security.brcmlabs.com/v1
+kind: Gateway
+metadata:
+ name: otk-ssg-dmz
+spec:
+ version: "11.1.3"
+ license:
+ accept: true
+ secretName: gateway-license
+ app:
+ replicas: 1
+ image: docker.io/caapim/gateway:11.1.3
+ imagePullPolicy: IfNotPresent
+ updateStrategy:
+ type: rollingUpdate
+ rollingUpdate:
+ maxUnavailable: 0
+ maxSurge: 2
+ resources:
+ requests:
+ memory: 8Gi
+ cpu: 3
+ limits:
+ memory: 8Gi
+ cpu: 3
+ externalSecrets:
+ - name: gateway-secret
+ enabled: true
+ variableReferencable: true
+ description: Gateway Secret
+ # ExternalKeys with otk flag set to true for OTK-specific key usage
+ externalKeys:
+ - name: otk-dmz-tls-secret
+ enabled: true
+ alias: otk-dmz-key
+ keyUsageType: SSL
+ otk: true
+ otk:
+ enabled: true
+ initContainerImage: docker.io/caapim/otk-install:4.6.4
+ type: dmz
+ internalAuthSecret: otk-internal-auth-secret
+ internalGatewayReference: as673366-gw-upgrade-0.apim.labs.broadcom.net
+ # InternalGatewayPort is used when the Internal gateway is external (not managed by operator)
+ # If not specified, defaults to 9443 or the gateway's graphmanDynamicSync port
+ internalGatewayPort: 8443
+ # SyncIntervalSeconds determines how often DMZ and Internal gateways should update certificates
+ # Defaults to RuntimeSyncIntervalSeconds if not specified, or 10 seconds if neither is set
+ syncIntervalSeconds: 30
+ # Reference to the TLS secret for DMZ key (used by OTK reconciliation)
+ dmzKeySecret: otk-dmz-tls-secret
+ database:
+ type: mysql
+ create: true
+ connectionName: OAuth
+ auth:
+ # A single secret containing all of the values defined here will be created
+ # if existingSecret is set the corresponding gateway, readOnly or admin will be omitted from the secret
+ # if no values are set, a secret will not be created or referenced and the deployment will be invalidated.
+ # existingSecret: otk-db-secret
+ gateway:
+ username: otk_user
+ password: otkUserPass
+ readOnly:
+ # username: readonly_user
+ username: readonly_user
+ password: readonly_userPass
+ admin:
+ # username: admin
+ username: admin
+ password: adminPass
+ properties:
+ minimumPoolSize: 3
+ maximumPoolSize: 15
+ sql:
+ databaseName: otk_db
+ #jdbcUrl: jdbc:mysql://:/
+ jdbcUrl: jdbc:mysql://mysql.brcmlabs.com:3306/otk_db_init
+ jdbcDriverClass: com.mysql.cj.jdbc.Driver
+ connectionProperties:
+ c3p0.maxConnectionAge: "100"
+ c3p0.maxIdleTime: "1000"
+ manageSchema: true
+ databaseWaitTimeout: 60
+ autoscaling:
+ enabled: false
+ bundle:
+ - type: restman
+ source: secret
+ name: restman-bootstrap-bundle
+ - type: graphman
+ source: secret
+ name: graphman-bootstrap-bundle
+ repositoryReferences:
+ - name: l7-gw-myframework
+ enabled: true
+ type: static
+ encryption:
+ existingSecret: graphman-encryption-secret
+ key: FRAMEWORK_ENCRYPTION_PASSPHRASE
+ - name: l7-gw-myapis
+ enabled: true
+ type: dynamic
+ encryption:
+ existingSecret: graphman-encryption-secret
+ key: APIS_ENCRYPTION_PASSPHRASE
+ - name: l7-gw-mysubscriptions
+ enabled: true
+ type: dynamic
+ encryption:
+ existingSecret: graphman-encryption-secret
+ key: SUBSCRIPTIONS_ENCRYPTION_PASSPHRASE
+ - name: local-reference-repository
+ enabled: true
+ type: dynamic
+ encryption: { }
+ - name: otk-customizations-dmz
+ enabled: true
+ type: dynamic
+ encryption: { }
+ bootstrap:
+ script:
+ enabled: true
+ initContainers: []
+ hazelcast:
+ external: false
+ endpoint: hazelcast.example.com:5701
+ management:
+ secretName: gateway-secret
+ #username: admin
+ #password: 7layer
+ # Management port requires a separate service...
+ service:
+ enabled: true
+ annotations:
+ projectcontour.io/upstream-protocol.tls: "8443"
+ type: LoadBalancer
+ ports:
+ - name: management
+ port: 9443
+ targetPort: 9443
+ protocol: TCP
+ restman:
+ enabled: false
+ graphman:
+ enabled: true
+ initContainerImage: docker.io/caapim/graphman-static-init:1.0.4
+ dynamicSyncPort: 9443
+ cluster:
+ #password: 7layer
+ hostname: gateway.brcmlabs.com
+ database:
+ enabled: false # this runs the gateway in dbbacked/ephemeral mode
+ # jdbcUrl: "jdbc:mysql://cluster1-haproxy.pxc.svc.cluster.local:3306/ssg"
+ # username: "gateway"
+ # password: "ACm8BDr3Rfk2Flx9V"
+ java:
+ jvmHeap:
+ calculate: true
+ percentage: 50
+ default: 4g
+ extraArgs:
+ - -Dcom.l7tech.server.audit.message.saveToInternal=false
+ - -Dcom.l7tech.server.audit.admin.saveToInternal=false
+ - -Dcom.l7tech.server.audit.system.saveToInternal=false
+ - -Dcom.l7tech.server.audit.log.format=json
+ - -Djava.util.logging.config.file=/opt/SecureSpan/Gateway/node/default/etc/conf/log-override.properties
+ - -Dcom.l7tech.security.ssl.hostAllowWildcard=true
+ - -Dcom.l7tech.server.pkix.useDefaultTrustAnchors=true
+ #- -Dcom.l7tech.bootstrap.autoTrustSslKey=trustAnchor,TrustedFor.SSL,TrustedFor.SAML_ISSUER
+ listenPorts:
+ harden: true
+ custom:
+ enabled: false
+ ports: []
+ cwp:
+ enabled: true
+ properties:
+ - name: io.httpsHostAllowWildcard
+ value: "true"
+ - name: log.levels
+ value: |
+ com.l7tech.level = CONFIG
+ com.l7tech.server.policy.variable.ServerVariables.level = SEVERE
+ com.l7tech.external.assertions.odata.server.producer.jdbc.GenerateSqlQuery.level = SEVERE
+ com.l7tech.server.policy.assertion.ServerSetVariableAssertion.level = SEVERE
+ com.l7tech.external.assertions.comparison.server.ServerComparisonAssertion.level = SEVERE
+ - name: audit.setDetailLevel.FINE
+ value: 152 7101 7103 9648 9645 7026 7027 4155 150 4716 4114 6306 4100 9655 150 151 11000 4104
+ system:
+ properties: |-
+ # Default Gateway system properties
+ # Configuration properties for shared state extensions.
+ com.l7tech.server.extension.sharedKeyValueStoreProvider=embeddedhazelcast
+ com.l7tech.server.extension.sharedCounterProvider=ssgdb
+ com.l7tech.server.extension.sharedClusterInfoProvider=ssgdb
+ # By default, FIPS module will block an RSA modulus from being used for encryption if it has been used for
+ # signing, or visa-versa. Set true to disable this default behaviour and remain backwards compatible.
+ com.l7tech.org.bouncycastle.rsa.allow_multi_use=true
+ # Specifies the type of Trust Store (JKS/PKCS12) provided by AdoptOpenJDK that is used by Gateway.
+ # Must be set correctly when Gateway is running in FIPS mode. If not specified it will default to PKCS12.
+ javax.net.ssl.trustStoreType=jks
+ com.l7tech.server.clusterStaleNodeCleanupTimeoutSeconds=86400
+ # Additional properties go here
+ service:
+ annotations:
+ projectcontour.io/upstream-protocol.tls: "8443"
+ type: ClusterIP
+ ports:
+ - name: https
+ port: 8443
+ targetPort: 8443
+ protocol: TCP
+ ingress:
+ enabled: true
+ ingressClassName: contour
+ annotations: {}
+ tls:
+ - hosts:
+ - otk-ssg-dmz.brcmlabs.com
+ secretName: brcmlabs
+ rules:
+ - host: otk-ssg-dmz.brcmlabs.com
+ # containerSecurityContext:
+ # runAsNonRoot: true
+ # runAsUser: 1000669998
+ # capabilities:
+ # drop:
+ # - ALL
+ # allowPrivilegeEscalation: false
+ # podSecurityContext:
+ # runAsUser: 1000669998
+ # runAsGroup: 1000669998
+
+
diff --git a/example/gateway/otel-prometheus-gateway.yaml b/example/gateway/otk/otk-ssg-internal.yaml
similarity index 60%
rename from example/gateway/otel-prometheus-gateway.yaml
rename to example/gateway/otk/otk-ssg-internal.yaml
index 42ea05ec..6cce28b6 100644
--- a/example/gateway/otel-prometheus-gateway.yaml
+++ b/example/gateway/otk/otk-ssg-internal.yaml
@@ -1,17 +1,13 @@
apiVersion: security.brcmlabs.com/v1
kind: Gateway
metadata:
- name: ssg
+ name: otk-ssg-internal
spec:
version: "11.1.3"
license:
- accept: false
+ accept: true
secretName: gateway-license
app:
- podAnnotations:
- sidecar.opentelemetry.io/inject: "ssg-prom"
- instrumentation.opentelemetry.io/inject-java: "true"
- instrumentation.opentelemetry.io/container-names: "gateway"
replicas: 1
image: docker.io/caapim/gateway:11.1.3
imagePullPolicy: IfNotPresent
@@ -21,14 +17,74 @@ spec:
maxUnavailable: 0
maxSurge: 2
resources:
- requests: {}
- limits: {}
+ requests:
+ memory: 8Gi
+ cpu: 3
+ limits:
+ memory: 8Gi
+ cpu: 3
+ # ExternalKeys with otk flag set to true for OTK-specific key usage
+ externalKeys:
+ - name: otk-internal-tls-secret
+ enabled: true
+ alias: otk-internal-key
+ keyUsageType: SSL
+ otk: true
+ otk:
+ enabled: true
+ initContainerImage: docker.io/caapim/otk-install:4.6.4
+ type: internal
+ dmzGatewayReference: otk-ssg-dmz
+ # DmzGatewayPort is used when the DMZ gateway is external (not managed by operator)
+ # If not specified, defaults to 9443 or the gateway's graphmanDynamicSync port
+ dmzGatewayPort: 9443
+ # SyncIntervalSeconds determines how often DMZ and Internal gateways should update certificates
+ # Defaults to RuntimeSyncIntervalSeconds if not specified, or 10 seconds if neither is set
+ syncIntervalSeconds: 30
+ # Reference to the TLS secret for Internal key (used by OTK reconciliation)
+ internalKeySecret: otk-internal-tls-secret
+ database:
+ type: mysql
+ create: true
+ connectionName: OAuth
+ auth:
+ # A single secret containing all of the values defined here will be created
+ # if existingSecret is set the corresponding gateway, readOnly or admin will be omitted from the secret
+ # if no values are set, a secret will not be created or referenced and the deployment will be invalidated.
+ # existingSecret: otk-db-secret
+ gateway:
+ username: otk_user
+ password: otkUserPass
+ readOnly:
+ # username: readonly_user
+ username: readonly_user
+ password: readonly_userPass
+ admin:
+ # username: admin
+ username: admin
+ password: adminPass
+ properties:
+ minimumPoolSize: 3
+ maximumPoolSize: 15
+ sql:
+ databaseName: otk_db
+ #jdbcUrl: jdbc:mysql://:/
+ jdbcUrl: jdbc:mysql://mysql.brcmlabs.com:3306/otk_db_init
+ jdbcDriverClass: com.mysql.cj.jdbc.Driver
+ connectionProperties:
+ c3p0.maxConnectionAge: "100"
+ c3p0.maxIdleTime: "1000"
+ manageSchema: true
+ databaseWaitTimeout: 60
autoscaling:
enabled: false
bundle:
+ - type: restman
+ source: secret
+ name: restman-bootstrap-bundle
- type: graphman
source: secret
- name: global-bundle
+ name: graphman-bootstrap-bundle
repositoryReferences:
- name: l7-gw-myframework
enabled: true
@@ -48,9 +104,17 @@ spec:
encryption:
existingSecret: graphman-encryption-secret
key: SUBSCRIPTIONS_ENCRYPTION_PASSPHRASE
+ - name: local-reference-repository
+ enabled: true
+ type: dynamic
+ encryption: { }
+ - name: otk-customizations-internal
+ enabled: true
+ type: dynamic
+ encryption: { }
bootstrap:
script:
- enabled: false
+ enabled: true
initContainers: []
hazelcast:
external: false
@@ -64,7 +128,7 @@ spec:
enabled: false
#annotations:
# cloud.google.com/load-balancer-type: "Internal"
- type: ClusterIP
+ type: LoadBalancer
ports:
- name: management
port: 9443
@@ -87,29 +151,21 @@ spec:
jvmHeap:
calculate: true
percentage: 50
- default: 2g
+ default: 4g
extraArgs:
- - -Dcom.l7tech.bootstrap.autoTrustSslKey=trustAnchor,TrustedFor.SSL,TrustedFor.SAML_ISSUER
- -Dcom.l7tech.server.audit.message.saveToInternal=false
- -Dcom.l7tech.server.audit.admin.saveToInternal=false
- -Dcom.l7tech.server.audit.system.saveToInternal=false
- -Dcom.l7tech.server.audit.log.format=json
- -Djava.util.logging.config.file=/opt/SecureSpan/Gateway/node/default/etc/conf/log-override.properties
- - -Dcom.l7tech.server.pkix.useDefaultTrustAnchors=true
- -Dcom.l7tech.security.ssl.hostAllowWildcard=true
+ - -Dcom.l7tech.server.pkix.useDefaultTrustAnchors=true
+ #- -Dcom.l7tech.bootstrap.autoTrustSslKey=trustAnchor,TrustedFor.SSL,TrustedFor.SAML_ISSUER
listenPorts:
harden: true
custom:
enabled: false
ports: []
- log:
- override: true
- properties: |-
- handlers = com.l7tech.server.log.GatewayRootLoggingHandler, com.l7tech.server.log.ConsoleMessageSink$L7ConsoleHandler
- com.l7tech.server.log.GatewayRootLoggingHandler.formatter = com.l7tech.util.JsonLogFormatter
- java.util.logging.SimpleFormatter.format=
- com.l7tech.server.log.ConsoleMessageSink$L7ConsoleHandler.formatter = com.l7tech.util.JsonLogFormatter
- com.l7tech.server.log.ConsoleMessageSink$L7ConsoleHandler.level = CONFIG
cwp:
enabled: true
properties:
@@ -124,21 +180,6 @@ spec:
com.l7tech.external.assertions.comparison.server.ServerComparisonAssertion.level = SEVERE
- name: audit.setDetailLevel.FINE
value: 152 7101 7103 9648 9645 7026 7027 4155 150 4716 4114 6306 4100 9655 150 151 11000 4104
- - name: otel.enabled
- value: "true"
- - name: otel.serviceMetricEnabled
- value: "true"
- - name: otel.traceEnabled
- value: "true"
- - name: otel.metricPrefix
- value: l7_
- - name: otel.traceConfig
- value: |
- {
- "services": [
- {"resolutionPath": ".*"}
- ]
- }
system:
properties: |-
# Default Gateway system properties
@@ -153,17 +194,11 @@ spec:
# Must be set correctly when Gateway is running in FIPS mode. If not specified it will default to PKCS12.
javax.net.ssl.trustStoreType=jks
com.l7tech.server.clusterStaleNodeCleanupTimeoutSeconds=86400
- # OpenTelemetry Agent Configuration
- otel.instrumentation.common.default-enabled=true
- otel.instrumentation.opentelemetry-api.enabled=true
- otel.instrumentation.runtime-metrics.enabled=true
- otel.instrumentation.runtime-telemetry.enabled=true
- otel.instrumentation.opentelemetry-instrumentation-annotations.enabled=true
- otel.java.global-autoconfigure.enabled=true
# Additional properties go here
service:
- # annotations:
- type: LoadBalancer
+ annotations:
+ projectcontour.io/upstream-protocol.tls: "8443,9443"
+ type: ClusterIP
ports:
- name: https
port: 8443
@@ -172,23 +207,17 @@ spec:
- name: management
port: 9443
targetPort: 9443
- protocol: TCP
- - name: monitoring
- port: 8889
- targetPort: 8889
- protocol: TCP
+ protocol: TCP
ingress:
enabled: true
- ingressClassName: nginx
- annotations:
- nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
- # nginx.ingress.kubernetes.io/ssl-passthrough: "true"
+ ingressClassName: contour
+ annotations: {}
tls:
- hosts:
- - gateway.brcmlabs.com
- secretName: default
+ - otk-ssg-internal.brcmlabs.com
+ secretName: brcmlabs
rules:
- - host: gateway.brcmlabs.com
+ - host: otk-ssg-internal.brcmlabs.com
# containerSecurityContext:
# runAsNonRoot: true
# runAsUser: 1000669998
@@ -198,4 +227,6 @@ spec:
# allowPrivilegeEscalation: false
# podSecurityContext:
# runAsUser: 1000669998
- # runAsGroup: 1000669998
\ No newline at end of file
+ # runAsGroup: 1000669998
+
+
diff --git a/example/gateway/portal-gateway.yaml b/example/gateway/portal-gateway.yaml
index d98c470b..63fec246 100644
--- a/example/gateway/portal-gateway.yaml
+++ b/example/gateway/portal-gateway.yaml
@@ -241,7 +241,8 @@ spec:
com.l7tech.external.assertions.keyvaluestore.sharedKeyValueStoreProvider=redis
com.l7tech.external.assertions.keyvaluestore.storeIdList=GW_STORE_ID
service:
- # annotations:
+ annotations:
+ projectcontour.io/upstream-protocol.tls: "8443,9443"
type: ClusterIP
ports:
- name: https
@@ -254,9 +255,8 @@ spec:
protocol: TCP
ingress:
enabled: true
- ingressClassName: nginx
- annotations:
- nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
+ ingressClassName: contour
+ annotations: {}
tls:
- hosts:
- gateway.brcmlabs.com
diff --git a/example/images/elastic-assets.gif b/example/images/elastic-assets.gif
deleted file mode 100644
index a51ccdfd..00000000
Binary files a/example/images/elastic-assets.gif and /dev/null differ
diff --git a/example/otel-elastic/README.md b/example/otel-elastic/README.md
index 1f9544ac..9fa27911 100644
--- a/example/otel-elastic/README.md
+++ b/example/otel-elastic/README.md
@@ -10,7 +10,7 @@ By the end of this example you should have a better understanding of the how to
- Filebeat
- MetricBeat
- Kibana
-- Nginx (Ingress Controller)
+- [Contour](https://projectcontour.io/) (Ingress Controller)
### Elastic Stack Note
This example creates a single [Elastic Search](./components/es.yaml) node with a 100GB volume. This is not production ready implementation, please refer to the [Official Elastic Documentation](https://www.elastic.co/guide/en/cloud-on-k8s/current/index.html) for sizing guidelines and additional configuration options.
@@ -24,9 +24,10 @@ We make use of Filebeat for container log files (the Gateway + everything else)

## Prerequisites
-- Kubernetes v1.25+
+- Kubernetes v1.34+
- Gateway v11.x License
- Ingress Controller (for kibana)
+ - we have switched all examples from [Nginx](https://kubernetes.github.io/ingress-nginx/) to [Contour](https://projectcontour.io/)
This OTel Elastic Example requires multiple namespaces for the additional components. Your Kubernetes user or service account must have sufficient privileges to create namespaces, deployments, configmaps, secrets, service accounts, roles, etc.
@@ -105,15 +106,15 @@ If you have a docker machine available you can use [Kind](https://kind.sigs.k8s.
```
3. If you would like to create a TLS secret for your ingress controller then add tls.crt and tls.key to [base/resources/secrets/tls](../base/resources/secrets/tls)
- these will be referenced later on.
-4. You will need an ingress controller like nginx
+4. You will need an ingress controller like contour
- if you do not have one installed already you can use the makefile in the example directory to deploy one
- ```cd example```
- Generic Kubernetes
- - ```make nginx```
+ - ```make contour```
- Kind (Kubernetes in Docker)
- follow the steps in Quickstart
or
- - ```make nginx-kind```
+ - ```make contour-kind```
- return to the previous folder
- ```cd ..```
@@ -133,9 +134,9 @@ If you use Quickstart you do not need to install/deploy any additional resources
### Monitoring/Observability Components
- [Install Cert Manager](#install-cert-manager)
- [Install Open Telemetry](#install-open-telemetry)
-- [Install an Ingress Controller(optional)](#install-nginx)
+- [Install an Ingress Controller(optional)](#install-contour)
- [Install the Elastic Stack](#install-the-elastic-stack)
-- [Install APM Components (Kibana UI)](#elastic-post-installation-tasks)
+- [Deploy the Layer7 Dashboard (Kibana UI)](#elastic-post-installation-tasks)
### Layer7 Operator
- [Deploy the Operator](#deploy-the-layer7-operator)
@@ -149,7 +150,7 @@ If you use Quickstart you do not need to install/deploy any additional resources
The container gateway configuration required for this integration is relatively simple. We will set some environment variables in our OTel [instrumentation](./instrumentation.yaml) that the Otel Agent present on the Container Gateway will use to send logs, traces and metrics to the Otel Collector sidecar.
```
-apiVersion: opentelemetry.io/v1alpha1
+apiVersion: opentelemetry.io/v1beta1
kind: Instrumentation
metadata:
name: otel-instrumentation
@@ -354,29 +355,30 @@ This quickstart uses the Makefile to install of the necessary components into yo
```
cd example
```
-If you don't already have an ingress controller you can deploy nginx with the following command
+If you don't already have an ingress controller you can deploy contour with the following command
- Suppports most Kubernetes Environments
```
-make nginx
+make contour
```
- If you're using Kind
```
-make nginx-kind
+make contour-kind
```
- Additional options can be found here
```
-https://github.com/kubernetes/ingress-nginx/tree/main/deploy/static/provider
+https://projectcontour.io/docs/1.33/
```
-- Once nginx has been installed get the L4 LoadBalancer address
+- Once contour has been installed get the L4 LoadBalancer address
```
-kubectl get svc -n ingress-nginx
+kubectl get svc -n projectcontour
```
output
```
-NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
-ingress-nginx-controller LoadBalancer 10.152.183.52 192.168.1.190 80:30183/TCP,443:30886/TCP 24m
-ingress-nginx-controller-admission ClusterIP 10.152.183.132 443/TCP 24m
+NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
+contour ClusterIP 10.96.134.188 8001/TCP 29m
+contour-envoy LoadBalancer 10.96.165.146 192.168.1.190 80:30377/TCP,443:31908/TCP 29m
+
```
- You probably don't have access to a DNS server for this demo so you will need to add the following entries to your hosts file
```
@@ -398,7 +400,7 @@ export elasticPass=$(kubectl get secret quickstart-es-elastic-user -o go-templat
```
Create Dashboard
```
-curl -XPOST https://kibana.brcmlabs.com/api/saved_objects/_import?createNewCopies=false -H "kbn-xsrf: true" -k -uelastic:$elasticPass -F "file=@./otel-elastic/dashboard/apim-dashboard.ndjson"
+curl -XPOST "https://kibana.brcmlabs.com/api/saved_objects/_import?createNewCopies=false" -H "kbn-xsrf: true" -k -uelastic:$elasticPass -F "file=@./otel-elastic/dashboard/apim-dashboard.ndjson"
```
- wait for all components to be ready
@@ -428,7 +430,7 @@ You can now move on to test your gateway deployment!
### Install Cert Manager
These steps are based the official documentation for installing Cert-Manager [here](https://cert-manager.io/docs/installation/). Cert-Manager is a pre-requisite for the Open Telemetry Operator.
```
-kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.11.0/cert-manager.yaml
+kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.20.0/cert-manager.yaml
```
#### View CertManager Components
@@ -462,7 +464,7 @@ These steps are based the official documentation for installing Open Telemetry [
- Install the Open Telemetry Operator.
```
-kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/download/v0.76.1/opentelemetry-operator.yaml
+kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/download/v0.146.0/opentelemetry-operator.yaml
```
##### View Open Telemetry Components
@@ -483,20 +485,51 @@ NAME DESIRED
replicaset.apps/opentelemetry-operator-controller-manager-5d84764d4b 1 1 1 72d
```
-### Install Nginx
-This command will deploy an nginx ingress controller. If you already have nginx or another ingress controller running in your Kubernetes cluster you can safely ignore this step.
+### Install Contour
+This command will deploy the [contour](https://projectcontour.io/) ingress controller. If you already have contour or another ingress controller running in your Kubernetes cluster you can safely ignore this step.
Suppports most Kubernetes Environments
```
-kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
+helm repo add contour https://projectcontour.github.io/helm-charts/
+helm upgrade --install contour contour/contour --namespace projectcontour --create-namespace
+kubectl wait --for=condition=ready --timeout=600s pod -l app.kubernetes.io/name=contour,app.kubernetes.io/component=contour -n projectcontour
+kubectl wait --for=condition=ready --timeout=600s pod -l app.kubernetes.io/name=contour,app.kubernetes.io/component=envoy -n projectcontour
```
If you're using Kind
```
-kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
+helm repo add contour https://projectcontour.github.io/helm-charts/
+helm upgrade --install contour contour/contour --namespace projectcontour --set envoy.useHostPort.http=true --set envoy.useHostPort.https=true --create-namespace
+kubectl wait --for=condition=ready --timeout=600s pod -l app.kubernetes.io/name=contour,app.kubernetes.io/component=contour -n projectcontour
+kubectl wait --for=condition=ready --timeout=600s pod -l app.kubernetes.io/name=contour,app.kubernetes.io/component=envoy -n projectcontour
```
Additional options can be found here
```
-https://github.com/kubernetes/ingress-nginx/tree/main/deploy/static/provider
+https://projectcontour.io/docs/1.33/
+```
+
+#### Create a self-signed certificate for Contour to use
+This is done automatically if you are using the quickstart commands via the Makefile. These steps can be simplified to the following
+```
+make pki NAMESPACE=default
+```
+
+##### If you would like to run the steps manually do the following.
+
+- Set your namespace
+```
+export NAMESPACE=default
+```
+- Create self signed cert using openssl (this will be saved to your /tmp folder)
+```
+openssl req -x509 -newkey rsa:2048 -nodes -days 365 -subj "/CN=*.brcmlabs.com" \
+ -addext "subjectAltName=DNS:*.brcmlabs.com,DNS:brcmlabs.com" \
+ -keyout /tmp/tls.key -out /tmp/tls.crt
+```
+- Create a Kubernetes TLS secret
+```
+kubectl create secret tls brcmlabs \
+ --cert=/tmp/tls.crt --key=/tmp/tls.key \
+ -n $NAMESPACE --dry-run=client -o yaml | kubectl apply -f -
```
### Install the Elastic Stack
@@ -504,8 +537,8 @@ These steps are based the [official documentation](https://www.elastic.co/guide/
#### Install Elastic Operator and Custom Resource Definitions
```
-kubectl create -f https://download.elastic.co/downloads/eck/2.8.0/crds.yaml
-kubectl apply -f https://download.elastic.co/downloads/eck/2.8.0/operator.yaml
+kubectl create -f https://download.elastic.co/downloads/eck/3.3.1/crds.yaml
+kubectl apply -f https://download.elastic.co/downloads/eck/3.3.1/operator.yaml
kubectl wait --for=condition=ready --timeout=60s pod -l control-plane=elastic-operator -n elastic-system
```
@@ -547,33 +580,16 @@ kubectl apply -f ./example/otel-elastic/instrumentation.yaml
```
#### Elastic Post Installation Tasks
-The Layer7 Dashboard can be installed via the Kibana API, Elastic APM Components need to be manually installed via Kibana in a web browser.
+The Layer7 Dashboard can be installed via the Kibana API.
#### Create the Layer7 Dashboard
Get the Elastic user password, you will use this password when logging into Kibana.
```
export elasticPass=$(kubectl get secret quickstart-es-elastic-user -o go-template='{{.data.elastic | base64decode}}')
-curl -XPOST https://kibana.brcmlabs.com/api/saved_objects/_import?createNewCopies=false -H "kbn-xsrf: true" -k -uelastic:$elasticPass -F "file=@./example/otel-elastic/dashboard/apim-dashboard.ndjson"
+curl -XPOST "https://kibana.brcmlabs.com/api/saved_objects/_import?createNewCopies=false" -H "kbn-xsrf: true" -k -uelastic:$elasticPass -F "file=@./example/otel-elastic/dashboard/apim-dashboard.ndjson"
```
-#### Install APM Components
-There are additional APM Components that need to be installed via Kibana in a browser to see Gateway traces.
-
-- Navigate to the following [link](https://kibana.brcmlabs.com/app/integrations/detail/apm/overview) in a browser, you will need to accept the certificate warning and continue.
-- Sign in
- - username: elastic
- - password: elastic-user-password
- ```
- echo $elasticPass
- ```
-- Click on the settings tab
- - Install Elastic APM Assets
- - Install Elastic APM
-
-
-
-
### Deploy the Layer7 Operator
This step will deploy the Layer7 Operator and all of its resources in namespaced mode. This means that it will only manage Gateway and Repository Custom Resources in the Kubernetes Namespace that it's deployed in.
@@ -677,8 +693,8 @@ kubectl describe pods ssg-57d96567cb-n24g9
Init Containers:
graphman-static-init-c1b58adb6d:
Container ID: containerd://21924ae85d25437d3634ea5da1415c9bb58d678600f9fd67d4f0b0360857d7c5
- Image: docker.io/layer7api/graphman-static-init:1.0.0
- Image ID: docker.io/layer7api/graphman-static-init@sha256:24189a432c0283845664c6fd54c3e8d9f86ad9d35ef12714bb3a18b7aba85aa4
+ Image: docker.io/caapim/graphman-static-init:1.0.4
+ Image ID: docker.io/caapim/graphman-static-init@sha256:8cb1035035b18fa9dc2c95e2b584c758e78909b3f615ee5f49dce166e8aae213
Port:
Host Port:
State: Terminated
@@ -766,7 +782,7 @@ status:
kubectl get ingress
NAME CLASS HOSTS ADDRESS PORTS AGE
-ssg nginx gateway.brcmlabs.com 34.89.126.80 80, 443 54m
+ssg contour gateway.brcmlabs.com 34.89.126.80 80, 443 54m
```
Add the following to your hosts file for DNS resolution
@@ -855,19 +871,19 @@ make uninstall-kind
kubectl delete -f ./example/otel-elastic/components
kubectl delete -f ./example/otel-elastic/collector.yaml
kubectl delete -f ./example/otel-elastic/instrumentation.yaml
-kubectl delete -f https://download.elastic.co/downloads/eck/2.8.0/crds.yaml
-kubectl delete -f https://download.elastic.co/downloads/eck/2.8.0/operator.yaml
-kubectl delete -f https://github.com/open-telemetry/opentelemetry-operator/releases/download/v0.76.1/opentelemetry-operator.yaml
-kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.11.0/cert-manager.yaml
+kubectl delete -f https://download.elastic.co/downloads/eck/3.3.1/crds.yaml
+kubectl delete -f https://download.elastic.co/downloads/eck/3.3.1/operator.yaml
+kubectl delete -f https://github.com/open-telemetry/opentelemetry-operator/releases/download/v0.146.0/opentelemetry-operator.yaml
+kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.20.0/cert-manager.yaml
kubectl delete -k ./example/repositories/
kubectl delete -f ./example/gateway/otel-elastic-gateway.yaml
```
-If you deployed Nginx manually
+If you deployed Contour manually
```
-kubectl delete -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
+helm uninstall contour -n projectcontour
```
### Uninstall the Operator
diff --git a/example/otel-elastic/collector.yaml b/example/otel-elastic/collector.yaml
index bb714338..c5bf04be 100644
--- a/example/otel-elastic/collector.yaml
+++ b/example/otel-elastic/collector.yaml
@@ -1,11 +1,11 @@
-apiVersion: opentelemetry.io/v1alpha1
+apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
name: ssg-eck
spec:
- image: otel/opentelemetry-collector-contrib:0.97.0
+ image: otel/opentelemetry-collector-contrib:0.147.0
mode: sidecar
- config: |
+ config:
receivers:
otlp:
protocols:
@@ -14,7 +14,6 @@ spec:
http:
endpoint: 0.0.0.0:4318
processors:
- batch:
resource:
attributes:
- key: layer7gw.name
@@ -30,20 +29,15 @@ spec:
headers:
Authorization: "Bearer APM_AUTH_TOKEN"
service:
- telemetry:
- logs:
- level: "debug"
- metrics:
- address: "0.0.0.0:8888"
pipelines:
traces:
receivers: [otlp]
- processors: [resource,batch]
+ processors: [resource]
exporters: [otlp/elastic]
metrics:
receivers: [otlp]
- processors: [resource,batch]
- exporters: [otlp/elastic,debug]
+ processors: [resource]
+ exporters: [otlp/elastic]
logs:
receivers: [otlp]
- exporters: [otlp/elastic, debug]
\ No newline at end of file
+ exporters: [otlp/elastic]
\ No newline at end of file
diff --git a/example/otel-elastic/components/agent.yaml b/example/otel-elastic/components/agent.yaml
index a87cf6fc..3f5efdd1 100644
--- a/example/otel-elastic/components/agent.yaml
+++ b/example/otel-elastic/components/agent.yaml
@@ -3,7 +3,7 @@ kind: Agent
metadata:
name: elastic-agent
spec:
- version: 8.8.2
+ version: 9.3.1
elasticsearchRefs:
- name: quickstart
daemonSet:
@@ -38,7 +38,7 @@ spec:
meta:
package:
name: kubernetes
- version: 0.2.8
+ version: 1.35.2
data_stream:
namespace: k8s
streams:
diff --git a/example/otel-elastic/components/apm.yaml b/example/otel-elastic/components/apm.yaml
index 092b1f82..95648831 100644
--- a/example/otel-elastic/components/apm.yaml
+++ b/example/otel-elastic/components/apm.yaml
@@ -3,7 +3,7 @@ kind: ApmServer
metadata:
name: apm-server-quickstart
spec:
- version: 8.8.2
+ version: 9.3.1
count: 1
elasticsearchRef:
name: quickstart
diff --git a/example/otel-elastic/components/es.yaml b/example/otel-elastic/components/es.yaml
index 3c966781..9bd9331f 100644
--- a/example/otel-elastic/components/es.yaml
+++ b/example/otel-elastic/components/es.yaml
@@ -38,12 +38,6 @@ spec:
- -c
- sysctl -w vm.max_map_count=262144
name: sysctl
- # - name: install-plugins
- # command:
- # - sh
- # - -c
- # - |
- # bin/elasticsearch-plugin install --batch elastic-apm
resources: {}
securityContext:
privileged: true
@@ -57,4 +51,4 @@ spec:
certificate: {}
updateStrategy:
changeBudget: {}
- version: 8.8.2
+ version: 9.3.1
diff --git a/example/otel-elastic/components/filebeat.yaml b/example/otel-elastic/components/filebeat.yaml
index cfc1347a..f6771a4f 100644
--- a/example/otel-elastic/components/filebeat.yaml
+++ b/example/otel-elastic/components/filebeat.yaml
@@ -4,7 +4,7 @@ metadata:
name: filebeat
spec:
type: filebeat
- version: 8.8.2
+ version: 9.3.1
elasticsearchRef:
name: quickstart
kibanaRef:
diff --git a/example/otel-elastic/components/ingress.yaml b/example/otel-elastic/components/ingress.yaml
index 26115114..c25cb07d 100644
--- a/example/otel-elastic/components/ingress.yaml
+++ b/example/otel-elastic/components/ingress.yaml
@@ -1,11 +1,9 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
- annotations:
- nginx.ingress.kubernetes.io/backend-protocol: HTTPS
name: kibana
spec:
- ingressClassName: nginx
+ ingressClassName: contour
rules:
- host: kibana.brcmlabs.com
http:
@@ -20,4 +18,4 @@ spec:
tls:
- hosts:
- kibana.brcmlabs.com
- secretName: default
\ No newline at end of file
+ secretName: brcmlabs
\ No newline at end of file
diff --git a/example/otel-elastic/components/kibana.yaml b/example/otel-elastic/components/kibana.yaml
index 7e0062f6..8c2daf12 100644
--- a/example/otel-elastic/components/kibana.yaml
+++ b/example/otel-elastic/components/kibana.yaml
@@ -3,11 +3,14 @@ kind: Kibana
metadata:
name: quickstart
spec:
- version: 8.8.2
+ version: 9.3.1
count: 1
elasticsearchRef:
name: quickstart
http:
service:
+ metadata:
+ annotations:
+ projectcontour.io/upstream-protocol.tls: "5601"
spec:
type: ClusterIP # default is ClusterIP
diff --git a/example/otel-elastic/components/metricbeat.yaml b/example/otel-elastic/components/metricbeat.yaml
index 16d3216f..c3d7dcfb 100644
--- a/example/otel-elastic/components/metricbeat.yaml
+++ b/example/otel-elastic/components/metricbeat.yaml
@@ -4,7 +4,7 @@ metadata:
name: metricbeat
spec:
type: metricbeat
- version: 8.8.2
+ version: 9.3.1
elasticsearchRef:
name: quickstart
kibanaRef:
@@ -73,7 +73,7 @@ spec:
- -e
- -c
- /etc/beat.yml
- - -system.hostfs=/hostfs
+ - --system.hostfs=/hostfs
name: metricbeat
volumeMounts:
- mountPath: /hostfs/sys/fs/cgroup
diff --git a/example/otel-elastic/dashboard/apim-dashboard.ndjson b/example/otel-elastic/dashboard/apim-dashboard.ndjson
index 5321762c..7e361655 100644
--- a/example/otel-elastic/dashboard/apim-dashboard.ndjson
+++ b/example/otel-elastic/dashboard/apim-dashboard.ndjson
@@ -1,3 +1,3 @@
-{"attributes":{"allowNoIndex":true,"fieldAttrs":"{\"layer7_service_routing_latency\":{\"count\":5},\"broadcom_totalBackendLatency\":{\"count\":1},\"@timestamp\":{\"count\":1},\"layer7_totalBackendLatency\":{\"count\":2},\"layer7_totalBackendLatencyV1\":{\"count\":1},\"layer7_totalFrontendLatency\":{\"count\":1},\"db.client.connections.usage\":{\"count\":2},\"labels.pool_name\":{\"count\":1},\"labels.state\":{\"count\":1},\"process.runtime.jvm.classes.loaded\":{\"count\":2},\"db.client.connections.pending_requests\":{\"count\":1},\"labels.process_runtime_description\":{\"count\":2},\"process.runtime.jvm.gc.duration\":{\"count\":1},\"layer7_service_total\":{\"count\":1},\"process.runtime.jvm.memory.limit\":{\"count\":2},\"process.runtime.jvm.memory.usage\":{\"count\":1},\"process.runtime.jvm.system.cpu.load_1m\":{\"count\":1},\"layer7_routing_failues\":{\"count\":1},\"layer7_service_success\":{\"count\":1},\"layer7_service_latency\":{\"count\":2},\"labels.serviceName\":{\"count\":1},\"labels.gc\":{\"count\":1},\"labels.method\":{\"count\":1},\"numeric_labels.code\":{\"count\":1},\"process.runtime.jvm.threads.count\":{\"count\":1},\"span.name\":{\"count\":3},\"l7_service_latency\":{\"count\":1},\"l7_service_policy_violations\":{\"count\":1},\"labels.l7_serviceName\":{\"count\":1},\"labels.layer7gw_name\":{\"count\":1}}","fieldFormatMap":"{\"trace.id\":{\"id\":\"url\",\"params\":{\"urlTemplate\":\"apm/link-to/trace/{{value}}\",\"labelTemplate\":\"{{value}}\"}},\"transaction.id\":{\"id\":\"url\",\"params\":{\"urlTemplate\":\"apm/link-to/transaction/{{value}}\",\"labelTemplate\":\"{{value}}\"}},\"transaction.duration.us\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"microseconds\",\"outputFormat\":\"asMilliseconds\",\"showSuffix\":true,\"useShortSuffix\":true,\"outputPrecision\":2,\"includeSpaceWithSuffix\":true}}}","fields":"[]","name":"APM","runtimeFieldMap":"{}","sourceFilters":"[]","timeFieldName":"@timestamp","title":"traces-apm*,apm-*,logs-apm*,apm-*,metrics-apm*,apm-*","typeMeta":"{}"},"coreMigrationVersion":"8.8.0","created_at":"2024-05-14T07:23:11.980Z","id":"apm_static_index_pattern_id","managed":false,"references":[],"type":"index-pattern","typeMigrationVersion":"8.0.0","updated_at":"2024-05-14T07:23:11.980Z","version":"WzQyMiwxXQ=="}
-{"attributes":{"controlGroupInput":{"chainingSystem":"HIERARCHICAL","controlStyle":"twoLine","ignoreParentSettingsJSON":"{\"ignoreFilters\":false,\"ignoreQuery\":false,\"ignoreTimerange\":false,\"ignoreValidations\":false}","panelsJSON":"{\"d3e0d4d0-b1de-465c-8772-806a49213c2b\":{\"type\":\"optionsListControl\",\"order\":0,\"grow\":true,\"width\":\"medium\",\"explicitInput\":{\"id\":\"d3e0d4d0-b1de-465c-8772-806a49213c2b\",\"fieldName\":\"labels.layer7gw_name\",\"title\":\"Gateway\",\"selectedOptions\":[],\"enhancements\":{},\"existsSelected\":false}}}"},"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"optionsJSON":"{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}","panelsJSON":"[{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":22,\"h\":11,\"i\":\"675c235a-535c-48d9-a5ed-848810986e5a\"},\"panelIndex\":\"675c235a-535c-48d9-a5ed-848810986e5a\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"description\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-8638d8b0-f850-42f0-9e64-35e6f239e0d0\"}],\"state\":{\"visualization\":{\"columns\":[{\"columnId\":\"82dab02b-8829-488e-bd30-aa8c45996590\",\"isTransposed\":false,\"summaryRow\":\"sum\"},{\"columnId\":\"ae1e2f3d-6ec8-49c9-a444-8249ed271df8\",\"isTransposed\":false,\"summaryRow\":\"sum\",\"summaryLabel\":\"\"},{\"columnId\":\"ff0032fe-94ec-4bf8-a50f-9905301868f9\",\"isTransposed\":false,\"summaryRow\":\"sum\",\"summaryLabel\":\"\"},{\"columnId\":\"ed1df4b3-0bcd-4059-965d-39bc63eef215\",\"isTransposed\":false}],\"layerId\":\"8638d8b0-f850-42f0-9e64-35e6f239e0d0\",\"layerType\":\"data\",\"paging\":{\"size\":10,\"enabled\":true}},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"8638d8b0-f850-42f0-9e64-35e6f239e0d0\":{\"columns\":{\"ed1df4b3-0bcd-4059-965d-39bc63eef215\":{\"label\":\"Service Name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"labels.l7_serviceName\",\"isBucketed\":true,\"params\":{\"size\":10,\"orderBy\":{\"type\":\"column\",\"columnId\":\"82dab02b-8829-488e-bd30-aa8c45996590\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"82dab02b-8829-488e-bd30-aa8c45996590\":{\"label\":\"Policy Violations\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"l7_service_policy_violations\",\"filter\":{\"query\":\"l7_service_policy_violations: *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"ae1e2f3d-6ec8-49c9-a444-8249ed271df8\":{\"label\":\"Success\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"l7_service_success\",\"filter\":{\"query\":\"l7_service_success: *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"ff0032fe-94ec-4bf8-a50f-9905301868f9\":{\"label\":\"Routing Failures\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"l7_service_routing_failures\",\"filter\":{\"query\":\"l7_service_routing_failures: *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true}},\"columnOrder\":[\"ed1df4b3-0bcd-4059-965d-39bc63eef215\",\"82dab02b-8829-488e-bd30-aa8c45996590\",\"ae1e2f3d-6ec8-49c9-a444-8249ed271df8\",\"ff0032fe-94ec-4bf8-a50f-9905301868f9\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Usage\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":22,\"y\":0,\"w\":26,\"h\":11,\"i\":\"0ae50fd8-f924-4207-b546-5d600ac701b3\"},\"panelIndex\":\"0ae50fd8-f924-4207-b546-5d600ac701b3\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-cad7aae7-308f-4c4f-abbd-b03792fbec56\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"title\":\"Empty XY chart\",\"legend\":{\"isVisible\":true,\"position\":\"bottom\"},\"valueLabels\":\"hide\",\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"cad7aae7-308f-4c4f-abbd-b03792fbec56\",\"accessors\":[\"4ee0c11f-c34e-48b9-ba2b-3a855498cd44\"],\"position\":\"top\",\"seriesType\":\"line\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"bf646547-1ad3-4810-8d0c-ac6d35be61ec\",\"splitAccessor\":\"2bffabd5-d07e-4187-a67d-c1d085ea598a\"}],\"curveType\":\"CURVE_MONOTONE_X\",\"fittingFunction\":\"Zero\",\"emphasizeFitting\":true,\"endValue\":\"Zero\",\"valuesInLegend\":false,\"axisTitlesVisibilitySettings\":{\"x\":false,\"yLeft\":true,\"yRight\":true},\"yTitle\":\"Requests\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"cad7aae7-308f-4c4f-abbd-b03792fbec56\":{\"columns\":{\"bf646547-1ad3-4810-8d0c-ac6d35be61ec\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":false,\"dropPartials\":false}},\"2bffabd5-d07e-4187-a67d-c1d085ea598a\":{\"label\":\"Top 10 values of labels.l7_serviceName\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"labels.l7_serviceName\",\"isBucketed\":true,\"params\":{\"size\":10,\"orderBy\":{\"type\":\"alphabetical\",\"fallback\":true},\"orderDirection\":\"asc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]}},\"4ee0c11f-c34e-48b9-ba2b-3a855498cd44\":{\"label\":\"Requests\",\"dataType\":\"number\",\"operationType\":\"counter_rate\",\"isBucketed\":false,\"scale\":\"ratio\",\"references\":[\"82148cde-9560-4544-a841-38ccaf7b66f5\"],\"filter\":{\"query\":\"\",\"language\":\"kuery\"},\"params\":{\"format\":{\"id\":\"number\",\"params\":{\"decimals\":0}}},\"customLabel\":true},\"82148cde-9560-4544-a841-38ccaf7b66f5\":{\"label\":\"Maximum of l7_service_attempted\",\"dataType\":\"number\",\"operationType\":\"max\",\"sourceField\":\"l7_service_attempted\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"emptyAsNull\":true}}},\"columnOrder\":[\"2bffabd5-d07e-4187-a67d-c1d085ea598a\",\"bf646547-1ad3-4810-8d0c-ac6d35be61ec\",\"4ee0c11f-c34e-48b9-ba2b-3a855498cd44\",\"82148cde-9560-4544-a841-38ccaf7b66f5\"],\"sampling\":1,\"incompleteColumns\":{}}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Message Rate\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":11,\"w\":22,\"h\":11,\"i\":\"ee3d33f8-243e-42d9-87fa-09c00dbfd1b7\"},\"panelIndex\":\"ee3d33f8-243e-42d9-87fa-09c00dbfd1b7\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-fd66544d-5ee7-4f36-8966-c7aa38197646\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"bottom\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"yTitle\":\"Latency (ms)\",\"axisTitlesVisibilitySettings\":{\"x\":false,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"fd66544d-5ee7-4f36-8966-c7aa38197646\",\"accessors\":[\"6da1dadd-1f1a-42d6-b954-e8bd5a318f4b\",\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"c973fd1a-9645-46a1-ad45-483cf1ff0441\",\"splitAccessor\":\"4ef8265b-6ee1-449f-9ced-ae065efc7296\"}],\"showCurrentTimeMarker\":false,\"yLeftScale\":\"linear\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"fd66544d-5ee7-4f36-8966-c7aa38197646\":{\"columns\":{\"c973fd1a-9645-46a1-ad45-483cf1ff0441\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X0\":{\"label\":\"Part of Frontend\",\"dataType\":\"number\",\"operationType\":\"average\",\"sourceField\":\"l7_service_latency\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X1\":{\"label\":\"Part of Frontend\",\"dataType\":\"number\",\"operationType\":\"average\",\"sourceField\":\"l7_service_routing_latency\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X2\":{\"label\":\"Part of Frontend\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"subtract\",\"args\":[\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X0\",\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X1\"],\"location\":{\"min\":0,\"max\":63},\"text\":\"average(l7_service_latency)-average(l7_service_routing_latency)\"}},\"references\":[\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X0\",\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X1\"],\"customLabel\":true},\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5\":{\"label\":\"Frontend\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"average(l7_service_latency)-average(l7_service_routing_latency)\",\"isFormulaBroken\":false},\"references\":[\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X2\"],\"customLabel\":true},\"6da1dadd-1f1a-42d6-b954-e8bd5a318f4bX0\":{\"label\":\"Part of Backend\",\"dataType\":\"number\",\"operationType\":\"average\",\"sourceField\":\"l7_service_routing_latency\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"6da1dadd-1f1a-42d6-b954-e8bd5a318f4b\":{\"label\":\"Backend\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"average(l7_service_routing_latency)\",\"isFormulaBroken\":false},\"references\":[\"6da1dadd-1f1a-42d6-b954-e8bd5a318f4bX0\"],\"customLabel\":true},\"4ef8265b-6ee1-449f-9ced-ae065efc7296\":{\"label\":\"Top 10 values of labels.l7_serviceName\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"labels.l7_serviceName\",\"isBucketed\":true,\"params\":{\"size\":10,\"orderBy\":{\"type\":\"alphabetical\",\"fallback\":true},\"orderDirection\":\"asc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]}}},\"columnOrder\":[\"4ef8265b-6ee1-449f-9ced-ae065efc7296\",\"c973fd1a-9645-46a1-ad45-483cf1ff0441\",\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5\",\"6da1dadd-1f1a-42d6-b954-e8bd5a318f4b\",\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X0\",\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X2\",\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X1\",\"6da1dadd-1f1a-42d6-b954-e8bd5a318f4bX0\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Latency\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":22,\"y\":11,\"w\":26,\"h\":11,\"i\":\"d9305573-c761-4802-9c0b-6f6326266125\"},\"panelIndex\":\"d9305573-c761-4802-9c0b-6f6326266125\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-8638d8b0-f850-42f0-9e64-35e6f239e0d0\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"bottom\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"yTitle\":\"Number of Messages\",\"axisTitlesVisibilitySettings\":{\"x\":false,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"8638d8b0-f850-42f0-9e64-35e6f239e0d0\",\"seriesType\":\"bar\",\"accessors\":[\"28a49db2-d0b2-47ea-bd58-12e827e9851d\",\"6d6fe07e-c712-4d47-89c6-1ebdeaa23304\",\"231179ca-b88a-4495-b857-8006bca2b409\"],\"layerType\":\"data\",\"yConfig\":[{\"forAccessor\":\"231179ca-b88a-4495-b857-8006bca2b409\",\"color\":\"#8b8c2b\",\"axisMode\":\"left\"},{\"forAccessor\":\"28a49db2-d0b2-47ea-bd58-12e827e9851d\",\"color\":\"#2da275\",\"axisMode\":\"left\"},{\"forAccessor\":\"6d6fe07e-c712-4d47-89c6-1ebdeaa23304\",\"color\":\"#781032\",\"axisMode\":\"left\"}],\"xAccessor\":\"227364f6-80d8-4d15-89ca-7166dc900804\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"8638d8b0-f850-42f0-9e64-35e6f239e0d0\":{\"columns\":{\"227364f6-80d8-4d15-89ca-7166dc900804\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"m\",\"includeEmptyRows\":false,\"dropPartials\":false}},\"231179ca-b88a-4495-b857-8006bca2b409\":{\"label\":\"Routing failues\",\"dataType\":\"number\",\"operationType\":\"counter_rate\",\"isBucketed\":false,\"scale\":\"ratio\",\"references\":[\"6e76dd16-427c-4267-a977-522b4f1a8eba\"],\"customLabel\":true,\"params\":{\"format\":{\"id\":\"number\",\"params\":{\"decimals\":0}}}},\"6e76dd16-427c-4267-a977-522b4f1a8eba\":{\"label\":\"Maximum of l7_service_routing_failures\",\"dataType\":\"number\",\"operationType\":\"max\",\"sourceField\":\"l7_service_routing_failures\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"emptyAsNull\":true}},\"6d6fe07e-c712-4d47-89c6-1ebdeaa23304\":{\"label\":\"Policy Violations\",\"dataType\":\"number\",\"operationType\":\"counter_rate\",\"isBucketed\":false,\"scale\":\"ratio\",\"references\":[\"84104e54-bd82-47f6-b34d-b04a1db60694\"],\"timeScale\":\"s\",\"params\":{\"format\":{\"id\":\"number\",\"params\":{\"decimals\":0}}},\"customLabel\":true},\"84104e54-bd82-47f6-b34d-b04a1db60694\":{\"label\":\"Maximum of l7_service_policy_violations\",\"dataType\":\"number\",\"operationType\":\"max\",\"sourceField\":\"l7_service_policy_violations\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"emptyAsNull\":true}},\"28a49db2-d0b2-47ea-bd58-12e827e9851d\":{\"label\":\"Success\",\"dataType\":\"number\",\"operationType\":\"counter_rate\",\"isBucketed\":false,\"scale\":\"ratio\",\"references\":[\"3da518c4-50c1-415f-8248-b11b5be8873f\"],\"timeScale\":\"s\",\"params\":{\"format\":{\"id\":\"number\",\"params\":{\"decimals\":0}}},\"customLabel\":true},\"3da518c4-50c1-415f-8248-b11b5be8873f\":{\"label\":\"Maximum of l7_service_attempted\",\"dataType\":\"number\",\"operationType\":\"max\",\"sourceField\":\"l7_service_attempted\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"emptyAsNull\":true}}},\"columnOrder\":[\"227364f6-80d8-4d15-89ca-7166dc900804\",\"28a49db2-d0b2-47ea-bd58-12e827e9851d\",\"231179ca-b88a-4495-b857-8006bca2b409\",\"6e76dd16-427c-4267-a977-522b4f1a8eba\",\"6d6fe07e-c712-4d47-89c6-1ebdeaa23304\",\"84104e54-bd82-47f6-b34d-b04a1db60694\",\"3da518c4-50c1-415f-8248-b11b5be8873f\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Service Status\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":22,\"w\":48,\"h\":15,\"i\":\"868932e9-487a-408f-89fd-14f9324534e9\"},\"panelIndex\":\"868932e9-487a-408f-89fd-14f9324534e9\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-2381ace6-24bb-4e47-b57b-6fe06c980216\",\"type\":\"index-pattern\"},{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-06696642-3076-4612-8291-189dcb25dd9e\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\",\"isInside\":false,\"verticalAlignment\":\"bottom\",\"horizontalAlignment\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"Zero\",\"curveType\":\"CURVE_MONOTONE_X\",\"yLeftScale\":\"sqrt\",\"axisTitlesVisibilitySettings\":{\"x\":false,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar\",\"layers\":[{\"layerId\":\"2381ace6-24bb-4e47-b57b-6fe06c980216\",\"accessors\":[\"b13dba51-c5c9-4c20-9212-e8607d048660\"],\"position\":\"top\",\"seriesType\":\"bar\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"209b6a96-6641-42d5-b243-cd7a68dc55be\",\"splitAccessor\":\"b8a1138e-65ed-4595-8c72-23c294313fc5\",\"collapseFn\":\"\"},{\"layerId\":\"06696642-3076-4612-8291-189dcb25dd9e\",\"layerType\":\"data\",\"accessors\":[\"74470d07-35e7-40c2-bf78-7bd282323271\"],\"seriesType\":\"line\",\"xAccessor\":\"96a4345f-06e4-4252-9ed1-31ed39ee347c\",\"splitAccessor\":\"8756242d-1a48-4550-9fd5-66057b194995\"}],\"emphasizeFitting\":true,\"yTitle\":\"Connections\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"2381ace6-24bb-4e47-b57b-6fe06c980216\":{\"columns\":{\"b8a1138e-65ed-4595-8c72-23c294313fc5\":{\"label\":\"Top values of labels.pool_name + 1 other\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"labels.pool_name\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"b13dba51-c5c9-4c20-9212-e8607d048660\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"multi_terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[\"labels.state\"]}},\"209b6a96-6641-42d5-b243-cd7a68dc55be\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"b13dba51-c5c9-4c20-9212-e8607d048660\":{\"label\":\"conns\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"db.client.connections.usage\",\"filter\":{\"query\":\"db.client.connections.usage: *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true}},\"columnOrder\":[\"b8a1138e-65ed-4595-8c72-23c294313fc5\",\"209b6a96-6641-42d5-b243-cd7a68dc55be\",\"b13dba51-c5c9-4c20-9212-e8607d048660\"],\"incompleteColumns\":{},\"sampling\":1},\"06696642-3076-4612-8291-189dcb25dd9e\":{\"linkToLayers\":[],\"columns\":{\"74470d07-35e7-40c2-bf78-7bd282323271\":{\"label\":\"pending requests\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"db.client.connections.pending_requests\",\"filter\":{\"query\":\"db.client.connections.pending_requests: *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"96a4345f-06e4-4252-9ed1-31ed39ee347c\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"8756242d-1a48-4550-9fd5-66057b194995\":{\"label\":\"Top 3 values of labels.pool_name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"labels.pool_name\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"74470d07-35e7-40c2-bf78-7bd282323271\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false}}},\"columnOrder\":[\"8756242d-1a48-4550-9fd5-66057b194995\",\"96a4345f-06e4-4252-9ed1-31ed39ee347c\",\"74470d07-35e7-40c2-bf78-7bd282323271\"],\"sampling\":1,\"incompleteColumns\":{}}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"DB Connections\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":37,\"w\":22,\"h\":10,\"i\":\"9a54b939-5371-49f6-8888-ab92e165e625\"},\"panelIndex\":\"9a54b939-5371-49f6-8888-ab92e165e625\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-a57f2de0-c4c8-4a18-9b3a-533ad5572097\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"bottom\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"yLeftExtent\":{\"mode\":\"full\"},\"axisTitlesVisibilitySettings\":{\"x\":false,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"a57f2de0-c4c8-4a18-9b3a-533ad5572097\",\"accessors\":[\"f0c37a83-1464-4350-bb91-e57c2198b927\",\"cdcae1da-c18f-40a5-aeed-1be00a243149\"],\"position\":\"top\",\"seriesType\":\"bar\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"deb7bb17-0f00-4a18-b2be-e6a5a2becb7e\",\"yConfig\":[{\"forAccessor\":\"cdcae1da-c18f-40a5-aeed-1be00a243149\",\"color\":\"#e7664c\"}]}],\"yTitle\":\"CPU utilization (0-100)\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"a57f2de0-c4c8-4a18-9b3a-533ad5572097\":{\"columns\":{\"deb7bb17-0f00-4a18-b2be-e6a5a2becb7e\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"f0c37a83-1464-4350-bb91-e57c2198b927X0\":{\"label\":\"Part of System CPU utilization\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"process.runtime.jvm.system.cpu.utilization\",\"filter\":{\"query\":\"process.runtime.jvm.system.cpu.utilization: *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"f0c37a83-1464-4350-bb91-e57c2198b927X1\":{\"label\":\"Part of System CPU utilization\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"multiply\",\"args\":[\"f0c37a83-1464-4350-bb91-e57c2198b927X0\",100],\"location\":{\"min\":0,\"max\":121},\"text\":\"multiply(last_value(process.runtime.jvm.system.cpu.utilization, kql='process.runtime.jvm.system.cpu.utilization: *'),100)\"}},\"references\":[\"f0c37a83-1464-4350-bb91-e57c2198b927X0\"],\"customLabel\":true},\"f0c37a83-1464-4350-bb91-e57c2198b927\":{\"label\":\"System CPU utilization\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"multiply(last_value(process.runtime.jvm.system.cpu.utilization, kql='process.runtime.jvm.system.cpu.utilization: *'),100)\",\"isFormulaBroken\":false},\"references\":[\"f0c37a83-1464-4350-bb91-e57c2198b927X1\"],\"customLabel\":true},\"cdcae1da-c18f-40a5-aeed-1be00a243149X0\":{\"label\":\"Part of JVM CPU utilization\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"process.runtime.jvm.cpu.utilization\",\"filter\":{\"query\":\"process.runtime.jvm.cpu.utilization: *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"cdcae1da-c18f-40a5-aeed-1be00a243149\":{\"label\":\"JVM CPU utilization\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"last_value(process.runtime.jvm.cpu.utilization, kql='process.runtime.jvm.cpu.utilization: *')\",\"isFormulaBroken\":false},\"references\":[\"cdcae1da-c18f-40a5-aeed-1be00a243149X0\"],\"customLabel\":true}},\"columnOrder\":[\"deb7bb17-0f00-4a18-b2be-e6a5a2becb7e\",\"f0c37a83-1464-4350-bb91-e57c2198b927\",\"f0c37a83-1464-4350-bb91-e57c2198b927X0\",\"f0c37a83-1464-4350-bb91-e57c2198b927X1\",\"cdcae1da-c18f-40a5-aeed-1be00a243149\",\"cdcae1da-c18f-40a5-aeed-1be00a243149X0\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"CPU/System Utilization\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":22,\"y\":37,\"w\":26,\"h\":10,\"i\":\"2a2057e2-ce45-4804-8ce0-3d4ed94679d7\"},\"panelIndex\":\"2a2057e2-ce45-4804-8ce0-3d4ed94679d7\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-04cd0fc2-f652-4583-a7d4-c1a8f6f8818f\",\"type\":\"index-pattern\"},{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-b369a9a0-f9ee-4b7e-ba8f-97d2722cd89d\",\"type\":\"index-pattern\"},{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-66ce3428-e822-4b54-afc8-69bbffd9c106\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"bottom\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":false,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"04cd0fc2-f652-4583-a7d4-c1a8f6f8818f\",\"accessors\":[\"371f4c5e-dca1-4de3-b495-b29d0c51ad42\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"7e7413d7-db3d-4473-b46f-d76132f403b0\",\"splitAccessor\":\"06b7cd00-d4bf-4c98-a2e1-2932a19a92ae\",\"palette\":{\"type\":\"palette\",\"name\":\"status\"},\"collapseFn\":\"\",\"yConfig\":[]},{\"layerId\":\"b369a9a0-f9ee-4b7e-ba8f-97d2722cd89d\",\"layerType\":\"referenceLine\",\"accessors\":[\"81fcf196-8145-4246-9d3a-f1679cb62c81\"],\"yConfig\":[{\"forAccessor\":\"81fcf196-8145-4246-9d3a-f1679cb62c81\",\"axisMode\":\"left\",\"icon\":\"bolt\",\"iconPosition\":\"auto\",\"lineWidth\":2,\"color\":\"#9d2022\"}]},{\"layerId\":\"66ce3428-e822-4b54-afc8-69bbffd9c106\",\"layerType\":\"data\",\"accessors\":[\"323e403c-e4a1-481d-897e-907192f1cc4a\"],\"seriesType\":\"line\",\"xAccessor\":\"f8721fc3-00f3-4106-96eb-0121ce00e6aa\",\"yConfig\":[{\"forAccessor\":\"323e403c-e4a1-481d-897e-907192f1cc4a\",\"color\":\"#040f12\"}]}],\"yLeftExtent\":{\"mode\":\"full\"},\"yTitle\":\"Megabytes\",\"yLeftScale\":\"log\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"04cd0fc2-f652-4583-a7d4-c1a8f6f8818f\":{\"columns\":{\"7e7413d7-db3d-4473-b46f-d76132f403b0\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":false,\"dropPartials\":false}},\"371f4c5e-dca1-4de3-b495-b29d0c51ad42X0\":{\"label\":\"Part of Heap\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"process.runtime.jvm.memory.usage\",\"filter\":{\"query\":\"process.runtime.jvm.memory.usage: * and labels.type: heap\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"371f4c5e-dca1-4de3-b495-b29d0c51ad42X1\":{\"label\":\"Part of Heap\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"divide\",\"args\":[\"371f4c5e-dca1-4de3-b495-b29d0c51ad42X0\",1048576],\"location\":{\"min\":0,\"max\":126},\"text\":\"divide(last_value(process.runtime.jvm.memory.usage, kql='process.runtime.jvm.memory.usage: * and labels.type: heap'), 1048576)\"}},\"references\":[\"371f4c5e-dca1-4de3-b495-b29d0c51ad42X0\"],\"customLabel\":true},\"371f4c5e-dca1-4de3-b495-b29d0c51ad42\":{\"label\":\"Heap\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"divide(last_value(process.runtime.jvm.memory.usage, kql='process.runtime.jvm.memory.usage: * and labels.type: heap'), 1048576)\",\"isFormulaBroken\":false},\"references\":[\"371f4c5e-dca1-4de3-b495-b29d0c51ad42X1\"],\"customLabel\":true},\"06b7cd00-d4bf-4c98-a2e1-2932a19a92ae\":{\"label\":\"Top 10 values of labels.pool\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"labels.pool\",\"isBucketed\":true,\"params\":{\"size\":10,\"orderBy\":{\"type\":\"alphabetical\",\"fallback\":true},\"orderDirection\":\"asc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"accuracyMode\":true}}},\"columnOrder\":[\"06b7cd00-d4bf-4c98-a2e1-2932a19a92ae\",\"7e7413d7-db3d-4473-b46f-d76132f403b0\",\"371f4c5e-dca1-4de3-b495-b29d0c51ad42\",\"371f4c5e-dca1-4de3-b495-b29d0c51ad42X0\",\"371f4c5e-dca1-4de3-b495-b29d0c51ad42X1\"],\"incompleteColumns\":{},\"sampling\":1},\"b369a9a0-f9ee-4b7e-ba8f-97d2722cd89d\":{\"linkToLayers\":[],\"columns\":{\"81fcf196-8145-4246-9d3a-f1679cb62c81X0\":{\"label\":\"Part of Max\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"process.runtime.jvm.memory.limit\",\"filter\":{\"query\":\"process.runtime.jvm.memory.limit: * and labels.type: heap\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"81fcf196-8145-4246-9d3a-f1679cb62c81X1\":{\"label\":\"Part of Max\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"divide\",\"args\":[\"81fcf196-8145-4246-9d3a-f1679cb62c81X0\",1048576],\"location\":{\"min\":0,\"max\":126},\"text\":\"divide(last_value(process.runtime.jvm.memory.limit, kql='process.runtime.jvm.memory.limit: * and labels.type: heap'), 1048576)\"}},\"references\":[\"81fcf196-8145-4246-9d3a-f1679cb62c81X0\"],\"customLabel\":true},\"81fcf196-8145-4246-9d3a-f1679cb62c81\":{\"label\":\"Max\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"divide(last_value(process.runtime.jvm.memory.limit, kql='process.runtime.jvm.memory.limit: * and labels.type: heap'), 1048576)\",\"isFormulaBroken\":false,\"format\":{\"id\":\"number\",\"params\":{\"decimals\":0}}},\"references\":[\"81fcf196-8145-4246-9d3a-f1679cb62c81X1\"],\"customLabel\":true}},\"columnOrder\":[\"81fcf196-8145-4246-9d3a-f1679cb62c81\",\"81fcf196-8145-4246-9d3a-f1679cb62c81X0\",\"81fcf196-8145-4246-9d3a-f1679cb62c81X1\"],\"sampling\":1,\"incompleteColumns\":{}},\"66ce3428-e822-4b54-afc8-69bbffd9c106\":{\"linkToLayers\":[],\"columns\":{\"f8721fc3-00f3-4106-96eb-0121ce00e6aa\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"323e403c-e4a1-481d-897e-907192f1cc4aX0\":{\"label\":\"Part of Non-Heap\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"process.runtime.jvm.memory.usage\",\"filter\":{\"query\":\"process.runtime.jvm.memory.usage: * and labels.type: non_heap\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"323e403c-e4a1-481d-897e-907192f1cc4aX1\":{\"label\":\"Part of Non-Heap\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"divide\",\"args\":[\"323e403c-e4a1-481d-897e-907192f1cc4aX0\",1048576],\"location\":{\"min\":0,\"max\":130},\"text\":\"divide(last_value(process.runtime.jvm.memory.usage, kql='process.runtime.jvm.memory.usage: * and labels.type: non_heap'), 1048576)\"}},\"references\":[\"323e403c-e4a1-481d-897e-907192f1cc4aX0\"],\"customLabel\":true},\"323e403c-e4a1-481d-897e-907192f1cc4a\":{\"label\":\"Non-Heap\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"divide(last_value(process.runtime.jvm.memory.usage, kql='process.runtime.jvm.memory.usage: * and labels.type: non_heap'), 1048576)\",\"isFormulaBroken\":false},\"references\":[\"323e403c-e4a1-481d-897e-907192f1cc4aX1\"],\"customLabel\":true}},\"columnOrder\":[\"f8721fc3-00f3-4106-96eb-0121ce00e6aa\",\"323e403c-e4a1-481d-897e-907192f1cc4a\",\"323e403c-e4a1-481d-897e-907192f1cc4aX1\",\"323e403c-e4a1-481d-897e-907192f1cc4aX0\"],\"sampling\":1,\"incompleteColumns\":{}}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{},\"hidePanelTitles\":false},\"title\":\"Memory Usage\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":47,\"w\":22,\"h\":11,\"i\":\"542275ac-682e-43b8-b1ac-cf919d206e02\"},\"panelIndex\":\"542275ac-682e-43b8-b1ac-cf919d206e02\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-28f4234a-7411-4d15-8ad9-36ac978f7e19\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"yLeftExtent\":{\"mode\":\"full\"},\"axisTitlesVisibilitySettings\":{\"x\":false,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"28f4234a-7411-4d15-8ad9-36ac978f7e19\",\"accessors\":[\"04481efd-b3d8-44bc-be6c-5a0af56e241b\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"5e07b038-8927-4bdb-a933-ddbd1f7d0374\"}],\"yTitle\":\"System Load (0-100)\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"28f4234a-7411-4d15-8ad9-36ac978f7e19\":{\"columns\":{\"5e07b038-8927-4bdb-a933-ddbd1f7d0374\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"04481efd-b3d8-44bc-be6c-5a0af56e241bX0\":{\"label\":\"Part of System Load\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"process.runtime.jvm.system.cpu.load_1m\",\"filter\":{\"query\":\"process.runtime.jvm.system.cpu.load_1m: *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"04481efd-b3d8-44bc-be6c-5a0af56e241b\":{\"label\":\"System Load\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"last_value(process.runtime.jvm.system.cpu.load_1m, kql='process.runtime.jvm.system.cpu.load_1m: *')\",\"isFormulaBroken\":false},\"references\":[\"04481efd-b3d8-44bc-be6c-5a0af56e241bX0\"],\"customLabel\":true}},\"columnOrder\":[\"5e07b038-8927-4bdb-a933-ddbd1f7d0374\",\"04481efd-b3d8-44bc-be6c-5a0af56e241b\",\"04481efd-b3d8-44bc-be6c-5a0af56e241bX0\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"System Load\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":22,\"y\":47,\"w\":26,\"h\":11,\"i\":\"a3aace75-debc-4370-9954-e5a6e8ac6259\"},\"panelIndex\":\"a3aace75-debc-4370-9954-e5a6e8ac6259\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-067c1db7-2942-4bf9-8fd6-4ca0a42a23fa\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"bottom\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"067c1db7-2942-4bf9-8fd6-4ca0a42a23fa\",\"accessors\":[\"603e1430-a496-4249-b2da-73a5205b964e\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"2ab4d7f4-49aa-4e45-9ad7-73256400df18\",\"splitAccessor\":\"a9ec0126-a45f-4f86-b783-a4820badd7d8\",\"yConfig\":[{\"forAccessor\":\"603e1430-a496-4249-b2da-73a5205b964e\",\"axisMode\":\"left\"}],\"palette\":{\"type\":\"palette\",\"name\":\"status\"}}],\"yLeftScale\":\"log\",\"yTitle\":\"Megabytes\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"067c1db7-2942-4bf9-8fd6-4ca0a42a23fa\":{\"columns\":{\"2ab4d7f4-49aa-4e45-9ad7-73256400df18\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":false,\"dropPartials\":false}},\"603e1430-a496-4249-b2da-73a5205b964eX0\":{\"label\":\"Part of divide(last_value(process.runtime.jvm.memory.usage_after_last_gc, kql='process.runtime.jvm.memory.usage_after_last_gc: * and labels.type: heap'), 1048576)\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"process.runtime.jvm.memory.usage_after_last_gc\",\"filter\":{\"query\":\"process.runtime.jvm.memory.usage_after_last_gc: * and labels.type: heap\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"603e1430-a496-4249-b2da-73a5205b964eX1\":{\"label\":\"Part of divide(last_value(process.runtime.jvm.memory.usage_after_last_gc, kql='process.runtime.jvm.memory.usage_after_last_gc: * and labels.type: heap'), 1048576)\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"divide\",\"args\":[\"603e1430-a496-4249-b2da-73a5205b964eX0\",1048576],\"location\":{\"min\":0,\"max\":154},\"text\":\"divide(last_value(process.runtime.jvm.memory.usage_after_last_gc, kql='process.runtime.jvm.memory.usage_after_last_gc: * and labels.type: heap'), 1048576)\"}},\"references\":[\"603e1430-a496-4249-b2da-73a5205b964eX0\"],\"customLabel\":true},\"603e1430-a496-4249-b2da-73a5205b964e\":{\"label\":\"MB\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"divide(last_value(process.runtime.jvm.memory.usage_after_last_gc, kql='process.runtime.jvm.memory.usage_after_last_gc: * and labels.type: heap'), 1048576)\",\"isFormulaBroken\":false},\"references\":[\"603e1430-a496-4249-b2da-73a5205b964eX1\"],\"filter\":{\"query\":\"\",\"language\":\"kuery\"},\"customLabel\":true},\"a9ec0126-a45f-4f86-b783-a4820badd7d8\":{\"label\":\"Top 10 values of labels.pool\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"labels.pool\",\"isBucketed\":true,\"params\":{\"size\":10,\"orderBy\":{\"type\":\"alphabetical\",\"fallback\":true},\"orderDirection\":\"asc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false}}},\"columnOrder\":[\"a9ec0126-a45f-4f86-b783-a4820badd7d8\",\"2ab4d7f4-49aa-4e45-9ad7-73256400df18\",\"603e1430-a496-4249-b2da-73a5205b964e\",\"603e1430-a496-4249-b2da-73a5205b964eX0\",\"603e1430-a496-4249-b2da-73a5205b964eX1\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Memory after GC\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":58,\"w\":22,\"h\":10,\"i\":\"7f1f017e-d42b-4cf4-8cb2-3f4bb3de5367\"},\"panelIndex\":\"7f1f017e-d42b-4cf4-8cb2-3f4bb3de5367\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-a3ee7019-98bb-45cd-8536-e36a8e58297e\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"a3ee7019-98bb-45cd-8536-e36a8e58297e\",\"accessors\":[\"ebf7c494-f676-4642-b2cf-ead2e8e93dee\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"9c350955-95a1-4726-93fd-717b104a218c\",\"yConfig\":[{\"forAccessor\":\"ebf7c494-f676-4642-b2cf-ead2e8e93dee\",\"color\":\"#54b399\"}]}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"a3ee7019-98bb-45cd-8536-e36a8e58297e\":{\"columns\":{\"9c350955-95a1-4726-93fd-717b104a218c\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"ebf7c494-f676-4642-b2cf-ead2e8e93dee\":{\"label\":\"Threads count\",\"dataType\":\"number\",\"operationType\":\"median\",\"sourceField\":\"process.runtime.jvm.threads.count\",\"isBucketed\":false,\"scale\":\"ratio\",\"filter\":{\"query\":\"process.runtime.jvm.threads.count: *\",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"9c350955-95a1-4726-93fd-717b104a218c\",\"ebf7c494-f676-4642-b2cf-ead2e8e93dee\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Threads\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":22,\"y\":58,\"w\":26,\"h\":10,\"i\":\"4f987373-1b85-4e80-a7cc-c1c000349c5e\"},\"panelIndex\":\"4f987373-1b85-4e80-a7cc-c1c000349c5e\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-a45cd02a-4c62-4b34-bdce-c702b87b4246\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"bottom\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"yRightTitle\":\"Duration (ms)\",\"axisTitlesVisibilitySettings\":{\"x\":false,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"a45cd02a-4c62-4b34-bdce-c702b87b4246\",\"accessors\":[\"e3c6a7fb-d980-43d4-bb84-ae22018a0710\",\"4e7a6993-fcee-47ae-9599-0047809bb29e\"],\"position\":\"top\",\"seriesType\":\"bar\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"57050bde-2c14-47d2-9dde-6e35326cf5cf\",\"yConfig\":[{\"forAccessor\":\"e3c6a7fb-d980-43d4-bb84-ae22018a0710\",\"axisMode\":\"left\"},{\"forAccessor\":\"4e7a6993-fcee-47ae-9599-0047809bb29e\",\"color\":\"#e7664c\",\"axisMode\":\"left\"}]}],\"yTitle\":\"Duration (ms)\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"a45cd02a-4c62-4b34-bdce-c702b87b4246\":{\"columns\":{\"57050bde-2c14-47d2-9dde-6e35326cf5cf\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":false,\"dropPartials\":false}},\"e3c6a7fb-d980-43d4-bb84-ae22018a0710\":{\"label\":\"Minor GC\",\"dataType\":\"number\",\"operationType\":\"median\",\"sourceField\":\"process.runtime.jvm.gc.duration\",\"isBucketed\":false,\"scale\":\"ratio\",\"filter\":{\"query\":\"labels.action: \\\"end of minor GC\\\" \",\"language\":\"kuery\"},\"params\":{\"format\":{\"id\":\"number\",\"params\":{\"decimals\":2}},\"emptyAsNull\":true},\"customLabel\":true},\"4e7a6993-fcee-47ae-9599-0047809bb29e\":{\"label\":\"Major GC\",\"dataType\":\"number\",\"operationType\":\"median\",\"sourceField\":\"process.runtime.jvm.gc.duration\",\"isBucketed\":false,\"scale\":\"ratio\",\"filter\":{\"query\":\"labels.action : \\\"end of major GC\\\"\",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"57050bde-2c14-47d2-9dde-6e35326cf5cf\",\"e3c6a7fb-d980-43d4-bb84-ae22018a0710\",\"4e7a6993-fcee-47ae-9599-0047809bb29e\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Garbage Collection\"}]","timeRestore":false,"title":"Layer7 Gateway Dashboard","version":1},"coreMigrationVersion":"8.8.0","created_at":"2024-05-14T07:28:39.093Z","id":"c29a9900-2161-11ee-be6c-57cbef857d54","managed":false,"references":[{"id":"apm_static_index_pattern_id","name":"675c235a-535c-48d9-a5ed-848810986e5a:indexpattern-datasource-layer-8638d8b0-f850-42f0-9e64-35e6f239e0d0","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"0ae50fd8-f924-4207-b546-5d600ac701b3:indexpattern-datasource-layer-cad7aae7-308f-4c4f-abbd-b03792fbec56","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"ee3d33f8-243e-42d9-87fa-09c00dbfd1b7:indexpattern-datasource-layer-fd66544d-5ee7-4f36-8966-c7aa38197646","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"d9305573-c761-4802-9c0b-6f6326266125:indexpattern-datasource-layer-8638d8b0-f850-42f0-9e64-35e6f239e0d0","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"868932e9-487a-408f-89fd-14f9324534e9:indexpattern-datasource-layer-2381ace6-24bb-4e47-b57b-6fe06c980216","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"868932e9-487a-408f-89fd-14f9324534e9:indexpattern-datasource-layer-06696642-3076-4612-8291-189dcb25dd9e","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"9a54b939-5371-49f6-8888-ab92e165e625:indexpattern-datasource-layer-a57f2de0-c4c8-4a18-9b3a-533ad5572097","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"2a2057e2-ce45-4804-8ce0-3d4ed94679d7:indexpattern-datasource-layer-04cd0fc2-f652-4583-a7d4-c1a8f6f8818f","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"2a2057e2-ce45-4804-8ce0-3d4ed94679d7:indexpattern-datasource-layer-b369a9a0-f9ee-4b7e-ba8f-97d2722cd89d","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"2a2057e2-ce45-4804-8ce0-3d4ed94679d7:indexpattern-datasource-layer-66ce3428-e822-4b54-afc8-69bbffd9c106","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"542275ac-682e-43b8-b1ac-cf919d206e02:indexpattern-datasource-layer-28f4234a-7411-4d15-8ad9-36ac978f7e19","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"a3aace75-debc-4370-9954-e5a6e8ac6259:indexpattern-datasource-layer-067c1db7-2942-4bf9-8fd6-4ca0a42a23fa","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"7f1f017e-d42b-4cf4-8cb2-3f4bb3de5367:indexpattern-datasource-layer-a3ee7019-98bb-45cd-8536-e36a8e58297e","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"4f987373-1b85-4e80-a7cc-c1c000349c5e:indexpattern-datasource-layer-a45cd02a-4c62-4b34-bdce-c702b87b4246","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"controlGroup_d3e0d4d0-b1de-465c-8772-806a49213c2b:optionsListDataView","type":"index-pattern"}],"type":"dashboard","typeMigrationVersion":"8.7.0","updated_at":"2024-05-14T07:28:39.093Z","version":"WzE2ODksMV0="}
+{"attributes":{"allowNoIndex":true,"fieldAttrs":"{\"layer7_service_routing_latency\":{\"count\":5},\"broadcom_totalBackendLatency\":{\"count\":1},\"@timestamp\":{\"count\":1},\"layer7_totalBackendLatency\":{\"count\":2},\"layer7_totalBackendLatencyV1\":{\"count\":1},\"layer7_totalFrontendLatency\":{\"count\":1},\"db.client.connections.usage\":{\"count\":2},\"labels.pool_name\":{\"count\":1},\"labels.state\":{\"count\":1},\"process.runtime.jvm.classes.loaded\":{\"count\":2},\"db.client.connections.pending_requests\":{\"count\":1},\"labels.process_runtime_description\":{\"count\":2},\"process.runtime.jvm.gc.duration\":{\"count\":1},\"layer7_service_total\":{\"count\":1},\"process.runtime.jvm.memory.limit\":{\"count\":2},\"process.runtime.jvm.memory.usage\":{\"count\":1},\"process.runtime.jvm.system.cpu.load_1m\":{\"count\":1},\"layer7_routing_failues\":{\"count\":1},\"layer7_service_success\":{\"count\":1},\"layer7_service_latency\":{\"count\":2},\"labels.serviceName\":{\"count\":1},\"labels.gc\":{\"count\":1},\"labels.method\":{\"count\":1},\"numeric_labels.code\":{\"count\":1},\"process.runtime.jvm.threads.count\":{\"count\":1},\"span.name\":{\"count\":3},\"layer7_service_latency\":{\"count\":1},\"layer7_service_policy_violations\":{\"count\":1},\"labels.layer7_serviceName\":{\"count\":1},\"labels.layer7gw_name\":{\"count\":1}}","fieldFormatMap":"{\"trace.id\":{\"id\":\"url\",\"params\":{\"urlTemplate\":\"apm/link-to/trace/{{value}}\",\"labelTemplate\":\"{{value}}\"}},\"transaction.id\":{\"id\":\"url\",\"params\":{\"urlTemplate\":\"apm/link-to/transaction/{{value}}\",\"labelTemplate\":\"{{value}}\"}},\"transaction.duration.us\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"microseconds\",\"outputFormat\":\"asMilliseconds\",\"showSuffix\":true,\"useShortSuffix\":true,\"outputPrecision\":2,\"includeSpaceWithSuffix\":true}}}","fields":"[]","name":"APM","runtimeFieldMap":"{}","sourceFilters":"[]","timeFieldName":"@timestamp","title":"traces-apm*,apm-*,logs-apm*,apm-*,metrics-apm*,apm-*","typeMeta":"{}"},"coreMigrationVersion":"8.8.0","created_at":"2024-05-14T07:23:11.980Z","id":"apm_static_index_pattern_id","managed":false,"references":[],"type":"index-pattern","typeMigrationVersion":"8.0.0","updated_at":"2024-05-14T07:23:11.980Z","version":"WzQyMiwxXQ=="}
+{"attributes":{"controlGroupInput":{"chainingSystem":"HIERARCHICAL","controlStyle":"twoLine","ignoreParentSettingsJSON":"{\"ignoreFilters\":false,\"ignoreQuery\":false,\"ignoreTimerange\":false,\"ignoreValidations\":false}","panelsJSON":"{\"d3e0d4d0-b1de-465c-8772-806a49213c2b\":{\"type\":\"optionsListControl\",\"order\":0,\"grow\":true,\"width\":\"medium\",\"explicitInput\":{\"id\":\"d3e0d4d0-b1de-465c-8772-806a49213c2b\",\"fieldName\":\"labels.layer7gw_name\",\"title\":\"Gateway\",\"selectedOptions\":[],\"enhancements\":{},\"existsSelected\":false}}}"},"description":"","kibanaSavedObjectMeta":{"searchSourceJSON":"{\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filter\":[]}"},"optionsJSON":"{\"useMargins\":true,\"syncColors\":false,\"syncCursor\":true,\"syncTooltips\":false,\"hidePanelTitles\":false}","panelsJSON":"[{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":0,\"w\":22,\"h\":11,\"i\":\"675c235a-535c-48d9-a5ed-848810986e5a\"},\"panelIndex\":\"675c235a-535c-48d9-a5ed-848810986e5a\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"description\":\"\",\"visualizationType\":\"lnsDatatable\",\"type\":\"lens\",\"references\":[{\"type\":\"index-pattern\",\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-8638d8b0-f850-42f0-9e64-35e6f239e0d0\"}],\"state\":{\"visualization\":{\"columns\":[{\"columnId\":\"82dab02b-8829-488e-bd30-aa8c45996590\",\"isTransposed\":false,\"summaryRow\":\"sum\"},{\"columnId\":\"ae1e2f3d-6ec8-49c9-a444-8249ed271df8\",\"isTransposed\":false,\"summaryRow\":\"sum\",\"summaryLabel\":\"\"},{\"columnId\":\"ff0032fe-94ec-4bf8-a50f-9905301868f9\",\"isTransposed\":false,\"summaryRow\":\"sum\",\"summaryLabel\":\"\"},{\"columnId\":\"ed1df4b3-0bcd-4059-965d-39bc63eef215\",\"isTransposed\":false}],\"layerId\":\"8638d8b0-f850-42f0-9e64-35e6f239e0d0\",\"layerType\":\"data\",\"paging\":{\"size\":10,\"enabled\":true}},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"8638d8b0-f850-42f0-9e64-35e6f239e0d0\":{\"columns\":{\"ed1df4b3-0bcd-4059-965d-39bc63eef215\":{\"label\":\"Service Name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"labels.layer7_serviceName\",\"isBucketed\":true,\"params\":{\"size\":10,\"orderBy\":{\"type\":\"column\",\"columnId\":\"82dab02b-8829-488e-bd30-aa8c45996590\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]},\"customLabel\":true},\"82dab02b-8829-488e-bd30-aa8c45996590\":{\"label\":\"Policy Violations\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"layer7_service_policy_violations\",\"filter\":{\"query\":\"layer7_service_policy_violations: *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"ae1e2f3d-6ec8-49c9-a444-8249ed271df8\":{\"label\":\"Success\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"layer7_service_success\",\"filter\":{\"query\":\"layer7_service_success: *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"ff0032fe-94ec-4bf8-a50f-9905301868f9\":{\"label\":\"Routing Failures\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"layer7_service_routing_failures\",\"filter\":{\"query\":\"layer7_service_routing_failures: *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true}},\"columnOrder\":[\"ed1df4b3-0bcd-4059-965d-39bc63eef215\",\"82dab02b-8829-488e-bd30-aa8c45996590\",\"ae1e2f3d-6ec8-49c9-a444-8249ed271df8\",\"ff0032fe-94ec-4bf8-a50f-9905301868f9\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Usage\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":22,\"y\":0,\"w\":26,\"h\":11,\"i\":\"0ae50fd8-f924-4207-b546-5d600ac701b3\"},\"panelIndex\":\"0ae50fd8-f924-4207-b546-5d600ac701b3\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-cad7aae7-308f-4c4f-abbd-b03792fbec56\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"title\":\"Empty XY chart\",\"legend\":{\"isVisible\":true,\"position\":\"bottom\"},\"valueLabels\":\"hide\",\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"cad7aae7-308f-4c4f-abbd-b03792fbec56\",\"accessors\":[\"4ee0c11f-c34e-48b9-ba2b-3a855498cd44\"],\"position\":\"top\",\"seriesType\":\"line\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"bf646547-1ad3-4810-8d0c-ac6d35be61ec\",\"splitAccessor\":\"2bffabd5-d07e-4187-a67d-c1d085ea598a\"}],\"curveType\":\"CURVE_MONOTONE_X\",\"fittingFunction\":\"Zero\",\"emphasizeFitting\":true,\"endValue\":\"Zero\",\"valuesInLegend\":false,\"axisTitlesVisibilitySettings\":{\"x\":false,\"yLeft\":true,\"yRight\":true},\"yTitle\":\"Requests\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"cad7aae7-308f-4c4f-abbd-b03792fbec56\":{\"columns\":{\"bf646547-1ad3-4810-8d0c-ac6d35be61ec\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":false,\"dropPartials\":false}},\"2bffabd5-d07e-4187-a67d-c1d085ea598a\":{\"label\":\"Top 10 values of labels.layer7_serviceName\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"labels.layer7_serviceName\",\"isBucketed\":true,\"params\":{\"size\":10,\"orderBy\":{\"type\":\"alphabetical\",\"fallback\":true},\"orderDirection\":\"asc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]}},\"4ee0c11f-c34e-48b9-ba2b-3a855498cd44\":{\"label\":\"Requests\",\"dataType\":\"number\",\"operationType\":\"counter_rate\",\"isBucketed\":false,\"scale\":\"ratio\",\"references\":[\"82148cde-9560-4544-a841-38ccaf7b66f5\"],\"filter\":{\"query\":\"\",\"language\":\"kuery\"},\"params\":{\"format\":{\"id\":\"number\",\"params\":{\"decimals\":0}}},\"customLabel\":true},\"82148cde-9560-4544-a841-38ccaf7b66f5\":{\"label\":\"Maximum of layer7_service_attempted\",\"dataType\":\"number\",\"operationType\":\"max\",\"sourceField\":\"layer7_service_attempted\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"emptyAsNull\":true}}},\"columnOrder\":[\"2bffabd5-d07e-4187-a67d-c1d085ea598a\",\"bf646547-1ad3-4810-8d0c-ac6d35be61ec\",\"4ee0c11f-c34e-48b9-ba2b-3a855498cd44\",\"82148cde-9560-4544-a841-38ccaf7b66f5\"],\"sampling\":1,\"incompleteColumns\":{}}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Message Rate\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":11,\"w\":22,\"h\":11,\"i\":\"ee3d33f8-243e-42d9-87fa-09c00dbfd1b7\"},\"panelIndex\":\"ee3d33f8-243e-42d9-87fa-09c00dbfd1b7\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-fd66544d-5ee7-4f36-8966-c7aa38197646\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"bottom\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"yTitle\":\"Latency (ms)\",\"axisTitlesVisibilitySettings\":{\"x\":false,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"fd66544d-5ee7-4f36-8966-c7aa38197646\",\"accessors\":[\"6da1dadd-1f1a-42d6-b954-e8bd5a318f4b\",\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"c973fd1a-9645-46a1-ad45-483cf1ff0441\",\"splitAccessor\":\"4ef8265b-6ee1-449f-9ced-ae065efc7296\"}],\"showCurrentTimeMarker\":false,\"yLeftScale\":\"linear\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"fd66544d-5ee7-4f36-8966-c7aa38197646\":{\"columns\":{\"c973fd1a-9645-46a1-ad45-483cf1ff0441\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X0\":{\"label\":\"Part of Frontend\",\"dataType\":\"number\",\"operationType\":\"average\",\"sourceField\":\"layer7_service_latency\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X1\":{\"label\":\"Part of Frontend\",\"dataType\":\"number\",\"operationType\":\"average\",\"sourceField\":\"layer7_service_routing_latency\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X2\":{\"label\":\"Part of Frontend\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"subtract\",\"args\":[\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X0\",\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X1\"],\"location\":{\"min\":0,\"max\":63},\"text\":\"average(layer7_service_latency)-average(layer7_service_routing_latency)\"}},\"references\":[\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X0\",\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X1\"],\"customLabel\":true},\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5\":{\"label\":\"Frontend\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"average(layer7_service_latency)-average(layer7_service_routing_latency)\",\"isFormulaBroken\":false},\"references\":[\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X2\"],\"customLabel\":true},\"6da1dadd-1f1a-42d6-b954-e8bd5a318f4bX0\":{\"label\":\"Part of Backend\",\"dataType\":\"number\",\"operationType\":\"average\",\"sourceField\":\"layer7_service_routing_latency\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"emptyAsNull\":false},\"customLabel\":true},\"6da1dadd-1f1a-42d6-b954-e8bd5a318f4b\":{\"label\":\"Backend\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"average(layer7_service_routing_latency)\",\"isFormulaBroken\":false},\"references\":[\"6da1dadd-1f1a-42d6-b954-e8bd5a318f4bX0\"],\"customLabel\":true},\"4ef8265b-6ee1-449f-9ced-ae065efc7296\":{\"label\":\"Top 10 values of labels.layer7_serviceName\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"labels.layer7_serviceName\",\"isBucketed\":true,\"params\":{\"size\":10,\"orderBy\":{\"type\":\"alphabetical\",\"fallback\":true},\"orderDirection\":\"asc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[]}}},\"columnOrder\":[\"4ef8265b-6ee1-449f-9ced-ae065efc7296\",\"c973fd1a-9645-46a1-ad45-483cf1ff0441\",\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5\",\"6da1dadd-1f1a-42d6-b954-e8bd5a318f4b\",\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X0\",\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X2\",\"f4fc3664-ef1d-44f5-b9ce-edb2168d5ce5X1\",\"6da1dadd-1f1a-42d6-b954-e8bd5a318f4bX0\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Latency\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":22,\"y\":11,\"w\":26,\"h\":11,\"i\":\"d9305573-c761-4802-9c0b-6f6326266125\"},\"panelIndex\":\"d9305573-c761-4802-9c0b-6f6326266125\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-8638d8b0-f850-42f0-9e64-35e6f239e0d0\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"bottom\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"yTitle\":\"Number of Messages\",\"axisTitlesVisibilitySettings\":{\"x\":false,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"8638d8b0-f850-42f0-9e64-35e6f239e0d0\",\"seriesType\":\"bar\",\"accessors\":[\"28a49db2-d0b2-47ea-bd58-12e827e9851d\",\"6d6fe07e-c712-4d47-89c6-1ebdeaa23304\",\"231179ca-b88a-4495-b857-8006bca2b409\"],\"layerType\":\"data\",\"yConfig\":[{\"forAccessor\":\"231179ca-b88a-4495-b857-8006bca2b409\",\"color\":\"#8b8c2b\",\"axisMode\":\"left\"},{\"forAccessor\":\"28a49db2-d0b2-47ea-bd58-12e827e9851d\",\"color\":\"#2da275\",\"axisMode\":\"left\"},{\"forAccessor\":\"6d6fe07e-c712-4d47-89c6-1ebdeaa23304\",\"color\":\"#781032\",\"axisMode\":\"left\"}],\"xAccessor\":\"227364f6-80d8-4d15-89ca-7166dc900804\"}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"8638d8b0-f850-42f0-9e64-35e6f239e0d0\":{\"columns\":{\"227364f6-80d8-4d15-89ca-7166dc900804\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"m\",\"includeEmptyRows\":false,\"dropPartials\":false}},\"231179ca-b88a-4495-b857-8006bca2b409\":{\"label\":\"Routing failues\",\"dataType\":\"number\",\"operationType\":\"counter_rate\",\"isBucketed\":false,\"scale\":\"ratio\",\"references\":[\"6e76dd16-427c-4267-a977-522b4f1a8eba\"],\"customLabel\":true,\"params\":{\"format\":{\"id\":\"number\",\"params\":{\"decimals\":0}}}},\"6e76dd16-427c-4267-a977-522b4f1a8eba\":{\"label\":\"Maximum of layer7_service_routing_failures\",\"dataType\":\"number\",\"operationType\":\"max\",\"sourceField\":\"layer7_service_routing_failures\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"emptyAsNull\":true}},\"6d6fe07e-c712-4d47-89c6-1ebdeaa23304\":{\"label\":\"Policy Violations\",\"dataType\":\"number\",\"operationType\":\"counter_rate\",\"isBucketed\":false,\"scale\":\"ratio\",\"references\":[\"84104e54-bd82-47f6-b34d-b04a1db60694\"],\"timeScale\":\"s\",\"params\":{\"format\":{\"id\":\"number\",\"params\":{\"decimals\":0}}},\"customLabel\":true},\"84104e54-bd82-47f6-b34d-b04a1db60694\":{\"label\":\"Maximum of layer7_service_policy_violations\",\"dataType\":\"number\",\"operationType\":\"max\",\"sourceField\":\"layer7_service_policy_violations\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"emptyAsNull\":true}},\"28a49db2-d0b2-47ea-bd58-12e827e9851d\":{\"label\":\"Success\",\"dataType\":\"number\",\"operationType\":\"counter_rate\",\"isBucketed\":false,\"scale\":\"ratio\",\"references\":[\"3da518c4-50c1-415f-8248-b11b5be8873f\"],\"timeScale\":\"s\",\"params\":{\"format\":{\"id\":\"number\",\"params\":{\"decimals\":0}}},\"customLabel\":true},\"3da518c4-50c1-415f-8248-b11b5be8873f\":{\"label\":\"Maximum of layer7_service_attempted\",\"dataType\":\"number\",\"operationType\":\"max\",\"sourceField\":\"layer7_service_attempted\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"emptyAsNull\":true}}},\"columnOrder\":[\"227364f6-80d8-4d15-89ca-7166dc900804\",\"28a49db2-d0b2-47ea-bd58-12e827e9851d\",\"231179ca-b88a-4495-b857-8006bca2b409\",\"6e76dd16-427c-4267-a977-522b4f1a8eba\",\"6d6fe07e-c712-4d47-89c6-1ebdeaa23304\",\"84104e54-bd82-47f6-b34d-b04a1db60694\",\"3da518c4-50c1-415f-8248-b11b5be8873f\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Service Status\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":22,\"w\":48,\"h\":15,\"i\":\"868932e9-487a-408f-89fd-14f9324534e9\"},\"panelIndex\":\"868932e9-487a-408f-89fd-14f9324534e9\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-2381ace6-24bb-4e47-b57b-6fe06c980216\",\"type\":\"index-pattern\"},{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-06696642-3076-4612-8291-189dcb25dd9e\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\",\"isInside\":false,\"verticalAlignment\":\"bottom\",\"horizontalAlignment\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"Zero\",\"curveType\":\"CURVE_MONOTONE_X\",\"yLeftScale\":\"sqrt\",\"axisTitlesVisibilitySettings\":{\"x\":false,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar\",\"layers\":[{\"layerId\":\"2381ace6-24bb-4e47-b57b-6fe06c980216\",\"accessors\":[\"b13dba51-c5c9-4c20-9212-e8607d048660\"],\"position\":\"top\",\"seriesType\":\"bar\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"209b6a96-6641-42d5-b243-cd7a68dc55be\",\"splitAccessor\":\"b8a1138e-65ed-4595-8c72-23c294313fc5\",\"collapseFn\":\"\"},{\"layerId\":\"06696642-3076-4612-8291-189dcb25dd9e\",\"layerType\":\"data\",\"accessors\":[\"74470d07-35e7-40c2-bf78-7bd282323271\"],\"seriesType\":\"line\",\"xAccessor\":\"96a4345f-06e4-4252-9ed1-31ed39ee347c\",\"splitAccessor\":\"8756242d-1a48-4550-9fd5-66057b194995\"}],\"emphasizeFitting\":true,\"yTitle\":\"Connections\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"2381ace6-24bb-4e47-b57b-6fe06c980216\":{\"columns\":{\"b8a1138e-65ed-4595-8c72-23c294313fc5\":{\"label\":\"Top values of labels.pool_name + 1 other\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"labels.pool_name\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"b13dba51-c5c9-4c20-9212-e8607d048660\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"multi_terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"secondaryFields\":[\"labels.state\"]}},\"209b6a96-6641-42d5-b243-cd7a68dc55be\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"b13dba51-c5c9-4c20-9212-e8607d048660\":{\"label\":\"conns\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"db.client.connections.usage\",\"filter\":{\"query\":\"db.client.connections.usage: *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true}},\"columnOrder\":[\"b8a1138e-65ed-4595-8c72-23c294313fc5\",\"209b6a96-6641-42d5-b243-cd7a68dc55be\",\"b13dba51-c5c9-4c20-9212-e8607d048660\"],\"incompleteColumns\":{},\"sampling\":1},\"06696642-3076-4612-8291-189dcb25dd9e\":{\"linkToLayers\":[],\"columns\":{\"74470d07-35e7-40c2-bf78-7bd282323271\":{\"label\":\"pending requests\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"db.client.connections.pending_requests\",\"filter\":{\"query\":\"db.client.connections.pending_requests: *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"96a4345f-06e4-4252-9ed1-31ed39ee347c\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"8756242d-1a48-4550-9fd5-66057b194995\":{\"label\":\"Top 3 values of labels.pool_name\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"labels.pool_name\",\"isBucketed\":true,\"params\":{\"size\":3,\"orderBy\":{\"type\":\"column\",\"columnId\":\"74470d07-35e7-40c2-bf78-7bd282323271\"},\"orderDirection\":\"desc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false}}},\"columnOrder\":[\"8756242d-1a48-4550-9fd5-66057b194995\",\"96a4345f-06e4-4252-9ed1-31ed39ee347c\",\"74470d07-35e7-40c2-bf78-7bd282323271\"],\"sampling\":1,\"incompleteColumns\":{}}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"DB Connections\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":37,\"w\":22,\"h\":10,\"i\":\"9a54b939-5371-49f6-8888-ab92e165e625\"},\"panelIndex\":\"9a54b939-5371-49f6-8888-ab92e165e625\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-a57f2de0-c4c8-4a18-9b3a-533ad5572097\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"bottom\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"yLeftExtent\":{\"mode\":\"full\"},\"axisTitlesVisibilitySettings\":{\"x\":false,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"a57f2de0-c4c8-4a18-9b3a-533ad5572097\",\"accessors\":[\"f0c37a83-1464-4350-bb91-e57c2198b927\",\"cdcae1da-c18f-40a5-aeed-1be00a243149\"],\"position\":\"top\",\"seriesType\":\"bar\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"deb7bb17-0f00-4a18-b2be-e6a5a2becb7e\",\"yConfig\":[{\"forAccessor\":\"cdcae1da-c18f-40a5-aeed-1be00a243149\",\"color\":\"#e7664c\"}]}],\"yTitle\":\"CPU utilization (0-100)\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"a57f2de0-c4c8-4a18-9b3a-533ad5572097\":{\"columns\":{\"deb7bb17-0f00-4a18-b2be-e6a5a2becb7e\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"f0c37a83-1464-4350-bb91-e57c2198b927X0\":{\"label\":\"Part of System CPU utilization\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"process.runtime.jvm.system.cpu.utilization\",\"filter\":{\"query\":\"process.runtime.jvm.system.cpu.utilization: *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"f0c37a83-1464-4350-bb91-e57c2198b927X1\":{\"label\":\"Part of System CPU utilization\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"multiply\",\"args\":[\"f0c37a83-1464-4350-bb91-e57c2198b927X0\",100],\"location\":{\"min\":0,\"max\":121},\"text\":\"multiply(last_value(process.runtime.jvm.system.cpu.utilization, kql='process.runtime.jvm.system.cpu.utilization: *'),100)\"}},\"references\":[\"f0c37a83-1464-4350-bb91-e57c2198b927X0\"],\"customLabel\":true},\"f0c37a83-1464-4350-bb91-e57c2198b927\":{\"label\":\"System CPU utilization\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"multiply(last_value(process.runtime.jvm.system.cpu.utilization, kql='process.runtime.jvm.system.cpu.utilization: *'),100)\",\"isFormulaBroken\":false},\"references\":[\"f0c37a83-1464-4350-bb91-e57c2198b927X1\"],\"customLabel\":true},\"cdcae1da-c18f-40a5-aeed-1be00a243149X0\":{\"label\":\"Part of JVM CPU utilization\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"process.runtime.jvm.cpu.utilization\",\"filter\":{\"query\":\"process.runtime.jvm.cpu.utilization: *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"cdcae1da-c18f-40a5-aeed-1be00a243149\":{\"label\":\"JVM CPU utilization\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"last_value(process.runtime.jvm.cpu.utilization, kql='process.runtime.jvm.cpu.utilization: *')\",\"isFormulaBroken\":false},\"references\":[\"cdcae1da-c18f-40a5-aeed-1be00a243149X0\"],\"customLabel\":true}},\"columnOrder\":[\"deb7bb17-0f00-4a18-b2be-e6a5a2becb7e\",\"f0c37a83-1464-4350-bb91-e57c2198b927\",\"f0c37a83-1464-4350-bb91-e57c2198b927X0\",\"f0c37a83-1464-4350-bb91-e57c2198b927X1\",\"cdcae1da-c18f-40a5-aeed-1be00a243149\",\"cdcae1da-c18f-40a5-aeed-1be00a243149X0\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"CPU/System Utilization\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":22,\"y\":37,\"w\":26,\"h\":10,\"i\":\"2a2057e2-ce45-4804-8ce0-3d4ed94679d7\"},\"panelIndex\":\"2a2057e2-ce45-4804-8ce0-3d4ed94679d7\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-04cd0fc2-f652-4583-a7d4-c1a8f6f8818f\",\"type\":\"index-pattern\"},{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-b369a9a0-f9ee-4b7e-ba8f-97d2722cd89d\",\"type\":\"index-pattern\"},{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-66ce3428-e822-4b54-afc8-69bbffd9c106\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"bottom\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":false,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"04cd0fc2-f652-4583-a7d4-c1a8f6f8818f\",\"accessors\":[\"371f4c5e-dca1-4de3-b495-b29d0c51ad42\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"7e7413d7-db3d-4473-b46f-d76132f403b0\",\"splitAccessor\":\"06b7cd00-d4bf-4c98-a2e1-2932a19a92ae\",\"palette\":{\"type\":\"palette\",\"name\":\"status\"},\"collapseFn\":\"\",\"yConfig\":[]},{\"layerId\":\"b369a9a0-f9ee-4b7e-ba8f-97d2722cd89d\",\"layerType\":\"referenceLine\",\"accessors\":[\"81fcf196-8145-4246-9d3a-f1679cb62c81\"],\"yConfig\":[{\"forAccessor\":\"81fcf196-8145-4246-9d3a-f1679cb62c81\",\"axisMode\":\"left\",\"icon\":\"bolt\",\"iconPosition\":\"auto\",\"lineWidth\":2,\"color\":\"#9d2022\"}]},{\"layerId\":\"66ce3428-e822-4b54-afc8-69bbffd9c106\",\"layerType\":\"data\",\"accessors\":[\"323e403c-e4a1-481d-897e-907192f1cc4a\"],\"seriesType\":\"line\",\"xAccessor\":\"f8721fc3-00f3-4106-96eb-0121ce00e6aa\",\"yConfig\":[{\"forAccessor\":\"323e403c-e4a1-481d-897e-907192f1cc4a\",\"color\":\"#040f12\"}]}],\"yLeftExtent\":{\"mode\":\"full\"},\"yTitle\":\"Megabytes\",\"yLeftScale\":\"log\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"04cd0fc2-f652-4583-a7d4-c1a8f6f8818f\":{\"columns\":{\"7e7413d7-db3d-4473-b46f-d76132f403b0\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":false,\"dropPartials\":false}},\"371f4c5e-dca1-4de3-b495-b29d0c51ad42X0\":{\"label\":\"Part of Heap\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"process.runtime.jvm.memory.usage\",\"filter\":{\"query\":\"process.runtime.jvm.memory.usage: * and labels.type: heap\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"371f4c5e-dca1-4de3-b495-b29d0c51ad42X1\":{\"label\":\"Part of Heap\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"divide\",\"args\":[\"371f4c5e-dca1-4de3-b495-b29d0c51ad42X0\",1048576],\"location\":{\"min\":0,\"max\":126},\"text\":\"divide(last_value(process.runtime.jvm.memory.usage, kql='process.runtime.jvm.memory.usage: * and labels.type: heap'), 1048576)\"}},\"references\":[\"371f4c5e-dca1-4de3-b495-b29d0c51ad42X0\"],\"customLabel\":true},\"371f4c5e-dca1-4de3-b495-b29d0c51ad42\":{\"label\":\"Heap\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"divide(last_value(process.runtime.jvm.memory.usage, kql='process.runtime.jvm.memory.usage: * and labels.type: heap'), 1048576)\",\"isFormulaBroken\":false},\"references\":[\"371f4c5e-dca1-4de3-b495-b29d0c51ad42X1\"],\"customLabel\":true},\"06b7cd00-d4bf-4c98-a2e1-2932a19a92ae\":{\"label\":\"Top 10 values of labels.pool\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"labels.pool\",\"isBucketed\":true,\"params\":{\"size\":10,\"orderBy\":{\"type\":\"alphabetical\",\"fallback\":true},\"orderDirection\":\"asc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false,\"accuracyMode\":true}}},\"columnOrder\":[\"06b7cd00-d4bf-4c98-a2e1-2932a19a92ae\",\"7e7413d7-db3d-4473-b46f-d76132f403b0\",\"371f4c5e-dca1-4de3-b495-b29d0c51ad42\",\"371f4c5e-dca1-4de3-b495-b29d0c51ad42X0\",\"371f4c5e-dca1-4de3-b495-b29d0c51ad42X1\"],\"incompleteColumns\":{},\"sampling\":1},\"b369a9a0-f9ee-4b7e-ba8f-97d2722cd89d\":{\"linkToLayers\":[],\"columns\":{\"81fcf196-8145-4246-9d3a-f1679cb62c81X0\":{\"label\":\"Part of Max\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"process.runtime.jvm.memory.limit\",\"filter\":{\"query\":\"process.runtime.jvm.memory.limit: * and labels.type: heap\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"81fcf196-8145-4246-9d3a-f1679cb62c81X1\":{\"label\":\"Part of Max\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"divide\",\"args\":[\"81fcf196-8145-4246-9d3a-f1679cb62c81X0\",1048576],\"location\":{\"min\":0,\"max\":126},\"text\":\"divide(last_value(process.runtime.jvm.memory.limit, kql='process.runtime.jvm.memory.limit: * and labels.type: heap'), 1048576)\"}},\"references\":[\"81fcf196-8145-4246-9d3a-f1679cb62c81X0\"],\"customLabel\":true},\"81fcf196-8145-4246-9d3a-f1679cb62c81\":{\"label\":\"Max\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"divide(last_value(process.runtime.jvm.memory.limit, kql='process.runtime.jvm.memory.limit: * and labels.type: heap'), 1048576)\",\"isFormulaBroken\":false,\"format\":{\"id\":\"number\",\"params\":{\"decimals\":0}}},\"references\":[\"81fcf196-8145-4246-9d3a-f1679cb62c81X1\"],\"customLabel\":true}},\"columnOrder\":[\"81fcf196-8145-4246-9d3a-f1679cb62c81\",\"81fcf196-8145-4246-9d3a-f1679cb62c81X0\",\"81fcf196-8145-4246-9d3a-f1679cb62c81X1\"],\"sampling\":1,\"incompleteColumns\":{}},\"66ce3428-e822-4b54-afc8-69bbffd9c106\":{\"linkToLayers\":[],\"columns\":{\"f8721fc3-00f3-4106-96eb-0121ce00e6aa\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"323e403c-e4a1-481d-897e-907192f1cc4aX0\":{\"label\":\"Part of Non-Heap\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"process.runtime.jvm.memory.usage\",\"filter\":{\"query\":\"process.runtime.jvm.memory.usage: * and labels.type: non_heap\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"323e403c-e4a1-481d-897e-907192f1cc4aX1\":{\"label\":\"Part of Non-Heap\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"divide\",\"args\":[\"323e403c-e4a1-481d-897e-907192f1cc4aX0\",1048576],\"location\":{\"min\":0,\"max\":130},\"text\":\"divide(last_value(process.runtime.jvm.memory.usage, kql='process.runtime.jvm.memory.usage: * and labels.type: non_heap'), 1048576)\"}},\"references\":[\"323e403c-e4a1-481d-897e-907192f1cc4aX0\"],\"customLabel\":true},\"323e403c-e4a1-481d-897e-907192f1cc4a\":{\"label\":\"Non-Heap\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"divide(last_value(process.runtime.jvm.memory.usage, kql='process.runtime.jvm.memory.usage: * and labels.type: non_heap'), 1048576)\",\"isFormulaBroken\":false},\"references\":[\"323e403c-e4a1-481d-897e-907192f1cc4aX1\"],\"customLabel\":true}},\"columnOrder\":[\"f8721fc3-00f3-4106-96eb-0121ce00e6aa\",\"323e403c-e4a1-481d-897e-907192f1cc4a\",\"323e403c-e4a1-481d-897e-907192f1cc4aX1\",\"323e403c-e4a1-481d-897e-907192f1cc4aX0\"],\"sampling\":1,\"incompleteColumns\":{}}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"enhancements\":{},\"hidePanelTitles\":false},\"title\":\"Memory Usage\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":47,\"w\":22,\"h\":11,\"i\":\"542275ac-682e-43b8-b1ac-cf919d206e02\"},\"panelIndex\":\"542275ac-682e-43b8-b1ac-cf919d206e02\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-28f4234a-7411-4d15-8ad9-36ac978f7e19\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"yLeftExtent\":{\"mode\":\"full\"},\"axisTitlesVisibilitySettings\":{\"x\":false,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"28f4234a-7411-4d15-8ad9-36ac978f7e19\",\"accessors\":[\"04481efd-b3d8-44bc-be6c-5a0af56e241b\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"5e07b038-8927-4bdb-a933-ddbd1f7d0374\"}],\"yTitle\":\"System Load (0-100)\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"28f4234a-7411-4d15-8ad9-36ac978f7e19\":{\"columns\":{\"5e07b038-8927-4bdb-a933-ddbd1f7d0374\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"04481efd-b3d8-44bc-be6c-5a0af56e241bX0\":{\"label\":\"Part of System Load\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"process.runtime.jvm.system.cpu.load_1m\",\"filter\":{\"query\":\"process.runtime.jvm.system.cpu.load_1m: *\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"04481efd-b3d8-44bc-be6c-5a0af56e241b\":{\"label\":\"System Load\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"last_value(process.runtime.jvm.system.cpu.load_1m, kql='process.runtime.jvm.system.cpu.load_1m: *')\",\"isFormulaBroken\":false},\"references\":[\"04481efd-b3d8-44bc-be6c-5a0af56e241bX0\"],\"customLabel\":true}},\"columnOrder\":[\"5e07b038-8927-4bdb-a933-ddbd1f7d0374\",\"04481efd-b3d8-44bc-be6c-5a0af56e241b\",\"04481efd-b3d8-44bc-be6c-5a0af56e241bX0\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"System Load\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":22,\"y\":47,\"w\":26,\"h\":11,\"i\":\"a3aace75-debc-4370-9954-e5a6e8ac6259\"},\"panelIndex\":\"a3aace75-debc-4370-9954-e5a6e8ac6259\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-067c1db7-2942-4bf9-8fd6-4ca0a42a23fa\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"bottom\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"067c1db7-2942-4bf9-8fd6-4ca0a42a23fa\",\"accessors\":[\"603e1430-a496-4249-b2da-73a5205b964e\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"2ab4d7f4-49aa-4e45-9ad7-73256400df18\",\"splitAccessor\":\"a9ec0126-a45f-4f86-b783-a4820badd7d8\",\"yConfig\":[{\"forAccessor\":\"603e1430-a496-4249-b2da-73a5205b964e\",\"axisMode\":\"left\"}],\"palette\":{\"type\":\"palette\",\"name\":\"status\"}}],\"yLeftScale\":\"log\",\"yTitle\":\"Megabytes\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"067c1db7-2942-4bf9-8fd6-4ca0a42a23fa\":{\"columns\":{\"2ab4d7f4-49aa-4e45-9ad7-73256400df18\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":false,\"dropPartials\":false}},\"603e1430-a496-4249-b2da-73a5205b964eX0\":{\"label\":\"Part of divide(last_value(process.runtime.jvm.memory.usage_after_last_gc, kql='process.runtime.jvm.memory.usage_after_last_gc: * and labels.type: heap'), 1048576)\",\"dataType\":\"number\",\"operationType\":\"last_value\",\"isBucketed\":false,\"scale\":\"ratio\",\"sourceField\":\"process.runtime.jvm.memory.usage_after_last_gc\",\"filter\":{\"query\":\"process.runtime.jvm.memory.usage_after_last_gc: * and labels.type: heap\",\"language\":\"kuery\"},\"params\":{\"sortField\":\"@timestamp\"},\"customLabel\":true},\"603e1430-a496-4249-b2da-73a5205b964eX1\":{\"label\":\"Part of divide(last_value(process.runtime.jvm.memory.usage_after_last_gc, kql='process.runtime.jvm.memory.usage_after_last_gc: * and labels.type: heap'), 1048576)\",\"dataType\":\"number\",\"operationType\":\"math\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"tinymathAst\":{\"type\":\"function\",\"name\":\"divide\",\"args\":[\"603e1430-a496-4249-b2da-73a5205b964eX0\",1048576],\"location\":{\"min\":0,\"max\":154},\"text\":\"divide(last_value(process.runtime.jvm.memory.usage_after_last_gc, kql='process.runtime.jvm.memory.usage_after_last_gc: * and labels.type: heap'), 1048576)\"}},\"references\":[\"603e1430-a496-4249-b2da-73a5205b964eX0\"],\"customLabel\":true},\"603e1430-a496-4249-b2da-73a5205b964e\":{\"label\":\"MB\",\"dataType\":\"number\",\"operationType\":\"formula\",\"isBucketed\":false,\"scale\":\"ratio\",\"params\":{\"formula\":\"divide(last_value(process.runtime.jvm.memory.usage_after_last_gc, kql='process.runtime.jvm.memory.usage_after_last_gc: * and labels.type: heap'), 1048576)\",\"isFormulaBroken\":false},\"references\":[\"603e1430-a496-4249-b2da-73a5205b964eX1\"],\"filter\":{\"query\":\"\",\"language\":\"kuery\"},\"customLabel\":true},\"a9ec0126-a45f-4f86-b783-a4820badd7d8\":{\"label\":\"Top 10 values of labels.pool\",\"dataType\":\"string\",\"operationType\":\"terms\",\"scale\":\"ordinal\",\"sourceField\":\"labels.pool\",\"isBucketed\":true,\"params\":{\"size\":10,\"orderBy\":{\"type\":\"alphabetical\",\"fallback\":true},\"orderDirection\":\"asc\",\"otherBucket\":true,\"missingBucket\":false,\"parentFormat\":{\"id\":\"terms\"},\"include\":[],\"exclude\":[],\"includeIsRegex\":false,\"excludeIsRegex\":false}}},\"columnOrder\":[\"a9ec0126-a45f-4f86-b783-a4820badd7d8\",\"2ab4d7f4-49aa-4e45-9ad7-73256400df18\",\"603e1430-a496-4249-b2da-73a5205b964e\",\"603e1430-a496-4249-b2da-73a5205b964eX0\",\"603e1430-a496-4249-b2da-73a5205b964eX1\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Memory after GC\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":0,\"y\":58,\"w\":22,\"h\":10,\"i\":\"7f1f017e-d42b-4cf4-8cb2-3f4bb3de5367\"},\"panelIndex\":\"7f1f017e-d42b-4cf4-8cb2-3f4bb3de5367\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-a3ee7019-98bb-45cd-8536-e36a8e58297e\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"right\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"axisTitlesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"a3ee7019-98bb-45cd-8536-e36a8e58297e\",\"accessors\":[\"ebf7c494-f676-4642-b2cf-ead2e8e93dee\"],\"position\":\"top\",\"seriesType\":\"bar_stacked\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"9c350955-95a1-4726-93fd-717b104a218c\",\"yConfig\":[{\"forAccessor\":\"ebf7c494-f676-4642-b2cf-ead2e8e93dee\",\"color\":\"#54b399\"}]}]},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"a3ee7019-98bb-45cd-8536-e36a8e58297e\":{\"columns\":{\"9c350955-95a1-4726-93fd-717b104a218c\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":true,\"dropPartials\":false}},\"ebf7c494-f676-4642-b2cf-ead2e8e93dee\":{\"label\":\"Threads count\",\"dataType\":\"number\",\"operationType\":\"median\",\"sourceField\":\"process.runtime.jvm.threads.count\",\"isBucketed\":false,\"scale\":\"ratio\",\"filter\":{\"query\":\"process.runtime.jvm.threads.count: *\",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"9c350955-95a1-4726-93fd-717b104a218c\",\"ebf7c494-f676-4642-b2cf-ead2e8e93dee\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Threads\"},{\"version\":\"8.8.2\",\"type\":\"lens\",\"gridData\":{\"x\":22,\"y\":58,\"w\":26,\"h\":10,\"i\":\"4f987373-1b85-4e80-a7cc-c1c000349c5e\"},\"panelIndex\":\"4f987373-1b85-4e80-a7cc-c1c000349c5e\",\"embeddableConfig\":{\"attributes\":{\"title\":\"\",\"visualizationType\":\"lnsXY\",\"type\":\"lens\",\"references\":[{\"id\":\"apm_static_index_pattern_id\",\"name\":\"indexpattern-datasource-layer-a45cd02a-4c62-4b34-bdce-c702b87b4246\",\"type\":\"index-pattern\"}],\"state\":{\"visualization\":{\"legend\":{\"isVisible\":true,\"position\":\"bottom\"},\"valueLabels\":\"hide\",\"fittingFunction\":\"None\",\"yRightTitle\":\"Duration (ms)\",\"axisTitlesVisibilitySettings\":{\"x\":false,\"yLeft\":true,\"yRight\":true},\"tickLabelsVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"labelsOrientation\":{\"x\":0,\"yLeft\":0,\"yRight\":0},\"gridlinesVisibilitySettings\":{\"x\":true,\"yLeft\":true,\"yRight\":true},\"preferredSeriesType\":\"bar_stacked\",\"layers\":[{\"layerId\":\"a45cd02a-4c62-4b34-bdce-c702b87b4246\",\"accessors\":[\"e3c6a7fb-d980-43d4-bb84-ae22018a0710\",\"4e7a6993-fcee-47ae-9599-0047809bb29e\"],\"position\":\"top\",\"seriesType\":\"bar\",\"showGridlines\":false,\"layerType\":\"data\",\"xAccessor\":\"57050bde-2c14-47d2-9dde-6e35326cf5cf\",\"yConfig\":[{\"forAccessor\":\"e3c6a7fb-d980-43d4-bb84-ae22018a0710\",\"axisMode\":\"left\"},{\"forAccessor\":\"4e7a6993-fcee-47ae-9599-0047809bb29e\",\"color\":\"#e7664c\",\"axisMode\":\"left\"}]}],\"yTitle\":\"Duration (ms)\"},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[],\"datasourceStates\":{\"formBased\":{\"layers\":{\"a45cd02a-4c62-4b34-bdce-c702b87b4246\":{\"columns\":{\"57050bde-2c14-47d2-9dde-6e35326cf5cf\":{\"label\":\"@timestamp\",\"dataType\":\"date\",\"operationType\":\"date_histogram\",\"sourceField\":\"@timestamp\",\"isBucketed\":true,\"scale\":\"interval\",\"params\":{\"interval\":\"auto\",\"includeEmptyRows\":false,\"dropPartials\":false}},\"e3c6a7fb-d980-43d4-bb84-ae22018a0710\":{\"label\":\"Minor GC\",\"dataType\":\"number\",\"operationType\":\"median\",\"sourceField\":\"process.runtime.jvm.gc.duration\",\"isBucketed\":false,\"scale\":\"ratio\",\"filter\":{\"query\":\"labels.action: \\\"end of minor GC\\\" \",\"language\":\"kuery\"},\"params\":{\"format\":{\"id\":\"number\",\"params\":{\"decimals\":2}},\"emptyAsNull\":true},\"customLabel\":true},\"4e7a6993-fcee-47ae-9599-0047809bb29e\":{\"label\":\"Major GC\",\"dataType\":\"number\",\"operationType\":\"median\",\"sourceField\":\"process.runtime.jvm.gc.duration\",\"isBucketed\":false,\"scale\":\"ratio\",\"filter\":{\"query\":\"labels.action : \\\"end of major GC\\\"\",\"language\":\"kuery\"},\"params\":{\"emptyAsNull\":true},\"customLabel\":true}},\"columnOrder\":[\"57050bde-2c14-47d2-9dde-6e35326cf5cf\",\"e3c6a7fb-d980-43d4-bb84-ae22018a0710\",\"4e7a6993-fcee-47ae-9599-0047809bb29e\"],\"incompleteColumns\":{},\"sampling\":1}}},\"textBased\":{\"layers\":{}}},\"internalReferences\":[],\"adHocDataViews\":{}}},\"hidePanelTitles\":false,\"enhancements\":{}},\"title\":\"Garbage Collection\"}]","timeRestore":false,"title":"Layer7 Gateway Dashboard","version":1},"coreMigrationVersion":"8.8.0","created_at":"2024-05-14T07:28:39.093Z","id":"c29a9900-2161-11ee-be6c-57cbef857d54","managed":false,"references":[{"id":"apm_static_index_pattern_id","name":"675c235a-535c-48d9-a5ed-848810986e5a:indexpattern-datasource-layer-8638d8b0-f850-42f0-9e64-35e6f239e0d0","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"0ae50fd8-f924-4207-b546-5d600ac701b3:indexpattern-datasource-layer-cad7aae7-308f-4c4f-abbd-b03792fbec56","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"ee3d33f8-243e-42d9-87fa-09c00dbfd1b7:indexpattern-datasource-layer-fd66544d-5ee7-4f36-8966-c7aa38197646","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"d9305573-c761-4802-9c0b-6f6326266125:indexpattern-datasource-layer-8638d8b0-f850-42f0-9e64-35e6f239e0d0","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"868932e9-487a-408f-89fd-14f9324534e9:indexpattern-datasource-layer-2381ace6-24bb-4e47-b57b-6fe06c980216","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"868932e9-487a-408f-89fd-14f9324534e9:indexpattern-datasource-layer-06696642-3076-4612-8291-189dcb25dd9e","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"9a54b939-5371-49f6-8888-ab92e165e625:indexpattern-datasource-layer-a57f2de0-c4c8-4a18-9b3a-533ad5572097","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"2a2057e2-ce45-4804-8ce0-3d4ed94679d7:indexpattern-datasource-layer-04cd0fc2-f652-4583-a7d4-c1a8f6f8818f","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"2a2057e2-ce45-4804-8ce0-3d4ed94679d7:indexpattern-datasource-layer-b369a9a0-f9ee-4b7e-ba8f-97d2722cd89d","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"2a2057e2-ce45-4804-8ce0-3d4ed94679d7:indexpattern-datasource-layer-66ce3428-e822-4b54-afc8-69bbffd9c106","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"542275ac-682e-43b8-b1ac-cf919d206e02:indexpattern-datasource-layer-28f4234a-7411-4d15-8ad9-36ac978f7e19","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"a3aace75-debc-4370-9954-e5a6e8ac6259:indexpattern-datasource-layer-067c1db7-2942-4bf9-8fd6-4ca0a42a23fa","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"7f1f017e-d42b-4cf4-8cb2-3f4bb3de5367:indexpattern-datasource-layer-a3ee7019-98bb-45cd-8536-e36a8e58297e","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"4f987373-1b85-4e80-a7cc-c1c000349c5e:indexpattern-datasource-layer-a45cd02a-4c62-4b34-bdce-c702b87b4246","type":"index-pattern"},{"id":"apm_static_index_pattern_id","name":"controlGroup_d3e0d4d0-b1de-465c-8772-806a49213c2b:optionsListDataView","type":"index-pattern"}],"type":"dashboard","typeMigrationVersion":"8.7.0","updated_at":"2024-05-14T07:28:39.093Z","version":"WzE2ODksMV0="}
{"excludedObjects":[],"excludedObjectsCount":0,"exportedCount":2,"missingRefCount":0,"missingReferences":[]}
\ No newline at end of file
diff --git a/example/otel-lgtm/collector.yaml b/example/otel-lgtm/collector.yaml
index f5bd99f6..e161fc20 100644
--- a/example/otel-lgtm/collector.yaml
+++ b/example/otel-lgtm/collector.yaml
@@ -1,11 +1,11 @@
-apiVersion: opentelemetry.io/v1alpha1
+apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
name: ssg-lgtm
spec:
mode: sidecar
- image: otel/opentelemetry-collector-contrib:0.97.0
- config: |
+ image: otel/opentelemetry-collector-contrib:0.147.0
+ config:
receivers:
otlp:
protocols:
@@ -15,6 +15,8 @@ spec:
endpoint: 0.0.0.0:4318
processors:
batch:
+ send_batch_max_size: 10000
+ timeout: 10s
transform:
metric_statements:
- context: datapoint
@@ -25,11 +27,9 @@ spec:
exporters:
debug:
verbosity: basic
- loki:
- endpoint: http://loki-loki-distributed-gateway.grafana-loki.svc.cluster.local/loki/api/v1/push
prometheusremotewrite:
- endpoint: http://mimir-nginx.grafana-loki.svc.cluster.local/api/v1/push
- otlp:
+ endpoint: http://mimir-gateway.grafana-loki.svc.cluster.local/api/v1/push
+ otlp/2:
endpoint: tempo.grafana-loki.svc.cluster.local:4317
tls:
insecure: true
@@ -37,20 +37,18 @@ spec:
telemetry:
logs:
level: "debug"
- metrics:
- address: "0.0.0.0:8888"
pipelines:
traces:
receivers: [otlp]
processors: [batch]
- exporters: [otlp]
+ exporters: [otlp/2]
metrics:
receivers: [otlp]
processors: [transform,batch]
exporters: [prometheusremotewrite, debug]
logs:
receivers: [otlp]
- exporters: [debug,loki]
+ exporters: [debug]
extensions:
health_check:
pprof:
diff --git a/example/otel-lgtm/layer7-operator/collector.yaml b/example/otel-lgtm/layer7-operator/collector.yaml
index 66edd098..cea6bded 100644
--- a/example/otel-lgtm/layer7-operator/collector.yaml
+++ b/example/otel-lgtm/layer7-operator/collector.yaml
@@ -1,11 +1,11 @@
-apiVersion: opentelemetry.io/v1alpha1
+apiVersion: opentelemetry.io/v1beta
kind: OpenTelemetryCollector
metadata:
name: layer7-operator
spec:
mode: deployment
image: otel/opentelemetry-collector-contrib:0.97.0
- config: |
+ config:
receivers:
otlp:
protocols:
@@ -19,7 +19,7 @@ spec:
debug:
verbosity: basic
prometheusremotewrite:
- endpoint: http://mimir-nginx.grafana-loki.svc.cluster.local/api/v1/push
+ endpoint: http://mimir-gateway.grafana-loki.svc.cluster.local/api/v1/push
service:
telemetry:
logs:
diff --git a/example/otel-lgtm/prometheus/grafana-dashboard/layer7-gateway-dashboard.json b/example/otel-lgtm/prometheus/grafana-dashboard/layer7-gateway-dashboard.json
index 946adb20..65c2b9d2 100644
--- a/example/otel-lgtm/prometheus/grafana-dashboard/layer7-gateway-dashboard.json
+++ b/example/otel-lgtm/prometheus/grafana-dashboard/layer7-gateway-dashboard.json
@@ -91,7 +91,7 @@
},
"editorMode": "code",
"exemplar": false,
- "expr": "sum(l7_service_attempted_count_total{job=\"$gatewayDeployment\"}) ",
+ "expr": "sum(layer7_service_attempted_count_total{job=\"$gatewayDeployment\"}) ",
"instant": false,
"interval": "",
"legendFormat": "{{podName}}",
@@ -158,7 +158,7 @@
},
"editorMode": "code",
"exemplar": true,
- "expr": "sum(l7_service_success_count_total{job=\"$gatewayDeployment\"})",
+ "expr": "sum(layer7_service_success_count_total{job=\"$gatewayDeployment\"})",
"interval": "",
"legendFormat": "{{pod}}",
"range": true,
@@ -226,7 +226,7 @@
},
"editorMode": "code",
"exemplar": true,
- "expr": "sum(l7_service_attempted_count_total{job=\"$gatewayDeployment\"} - l7_service_success_count_total{job=\"$gatewayDeployment\"})",
+ "expr": "sum(layer7_service_attempted_count_total{job=\"$gatewayDeployment\"} - layer7_service_success_count_total{job=\"$gatewayDeployment\"})",
"interval": "",
"legendFormat": "{{pod}}",
"range": true,
@@ -323,7 +323,7 @@
},
"editorMode": "code",
"exemplar": false,
- "expr": "sum(rate(l7_service_attempted_count_total{job=\"$gatewayDeployment\"}[5m]))",
+ "expr": "sum(rate(layer7_service_attempted_count_total{job=\"$gatewayDeployment\"}[5m]))",
"instant": false,
"interval": "",
"legendFormat": "${gatewayDeployment}",
@@ -418,7 +418,7 @@
},
"editorMode": "code",
"exemplar": true,
- "expr": "l7_service_policy_violations_count_total{job=\"$gatewayDeployment\"}",
+ "expr": "layer7_service_policy_violations_count_total{job=\"$gatewayDeployment\"}",
"format": "table",
"instant": true,
"interval": "",
@@ -441,8 +441,8 @@
"goid": true,
"instance": true,
"job": true,
- "l7_goid": true,
- "l7_method": false,
+ "layer7_goid": true,
+ "layer7_method": false,
"name": true,
"namespace": true,
"pod": false,
@@ -456,9 +456,9 @@
"__name__": "",
"apiName": "Service Name",
"container": "",
- "l7_method": "Method",
- "l7_serviceName": "Service Name",
- "l7_serviceUri": "Service URI",
+ "layer7_method": "Method",
+ "layer7_serviceName": "Service Name",
+ "layer7_serviceUri": "Service URI",
"namespace": "",
"pod": "Pod",
"service": ""
@@ -559,10 +559,10 @@
},
"editorMode": "code",
"exemplar": false,
- "expr": "rate(l7_service_attempted_count_total{l7_serviceName=\"$serviceName\",job=\"$gatewayDeployment\",l7_method=\"$requestMethod\"}[5m])",
+ "expr": "rate(layer7_service_attempted_count_total{layer7_serviceName=\"$serviceName\",job=\"$gatewayDeployment\",layer7_method=\"$requestMethod\"}[5m])",
"instant": false,
"interval": "",
- "legendFormat": "{{l7_serviceName}}",
+ "legendFormat": "{{layer7_serviceName}}",
"refId": "A"
}
],
@@ -627,9 +627,9 @@
},
"editorMode": "code",
"exemplar": true,
- "expr": "l7_service_latency_milliseconds_sum{job=\"$gatewayDeployment\"} / l7_service_latency_milliseconds_count{job=\"$gatewayDeployment\"}",
+ "expr": "layer7_service_latency_milliseconds_sum{job=\"$gatewayDeployment\"} / layer7_service_latency_milliseconds_count{job=\"$gatewayDeployment\"}",
"interval": "",
- "legendFormat": "{{pod}}-{{l7_serviceName}}",
+ "legendFormat": "{{pod}}-{{layer7_serviceName}}",
"range": true,
"refId": "A"
}
@@ -712,10 +712,10 @@
},
"editorMode": "code",
"exemplar": false,
- "expr": "histogram_quantile(0.95, l7_service_latency_milliseconds_bucket{})",
+ "expr": "histogram_quantile(0.95, layer7_service_latency_milliseconds_bucket{})",
"format": "time_series",
"instant": false,
- "legendFormat": "{{l7_serviceName}}",
+ "legendFormat": "{{layer7_serviceName}}",
"range": true,
"refId": "A"
}
@@ -837,7 +837,7 @@
},
"editorMode": "code",
"exemplar": false,
- "expr": "l7_service_attempted_count_total{job=\"$gatewayDeployment\", l7_method=\"$requestMethod\"}",
+ "expr": "layer7_service_attempted_count_total{job=\"$gatewayDeployment\", layer7_method=\"$requestMethod\"}",
"format": "table",
"instant": true,
"interval": "",
@@ -852,9 +852,9 @@
"options": {
"include": {
"names": [
- "l7_method",
- "l7_serviceName",
- "l7_serviceUri",
+ "layer7_method",
+ "layer7_serviceName",
+ "layer7_serviceUri",
"Value",
"pod"
]
@@ -870,9 +870,9 @@
"renameByName": {
"Value": "Count",
"exported_job": "",
- "l7_method": "Method",
- "l7_serviceName": "Service Name",
- "l7_serviceUri": "Service URI",
+ "layer7_method": "Method",
+ "layer7_serviceName": "Service Name",
+ "layer7_serviceUri": "Service URI",
"pod": "Pod"
}
}
@@ -961,7 +961,7 @@
}
],
"limit": 20,
- "query": "{.k8s.deployment.name=\"$gatewayDeployment\" && .k8s.pod.name=\"$gatewayPod\" && .l7_serviceName=\"$serviceName\"}",
+ "query": "{.k8s.pod.name=\"$gatewayPod\" && .layer7_serviceName=\"$serviceName\"}",
"queryType": "traceql",
"refId": "A",
"spss": 3,
@@ -1431,22 +1431,19 @@
"list": [
{
"allValue": "\"\"",
- "current": {
- "text": "ssg-otel-gateway",
- "value": "ssg-otel-gateway"
- },
+ "current": {},
"datasource": {
"type": "prometheus",
"uid": "mimir"
},
- "definition": "l7_service_attempted_count_total{job!=\"\"}",
+ "definition": "layer7_service_attempted_count_total{job!=\"\"}",
"includeAll": false,
"label": "Gateway Deployment",
"name": "gatewayDeployment",
"options": [],
"query": {
"qryType": 4,
- "query": "l7_service_attempted_count_total{job!=\"\"}",
+ "query": "layer7_service_attempted_count_total{job!=\"\"}",
"refId": "PrometheusVariableQueryEditor-VariableQuery"
},
"refresh": 2,
@@ -1455,23 +1452,19 @@
},
{
"allValue": "\"\"",
- "current": {
- "isNone": true,
- "text": "None",
- "value": ""
- },
+ "current": {},
"datasource": {
"type": "prometheus",
"uid": "mimir"
},
- "definition": "l7_service_attempted_count_total{pod!=\"\",job=\"$gatewayDeployment\"}",
+ "definition": "layer7_service_attempted_count_total{pod!=\"\",job=\"$gatewayDeployment\"}",
"includeAll": false,
"label": "Pod",
"name": "gatewayPod",
"options": [],
"query": {
"qryType": 4,
- "query": "l7_service_attempted_count_total{pod!=\"\",job=\"$gatewayDeployment\"}",
+ "query": "layer7_service_attempted_count_total{pod!=\"\",job=\"$gatewayDeployment\"}",
"refId": "PrometheusVariableQueryEditor-VariableQuery"
},
"refresh": 2,
@@ -1480,50 +1473,44 @@
},
{
"allValue": "\"\"",
- "current": {
- "text": "Test12345",
- "value": "Test12345"
- },
+ "current": {},
"datasource": {
"type": "prometheus",
"uid": "mimir"
},
- "definition": "l7_service_attempted_count_total{l7_serviceName!=\"\", job=\"$gatewayDeployment\"}",
+ "definition": "layer7_service_attempted_count_total{layer7_serviceName!=\"\", job=\"$gatewayDeployment\"}",
"includeAll": false,
"label": "Service Name",
"name": "serviceName",
"options": [],
"query": {
"qryType": 4,
- "query": "l7_service_attempted_count_total{l7_serviceName!=\"\", job=\"$gatewayDeployment\"}",
+ "query": "layer7_service_attempted_count_total{layer7_serviceName!=\"\", job=\"$gatewayDeployment\"}",
"refId": "PrometheusVariableQueryEditor-VariableQuery"
},
"refresh": 2,
- "regex": "/.*l7_serviceName=\"([^\"]*)\"/",
+ "regex": "/.*layer7_serviceName=\"([^\"]*)\"/",
"type": "query"
},
{
"allValue": "\"\"",
- "current": {
- "text": "GET",
- "value": "GET"
- },
+ "current": {},
"datasource": {
"type": "prometheus",
"uid": "mimir"
},
- "definition": "l7_service_attempted_count_total{l7_method!=\"\",l7_serviceName=\"$serviceName\", job=\"$gatewayDeployment\"}",
+ "definition": "layer7_service_attempted_count_total{layer7_method!=\"\",layer7_serviceName=\"$serviceName\", job=\"$gatewayDeployment\"}",
"includeAll": false,
"label": "Request Method",
"name": "requestMethod",
"options": [],
"query": {
"qryType": 4,
- "query": "l7_service_attempted_count_total{l7_method!=\"\",l7_serviceName=\"$serviceName\", job=\"$gatewayDeployment\"}",
+ "query": "layer7_service_attempted_count_total{layer7_method!=\"\",layer7_serviceName=\"$serviceName\", job=\"$gatewayDeployment\"}",
"refId": "PrometheusVariableQueryEditor-VariableQuery"
},
"refresh": 2,
- "regex": "/.*l7_method=\"([^\"]*)\"/",
+ "regex": "/.*layer7_method=\"([^\"]*)\"/",
"type": "query"
}
]
diff --git a/example/otel-lgtm/prometheus/prometheus-values.yaml b/example/otel-lgtm/prometheus/prometheus-values.yaml
index 62f9aa39..008d1c60 100644
--- a/example/otel-lgtm/prometheus/prometheus-values.yaml
+++ b/example/otel-lgtm/prometheus/prometheus-values.yaml
@@ -78,7 +78,7 @@ grafana:
editable: true
orgId: 1
type: prometheus
- url: http://mimir-nginx.grafana-loki.svc.cluster.local/prometheus
+ url: http://mimir-gateway.grafana-loki.svc.cluster.local/prometheus
- name: tempo-minimal
id: 6
editable: true
@@ -106,13 +106,11 @@ grafana:
## IngressClassName for Grafana Ingress.
## Should be provided if Ingress is enable.
##
- ingressClassName: nginx
+ ingressClassName: contour
## Annotations for Grafana Ingress
##
annotations: {}
- # kubernetes.io/ingress.class: nginx
- # kubernetes.io/tls-acme: "true"
## Labels to be added to the Ingress
##
diff --git a/example/otel-lgtm/readme.md b/example/otel-lgtm/readme.md
index 36d8e3b3..312a6886 100644
--- a/example/otel-lgtm/readme.md
+++ b/example/otel-lgtm/readme.md
@@ -21,7 +21,7 @@ As part of this guide we will deploy the following components
## Prerequisites
- Kubernetes v1.26+
- Ingress Controller (important for grafana)
- - the quickstart examples deploy the nginx ingress controller
+ - the quickstart examples deploy the contour ingress controller
You will also need to add the following entries to your hosts file
@@ -42,8 +42,8 @@ kubectl get ingress -n monitoring
```
output
```
-NAME CLASS HOSTS ADDRESS PORTS AGE
-prometheus-grafana nginx grafana.brcmlabs.com 80, 443 57m
+NAME CLASS HOSTS ADDRESS PORTS AGE
+prometheus-grafana contour grafana.brcmlabs.com 80, 443 57m
```
/etc/hosts - the ingress address will be the same for the Gateway Ingress record
```
@@ -62,15 +62,15 @@ prometheus-grafana nginx grafana.brcmlabs.com 80, 443 57m
```
3. If you would like to create a TLS secret for your ingress controller then add tls.crt and tls.key to [base/resources/secrets/tls](../base/resources/secrets/tls)
- these will be referenced later on.
-4. You will need an ingress controller like nginx
+4. You will need an ingress controller like contour
- if you do not have one installed already you can use the makefile in the example directory to deploy one
- ```cd example```
- Generic Kubernetes
- - ```make nginx```
+ - ```make contour```
- Kind (Kubernetes in Docker)
- follow the steps in Quickstart
or
- - ```make nginx-kind```
+ - ```make contour-kind```
- return to the previous folder
- ```cd ..```
@@ -79,7 +79,7 @@ This example uses multiple namespaces for the additional components. Your Kubern
The following namespaces will be created/used if you use the [quickstart](#quickstart) option to deploy this example
- monitoring (prometheus, grafana)
- grafana-loki (loki, tempo, promtail)
-- ingress-nginx (nginx ingress controller)
+- projectcontour (contour ingress controller)
If you deploy the OpenTelemetry Operator and Certmanager
- cert-manager
@@ -92,7 +92,7 @@ If you wish to use a different host and or configure a signed certificate for Gr
grafana:
ingress:
enabled: true
- ingressClassName: nginx
+ ingressClassName: contour
labels: {}
hosts:
- grafana.brcmlabs.com
@@ -113,10 +113,8 @@ If you wish to use a different host and or configure a signed certificate for th
```
ingress:
enabled: true
- ingressClassName: nginx
- annotations:
- nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
- # nginx.ingress.kubernetes.io/ssl-passthrough: "true"
+ ingressClassName: contour
+ annotations: {}
tls:
- hosts:
- gateway.brcmlabs.com
@@ -174,13 +172,13 @@ make kind-cluster otel-lgtm-example-kind enable-otel-l7operator
```
make otel-lgtm-example enable-otel-l7operator
```
-if you don't have an ingress controller you can deploy nginx with the following
+if you don't have an ingress controller you can deploy contour with the following
```
-make nginx
+make contour
```
if you are using kind
```
-make nginx-kind
+make contour-kind
```
#### Enabling OTel Metrics for the Layer7 Operator
@@ -260,7 +258,7 @@ the OpenTelemetry Operator is not a requirement, it makes configuring the Gatewa
- Deploy Cert-Manager (OTel Operator dependency)
```
-kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.5/cert-manager.yaml
+kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.20.0/cert-manager.yaml
```
verify cert-manager has been successfully deployed
```
@@ -271,7 +269,7 @@ kubectl wait --for=condition=ready --timeout=600s pod -l app=webhook -n cert-man
- Deploy the OpenTelemetry Operator
```
-kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/download/v0.97.1/opentelemetry-operator.yaml
+kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/download/v0.146.0/opentelemetry-operator.yaml
```
verify that the OpenTelemetry Operator has been successfully deployed
```
@@ -407,8 +405,8 @@ kubectl describe pods ssg-57d96567cb-n24g9
Init Containers:
graphman-static-init-c1b58adb6d:
Container ID: containerd://21924ae85d25437d3634ea5da1415c9bb58d678600f9fd67d4f0b0360857d7c5
- Image: docker.io/layer7api/graphman-static-init:1.0.0
- Image ID: docker.io/layer7api/graphman-static-init@sha256:24189a432c0283845664c6fd54c3e8d9f86ad9d35ef12714bb3a18b7aba85aa4
+ Image: docker.io/caapim/graphman-static-init:1.0.4
+ Image ID: docker.io/caapim/graphman-static-init@sha256:8cb1035035b18fa9dc2c95e2b584c758e78909b3f615ee5f49dce166e8aae213
Port:
Host Port:
State: Terminated
@@ -499,30 +497,31 @@ kubectl get pods -n grafana-loki
```
output
```
-NAME READY STATUS RESTARTS AGE
-loki-0 1/1 Running 0 4m
-loki-canary-hr5n6 1/1 Running 0 4m
-loki-chunks-cache-0 2/2 Running 0 4m
-loki-gateway-5cd888fb5b-lx68d 1/1 Running 0 4m
-loki-minio-0 1/1 Running 0 4m
-loki-results-cache-0 2/2 Running 0 4m
-mimir-alertmanager-0 1/1 Running 0 2m7s
-mimir-compactor-0 1/1 Running 0 2m7s
-mimir-distributor-75db4845b5-fwgx5 1/1 Running 0 2m7s
-mimir-ingester-0 1/1 Running 0 2m7s
-mimir-ingester-1 1/1 Running 0 2m7s
-mimir-make-minio-buckets-5.0.14-9ddtx 0/1 Completed 0 2m7s
-mimir-minio-66c9c9446c-vr6tx 1/1 Running 0 2m7s
-mimir-nginx-6c54df9bbf-xw5wm 1/1 Running 0 2m7s
-mimir-overrides-exporter-75c74b879-l4vd2 1/1 Running 0 2m7s
-mimir-querier-f4c7668c7-c2lkr 1/1 Running 0 2m7s
-mimir-query-frontend-86f49bdd54-57njx 1/1 Running 0 2m7s
-mimir-query-scheduler-9c9db55-ns8bw 1/1 Running 0 2m7s
-mimir-rollout-operator-589445cccd-2gktd 1/1 Running 0 2m7s
-mimir-ruler-87b575f97-xxv8z 1/1 Running 0 2m7s
-mimir-store-gateway-0 1/1 Running 0 2m7s
-promtail-92scb 1/1 Running 0 3m25s
-tempo-0 1/1 Running 0 3m17s
+NAME READY STATUS RESTARTS AGE
+loki-0 2/2 Running 0 3m
+loki-canary-dnc8b 1/1 Running 0 3m
+loki-chunks-cache-0 2/2 Running 0 3m
+loki-gateway-599bd8b86-wdpqg 1/1 Running 0 3m
+loki-minio-0 1/1 Running 0 3m
+loki-results-cache-0 2/2 Running 0 3m
+mimir-alertmanager-0 1/1 Running 0 3m
+mimir-compactor-0 1/1 Running 0 3m
+mimir-distributor-7495b688fb-s4jgc 1/1 Running 0 3m
+mimir-gateway-647dcf69cb-bbzzl 1/1 Running 0 3m
+mimir-ingester-0 1/1 Running 0 3m
+mimir-ingester-1 1/1 Running 0 3m
+mimir-kafka-0 1/1 Running 0 3m
+mimir-make-minio-buckets-5.4.0-xvxc6 0/1 Completed 0 3m
+mimir-minio-76f9f549db-4pvpm 1/1 Running 0 3m
+mimir-overrides-exporter-7d7b775fb8-w4pm9 1/1 Running 0 3m
+mimir-querier-85c594d56c-46d5m 1/1 Running 0 3m
+mimir-query-frontend-557b948666-sfrsf 1/1 Running 0 3m
+mimir-query-scheduler-9857bc85f-lkb5l 1/1 Running 0 3m
+mimir-rollout-operator-65b97658df-8dd98 1/1 Running 0 3m
+mimir-ruler-65f68d7c8d-zrhwj 1/1 Running 0 3m
+mimir-store-gateway-0 1/1 Running 0 3m
+promtail-2kvn4 1/1 Running 0 3m
+tempo-0 1/1 Running 0 3m
```
- Confirm all datasources are configured correctly in Grafana
@@ -542,8 +541,8 @@ tempo-0 1/1 Running 0 3m17s
```
kubectl get ingress
-NAME CLASS HOSTS ADDRESS PORTS AGE
-ssg nginx gateway.brcmlabs.com 34.89.126.80 80, 443 54m
+NAME CLASS HOSTS ADDRESS PORTS AGE
+ssg contour gateway.brcmlabs.com 34.89.126.80 80, 443 54m
```
Add the following to your hosts file for DNS resolution
@@ -601,13 +600,7 @@ If you used an existing Kubernetes Cluster
make uninstall
```
-- If you deployed nginx
-
-If you used kind
-```
-make uninstall-nginx-kind
-```
-If you used an existing Kubernetes Cluster
+- If you deployed contour
```
-make uninstall-nginx
+make uninstall-contour
```
diff --git a/example/otel-prometheus/README.md b/example/otel-prometheus/README.md
deleted file mode 100644
index 264133a6..00000000
--- a/example/otel-prometheus/README.md
+++ /dev/null
@@ -1,848 +0,0 @@
-# Open Telemetry Integration (Prometheus)
-By the end of this example you should have a better understanding of the how to utilise the Gateway's Open Telemetry integration to increase observability across your Operator Managed Gateways. This example uses a Simple Gateway as a base and includes installing the following.
-
-- CertManager Operator (required for OTel)
-- OpenTelemetry Operator
-- Prometheus Stack
-- Nginx (Ingress Controller)
-- Jaeger
-
-
-
-## Prerequisites
-- Kubernetes v1.25+
-- Gateway v11.x License
-- Ingress Controller (important for grafana and jaeger)
-
-### Getting started
-1. Place a gateway v11 license in [base/resources/secrets/license/](../base/resources/secrets/license/) called license.xml.
-2. Accept the Gateway License
- - license.accept defaults to false in [Gateway examples](../gateway/otel-prometheus-gateway.yaml)
- - update license.accept to true before proceeding
- ```
- license:
- accept: true
- secretName: gateway-license
- ```
-3. If you would like to create a TLS secret for your ingress controller then add tls.crt and tls.key to [base/resources/secrets/tls](../base/resources/secrets/tls)
- - these will be referenced later on.
-4. You will need an ingress controller like nginx
- - if you do not have one installed already you can use the makefile in the example directory to deploy one
- - ```cd example```
- - Generic Kubernetes
- - ```make nginx```
- - Kind (Kubernetes in Docker)
- - follow the steps in Quickstart
- or
- - ```make nginx-kind```
- - return to the previous folder
- - ```cd ..```
-
-The OTel Example requires multiple namespaces for the additional components. Your Kubernetes user or service account must have sufficient privileges to create namespaces, deployments, configmaps, secrets, service accounts, roles, etc.
-
-***NOTE:*** to keep things simple we use the default namespace when creating namespaced resources including the Layer7 Operator, Gateway, Repositories and Prometheus Service Monitor. If you'd like to use a different namespace then you will need to update the following.
-
-- [servicemonitor.yaml](./servicemonitor.yaml)
-```
-apiVersion: monitoring.coreos.com/v1
-kind: ServiceMonitor
-metadata:
- labels:
- app: ssg
- name: ssg
-spec:
- endpoints:
- - interval: 10s
- path: /metrics
- port: monitoring
- jobLabel: ssg
- namespaceSelector:
- matchNames:
- - default ==> change this to your namespace
- selector:
- matchLabels:
- app.kubernetes.io/created-by: layer7-operator
- app.kubernetes.io/managed-by: layer7-operator
- app.kubernetes.io/name: ssg
- app.kubernetes.io/part-of: ssg
-```
-
-- [prometheus-values.yaml](./monitoring/prometheus/prometheus-values.yaml)
-```
-prometheusOperator:
- namespaces:
- releaseNamespace: true
- additional:
- - kube-system
- - layer7
- - default
- - addyournamespacehere
-...
-```
-
-- Update your Kubectl context
-```
-kubectl config set-context --current --namespace=yournamespace
-```
-
-If you have a docker machine available you can use [Kind](https://kind.sigs.k8s.io/) to try out this example!
-
-### Getting started
-1. Place a gateway v11 license in [base/resources/secrets/license/](../base/resources/secrets/license/) called license.xml.
-2. Accept the Gateway License
- - license.accept defaults to false in [Gateway examples](../gateway/otel-prometheus-gateway.yaml)
- - update license.accept to true before proceeding
-3. If you would like to create a TLS secret for your ingress controller then add tls.crt and tls.key to [base/resources/secrets/tls](../base/resources/secrets/tls)
- - these will be referenced later on.
-4. You will need an ingress controller like nginx
- - if you do not have one installed already you can use the makefile in the example directory to deploy one
- - ```cd example```
- - Generic Kubernetes
- - ```make nginx```
- - Kind (Kubernetes in Docker)
- - follow the steps in Quickstart
- or
- - ```make nginx-kind```
- - return to the previous folder
- - ```cd ..```
-
-### Gateway Configuration
-- [Container Gateway](#container-gateway-configuration)
-- [OTel Collector](#otel-collector-configuration)
-- [Service Monitor](#service-monitor-configuration)
-- [Gateway Application](#gateway-application-configuration)
-- [Service Level](#service-level-configuration)
-
-### Guide
-- [Quickstart Kind](#quickstart-kind)
-- [Quickstart Existing Kubernetes Cluster](#quickstart-existing-cluster)
-
-### Monitoring/Observability Components
-- [Install Cert Manager](#install-cert-manager)
-- [Install Open Telemetry](#install-open-telemetry)
-- [Install Prometheus](#install-prometheus)
-- [Install Jaeger](#install-jaeger)
-- [Install an Ingress Controller(optional)](#install-nginx)
-
-### Layer7 Operator
-- [Deploy the Operator](#deploy-the-layer7-operator)
-- [Create Repositories](#create-repository-custom-resources)
-- [Create a Gateway](#create-a-gateway)
-- [Test Gateway Deployment](#test-your-gateway-deployment)
-- [Remove Kind Cluster](#remove-kind-cluster)
-- [Uninstall Demo Components and Custom Resources](#remove-demo-component-and-custom-resources)
-- [Uninstall the Operator CRs](#uninstall-the-operator)
-
-### Container Gateway Configuration
-The container gateway configuration required for this integration is relatively simple. We will set some environment variables in our OTel [instrumentation](./instrumentation.yaml) that the Otel Agent present on the Container Gateway will use to send logs, traces and metrics to the Otel Collector sidecar.
-
-```
-apiVersion: opentelemetry.io/v1alpha1
-kind: Instrumentation
-metadata:
- name: otel-instrumentation
-spec:
- exporter:
- endpoint: http://localhost:4317
- propagators:
- - tracecontext
- - baggage
- - b3
- sampler:
- type: parentbased_traceidratio
- argument: "0.25"
-```
-
-We also need to expose a monitoring endpoint so that Prometheus can scrape the Gateway service
-```
-service:
- type: LoadBalancer
- ports:
- ...
- - name: monitoring
- port: 8889
- protocol: TCP
-```
-
-### OTel Collector Configuration
-The OpenTelemetry Operator will automatically inject a sidecar into the Gateway Pod with our [OTel configuration](./collector.yaml). This configuration exposes a /metrics endpoint on the Gateway Pod on port 8889 for Prometheus to scrape.
-
-```
-receivers:
- otlp:
- protocols:
- grpc:
- http:
-processors:
- batch:
-exporters:
- logging:
- loglevel: warn
- prometheus:
- endpoint: "0.0.0.0:8889"
- const_labels:
- name: ssg
- jaeger:
- endpoint: simple-allinone-collector:14250
- tls:
- insecure: true
-service:
- telemetry:
- logs:
- level: "debug"
- metrics:
- address: "0.0.0.0:8888"
- pipelines:
- traces:
- receivers: [otlp]
- processors: [batch]
- exporters: [jaeger]
- metrics:
- receivers: [otlp]
- processors: [batch]
- exporters: [prometheus, logging]
- logs:
- receivers: [otlp]
- exporters: [logging]
-extensions:
- health_check:
- pprof:
- endpoint: 0.0.0.0:1777
- zpages:
- endpoint: 0.0.0.0:55679
-```
-
-### Service Monitor Configuration
-We need to tell Prometheus about the /metrics endpoint on the Gateway pod, we do this with a [ServiceMonitor](./servicemonitor.yaml)
-
-```
-apiVersion: monitoring.coreos.com/v1
-kind: ServiceMonitor
-metadata:
- labels:
- app: ssg
- name: ssg
-spec:
- endpoints:
- - interval: 10s ==> time between scrapes
- path: /metrics ==> the time
- port: monitoring
- jobLabel: ssg
- namespaceSelector:
- matchNames:
- - default ==> if you are not using the default namespace you will need to update this
- selector:
- matchLabels:
- app.kubernetes.io/created-by: layer7-operator
- app.kubernetes.io/managed-by: layer7-operator
- app.kubernetes.io/name: ssg
- app.kubernetes.io/part-of: ssg
-```
-
-### Gateway Application Configuration
-The Gateway has OTel specific configuration.
-
-- Pod Annotations
-```
- app:
- podAnnotations:
- sidecar.opentelemetry.io/inject: "ssg-eck" <== this injects the OpenTelemetryCollector sidecar
- instrumentation.opentelemetry.io/inject-java: "true" <== this loads the OpenTelemetry Java agent onto the Gateway
- instrumentation.opentelemetry.io/container-names: "gateway" <== this defines which container the Java Agent is loaded onto
-```
-
-- Cluster-Wide Properties
-```
-cwp:
- enabled: true
- properties:
- ...
- - name: otel.enabled
- value: "true"
- - name: otel.serviceMetricEnabled
- value: "true"
- - name: otel.traceEnabled
- value: "true"
- - name: otel.metricPrefix
- value: l7_
- - name: otel.traceConfig
- value: |
- {
- "services": [
- {"resolutionPath": ".*"}
- ]
- }
-```
-
-- System Properties
-```
-system:
- properties: |-
- ...
- # OpenTelemetry Agent Configuration
- otel.instrumentation.common.default-enabled=true
- otel.instrumentation.opentelemetry-api.enabled=true
- otel.instrumentation.runtime-metrics.enabled=true
- otel.instrumentation.runtime-telemetry.enabled=true
- otel.instrumentation.opentelemetry-instrumentation-annotations.enabled=true
- otel.java.global-autoconfigure.enabled=true
- # Additional properties go here
-```
-
-### Quickstart Kind
-A Makefile is included in the example directory that makes deploying this example a one step process. If you have access to a Docker Machine you can use [Kind](https://kind.sigs.k8s.io/) (Kubernetes in Docker). This example can optionally deploy a Kind Cluster for you (you just need to make sure that you've [installed Kind](https://kind.sigs.k8s.io/docs/user/quick-start/#installation))
-
-The kind configuration is in the base of the example folder. If your docker machine is remote (you are using a VM or remote machine) then uncomment the network section and set the apiServerAddress to the address of your VM/Remote machine
-```
-kind: Cluster
-apiVersion: kind.x-k8s.io/v1alpha4
-# networking:
-# apiServerAddress: "192.168.1.64"
-# apiServerPort: 6443
-nodes:
-- role: control-plane
- kubeadmConfigPatches:
- - |
- kind: InitConfiguration
- nodeRegistration:
- kubeletExtraArgs:
- node-labels: "ingress-ready=true"
- extraPortMappings:
- - containerPort: 80
- hostPort: 80
- protocol: TCP
- - containerPort: 443
- hostPort: 443
- protocol: TCP
-```
-
-This process takes a few minutes to complete
-
-- navigate to the example directory
-```
-cd example
-```
-- deploy the example
-```
-make kind-cluster otel-prometheus-example-kind
-```
-You will also need to add the following entries to your hosts file
-```
-127.0.0.1 gateway.brcmlabs.com jaeger.brcmlabs.com grafana.brcmlabs.com
-```
-
-- wait for all components to be ready
-```
-watch kubectl get pods
-```
-output
-```
-NAME READY STATUS RESTARTS AGE
-layer7-operator-controller-manager-69dc945d66-prshk 2/2 Running 0 6m49s
-simple-allinone-7d76ff5b7c-5nqnf 1/1 Running 0 4m40s
-ssg-84cd5d6c86-r7vm2 2/2 Running 0 3m13s
-```
-
-You can now move on to test your gateway deployment!
-- [Test Gateway Deployment](#test-your-gateway-deployment)
-
-### Quickstart Existing Cluster
-This quickstart uses the Makefile to install of the necessary components into your Kubernetes Cluster.
-
-- navigate to the example directory
-```
-cd example
-```
-- deploy the example
-```
-make otel-prometheus-example
-```
-
-If you don't already have an ingress controller you can deploy nginx with the following command
-
-- Suppports most Kubernetes Environments
-```
-make nginx
-```
-- If you're using Kind
-```
-make nginx-kind
-```
-- Additional options can be found here
-```
-https://github.com/kubernetes/ingress-nginx/tree/main/deploy/static/provider
-```
-
-- Once nginx has been installed get the L4 LoadBalancer address
-```
-kubectl get svc -n ingress-nginx
-```
-output
-```
-NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
-ingress-nginx-controller LoadBalancer 10.152.183.52 192.168.1.190 80:30183/TCP,443:30886/TCP 24m
-ingress-nginx-controller-admission ClusterIP 10.152.183.132 443/TCP 24m
-```
-- You probably don't have access to a DNS server for this demo so you will need to add the following entries to your hosts file
-```
-EXTERNAL-IP gateway.brcmlabs.com jaeger.brcmlabs.com grafana.brcmlabs.com
-
-example
-192.168.1.190 gateway.brcmlabs.com jaeger.brcmlabs.com grafana.brcmlabs.com
-```
-
-- wait for all components to be ready
-```
-watch kubectl get pods
-```
-output
-```
-NAME READY STATUS RESTARTS AGE
-layer7-operator-controller-manager-69dc945d66-prshk 2/2 Running 0 6m49s
-simple-allinone-7d76ff5b7c-5nqnf 1/1 Running 0 4m40s
-ssg-84cd5d6c86-r7vm2 2/2 Running 0 3m13s
-```
-
-You can now move on to test your gateway deployment!
-- [Test Gateway Deployment](#test-your-gateway-deployment)
-
-### Install Cert Manager
-These steps are based the official documentation for installing Cert-Manager [here](https://cert-manager.io/docs/installation/). Cert-Manager is a pre-requisite for the Open Telemetry Operator.
-```
- kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.5/cert-manager.yaml
-```
-
-#### View CertManager Components
-***Cert manager needs to be running before you continue onto the next step.***
-```
-kubectl get all -n cert-manager
-
-NAME READY STATUS RESTARTS AGE
-pod/cert-manager-cainjector-5fcd49c96-r97pk 1/1 Running 0 34s
-pod/cert-manager-6ffb79dfdb-thpft 1/1 Running 0 34s
-pod/cert-manager-webhook-796ff7697b-5gbzw 1/1 Running 0 34s
-
-NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
-service/cert-manager ClusterIP 10.152.183.216 9402/TCP 34s
-service/cert-manager-webhook ClusterIP 10.152.183.85 443/TCP 34s
-
-NAME READY UP-TO-DATE AVAILABLE AGE
-deployment.apps/cert-manager-cainjector 1/1 1 1 34s
-deployment.apps/cert-manager 1/1 1 1 34s
-deployment.apps/cert-manager-webhook 1/1 1 1 34s
-
-NAME DESIRED CURRENT READY AGE
-replicaset.apps/cert-manager-cainjector-5fcd49c96 1 1 1 34s
-replicaset.apps/cert-manager-6ffb79dfdb 1 1 1 34s
-replicaset.apps/cert-manager-webhook-796ff7697b 1 1 1 34s
-```
-
-
-### Install Open Telemetry
-These steps are based the official documentation for installing Open Telemetry [here](https://cert-manager.io/docs/installation/). Open Telemetry depends on cert-manager, ***make sure that cert-manager is running before installing open telemetry.***
-
-- Install the Open Telemetry Operator.
-```
-kubectl apply -f https://github.com/open-telemetry/opentelemetry-operator/releases/download/v0.97.1/opentelemetry-operator.yaml
-```
-
-#### View Open Telemetry Components
-```
-kubectl get all -n opentelemetry-operator-system
-
-NAME READY STATUS RESTARTS AGE
-pod/opentelemetry-operator-controller-manager-5d84764d4b-6zdtb 2/2 Running 18 (8d ago) 28d
-
-NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
-service/opentelemetry-operator-controller-manager-metrics-service ClusterIP 10.68.1.93 8443/TCP 72d
-service/opentelemetry-operator-webhook-service ClusterIP 10.68.3.243 443/TCP 72d
-
-NAME READY UP-TO-DATE AVAILABLE AGE
-deployment.apps/opentelemetry-operator-controller-manager 1/1 1 1 72d
-
-NAME DESIRED CURRENT READY AGE
-replicaset.apps/opentelemetry-operator-controller-manager-5d84764d4b 1 1 1 72d
-```
-
-***The OpenTelemetry Operator needs to be running before you continue onto the next step.***
-- Create an OpenTelemetryCollector resource
-```
-kubectl apply -f ./example/otel-prometheus/collector.yaml
-```
-- Create OpenTelemetry Instrumentation
-```
-kubectl apply -f ./example/otel-prometheus/instrumentation.yaml
-```
-
-### Install the Prometheus Stack
-These steps are based on instructions that can be found in the Prometheus Community Helm Chart [documentation](https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus).
-
-- Add the Prometheus Community Helm Chart repository
-```
-helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
-helm repo update
-```
-- Create a namespace called monitoring
-```
-kubectl create ns monitoring
-```
-- Create the Layer7 Grafana Dashboard
-```
-kubectl apply -k ./example/otel-prometheus/monitoring/grafana/
-```
-- Install the Prometheus Helm Chart in the monitoring namespace
-```
-helm upgrade -i prometheus -f ./example/otel-prometheus/monitoring/prometheus/prometheus-values.yaml prometheus-community/kube-prometheus-stack -n monitoring
-```
-- Create a Service Monitor
-```
-kubectl apply -f ./example/otel-prometheus/servicemonitor.yaml
-```
-
-### Install Jaeger
-These steps are based on instructions that can be found in the Jaeger [documentation](https://www.jaegertracing.io/docs/1.44/operator/)
-
-- Create a namespace called observability
-```
-kubectl create namespace observability
-```
-- Install the Jaeger Operator
-```
-kubectl create -f https://github.com/jaegertracing/jaeger-operator/releases/download/v1.44.0/jaeger-operator.yaml -n observability
-```
-
-#### View Jaeger Components
-```
-kubectl get all -n observability
-
-NAME READY STATUS RESTARTS AGE
-pod/jaeger-operator-6cf68b6f65-z8jtv 2/2 Running 0 16s
-
-NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
-service/jaeger-operator-metrics ClusterIP 10.68.15.46 8443/TCP 17s
-service/jaeger-operator-webhook-service ClusterIP 10.68.1.180 443/TCP 17s
-
-NAME READY UP-TO-DATE AVAILABLE AGE
-deployment.apps/jaeger-operator 1/1 1 1 17s
-
-NAME DESIRED CURRENT READY AGE
-replicaset.apps/jaeger-operator-6cf68b6f65 1 1 1 17s
-```
-
-- Deploy a Jaeger Custom Resource
-```
-kubectl apply -f ./example/otel-prometheus/observability/jaeger/jaeger.yaml
-```
-
-- Create an ingress resource for Jaeger.
-```
-kubectl apply -f ./example/otel-prometheus/observability/jaeger/ingress.yaml
-```
-
-### Install Nginx
-This command will deploy an nginx ingress controller. If you already have nginx or another ingress controller running in your Kubernetes cluster you can safely ignore this step.
-
-Suppports most Kubernetes Environments
-```
-kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
-```
-If you're using Kind
-```
-kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
-```
-Additional options can be found here
-```
-https://github.com/kubernetes/ingress-nginx/tree/main/deploy/static/provider
-```
-
-### Deploy the Layer7 Operator
-This step will deploy the Layer7 Operator and all of its resources in namespaced mode. This means that it will only manage Gateway and Repository Custom Resources in the Kubernetes Namespace that it's deployed in.
-
-```
-kubectl apply -f https://github.com/CAAPIM/layer7-operator/releases/download/v1.2.2/bundle.yaml
-```
-
-#### Verify the Operator is up and running
-```
-kubectl get pods
-
-NAME READY STATUS RESTARTS AGE
-layer7-operator-controller-manager-7647b58697-qd9vg 2/2 Running 0 27s
-```
-
-### Create Repository Custom Resources
-This example ships with 3 pre-configured Graphman repositories. The repository controller is responsible for synchronising these with the Operator and should always be created before Gateway resources that reference them to avoid race conditions. ***race conditions will be resolved automatically.***
-
-- [l7-gw-myframework](https://github.com/Gazza7205/l7GWMyFramework)
-- [l7-gw-mysubscriptions](https://github.com/Gazza7205/l7GWMySubscriptions)
-- [l7-gw-myapis](https://github.com/Gazza7205/l7GWMyAPIs)
-
-```
-kubectl apply -k ./example/repositories
-```
-
-#### View the Operator Logs
-```
-kubectl logs -f -l app.kubernetes.io/name=layer7-operator
-```
-
-#### Repository CR
-The Repository Controller keeps tracks the latest available commit, where it's stored (if it's less than 1mb we create a Kubernetes secret) and when it was last updated. The Storage Secret is a gzipped graphman bundle (json) used in the Graphman Init Container to remove dependencies on git during deployment.
-
-***Note: If the repository exceeds 1mb in compressed format each Graphman Init Container will clone it at runtime. This represents a single point of failure if your Git Server is down, we recommended creating your own initContainer with the larger graphman bundle.***
-```
-kubectl get repositories
-
-NAME AGE
-l7-gw-myapis 10s
-l7-gw-myframework 10s
-l7-gw-mysubscriptions 10s
-
-kubectl get repository l7-gw-myapis -oyaml
-...
-status:
- commit: 3791f11c9b588b383ce87535f46d4fc1526ae83b
- name: l7-gw-myapis
- storageSecretName: l7-gw-myapis-repository
- updated: 2023-04-04 02:53:53.298060678 +0000 UTC m=+752.481758238
- vendor: Github
-```
-
-### Create a Gateway
-```
-kubectl apply -f ./gateway/otel-prometheus-gateway.yaml
-```
-
-#### Referencing the repositories we created
-[otel-prometheus-gateway.yaml](../gateway/otel-prometheus-gateway.yaml) contains 3 repository references, the 'type' defines how a repository is applied to the Container Gateway.
-- Dynamic repositories are applied directly to the Graphman endpoint on the Gateway which does not require a gateway restart
-- Static repositories are bootstrapped to the Container Gateway with an initContainer which requires a gateway restart.
-```
-repositoryReferences:
- - name: l7-gw-myframework
- enabled: true
- type: ***static***
- encryption:
- existingSecret: graphman-encryption-secret
- key: FRAMEWORK_ENCRYPTION_PASSPHRASE
- - name: l7-gw-myapis
- enabled: true
- type: ***dynamic***
- encryption:
- existingSecret: graphman-encryption-secret
- key: APIS_ENCRYPTION_PASSPHRASE
- - name: l7-gw-mysubscriptions
- enabled: true
- type: ***dynamic***
- encryption:
- existingSecret: graphman-encryption-secret
- key: SUBSCRIPTIONS_ENCRYPTION_PASSPHRASE
-```
-
-#### View your new Gateway
-```
-kubectl get pods
-
-NAME READY STATUS RESTARTS AGE
-layer7-operator-controller-manager-7647b58697-qd9vg 2/2 Running 0 15m
-ssg-57d96567cb-n24g9 2/2 Running 0 73s
-```
-
-#### Static Graphman Repositories
-Because we created the l7-gw-myframework repository reference with type 'static' the Layer7 Operator automatically injects an initContainer to bootstrap the repository to the Container Gateway.
-Note: the suffix here graphman-static-init-***c1b58adb6d*** is generated using all static commit ids, if a static repository changes the Gateway will be updated.
-```
-kubectl describe pods ssg-57d96567cb-n24g9
-
-...
-Init Containers:
- graphman-static-init-c1b58adb6d:
- Container ID: containerd://21924ae85d25437d3634ea5da1415c9bb58d678600f9fd67d4f0b0360857d7c5
- Image: docker.io/layer7api/graphman-static-init:1.0.0
- Image ID: docker.io/layer7api/graphman-static-init@sha256:24189a432c0283845664c6fd54c3e8d9f86ad9d35ef12714bb3a18b7aba85aa4
- Port:
- Host Port:
- State: Terminated
- Reason: Completed
- Exit Code: 0
- Started: Tue, 04 Apr 2023 04:11:18 +0100
- Finished: Tue, 04 Apr 2023 04:11:18 +0100
-...
-```
-#### View the Graphman InitContainer logs
-We should see that our static repository l7-gw-myframework has been picked up and moved to the bootstrap folder.
-```
-kubectl logs ssg-57d96567cb-n24g9 graphman-static-init-c1b58adb6d
-
-l7-gw-myframework with 40kbs written to /opt/SecureSpan/Gateway/node/default/etc/bootstrap/bundle/graphman/0/0_l7-gw-myframework.json
-```
-
-#### View the Operator logs
-```
-kubectl logs -f -l app.kubernetes.io/name=layer7-operator
-```
-
-#### Inspect the Status of your Custom Resources
-
-#### Gateway CR
-The Gateway Controller tracks gateway pods and the repositories that have been applied to the deployment
-```
-kubectl get gateway ssg -oyaml
-
-status:
- ...
- gateway:
- - name: ssg-6b7d7fd999-n5bsj
- phase: Running
- ready: true
- startTime: 2023-04-03 18:57:24 +0000 UTC
- host: gateway.brcmlabs.com
- image: caapim/gateway:11.1.3
- ready: 1
- replicas: 1
-repositoryStatus:
-- branch: main
- commit: c93028b807cf1b62bce0142a80ad4f6203207e8d
- enabled: true
- endpoint: https://github.com/Gazza7205/l7GWMyFramework
- name: l7-gw-myframework
- secretName: graphman-repository-secret
- storageSecretName: l7-gw-myframework-repository
- type: static
-- branch: main
- commit: 3791f11c9b588b383ce87535f46d4fc1526ae83b
- enabled: true
- endpoint: https://github.com/Gazza7205/l7GWMyAPIs
- name: l7-gw-myapis
- secretName: graphman-repository-secret
- storageSecretName: l7-gw-myapis-repository
- type: dynamic
-- branch: main
- commit: fd6b225159fcd8fccf4bd61e31f40cdac64eccfa
- enabled: true
- endpoint: https://github.com/Gazza7205/l7GWMySubscriptions
- name: l7-gw-mysubscriptions
- secretName: graphman-repository-secret
- storageSecretName: l7-gw-mysubscriptions-repository
- type: dynamic
-state: Ready
-version: 11.1.3
-```
-
-#### Repository CR
-The Repository Controller keeps tracks the latest available commit, where it's stored (if it's less than 1mb we create a Kubernetes secret) and when it was last updated.
-```
-kubectl get repository l7-gw-myapis -oyaml
-...
-status:
- commit: 7332f861e11612a91ca9de6b079826b9377dae6a
- name: l7-gw-myapis
- storageSecretName: l7-gw-myapis-repository
- updated: 2023-04-06 15:00:20.144406434 +0000 UTC m=+21.758241719
- vendor: Github
-```
-
-### Test your Gateway Deployment
-```
-kubectl get ingress
-
-NAME CLASS HOSTS ADDRESS PORTS AGE
-ssg nginx gateway.brcmlabs.com 34.89.126.80 80, 443 54m
-```
-
-Add the following to your hosts file for DNS resolution
-```
-Format
-$ADDRESS $HOST
-
-example
-34.89.126.80 gateway.brcmlabs.com
-```
-Curl
-```
-curl https://gateway.brcmlabs.com/api1 -H "client-id: D63FA04C8447" -k
-```
-Response
-```
-{
- "client" : "D63FA04C8447",
- "plan" : "plan_a",
- "service" : "hello api 1",
- "myDemoConfigVal" : "Mondays"
-}
-```
-
-#### Sign into Policy Manager
-Policy Manager access is less relevant in a deployment like this because we haven't specified an external MySQL database, any changes that we make will only apply to the Gateway that we're connected to and won't survive a restart. It is still useful to check what's been applied. We configured custom ports where we disabled Policy Manager access on 8443, we're also using an ingress controller meaning that port 9443 is not accessible without port forwarding.
-
-Port-Forward
-```
-kubectl get pods
-NAME READY STATUS RESTARTS AGE
-...
-ssg-7698bc565b-szrbj 1/1 Running 0 54m
-
-kubectl port-forward ssg-7698bc565b-szrbj 9443:9443
-```
-Policy Manager
-```
-username: admin
-password: 7layer
-gateway: localhost:9443
-```
-
-#### Access Jaeger
-Jaeger has been configured via ingress which should resolve to https://jaeger.brcmlabs.com. You can use Jaeger to view assertion level traces of the test policy we just tested with curl.
-
-
-
-
-#### Access Grafana
-Grafana has been configured via ingress which should resolve to https://grafana.brcmlabs.com. You can use Grafana to view Gateway service level + general metrics of your Gateway Deployment.
-
-```
-username: admin
-password: 7layer
-```
-
-
-
-### Remove Kind Cluster
-If you used the Quickstart option and deployed Kind, all you will need to do is remove the Kind Cluster.
-
-Make sure that you're in the example folder
-```
-pwd
-```
-
-output
-```
-/path/to/layer7-operator/example
-```
-
-Remove the Kind Cluster
-```
-make uninstall-kind
-```
-
-### Remove Demo Component and Custom Resources
-```
-kubectl delete -f ./example/gateway/otel-prometheus-gateway.yaml
-kubectl delete -k ./example/repositories/
-kubectl delete -k ./example/otel-prometheus/monitoring/grafana
-kubectl delete -f ./example/otel-prometheus/servicemonitor.yaml
-kubectl delete -f ./example/otel-prometheus/collector.yaml
-kubectl delete -f ./example/otel-prometheus/instrumentation.yaml
-kubectl delete -f ./example/otel-prometheus/observability/jaeger/jaeger.yaml
-kubectl delete -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
-kubectl delete -f https://github.com/open-telemetry/opentelemetry-operator/releases/download/v0.76.1/opentelemetry-operator.yaml
-kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.11.0/cert-manager.yaml
-helm uninstall prometheus -n monitoring
-kubectl delete ns monitoring
-kubectl delete ns observability
-```
-
-### Uninstall the Operator
-```
-kubectl delete -f https://github.com/CAAPIM/layer7-operator/releases/download/v1.2.2/bundle.yaml
-```
\ No newline at end of file
diff --git a/example/otel-prometheus/collector.yaml b/example/otel-prometheus/collector.yaml
deleted file mode 100644
index 581e7cde..00000000
--- a/example/otel-prometheus/collector.yaml
+++ /dev/null
@@ -1,52 +0,0 @@
-apiVersion: opentelemetry.io/v1alpha1
-kind: OpenTelemetryCollector
-metadata:
- name: ssg-prom
-spec:
- image: otel/opentelemetry-collector-contrib:0.97.0
- mode: sidecar
- config: |
- receivers:
- otlp:
- protocols:
- grpc:
- endpoint: 0.0.0.0:4317
- http:
- endpoint: 0.0.0.0:4318
- processors:
- batch:
- exporters:
- debug:
- verbosity: basic
- prometheus:
- endpoint: "0.0.0.0:8889"
- const_labels:
- name: ssg
- otlp:
- endpoint: simple-allinone-collector:4317
- tls:
- insecure: true
- service:
- telemetry:
- logs:
- level: "debug"
- metrics:
- address: "0.0.0.0:8888"
- pipelines:
- traces:
- receivers: [otlp]
- processors: [batch]
- exporters: [otlp]
- metrics:
- receivers: [otlp]
- processors: [batch]
- exporters: [prometheus, debug]
- logs:
- receivers: [otlp]
- exporters: [debug]
- extensions:
- health_check:
- pprof:
- endpoint: 0.0.0.0:1777
- zpages:
- endpoint: 0.0.0.0:55679
\ No newline at end of file
diff --git a/example/otel-prometheus/instrumentation.yaml b/example/otel-prometheus/instrumentation.yaml
deleted file mode 100644
index f79b8745..00000000
--- a/example/otel-prometheus/instrumentation.yaml
+++ /dev/null
@@ -1,23 +0,0 @@
-apiVersion: opentelemetry.io/v1alpha1
-kind: Instrumentation
-metadata:
- name: otel-instrumentation
-spec:
- env:
- - name: OTEL_SERVICE_NAME
- value: ssg
- - name: OTEL_METRICS_EXPORTER
- value: otlp
- - name: OTEL_TRACES_EXPORTER
- value: otlp
- - name: OTEL_RESOURCE_ATTRIBUTES
- value: service.version=11.0.00_CR1,deployment.environment=development
- exporter:
- endpoint: http://localhost:4317
- propagators:
- - tracecontext
- - baggage
- - b3
- sampler:
- type: parentbased_traceidratio
- argument: "0.25"
\ No newline at end of file
diff --git a/example/otel-prometheus/monitoring/grafana/kustomization.yaml b/example/otel-prometheus/monitoring/grafana/kustomization.yaml
deleted file mode 100644
index 535b9faa..00000000
--- a/example/otel-prometheus/monitoring/grafana/kustomization.yaml
+++ /dev/null
@@ -1,10 +0,0 @@
-apiVersion: kustomize.config.k8s.io/v1beta1
-kind: Kustomization
-namespace: monitoring
-generatorOptions:
- disableNameSuffixHash: true
-configMapGenerator:
- - name: layer7-gateway-dashboard
- files:
- - "./layer7-gateway-dashboard.json"
-
diff --git a/example/otel-prometheus/monitoring/grafana/layer7-gateway-dashboard.json b/example/otel-prometheus/monitoring/grafana/layer7-gateway-dashboard.json
deleted file mode 100644
index eb76e807..00000000
--- a/example/otel-prometheus/monitoring/grafana/layer7-gateway-dashboard.json
+++ /dev/null
@@ -1,1414 +0,0 @@
-{
- "annotations": {
- "list": [
- {
- "builtIn": 1,
- "datasource": {
- "type": "datasource",
- "uid": "grafana"
- },
- "enable": true,
- "hide": true,
- "iconColor": "rgba(0, 211, 255, 1)",
- "name": "Annotations & Alerts",
- "type": "dashboard"
- }
- ]
- },
- "editable": true,
- "fiscalYearStartMonth": 0,
- "graphTooltip": 0,
- "links": [],
- "liveNow": false,
- "panels": [
- {
- "collapsed": false,
- "datasource": {
- "type": "prometheus",
- "uid": "prometheus"
- },
- "gridPos": {
- "h": 1,
- "w": 24,
- "x": 0,
- "y": 0
- },
- "id": 18,
- "panels": [],
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "prometheus"
- },
- "refId": "A"
- }
- ],
- "title": "Gateway Service Metrics",
- "type": "row"
- },
- {
- "datasource": {
- "type": "prometheus",
- "uid": "prometheus"
- },
- "fieldConfig": {
- "defaults": {
- "color": {
- "mode": "thresholds"
- },
- "mappings": [],
- "thresholds": {
- "mode": "absolute",
- "steps": [
- {
- "color": "green",
- "value": null
- }
- ]
- }
- },
- "overrides": []
- },
- "gridPos": {
- "h": 5,
- "w": 3,
- "x": 0,
- "y": 1
- },
- "id": 3,
- "options": {
- "colorMode": "value",
- "graphMode": "area",
- "justifyMode": "auto",
- "orientation": "auto",
- "reduceOptions": {
- "calcs": [
- "lastNotNull"
- ],
- "fields": "",
- "values": false
- },
- "showPercentChange": false,
- "text": {},
- "textMode": "auto",
- "wideLayout": true
- },
- "pluginVersion": "10.4.1",
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "mimir"
- },
- "editorMode": "code",
- "exemplar": false,
- "expr": "sum(l7_service_attempted_count_total{job=\"$gatewayDeployment\"})",
- "instant": false,
- "interval": "",
- "legendFormat": "{{podName}}",
- "refId": "A"
- }
- ],
- "title": "Total Requests",
- "type": "stat"
- },
- {
- "datasource": {
- "type": "prometheus",
- "uid": "prometheus"
- },
- "fieldConfig": {
- "defaults": {
- "color": {
- "mode": "thresholds"
- },
- "mappings": [],
- "thresholds": {
- "mode": "absolute",
- "steps": [
- {
- "color": "green",
- "value": null
- }
- ]
- }
- },
- "overrides": []
- },
- "gridPos": {
- "h": 5,
- "w": 3,
- "x": 3,
- "y": 1
- },
- "id": 12,
- "options": {
- "colorMode": "value",
- "graphMode": "area",
- "justifyMode": "auto",
- "orientation": "auto",
- "reduceOptions": {
- "calcs": [
- "lastNotNull"
- ],
- "fields": "",
- "values": false
- },
- "showPercentChange": false,
- "text": {},
- "textMode": "auto",
- "wideLayout": true
- },
- "pluginVersion": "10.4.1",
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "mimir"
- },
- "editorMode": "code",
- "exemplar": true,
- "expr": "sum(l7_service_success_count_total{job=\"$gatewayDeployment\"})",
- "interval": "",
- "legendFormat": "{{pod}}",
- "range": true,
- "refId": "A"
- }
- ],
- "title": "Successful Requests",
- "type": "stat"
- },
- {
- "datasource": {
- "type": "prometheus",
- "uid": "prometheus"
- },
- "fieldConfig": {
- "defaults": {
- "color": {
- "mode": "thresholds"
- },
- "mappings": [],
- "noValue": "0",
- "thresholds": {
- "mode": "absolute",
- "steps": [
- {
- "color": "green",
- "value": null
- }
- ]
- }
- },
- "overrides": []
- },
- "gridPos": {
- "h": 5,
- "w": 3,
- "x": 6,
- "y": 1
- },
- "id": 13,
- "options": {
- "colorMode": "value",
- "graphMode": "area",
- "justifyMode": "auto",
- "orientation": "auto",
- "reduceOptions": {
- "calcs": [
- "lastNotNull"
- ],
- "fields": "",
- "values": false
- },
- "showPercentChange": false,
- "text": {},
- "textMode": "auto",
- "wideLayout": true
- },
- "pluginVersion": "10.4.1",
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "mimir"
- },
- "editorMode": "code",
- "exemplar": true,
- "expr": "sum(l7_service_attempted_count_total{job=\"$gatewayDeployment\"} - l7_service_success_count_total{job=\"$gatewayDeployment\"})",
- "interval": "",
- "legendFormat": "{{pod}}",
- "range": true,
- "refId": "A"
- }
- ],
- "title": "Routing Failures",
- "type": "stat"
- },
- {
- "datasource": {
- "type": "prometheus",
- "uid": "prometheus"
- },
- "fieldConfig": {
- "defaults": {
- "color": {
- "mode": "palette-classic"
- },
- "custom": {
- "axisBorderShow": false,
- "axisCenteredZero": false,
- "axisColorMode": "text",
- "axisLabel": "",
- "axisPlacement": "auto",
- "barAlignment": 0,
- "drawStyle": "line",
- "fillOpacity": 10,
- "gradientMode": "none",
- "hideFrom": {
- "graph": false,
- "legend": false,
- "tooltip": false,
- "viz": false
- },
- "insertNulls": false,
- "lineInterpolation": "linear",
- "lineWidth": 1,
- "pointSize": 5,
- "scaleDistribution": {
- "type": "linear"
- },
- "showPoints": "never",
- "spanNulls": true,
- "stacking": {
- "group": "A",
- "mode": "none"
- },
- "thresholdsStyle": {
- "mode": "off"
- }
- },
- "mappings": [],
- "thresholds": {
- "mode": "absolute",
- "steps": [
- {
- "color": "green",
- "value": null
- }
- ]
- },
- "unit": "short"
- },
- "overrides": []
- },
- "gridPos": {
- "h": 7,
- "w": 15,
- "x": 9,
- "y": 1
- },
- "id": 8,
- "options": {
- "graph": {},
- "legend": {
- "calcs": [],
- "displayMode": "list",
- "placement": "bottom",
- "showLegend": true
- },
- "tooltip": {
- "mode": "single",
- "sort": "none"
- }
- },
- "pluginVersion": "7.5.11",
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "mimir"
- },
- "editorMode": "code",
- "exemplar": false,
- "expr": "sum(rate(l7_service_attempted_count_total{job=\"$gatewayDeployment\"}[5m]))",
- "instant": false,
- "interval": "",
- "legendFormat": "${gatewayDeployment}",
- "refId": "A"
- }
- ],
- "title": "Transaction Rate (Cluster[5m])",
- "type": "timeseries"
- },
- {
- "datasource": {
- "type": "prometheus",
- "uid": "prometheus"
- },
- "fieldConfig": {
- "defaults": {
- "color": {
- "mode": "thresholds"
- },
- "custom": {
- "align": "left",
- "cellOptions": {
- "type": "auto"
- },
- "filterable": false,
- "inspect": false
- },
- "mappings": [],
- "thresholds": {
- "mode": "absolute",
- "steps": [
- {
- "color": "green",
- "value": null
- }
- ]
- }
- },
- "overrides": [
- {
- "matcher": {
- "id": "byName",
- "options": "serviceUri"
- },
- "properties": [
- {
- "id": "custom.width",
- "value": 218
- }
- ]
- },
- {
- "matcher": {
- "id": "byName",
- "options": "Service Name"
- },
- "properties": [
- {
- "id": "custom.width",
- "value": 282
- }
- ]
- }
- ]
- },
- "gridPos": {
- "h": 6,
- "w": 9,
- "x": 0,
- "y": 6
- },
- "id": 2,
- "options": {
- "cellHeight": "sm",
- "footer": {
- "countRows": false,
- "fields": "",
- "reducer": [
- "sum"
- ],
- "show": false
- },
- "showHeader": true,
- "sortBy": []
- },
- "pluginVersion": "10.4.1",
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "mimir"
- },
- "editorMode": "code",
- "exemplar": true,
- "expr": "l7_service_policy_violations_count_total{job=\"$gatewayDeployment\"}",
- "format": "table",
- "instant": true,
- "interval": "",
- "intervalFactor": 1,
- "legendFormat": "{{apiName}}",
- "refId": "A"
- }
- ],
- "title": "Policy Violations",
- "transformations": [
- {
- "id": "organize",
- "options": {
- "excludeByName": {
- "Time": true,
- "__name__": true,
- "container": true,
- "endpoint": true,
- "exported_job": true,
- "goid": true,
- "instance": true,
- "job": true,
- "l7_goid": true,
- "l7_method": false,
- "name": true,
- "namespace": true,
- "pod": false,
- "service": true,
- "serviceUri": true
- },
- "includeByName": {},
- "indexByName": {},
- "renameByName": {
- "Value": "Count",
- "__name__": "",
- "apiName": "Service Name",
- "container": "",
- "l7_method": "Method",
- "l7_serviceName": "Service Name",
- "l7_serviceUri": "Service URI",
- "namespace": "",
- "pod": "Pod",
- "service": ""
- }
- }
- }
- ],
- "type": "table"
- },
- {
- "datasource": {
- "type": "prometheus",
- "uid": "prometheus"
- },
- "fieldConfig": {
- "defaults": {
- "color": {
- "mode": "palette-classic"
- },
- "custom": {
- "axisBorderShow": false,
- "axisCenteredZero": false,
- "axisColorMode": "text",
- "axisLabel": "",
- "axisPlacement": "auto",
- "barAlignment": 0,
- "drawStyle": "line",
- "fillOpacity": 10,
- "gradientMode": "none",
- "hideFrom": {
- "graph": false,
- "legend": false,
- "tooltip": false,
- "viz": false
- },
- "insertNulls": false,
- "lineInterpolation": "linear",
- "lineWidth": 1,
- "pointSize": 5,
- "scaleDistribution": {
- "type": "linear"
- },
- "showPoints": "never",
- "spanNulls": true,
- "stacking": {
- "group": "A",
- "mode": "none"
- },
- "thresholdsStyle": {
- "mode": "off"
- }
- },
- "mappings": [],
- "thresholds": {
- "mode": "absolute",
- "steps": [
- {
- "color": "green",
- "value": null
- },
- {
- "color": "red",
- "value": 80
- }
- ]
- },
- "unit": "short"
- },
- "overrides": []
- },
- "gridPos": {
- "h": 8,
- "w": 15,
- "x": 9,
- "y": 8
- },
- "id": 7,
- "options": {
- "graph": {},
- "legend": {
- "calcs": [],
- "displayMode": "list",
- "placement": "bottom",
- "showLegend": true
- },
- "tooltip": {
- "mode": "single",
- "sort": "none"
- }
- },
- "pluginVersion": "7.5.11",
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "mimir"
- },
- "editorMode": "code",
- "exemplar": false,
- "expr": "rate(l7_service_attempted_count_total{l7_serviceName=\"$serviceName\",job=\"$gatewayDeployment\",l7_method=\"$requestMethod\"}[5m])",
- "instant": false,
- "interval": "",
- "legendFormat": "{{l7_serviceName}}",
- "refId": "A"
- }
- ],
- "title": "Transactions Rate (Service[5m])",
- "type": "timeseries"
- },
- {
- "datasource": {
- "type": "prometheus",
- "uid": "prometheus"
- },
- "fieldConfig": {
- "defaults": {
- "color": {
- "mode": "thresholds"
- },
- "mappings": [],
- "thresholds": {
- "mode": "absolute",
- "steps": [
- {
- "color": "green",
- "value": null
- }
- ]
- },
- "unit": "ms"
- },
- "overrides": []
- },
- "gridPos": {
- "h": 5,
- "w": 9,
- "x": 0,
- "y": 12
- },
- "id": 15,
- "options": {
- "colorMode": "value",
- "graphMode": "area",
- "justifyMode": "auto",
- "orientation": "auto",
- "reduceOptions": {
- "calcs": [
- "lastNotNull"
- ],
- "fields": "",
- "values": false
- },
- "showPercentChange": false,
- "text": {},
- "textMode": "auto",
- "wideLayout": true
- },
- "pluginVersion": "10.4.1",
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "mimir"
- },
- "editorMode": "code",
- "exemplar": true,
- "expr": "l7_service_latency_milliseconds_sum{job=\"$gatewayDeployment\"} / l7_service_latency_milliseconds_count{job=\"$gatewayDeployment\"}",
- "interval": "",
- "legendFormat": "{{pod}}-{{l7_serviceName}}",
- "range": true,
- "refId": "A"
- }
- ],
- "title": "Avg. Latency (milliseconds) $serviceName",
- "type": "stat"
- },
- {
- "datasource": {
- "type": "prometheus",
- "uid": "prometheus"
- },
- "description": "",
- "fieldConfig": {
- "defaults": {
- "color": {
- "mode": "palette-classic"
- },
- "custom": {
- "fillOpacity": 80,
- "gradientMode": "none",
- "hideFrom": {
- "legend": false,
- "tooltip": false,
- "viz": false
- },
- "lineWidth": 1
- },
- "mappings": [],
- "thresholds": {
- "mode": "absolute",
- "steps": [
- {
- "color": "green",
- "value": null
- },
- {
- "color": "red",
- "value": 80
- }
- ]
- },
- "unit": "ms"
- },
- "overrides": []
- },
- "gridPos": {
- "h": 7,
- "w": 15,
- "x": 9,
- "y": 16
- },
- "id": 29,
- "options": {
- "bucketOffset": 0,
- "combine": false,
- "legend": {
- "calcs": [
- "lastNotNull"
- ],
- "displayMode": "list",
- "placement": "bottom",
- "showLegend": true
- }
- },
- "pluginVersion": "10.4.0",
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "mimir"
- },
- "editorMode": "code",
- "exemplar": false,
- "expr": "histogram_quantile(0.95, l7_service_latency_milliseconds_bucket{})",
- "format": "time_series",
- "instant": false,
- "legendFormat": "{{l7_serviceName}}",
- "range": true,
- "refId": "A"
- }
- ],
- "title": "Service Latency Histogram",
- "type": "histogram"
- },
- {
- "datasource": {
- "type": "prometheus",
- "uid": "prometheus"
- },
- "fieldConfig": {
- "defaults": {
- "color": {
- "mode": "thresholds"
- },
- "custom": {
- "align": "left",
- "cellOptions": {
- "type": "auto"
- },
- "filterable": false,
- "inspect": false
- },
- "mappings": [],
- "thresholds": {
- "mode": "absolute",
- "steps": [
- {
- "color": "green",
- "value": null
- }
- ]
- }
- },
- "overrides": [
- {
- "matcher": {
- "id": "byName",
- "options": "Request URI"
- },
- "properties": [
- {
- "id": "custom.width",
- "value": 160
- }
- ]
- },
- {
- "matcher": {
- "id": "byName",
- "options": "Service Name"
- },
- "properties": [
- {
- "id": "custom.width",
- "value": 124
- }
- ]
- },
- {
- "matcher": {
- "id": "byName",
- "options": "Pod"
- },
- "properties": [
- {
- "id": "custom.width",
- "value": 206
- }
- ]
- },
- {
- "matcher": {
- "id": "byName",
- "options": "request_method"
- },
- "properties": [
- {
- "id": "custom.width",
- "value": 125
- }
- ]
- }
- ]
- },
- "gridPos": {
- "h": 6,
- "w": 9,
- "x": 0,
- "y": 17
- },
- "id": 6,
- "options": {
- "cellHeight": "sm",
- "footer": {
- "countRows": false,
- "fields": "",
- "reducer": [
- "sum"
- ],
- "show": false
- },
- "showHeader": true,
- "sortBy": [
- {
- "desc": false,
- "displayName": "Pod"
- }
- ]
- },
- "pluginVersion": "10.4.1",
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "mimir"
- },
- "editorMode": "code",
- "exemplar": false,
- "expr": "l7_service_attempted_count_total{job=\"$gatewayDeployment\", l7_method=\"$requestMethod\"}",
- "format": "table",
- "instant": true,
- "interval": "",
- "legendFormat": "",
- "refId": "A"
- }
- ],
- "title": "Requests per service",
- "transformations": [
- {
- "id": "filterFieldsByName",
- "options": {
- "include": {
- "names": [
- "l7_method",
- "l7_serviceName",
- "l7_serviceUri",
- "Value",
- "pod"
- ]
- }
- }
- },
- {
- "id": "organize",
- "options": {
- "excludeByName": {},
- "includeByName": {},
- "indexByName": {},
- "renameByName": {
- "Value": "Count",
- "exported_job": "",
- "l7_method": "Method",
- "l7_serviceName": "Service Name",
- "l7_serviceUri": "Service URI",
- "pod": "Pod"
- }
- }
- }
- ],
- "type": "table"
- },
- {
- "collapsed": false,
- "datasource": {
- "type": "prometheus",
- "uid": "prometheus"
- },
- "gridPos": {
- "h": 1,
- "w": 24,
- "x": 0,
- "y": 23
- },
- "id": 20,
- "panels": [],
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "prometheus"
- },
- "refId": "A"
- }
- ],
- "title": "Gateway Application Metrics",
- "type": "row"
- },
- {
- "datasource": {
- "type": "prometheus",
- "uid": "prometheus"
- },
- "fieldConfig": {
- "defaults": {
- "color": {
- "mode": "palette-classic"
- },
- "custom": {
- "axisBorderShow": false,
- "axisCenteredZero": false,
- "axisColorMode": "text",
- "axisLabel": "",
- "axisPlacement": "auto",
- "barAlignment": 0,
- "drawStyle": "line",
- "fillOpacity": 10,
- "gradientMode": "none",
- "hideFrom": {
- "legend": false,
- "tooltip": false,
- "viz": false
- },
- "insertNulls": false,
- "lineInterpolation": "linear",
- "lineWidth": 1,
- "pointSize": 5,
- "scaleDistribution": {
- "type": "linear"
- },
- "showPoints": "never",
- "spanNulls": false,
- "stacking": {
- "group": "A",
- "mode": "none"
- },
- "thresholdsStyle": {
- "mode": "off"
- }
- },
- "mappings": [],
- "thresholds": {
- "mode": "absolute",
- "steps": [
- {
- "color": "green",
- "value": null
- },
- {
- "color": "red",
- "value": 80
- }
- ]
- },
- "unit": "percentunit"
- },
- "overrides": []
- },
- "gridPos": {
- "h": 8,
- "w": 12,
- "x": 0,
- "y": 24
- },
- "id": 22,
- "options": {
- "legend": {
- "calcs": [],
- "displayMode": "list",
- "placement": "bottom",
- "showLegend": true
- },
- "tooltip": {
- "mode": "multi",
- "sort": "none"
- }
- },
- "pluginVersion": "10.0.3",
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "mimir"
- },
- "editorMode": "code",
- "exemplar": true,
- "expr": "process_runtime_jvm_system_cpu_utilization_ratio",
- "interval": "",
- "legendFormat": "{{pod}}",
- "range": true,
- "refId": "A"
- }
- ],
- "title": "CPU Utilization",
- "type": "timeseries"
- },
- {
- "datasource": {
- "type": "prometheus",
- "uid": "prometheus"
- },
- "fieldConfig": {
- "defaults": {
- "color": {
- "mode": "palette-classic"
- },
- "custom": {
- "axisBorderShow": false,
- "axisCenteredZero": false,
- "axisColorMode": "text",
- "axisLabel": "",
- "axisPlacement": "auto",
- "barAlignment": 0,
- "drawStyle": "line",
- "fillOpacity": 10,
- "gradientMode": "none",
- "hideFrom": {
- "legend": false,
- "tooltip": false,
- "viz": false
- },
- "insertNulls": false,
- "lineInterpolation": "linear",
- "lineWidth": 1,
- "pointSize": 5,
- "scaleDistribution": {
- "type": "linear"
- },
- "showPoints": "never",
- "spanNulls": false,
- "stacking": {
- "group": "A",
- "mode": "none"
- },
- "thresholdsStyle": {
- "mode": "off"
- }
- },
- "mappings": [],
- "thresholds": {
- "mode": "absolute",
- "steps": [
- {
- "color": "green",
- "value": null
- },
- {
- "color": "red",
- "value": 80
- }
- ]
- },
- "unit": "none"
- },
- "overrides": []
- },
- "gridPos": {
- "h": 8,
- "w": 12,
- "x": 12,
- "y": 24
- },
- "id": 24,
- "options": {
- "legend": {
- "calcs": [],
- "displayMode": "list",
- "placement": "bottom",
- "showLegend": true
- },
- "tooltip": {
- "mode": "multi",
- "sort": "none"
- }
- },
- "pluginVersion": "10.0.3",
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "mimir"
- },
- "editorMode": "code",
- "exemplar": true,
- "expr": "process_runtime_jvm_system_cpu_load_1m",
- "interval": "",
- "legendFormat": "{{pod}}",
- "range": true,
- "refId": "A"
- }
- ],
- "title": "System Load (1m)",
- "type": "timeseries"
- },
- {
- "datasource": {
- "type": "prometheus",
- "uid": "prometheus"
- },
- "fieldConfig": {
- "defaults": {
- "color": {
- "mode": "palette-classic"
- },
- "custom": {
- "axisBorderShow": false,
- "axisCenteredZero": false,
- "axisColorMode": "text",
- "axisLabel": "",
- "axisPlacement": "auto",
- "barAlignment": 0,
- "drawStyle": "line",
- "fillOpacity": 10,
- "gradientMode": "none",
- "hideFrom": {
- "legend": false,
- "tooltip": false,
- "viz": false
- },
- "insertNulls": false,
- "lineInterpolation": "linear",
- "lineWidth": 1,
- "pointSize": 5,
- "scaleDistribution": {
- "type": "linear"
- },
- "showPoints": "never",
- "spanNulls": false,
- "stacking": {
- "group": "A",
- "mode": "none"
- },
- "thresholdsStyle": {
- "mode": "off"
- }
- },
- "mappings": [],
- "thresholds": {
- "mode": "absolute",
- "steps": [
- {
- "color": "green",
- "value": null
- },
- {
- "color": "red",
- "value": 80
- }
- ]
- },
- "unit": "decbytes"
- },
- "overrides": []
- },
- "gridPos": {
- "h": 8,
- "w": 12,
- "x": 0,
- "y": 32
- },
- "id": 23,
- "options": {
- "legend": {
- "calcs": [],
- "displayMode": "list",
- "placement": "bottom",
- "showLegend": true
- },
- "tooltip": {
- "mode": "multi",
- "sort": "none"
- }
- },
- "pluginVersion": "10.0.3",
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "mimir"
- },
- "editorMode": "code",
- "exemplar": true,
- "expr": "process_runtime_jvm_memory_usage_bytes{type=\"non_heap\"}",
- "interval": "",
- "legendFormat": "{{pod}}-{{pool}}-{{type}}",
- "range": true,
- "refId": "A"
- }
- ],
- "title": "Memory Usage (non-heap)",
- "type": "timeseries"
- },
- {
- "datasource": {
- "type": "prometheus",
- "uid": "prometheus"
- },
- "fieldConfig": {
- "defaults": {
- "color": {
- "mode": "palette-classic"
- },
- "custom": {
- "axisBorderShow": false,
- "axisCenteredZero": false,
- "axisColorMode": "text",
- "axisLabel": "",
- "axisPlacement": "auto",
- "barAlignment": 0,
- "drawStyle": "line",
- "fillOpacity": 10,
- "gradientMode": "none",
- "hideFrom": {
- "legend": false,
- "tooltip": false,
- "viz": false
- },
- "insertNulls": false,
- "lineInterpolation": "linear",
- "lineWidth": 1,
- "pointSize": 5,
- "scaleDistribution": {
- "type": "linear"
- },
- "showPoints": "never",
- "spanNulls": false,
- "stacking": {
- "group": "A",
- "mode": "none"
- },
- "thresholdsStyle": {
- "mode": "off"
- }
- },
- "mappings": [],
- "thresholds": {
- "mode": "absolute",
- "steps": [
- {
- "color": "green",
- "value": null
- },
- {
- "color": "red",
- "value": 80
- }
- ]
- },
- "unit": "decbytes"
- },
- "overrides": []
- },
- "gridPos": {
- "h": 8,
- "w": 12,
- "x": 12,
- "y": 32
- },
- "id": 25,
- "options": {
- "legend": {
- "calcs": [],
- "displayMode": "list",
- "placement": "bottom",
- "showLegend": true
- },
- "tooltip": {
- "mode": "multi",
- "sort": "none"
- }
- },
- "pluginVersion": "10.0.3",
- "targets": [
- {
- "datasource": {
- "type": "prometheus",
- "uid": "mimir"
- },
- "editorMode": "code",
- "exemplar": true,
- "expr": "process_runtime_jvm_memory_usage_bytes{type=\"heap\"}",
- "interval": "",
- "legendFormat": "{{pod}}-{{pool}}-{{type}}",
- "range": true,
- "refId": "A"
- }
- ],
- "title": "Memory Usage (heap)",
- "type": "timeseries"
- }
- ],
- "refresh": "5s",
- "schemaVersion": 39,
- "tags": [],
- "templating": {
- "list": [
- {
- "current": {
- "selected": false,
- "text": "ssg",
- "value": "ssg"
- },
- "definition": "label_values(l7_service_attempted_count_total,job)",
- "hide": 0,
- "includeAll": false,
- "label": "Gateway Deployment",
- "multi": false,
- "name": "gatewayDeployment",
- "options": [],
- "query": {
- "qryType": 1,
- "query": "label_values(l7_service_attempted_count_total,job)",
- "refId": "PrometheusVariableQueryEditor-VariableQuery"
- },
- "refresh": 1,
- "regex": "",
- "skipUrlSync": false,
- "sort": 0,
- "type": "query"
- },
- {
- "current": {
- "selected": false,
- "text": "ssg-5b88cc7874-5jjlm",
- "value": "ssg-5b88cc7874-5jjlm"
- },
- "definition": "label_values(l7_service_attempted_count_total{pod!=\"\", job=\"$gatewayDeployment\"},pod)",
- "hide": 0,
- "includeAll": false,
- "label": "Pod",
- "multi": false,
- "name": "gatewayPod",
- "options": [],
- "query": {
- "qryType": 1,
- "query": "label_values(l7_service_attempted_count_total{pod!=\"\", job=\"$gatewayDeployment\"},pod)",
- "refId": "PrometheusVariableQueryEditor-VariableQuery"
- },
- "refresh": 1,
- "regex": "",
- "skipUrlSync": false,
- "sort": 0,
- "type": "query"
- },
- {
- "current": {
- "selected": false,
- "text": "Gateway GraphQL Management Service",
- "value": "Gateway GraphQL Management Service"
- },
- "definition": "label_values(l7_service_attempted_count_total{job=\"$gatewayDeployment\", pod=\"$gatewayPod\"},l7_serviceName)",
- "hide": 0,
- "includeAll": false,
- "label": "Service Name",
- "multi": false,
- "name": "serviceName",
- "options": [],
- "query": {
- "qryType": 1,
- "query": "label_values(l7_service_attempted_count_total{job=\"$gatewayDeployment\", pod=\"$gatewayPod\"},l7_serviceName)",
- "refId": "PrometheusVariableQueryEditor-VariableQuery"
- },
- "refresh": 1,
- "regex": "",
- "skipUrlSync": false,
- "sort": 0,
- "type": "query"
- },
- {
- "current": {
- "selected": false,
- "text": "POST",
- "value": "POST"
- },
- "definition": "label_values(l7_service_attempted_count_total{job=\"$gatewayDeployment\", l7_serviceName=\"$serviceName\"},l7_method)",
- "hide": 0,
- "includeAll": false,
- "label": "Request Method",
- "multi": false,
- "name": "requestMethod",
- "options": [],
- "query": {
- "qryType": 1,
- "query": "label_values(l7_service_attempted_count_total{job=\"$gatewayDeployment\", l7_serviceName=\"$serviceName\"},l7_method)",
- "refId": "PrometheusVariableQueryEditor-VariableQuery"
- },
- "refresh": 1,
- "regex": "",
- "skipUrlSync": false,
- "sort": 0,
- "type": "query"
- }
- ]
- },
- "time": {
- "from": "now-5m",
- "to": "now"
- },
- "timepicker": {},
- "timezone": "",
- "title": "Gateway Dashboard",
- "uid": "K5qg2_14k",
- "version": 1,
- "weekStart": ""
-}
\ No newline at end of file
diff --git a/example/otel-prometheus/monitoring/prometheus/prometheus-values.yaml b/example/otel-prometheus/monitoring/prometheus/prometheus-values.yaml
deleted file mode 100644
index 97fb7668..00000000
--- a/example/otel-prometheus/monitoring/prometheus/prometheus-values.yaml
+++ /dev/null
@@ -1,80 +0,0 @@
-prometheusOperator:
- namespaces:
- releaseNamespace: true
- additional:
- - kube-system
- - layer7
- - default
- denyNamespaces: []
- prometheusInstanceNamespaces: []
- alertmanagerInstanceNamespaces: []
- thanosRulerInstanceNamespaces: []
-
-prometheus:
- prometheusSpec:
- serviceMonitorSelectorNilUsesHelmValues: false
- serviceMonitorSelector: {}
- serviceMonitorNamespaceSelector: {}
-
-grafana:
- enabled: true
- dashboardProviders:
- dashboardproviders.yaml:
- apiVersion: 1
- providers:
- - name: 'layer7'
- orgId: 1
- folder: 'Layer7'
- type: file
- disableDeletion: true
- editable: true
- options:
- path: /var/lib/grafana/dashboards/layer7
-
-
- dashboardsConfigMaps:
- layer7: layer7-gateway-dashboard
-
- adminPassword: 7layer
-
- rbac:
- ## If true, Grafana PSPs will be created
- ##
- pspEnabled: false
-
- ingress:
- ## If true, Grafana Ingress will be created
- ##
- enabled: true
-
- ## IngressClassName for Grafana Ingress.
- ## Should be provided if Ingress is enable.
- ##
- ingressClassName: nginx
-
- ## Annotations for Grafana Ingress
- ##
- annotations: {}
- # kubernetes.io/ingress.class: nginx
- # kubernetes.io/tls-acme: "true"
-
- ## Labels to be added to the Ingress
- ##
- labels: {}
-
- ## Hostnames.
- ## Must be provided if Ingress is enable.
- ##
- hosts:
- - grafana.brcmlabs.com
-
- ## Path for grafana ingress
- path: /
-
- ## TLS configuration for grafana Ingress
- ## Secret must be manually created in the namespace
- ##
- tls:
- - secretName: brcmlabs
- hosts:
- - grafana.brcmlabs.com
\ No newline at end of file
diff --git a/example/otel-prometheus/observability/jaeger/ingress.yaml b/example/otel-prometheus/observability/jaeger/ingress.yaml
deleted file mode 100644
index b65d3cc5..00000000
--- a/example/otel-prometheus/observability/jaeger/ingress.yaml
+++ /dev/null
@@ -1,22 +0,0 @@
-apiVersion: networking.k8s.io/v1
-kind: Ingress
-metadata:
- name: jaeger-ingress
- annotations: {}
-spec:
- ingressClassName: nginx
- rules:
- - host: jaeger.brcmlabs.com
- http:
- paths:
- - backend:
- service:
- name: simple-allinone-query
- port:
- number: 16686
- path: /
- pathType: Prefix
- tls:
- - hosts:
- - jaeger.brcmlabs.com
- secretName: default
\ No newline at end of file
diff --git a/example/otel-prometheus/observability/jaeger/jaeger.yaml b/example/otel-prometheus/observability/jaeger/jaeger.yaml
deleted file mode 100644
index d1a87f41..00000000
--- a/example/otel-prometheus/observability/jaeger/jaeger.yaml
+++ /dev/null
@@ -1,7 +0,0 @@
-apiVersion: jaegertracing.io/v1
-kind: Jaeger
-metadata:
- name: simple-allinone
-spec:
- ingress:
- secretName: default
\ No newline at end of file
diff --git a/example/otel-prometheus/servicemonitor.yaml b/example/otel-prometheus/servicemonitor.yaml
deleted file mode 100644
index 8bf21623..00000000
--- a/example/otel-prometheus/servicemonitor.yaml
+++ /dev/null
@@ -1,21 +0,0 @@
-apiVersion: monitoring.coreos.com/v1
-kind: ServiceMonitor
-metadata:
- labels:
- app: ssg
- name: ssg
-spec:
- endpoints:
- - interval: 10s
- path: /metrics
- port: monitoring
- jobLabel: ssg
- namespaceSelector:
- matchNames:
- - default
- selector:
- matchLabels:
- app.kubernetes.io/created-by: layer7-operator
- app.kubernetes.io/managed-by: layer7-operator
- app.kubernetes.io/name: ssg
- app.kubernetes.io/part-of: ssg
diff --git a/example/otk/dual/README.md b/example/otk/dual/README.md
index 1da54d76..7e42ea61 100644
--- a/example/otk/dual/README.md
+++ b/example/otk/dual/README.md
@@ -1,2 +1,498 @@
-# OTK Dual Mode Install
-This mode is currently not supported with the Layer7 Operator
\ No newline at end of file
+# Dual Gateway OTK Configuration Guide
+
+This guide describes how to configure a Dual Gateway OAuth Toolkit (OTK) deployment using the Layer7 Gateway Operator. In a dual gateway setup, one gateway acts as the DMZ (Demilitarized Zone) gateway and another acts as the Internal gateway, providing enhanced security and separation of concerns.
+
+## Table of Contents
+
+- [Overview](#overview)
+- [Architecture](#architecture)
+- [Prerequisites](#prerequisites)
+- [Configuration Overview](#configuration-overview)
+- [Step 1: Create Required Secrets](#step-1-create-required-secrets)
+- [Step 2: Configure DMZ Gateway](#step-2-configure-dmz-gateway)
+- [Step 3: Configure Internal Gateway](#step-3-configure-internal-gateway)
+- [Key Configuration Fields](#key-configuration-fields)
+- [Deployment](#deployment)
+- [Certificate Synchronization](#certificate-synchronization)
+- [External Gateway Support](#external-gateway-support)
+- [Troubleshooting](#troubleshooting)
+
+## Overview
+
+The Dual Gateway OTK deployment consists of:
+
+- **DMZ Gateway**: Handles external client requests and acts as the OAuth authorization server
+- **Internal Gateway**: Handles token validation and resource server operations
+
+The operator automatically synchronizes certificates and keys between the two gateways, ensuring secure communication and proper OAuth flow.
+
+## Configuration Overview
+
+The dual gateway setup requires:
+
+1. **TLS Secrets**: For DMZ and Internal gateway keys/certificates
+2. **Auth Secrets**: For gateway authentication credentials
+3. **DMZ Gateway Configuration**: With `type: dmz`
+4. **Internal Gateway Configuration**: With `type: internal`
+
+## Step 1: Create Required Secrets
+
+### Create TLS Secrets
+
+You need to create TLS secrets for both DMZ and Internal gateways. These secrets must be of type `kubernetes.io/tls` and contain:
+- `tls.crt`: The certificate
+- `tls.key`: The private key
+
+#### Option 1: Using the Provided Script
+
+A helper script is available to generate self-signed certificates and create all required secrets:
+
+```bash
+cd example/gateway/otk/secrets
+./create-secrets.sh
+```
+
+This script creates:
+- `otk-dmz-tls-secret`: TLS secret for DMZ gateway
+- `otk-internal-tls-secret`: TLS secret for Internal gateway
+- `otk-dmz-auth-secret`: Authentication secret for DMZ gateway (username: `admin`, password: `7layer`)
+- `otk-internal-auth-secret`: Authentication secret for Internal gateway (username: `admin`, password: `7layer`)
+
+#### Option 2: Manual Secret Creation
+
+**DMZ TLS Secret:**
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: otk-dmz-tls-secret
+ namespace: default
+type: kubernetes.io/tls
+data:
+ tls.crt:
+ tls.key:
+```
+
+**Internal TLS Secret:**
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: otk-internal-tls-secret
+ namespace: default
+type: kubernetes.io/tls
+data:
+ tls.crt:
+ tls.key:
+```
+
+**DMZ Auth Secret:**
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: otk-dmz-auth-secret
+ namespace: default
+type: Opaque
+stringData:
+ SSG_ADMIN_USERNAME: admin
+ SSG_ADMIN_PASSWORD: 7layer
+```
+
+**Internal Auth Secret:**
+
+```yaml
+apiVersion: v1
+kind: Secret
+metadata:
+ name: otk-internal-auth-secret
+ namespace: default
+type: Opaque
+stringData:
+ SSG_ADMIN_USERNAME: admin
+ SSG_ADMIN_PASSWORD: 7layer
+```
+
+## Step 2: Configure DMZ Gateway
+
+The DMZ gateway configuration should include:
+
+- `otk.type: dmz`
+- Reference to Internal gateway
+- DMZ key secret reference
+- Internal auth secret for communication with Internal gateway
+- Database configuration
+
+### Sample DMZ Gateway Configuration
+
+```yaml
+apiVersion: security.brcmlabs.com/v1
+kind: Gateway
+metadata:
+ name: otk-ssg-dmz
+spec:
+ version: "11.1.3"
+ license:
+ accept: true
+ secretName: gateway-license
+ app:
+ replicas: 1
+ image: docker.io/caapim/gateway:11.1.3
+ imagePullPolicy: IfNotPresent
+ resources:
+ requests:
+ memory: 8Gi
+ cpu: 3
+ limits:
+ memory: 8Gi
+ cpu: 3
+ # ExternalKeys with otk flag set to true for OTK-specific key usage
+ externalKeys:
+ - name: otk-dmz-tls-secret
+ enabled: true
+ alias: otk-dmz-key
+ keyUsageType: SSL
+ otk: true
+ otk:
+ enabled: true
+ initContainerImage: docker.io/caapim/otk-install:4.6.4
+ type: dmz
+ # Reference to Internal gateway (can be Gateway name or external hostname)
+ internalGatewayReference: otk-ssg-internal
+ # InternalGatewayPort is used when the Internal gateway is external
+ # If not specified, defaults to 9443 or the gateway's graphmanDynamicSync port
+ internalGatewayPort: 9443
+ # SyncIntervalSeconds determines how often certificates are synchronized
+ # Defaults to RuntimeSyncIntervalSeconds if not specified, or 10 seconds if neither is set
+ syncIntervalSeconds: 30
+ # Reference to the TLS secret for DMZ key
+ dmzKeySecret: otk-dmz-tls-secret
+ # Auth secret for Internal gateway communication
+ internalAuthSecret: otk-internal-auth-secret
+ database:
+ type: mysql
+ create: true
+ connectionName: OAuth
+ auth:
+ gateway:
+ username: otk_user
+ password: otkUserPass
+ readOnly:
+ username: readonly_user
+ password: readonly_userPass
+ admin:
+ username: admin
+ password: adminPass
+ properties:
+ minimumPoolSize: 3
+ maximumPoolSize: 15
+ sql:
+ databaseName: otk_db
+ jdbcUrl: jdbc:mysql://mysql.brcmlabs.com:3306/otk_db_init
+ jdbcDriverClass: com.mysql.cj.jdbc.Driver
+ connectionProperties:
+ c3p0.maxConnectionAge: "100"
+ c3p0.maxIdleTime: "1000"
+ manageSchema: true
+ databaseWaitTimeout: 60
+ management:
+ secretName: gateway-secret
+ graphman:
+ enabled: true
+ initContainerImage: docker.io/caapim/graphman-static-init:1.0.4
+ dynamicSyncPort: 9443
+ cluster:
+ hostname: gateway.brcmlabs.com
+ service:
+ type: ClusterIP
+ ports:
+ - name: https
+ port: 8443
+ targetPort: 8443
+ protocol: TCP
+```
+
+## Step 3: Configure Internal Gateway
+
+The Internal gateway configuration should include:
+
+- `otk.type: internal`
+- Reference to DMZ gateway
+- Internal key secret reference
+- DMZ auth secret for communication with DMZ gateway
+- Database configuration (shared with DMZ)
+
+### Sample Internal Gateway Configuration
+
+```yaml
+apiVersion: security.brcmlabs.com/v1
+kind: Gateway
+metadata:
+ name: otk-ssg-internal
+spec:
+ version: "11.1.3"
+ license:
+ accept: true
+ secretName: gateway-license
+ app:
+ replicas: 1
+ image: docker.io/caapim/gateway:11.1.3
+ imagePullPolicy: IfNotPresent
+ resources:
+ requests:
+ memory: 8Gi
+ cpu: 3
+ limits:
+ memory: 8Gi
+ cpu: 3
+ # ExternalKeys with otk flag set to true for OTK-specific key usage
+ externalKeys:
+ - name: otk-internal-tls-secret
+ enabled: true
+ alias: otk-internal-key
+ keyUsageType: SSL
+ otk: true
+ otk:
+ enabled: true
+ initContainerImage: docker.io/caapim/otk-install:4.6.4
+ type: internal
+ # Reference to DMZ gateway (can be Gateway name or external hostname)
+ dmzGatewayReference: otk-ssg-dmz
+ # DmzGatewayPort is used when the DMZ gateway is external
+ # If not specified, defaults to 9443 or the gateway's graphmanDynamicSync port
+ dmzGatewayPort: 9443
+ # SyncIntervalSeconds determines how often certificates are synchronized
+ # Defaults to RuntimeSyncIntervalSeconds if not specified, or 10 seconds if neither is set
+ syncIntervalSeconds: 30
+ # Reference to the TLS secret for Internal key
+ internalKeySecret: otk-internal-tls-secret
+ # Auth secret for DMZ gateway communication
+ dmzAuthSecret: otk-dmz-auth-secret
+ database:
+ type: mysql
+ create: true
+ connectionName: OAuth
+ auth:
+ gateway:
+ username: otk_user
+ password: otkUserPass
+ readOnly:
+ username: readonly_user
+ password: readonly_userPass
+ admin:
+ username: admin
+ password: adminPass
+ properties:
+ minimumPoolSize: 3
+ maximumPoolSize: 15
+ sql:
+ databaseName: otk_db
+ jdbcUrl: jdbc:mysql://mysql.brcmlabs.com:3306/otk_db_init
+ jdbcDriverClass: com.mysql.cj.jdbc.Driver
+ connectionProperties:
+ c3p0.maxConnectionAge: "100"
+ c3p0.maxIdleTime: "1000"
+ manageSchema: true
+ databaseWaitTimeout: 60
+ management:
+ secretName: gateway-secret
+ graphman:
+ enabled: true
+ initContainerImage: docker.io/caapim/graphman-static-init:1.0.4
+ cluster:
+ hostname: gateway.brcmlabs.com
+ service:
+ type: ClusterIP
+ ports:
+ - name: https
+ port: 8443
+ targetPort: 8443
+ protocol: TCP
+ - name: management
+ port: 9443
+ targetPort: 9443
+ protocol: TCP
+```
+
+## Key Configuration Fields
+
+### OTK-Specific Fields
+
+| Field | Description | Required | Default |
+|-------|-------------|----------|---------|
+| `otk.enabled` | Enable OTK installation | Yes | `false` |
+| `otk.type` | OTK type: `dmz`, `internal`, or `single` | Yes | - |
+| `otk.initContainerImage` | OTK init container image | Yes | - |
+| `otk.dmzKeySecret` | Reference to TLS secret containing DMZ key/cert | Yes (DMZ) | - |
+| `otk.internalKeySecret` | Reference to TLS secret containing Internal key/cert | Yes (Internal) | - |
+| `otk.dmzAuthSecret` | Reference to secret with DMZ gateway credentials | Yes (Internal) | - |
+| `otk.internalAuthSecret` | Reference to secret with Internal gateway credentials | Yes (DMZ) | - |
+| `otk.dmzGatewayReference` | Reference to DMZ gateway (name or hostname) | Yes (Internal) | - |
+| `otk.internalGatewayReference` | Reference to Internal gateway (name or hostname) | Yes (DMZ) | - |
+| `otk.dmzGatewayPort` | Port for DMZ gateway (when external) | No | `9443` or `graphmanDynamicSync` port |
+| `otk.internalGatewayPort` | Port for Internal gateway (when external) | No | `9443` or `graphmanDynamicSync` port |
+| `otk.syncIntervalSeconds` | Certificate sync interval in seconds | No | `RuntimeSyncIntervalSeconds` or `10` |
+| `otk.port` | OTK port (defaults to 8443) | No | `8443` |
+
+### External Keys Configuration
+
+Both gateways must have `externalKeys` configured with the `otk: true` flag:
+
+```yaml
+externalKeys:
+- name: otk-dmz-tls-secret # or otk-internal-tls-secret
+ enabled: true
+ alias: otk-dmz-key # or otk-internal-key
+ keyUsageType: SSL
+ otk: true # Required for OTK key handling
+```
+
+## Deployment
+
+### 1. Create Secrets
+
+```bash
+cd example/gateway/otk/secrets
+./create-secrets.sh default
+```
+
+### 2. Deploy DMZ Gateway
+
+```bash
+kubectl apply -f example/gateway/otk/otk-ssg-dmz.yaml
+```
+
+### 3. Deploy Internal Gateway
+
+```bash
+kubectl apply -f example/gateway/otk/otk-ssg-internal.yaml
+```
+
+### 4. Verify Deployment
+
+```bash
+# Check gateway pods
+kubectl get pods -l app=gateway
+
+# Check gateway status
+kubectl get gateway otk-ssg-dmz
+kubectl get gateway otk-ssg-internal
+
+# Check logs
+kubectl logs -l app=gateway,gateway-name=otk-ssg-dmz
+kubectl logs -l app=gateway,gateway-name=otk-ssg-internal
+```
+
+## Certificate Synchronization
+
+The operator automatically synchronizes certificates between DMZ and Internal gateways:
+
+1. **DMZ Certificate → Internal Gateway**: When the DMZ certificate is updated, it's automatically published to the Internal gateway as a trusted certificate and used for FIP (Federated Identity Provider) user creation.
+
+2. **Internal Certificate → DMZ Gateway**: When the Internal certificate is updated, it's automatically published to the DMZ gateway as a trusted certificate.
+
+3. **Sync Interval**: Controlled by `syncIntervalSeconds` (default: 10 seconds or `RuntimeSyncIntervalSeconds`).
+
+4. **Key Updates**: When DMZ or Internal keys are updated:
+ - The key is synchronized to the respective gateway
+ - The DMZ private key name is updated in the cluster-wide property `otk.dmz.private_key.name` (DMZ gateway only)
+ - Old certificates are removed before new ones are published
+
+## External Gateway Support
+
+The operator supports scenarios where one or both gateways are external (not managed by the operator):
+
+### External DMZ Gateway
+
+If the DMZ gateway is external, configure the Internal gateway with:
+
+```yaml
+otk:
+ type: internal
+ dmzGatewayReference: external-dmz-gateway.example.com
+ dmzGatewayPort: 9443 # Port for Graphman API
+ dmzAuthSecret: otk-dmz-auth-secret
+```
+
+### External Internal Gateway
+
+If the Internal gateway is external, configure the DMZ gateway with:
+
+```yaml
+otk:
+ type: dmz
+ internalGatewayReference: external-internal-gateway.example.com
+ internalGatewayPort: 9443 # Port for Graphman API
+ internalAuthSecret: otk-internal-auth-secret
+```
+
+### External Gateway Requirements
+
+- Graphman API must be enabled and accessible
+- Authentication credentials must be provided via auth secrets
+- The correct port must be specified if different from default (9443)
+- The gateway must be reachable from the operator's network
+
+## Troubleshooting
+
+### Common Issues
+
+1. **Certificates not synchronizing**
+ - Verify `syncIntervalSeconds` is set appropriately
+ - Check that Graphman is enabled on both gateways
+ - Verify auth secrets are correctly configured
+ - Check operator logs for errors
+
+2. **Gateway communication failures**
+ - Verify gateway references are correct (name or hostname)
+ - Check network connectivity between gateways
+ - Verify ports are correctly configured
+ - Ensure auth secrets contain valid credentials
+
+3. **Key update failures**
+ - Verify TLS secrets are of type `kubernetes.io/tls`
+ - Check that secrets contain both `tls.crt` and `tls.key`
+ - Ensure `externalKeys` have `otk: true` flag
+ - Verify alias matches the expected value
+
+4. **Database connection issues**
+ - Verify database credentials in `otk.database.auth`
+ - Check JDBC URL is correct and accessible
+ - Ensure database exists or `create: true` is set
+ - Verify database wait timeout is sufficient
+
+### Checking Certificate Sync Status
+
+```bash
+# Check annotations for certificate thumbprints
+kubectl get gateway otk-ssg-dmz -o jsonpath='{.metadata.annotations}'
+kubectl get gateway otk-ssg-internal -o jsonpath='{.metadata.annotations}'
+
+# Check cluster-wide properties
+kubectl exec -it -- /opt/SecureSpan/Gateway/node/default/bin/ssgconfig \
+ get cluster-wide-properties | grep otk.dmz.private_key.name
+```
+
+### Operator Logs
+
+```bash
+# View operator logs
+kubectl logs -n -l control-plane=controller-manager
+
+# Filter for OTK-related logs
+kubectl logs -n -l control-plane=controller-manager | grep -i otk
+```
+
+## Additional Resources
+
+- [Layer7 Gateway Operator Documentation](https://github.com/broadcom/layer7-operator)
+- [OAuth Toolkit Documentation](https://techdocs.broadcom.com/us/en/ca-enterprise-software/layer7-api-management/api-gateway/11-1.html)
+- Example configurations: `example/gateway/otk/`
+
+---
+
+**Note**: This configuration guide assumes you have a working Kubernetes cluster with the Layer7 Gateway Operator installed. Adjust namespaces, hostnames, and other values according to your environment.
+
diff --git a/example/otk/single/README.md b/example/otk/single/README.md
index b525c17a..1805ab9c 100644
--- a/example/otk/single/README.md
+++ b/example/otk/single/README.md
@@ -13,15 +13,15 @@ By the end of this example you should have a better understanding of the Layer7
```
3. If you would like to create a TLS secret for your ingress controller then add tls.crt and tls.key to [base/resources/secrets/tls](../base/resources/secrets/tls)
- these will be referenced later on.
-4. You will need an ingress controller like nginx
+4. You will need an ingress controller like contour
- if you do not have one installed already you can use the makefile in the example directory to deploy one
- ```cd example```
- Generic Kubernetes
- - ```make nginx```
+ - ```make contour```
- Kind (Kubernetes in Docker)
- follow the steps in Quickstart
or
- - ```make nginx-kind```
+ - ```make contour-kind```
- return to the previous folder
- ```cd ..```
@@ -38,11 +38,11 @@ cd example
```
make kind-cluster
```
-3. Deploy Nginx (based on your environment)
+3. Deploy Contour (based on your environment)
```
-make nginx
+make contour
or
-make nginx-kind
+make contour-kind
```
4. Deploy the example
```
@@ -382,8 +382,8 @@ Take note of your access_token, you will use that in the next step
```
kubectl get ingress
-NAME CLASS HOSTS ADDRESS PORTS AGE
-ssg nginx gateway.brcmlabs.com,gateway-otk-management.brcmlabs.com or localhost 80, 443 54m
+NAME CLASS HOSTS ADDRESS PORTS AGE
+ssg contour gateway.brcmlabs.com,gateway-otk-management.brcmlabs.com or localhost 80, 443 54m
```
Add the following to your hosts file for DNS resolution
diff --git a/example/portal-integration/portal-values.yaml b/example/portal-integration/portal-values.yaml
index 2a672658..6f7b2098 100644
--- a/example/portal-integration/portal-values.yaml
+++ b/example/portal-integration/portal-values.yaml
@@ -17,16 +17,15 @@ portal:
ingress:
class:
- name: nginx
+ name: contour
enabled: true
type:
- kubernetes: true
+ kubernetes: false
openshift: false
+ contour: true
secretName: dispatcher-tls
create: true
- annotations:
- nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
- nginx.ingress.kubernetes.io/ssl-passthrough: "true"
+ annotations: {}
tenantIds:
- portal
diff --git a/example/portal-integration/readme.md b/example/portal-integration/readme.md
index 2519d69b..fcb03f43 100644
--- a/example/portal-integration/readme.md
+++ b/example/portal-integration/readme.md
@@ -32,19 +32,6 @@ By the end of this example you should have a better understanding of the Layer7
```
***NOTE*** If you are using an existing Kubernetes Cluster you can retrieve the correct address after the Prometheus Stack has been deployed
- ```
- kubectl get ingress
- ```
- output
- ```
- NAME CLASS HOSTS ADDRESS PORTS AGE
- portal-ingress nginx apim-dev-portal.brcmlabs.com,dev-portal-ssg.brcmlabs.com,dev-portal-analytics.brcmlabs.com + 5 more... 80, 443 57m
- ```
- In your hosts file - the ingress address will be the same for the Gateway Ingress record
- ```
- gateway.brcmlabs.com portal.brcmlabs.com apim-dev-portal.brcmlabs.com dev-portal-ssg.brcmlabs.com dev-portal-enroll.brcmlabs.com dev-portal-sync.brcmlabs.com dev-portal-sso.brcmlabs.com dev-portal-analytics.brcmlabs.com dev-portal-broker.brcmlabs.com
- ```
-
- We recommend sticking with the defaults to try out this experimental example as they are used to provision a Portal Tenant
- If you wish to change the default you can do so in [portal-values.yaml](../portal-integration/portal-values.yaml)
- set portal.domain
@@ -56,20 +43,16 @@ By the end of this example you should have a better understanding of the Layer7
```
- Your hosts file will need to use yourportaldomain.com in place of brcmlabs.com
- The [enroll-payload](./enroll-payload.json) will also need to be updated
-6. You will need an ingress controller like nginx
+6. You will need an ingress controller like contour
- if you do not have one installed already you can use the makefile in the example directory to deploy one
- ```cd example```
- Generic Kubernetes
- - ```make nginx```
+ - ```make contour```
- Kind (Kubernetes in Docker)
- follow the steps in [Quickstart](#quickstart)
or
- - ```make nginx-kind```
+ - ```make contour-kind```
- **NOTE:** the Portal requires an ingress controller that supports ssl/tls passthrough for mutual ssl/tls.
- - This will add the following [command line argument](https://kubernetes.github.io/ingress-nginx/user-guide/cli-arguments/) to nginx, in the ingress-nginx namespace. **It has only been tested** deployed with the above commands
- - ```--enable-ssl-passthrough```
- - The following command will edit your nginx deployment
- - ```make configure-nginx-ssl-passthrough```
### Guide
@@ -82,7 +65,7 @@ export NAMESPACE=yournamespace
kubectl config set-context --current --namespace=yournamespace
```
-If you deploy the nginx ingress controller as part of this example, it will use a namespace called ingress-nginx
+If you deploy the contour ingress controller as part of this example, it will use a namespace called projectcontour
* [Quickstart](#quickstart)
* [Using an existing Kubernetes Cluster](#existing-kubernetes-cluster)
@@ -146,17 +129,17 @@ cd example
### Kind
```
-make kind-cluster nginx-kind configure-nginx-ssl-passthrough portal-example
+make kind-cluster contour-kind portal-example
```
### Existing Kubernetes Cluster
-An ingress controller is required for this example, if you don't have an ingress controller you can deploy nginx with the following
+An ingress controller is required for this example, if you don't have an ingress controller you can deploy contour with the following
```
-make nginx configure-nginx-ssl-passthrough
+make contour
```
if you are using kind
```
-make nginx-kind configure-nginx-ssl-passthrough
+make contour-kind
```
Deploy the example components
```
@@ -215,19 +198,7 @@ Enrollment key retrieved
3. Open your tenant gateway and enroll this gateway with the portal using the URL from step 2.
```
**Note** if this step fails, there are two likely scenarios
-1. You have not configured nginx for ssl/tls passthrough. Please see step 4 in [getting-started](#getting-started)
-2. You have not configured your local hosts file. Please see step 6 in [getting-started](#getting-started)
-
-
-
+1. You have not configured your local hosts file. Please see step 6 in [getting-started](#getting-started)
### Deploy the Layer7 Operator
This integration example uses v1.2.2 of the Layer7 Operator
diff --git a/example/repositories/kustomization.yaml b/example/repositories/kustomization.yaml
index 46194a77..903aa370 100644
--- a/example/repositories/kustomization.yaml
+++ b/example/repositories/kustomization.yaml
@@ -6,4 +6,6 @@ resources:
- ./apis-repository.yaml
- ./local-reference-repository.yaml
- ./otk-customizations-single.yaml
+# - ./otk-customizations-dmz.yaml
+# - ./otk-customizations-internal.yaml
- ../base
diff --git a/example/repositories/otk-customizations-dmz.yaml b/example/repositories/otk-customizations-dmz.yaml
new file mode 100644
index 00000000..0b9b755b
--- /dev/null
+++ b/example/repositories/otk-customizations-dmz.yaml
@@ -0,0 +1,10 @@
+apiVersion: security.brcmlabs.com/v1
+kind: Repository
+metadata:
+ name: otk-customizations-dmz
+spec:
+ enabled: true
+ endpoint: https://github.com/Layer7-Community/otk-customizations-dmz
+ branch: main
+ type: git
+ auth: {}
\ No newline at end of file
diff --git a/example/repositories/otk-customizations-internal.yaml b/example/repositories/otk-customizations-internal.yaml
new file mode 100644
index 00000000..2cfca944
--- /dev/null
+++ b/example/repositories/otk-customizations-internal.yaml
@@ -0,0 +1,10 @@
+apiVersion: security.brcmlabs.com/v1
+kind: Repository
+metadata:
+ name: otk-customizations-internal
+spec:
+ enabled: true
+ endpoint: https://github.com/Layer7-Community/otk-customizations-internal
+ branch: main
+ type: git
+ auth: {}
\ No newline at end of file
diff --git a/internal/controller/gateway/controller.go b/internal/controller/gateway/controller.go
index 1ee34b0b..a23c13b8 100644
--- a/internal/controller/gateway/controller.go
+++ b/internal/controller/gateway/controller.go
@@ -111,12 +111,12 @@ func (r *GatewayReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct
}
if gw.Spec.App.Otk.Enabled {
- if gw.Spec.App.Otk.Type == securityv1.OtkTypeDMZ || gw.Spec.App.Otk.Type == securityv1.OtkTypeInternal {
- ops = append(ops, ReconcileOperations{reconcile.ScheduledJobs, "scheduled jobs"})
- }
if gw.Spec.App.Otk.Type == securityv1.OtkTypeSingle && !gw.Spec.App.Management.Database.Enabled {
ops = append(ops, ReconcileOperations{reconcile.OTKDatabaseMaintenanceTasks, "otk-db-maintenance-tasks"})
}
+ if gw.Spec.App.Otk.Type == securityv1.OtkTypeInternal && len(gw.Spec.App.Otk.FipsCertificates) > 0 {
+ ops = append(ops, ReconcileOperations{reconcile.OtkFipsCerts, "otk-fips-certs"})
+ }
}
params := reconcile.Params{
@@ -236,6 +236,11 @@ func (r *GatewayReconciler) SetupWithManager(mgr ctrl.Manager) error {
req = append(req, creconcile.Request{NamespacedName: types.NamespacedName{Namespace: gateway.Namespace, Name: gateway.Name}})
}
}
+ // if gateway.Spec.App.Otk.Enabled {
+ // if gateway.Spec.App.Otk.DmzKeySecret == a.GetName() || gateway.Spec.App.Otk.InternalKeySecret == a.GetName() {
+ // req = append(req, creconcile.Request{NamespacedName: types.NamespacedName{Namespace: gateway.Namespace, Name: gateway.Name}})
+ // }
+ // }
}
return req
}),
diff --git a/pkg/gateway/deployment.go b/pkg/gateway/deployment.go
index d16fd90a..4a4709ba 100644
--- a/pkg/gateway/deployment.go
+++ b/pkg/gateway/deployment.go
@@ -826,6 +826,25 @@ func NewDeployment(gw *securityv1.Gateway, platform string) *appsv1.Deployment {
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
})
+
+ if OtkOverrideBundleRequired(gw) {
+ otkOverrideBundleName := gw.Name + "-otk-override-bundle"
+ volumeMounts = append(volumeMounts, corev1.VolumeMount{
+ Name: otkOverrideBundleName,
+ MountPath: "/opt/SecureSpan/Gateway/node/default/etc/bootstrap/bundle/001OTK",
+ })
+ volumes = append(volumes, corev1.Volume{
+ Name: otkOverrideBundleName,
+ VolumeSource: corev1.VolumeSource{
+ Secret: &corev1.SecretVolumeSource{
+ SecretName: otkOverrideBundleName,
+ DefaultMode: &defaultMode,
+ Optional: &optional,
+ },
+ },
+ })
+ }
+
if gw.Spec.App.Otk.Database.Type == securityv1.OtkDatabaseTypeMySQL || gw.Spec.App.Otk.Database.Type == securityv1.OtkDatabaseTypeOracle {
if gw.Spec.App.Otk.Database.Create {
otkDbInitContainer = true
@@ -834,37 +853,40 @@ func NewDeployment(gw *securityv1.Gateway, platform string) *appsv1.Deployment {
}
if otkInstallInitContainer {
- initContainers = append(initContainers, corev1.Container{
- Name: "otk-install-init",
- Image: otkInitContainerImage,
- ImagePullPolicy: otkInitContainerImagePullPolicy,
- SecurityContext: &otkInitContainerSecurityContext,
- VolumeMounts: otkInitContainerVolumeMounts,
- EnvFrom: []corev1.EnvFromSource{
- {
- ConfigMapRef: &corev1.ConfigMapEnvSource{
- LocalObjectReference: corev1.LocalObjectReference{
- Name: gw.Name + "-otk-shared-init-config",
- },
+ otkInstallEnvFrom := []corev1.EnvFromSource{
+ {
+ ConfigMapRef: &corev1.ConfigMapEnvSource{
+ LocalObjectReference: corev1.LocalObjectReference{
+ Name: gw.Name + "-otk-shared-init-config",
},
},
- {
- ConfigMapRef: &corev1.ConfigMapEnvSource{
- LocalObjectReference: corev1.LocalObjectReference{
- Name: gw.Name + "-otk-install-init-config",
- },
- Optional: &optional,
+ },
+ {
+ ConfigMapRef: &corev1.ConfigMapEnvSource{
+ LocalObjectReference: corev1.LocalObjectReference{
+ Name: gw.Name + "-otk-install-init-config",
},
+ Optional: &optional,
},
- {
- SecretRef: &corev1.SecretEnvSource{
- LocalObjectReference: corev1.LocalObjectReference{
- Name: otkInitContainerSecret,
- },
- Optional: &optional,
+ },
+ }
+ if gw.Spec.App.Otk.Type != securityv1.OtkTypeDMZ {
+ otkInstallEnvFrom = append(otkInstallEnvFrom, corev1.EnvFromSource{
+ SecretRef: &corev1.SecretEnvSource{
+ LocalObjectReference: corev1.LocalObjectReference{
+ Name: otkInitContainerSecret,
},
+ Optional: &optional,
},
- },
+ })
+ }
+ initContainers = append(initContainers, corev1.Container{
+ Name: "otk-install-init",
+ Image: otkInitContainerImage,
+ ImagePullPolicy: otkInitContainerImagePullPolicy,
+ SecurityContext: &otkInitContainerSecurityContext,
+ VolumeMounts: otkInitContainerVolumeMounts,
+ EnvFrom: otkInstallEnvFrom,
TerminationMessagePath: corev1.TerminationMessagePathDefault,
TerminationMessagePolicy: corev1.TerminationMessageReadFile,
})
diff --git a/pkg/gateway/reconcile/cron.go b/pkg/gateway/reconcile/cron.go
deleted file mode 100644
index 979c54f7..00000000
--- a/pkg/gateway/reconcile/cron.go
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
-* Copyright (c) 2025 Broadcom. All rights reserved.
-* The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
-* All trademarks, trade names, service marks, and logos referenced
-* herein belong to their respective companies.
-*
-* This software and all information contained therein is confidential
-* and proprietary and shall not be duplicated, used, disclosed or
-* disseminated in any way except as authorized by the applicable
-* license agreement, without the express written permission of Broadcom.
-* All authorized reproductions must be marked with this language.
-*
-* EXCEPT AS SET FORTH IN THE APPLICABLE LICENSE AGREEMENT, TO THE
-* EXTENT PERMITTED BY APPLICABLE LAW OR AS AGREED BY BROADCOM IN ITS
-* APPLICABLE LICENSE AGREEMENT, BROADCOM PROVIDES THIS DOCUMENTATION
-* "AS IS" WITHOUT WARRANTY OF ANY KIND, INCLUDING WITHOUT LIMITATION,
-* ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-* PURPOSE, OR. NONINFRINGEMENT. IN NO EVENT WILL BROADCOM BE LIABLE TO
-* THE END USER OR ANY THIRD PARTY FOR ANY LOSS OR DAMAGE, DIRECT OR
-* INDIRECT, FROM THE USE OF THIS DOCUMENTATION, INCLUDING WITHOUT LIMITATION,
-* LOST PROFITS, LOST INVESTMENT, BUSINESS INTERRUPTION, GOODWILL, OR
-* LOST DATA, EVEN IF BROADCOM IS EXPRESSLY ADVISED IN ADVANCE OF THE
-* POSSIBILITY OF SUCH LOSS OR DAMAGE.
-*
- */
-package reconcile
-
-import (
- "context"
- "time"
-
- securityv1 "github.com/caapim/layer7-operator/api/v1"
- "github.com/caapim/layer7-operator/pkg/util"
- "github.com/go-co-op/gocron"
-)
-
-var s = gocron.NewScheduler(time.Local)
-var syncCache = util.NewSyncCache(3 * time.Second)
-
-func ScheduledJobs(ctx context.Context, params Params) error {
-
- registerJobs(ctx, params)
-
- for _, j := range s.Jobs() {
- for _, t := range j.Tags() {
- if !j.IsRunning() {
- params.Log.V(2).Info("starting job", "job", t, "namespace", params.Instance.Namespace)
- err := s.RunByTag(t)
- if err != nil {
- params.Log.V(2).Info("no job with given tag", "job", t, "namespace", params.Instance.Namespace)
- }
- }
- }
- }
- if !s.IsRunning() {
- s.StartAsync()
- }
- return nil
-}
-
-func registerJobs(ctx context.Context, params Params) {
- s.TagsUnique()
- otkSyncInterval := 10
-
- if params.Instance.Spec.App.Otk.RuntimeSyncIntervalSeconds != 0 {
- otkSyncInterval = params.Instance.Spec.App.Otk.RuntimeSyncIntervalSeconds
- }
-
- if params.Instance.Spec.App.Otk.Enabled && (params.Instance.Spec.App.Otk.Type == securityv1.OtkTypeDMZ || params.Instance.Spec.App.Otk.Type == securityv1.OtkTypeInternal) {
- _, err := s.Every(otkSyncInterval).Seconds().Tag(params.Instance.Name+"-sync-otk-policies").Do(syncOtkPolicies, ctx, params)
-
- if err != nil {
- params.Log.V(2).Info("otk policy sync job already registered", "name", params.Instance.Name, "namespace", params.Instance.Namespace)
- }
- if params.Instance.Spec.App.Otk.Type == securityv1.OtkTypeDMZ || params.Instance.Spec.App.Otk.Type == securityv1.OtkTypeInternal {
- _, err = s.Every(otkSyncInterval).Seconds().Tag(params.Instance.Name+"-"+params.Instance.Namespace+"-sync-otk-certificates").Do(syncOtkCertificates, ctx, params)
- if err != nil {
- params.Log.V(2).Info("otk certificate sync job already registered", "name", params.Instance.Name, "namespace", params.Instance.Namespace)
- }
- _, err = s.Every(otkSyncInterval).Seconds().Tag(params.Instance.Name+"-"+params.Instance.Namespace+"-sync-otk-certificate-secret").Do(manageCertificateSecrets, ctx, params)
- if err != nil {
- params.Log.V(2).Info("otk certificate secret sync job already registered", "name", params.Instance.Name, "namespace", params.Instance.Namespace)
- }
- }
- }
-}
-
-func removeJob(tag string) error {
- err := s.RemoveByTag(tag)
- if err != nil {
- return err
- }
- return nil
-}
diff --git a/pkg/gateway/reconcile/deployment.go b/pkg/gateway/reconcile/deployment.go
index eb72bc03..bd1166e5 100644
--- a/pkg/gateway/reconcile/deployment.go
+++ b/pkg/gateway/reconcile/deployment.go
@@ -357,6 +357,18 @@ func setLabels(ctx context.Context, params Params, dep *appsv1.Deployment) (*app
}
}
}
+
+ if gateway.OtkOverrideBundleRequired(params.Instance) {
+ otkOverrideSecretName := params.Instance.Name + "-otk-override-bundle"
+ secret := corev1.Secret{}
+ err := params.Client.Get(ctx, types.NamespacedName{Name: otkOverrideSecretName, Namespace: params.Instance.Namespace}, &secret)
+ if err == nil {
+ if checksum, ok := secret.ObjectMeta.Annotations["checksum/data"]; ok {
+ dep.ObjectMeta.Labels[otkOverrideSecretName+"-checksum"] = checksum
+ }
+ }
+ }
+
commits := ""
for _, repoRef := range params.Instance.Spec.App.RepositoryReferences {
for _, repoStatus := range params.Instance.Status.RepositoryStatus {
diff --git a/pkg/gateway/reconcile/externalkeys.go b/pkg/gateway/reconcile/externalkeys.go
index de07af50..3192ec9d 100644
--- a/pkg/gateway/reconcile/externalkeys.go
+++ b/pkg/gateway/reconcile/externalkeys.go
@@ -32,6 +32,7 @@ import (
func ExternalKeys(ctx context.Context, params Params) error {
gateway := params.Instance
+
if len(gateway.Spec.App.ExternalKeys) == 0 && len(gateway.Status.LastAppliedExternalKeys) == 0 {
return nil
}
diff --git a/pkg/gateway/reconcile/gateway.go b/pkg/gateway/reconcile/gateway.go
index f01acbc3..28b9a6e2 100644
--- a/pkg/gateway/reconcile/gateway.go
+++ b/pkg/gateway/reconcile/gateway.go
@@ -96,6 +96,7 @@ const (
BundleTypeClusterProp BundleType = "cluster properties"
BundleTypeListenPort BundleType = "listen ports"
BundleTypeOTKDatabaseMaintenance BundleType = "otk db maintenance"
+ BundleTypeOTKFips BundleType = "otk fips"
)
type GatewayUpdateRequestOpt func(*GatewayUpdateRequest)
@@ -107,6 +108,8 @@ type MappingSource struct {
ThumbprintSha1 string `json:"thumbprintSha1,omitempty"`
}
+var syncCache = util.NewSyncCache(3 * time.Second)
+
func NewGwUpdateRequest(ctx context.Context, gateway *securityv1.Gateway, params Params, opts ...GatewayUpdateRequestOpt) (*GatewayUpdateRequest, error) {
graphmanPort := 9443
if gateway.Spec.App.Management.Graphman.DynamicSyncPort != 0 {
@@ -500,6 +503,7 @@ func NewGwUpdateRequest(ctx context.Context, gateway *securityv1.Gateway, params
found := false
for _, ek := range gateway.Spec.App.ExternalKeys {
if k == ek.Alias && ek.Enabled {
+ // Only process non-OTK keys in regular external keys flow
found = true
}
}
@@ -512,6 +516,7 @@ func NewGwUpdateRequest(ctx context.Context, gateway *securityv1.Gateway, params
for _, externalKey := range gateway.Spec.App.ExternalKeys {
if externalKey.Enabled {
+ // Skip keys with otk: true - they are handled separately by OTK reconciliation
secret, err := getGatewaySecret(ctx, params, externalKey.Name)
if err != nil {
return nil, err
@@ -693,6 +698,107 @@ func NewGwUpdateRequest(ctx context.Context, gateway *securityv1.Gateway, params
gwUpdReq.graphmanEncryptionPassphrase = ""
gwUpdReq.bundleName = string(gwUpdReq.bundleType)
gwUpdReq.externalEntities = externalSecrets
+ case BundleTypeOTKFips:
+ otkFipsCerts := []ExternalEntity{}
+
+ for k, v := range gateway.Status.LastAppliedOtkFipsCerts {
+ found := false
+ for _, fc := range gateway.Spec.App.Otk.FipsCertificates {
+ if k == fc.Name {
+ found = true
+ }
+ }
+ if !found {
+ bundleBytes, err := util.BuildFipUserDeleteBundle(v)
+ if err != nil {
+ return nil, err
+ }
+ annotation := "security.brcmlabs.com/otk-fips-certs-" + k
+ otkFipsCerts = append(otkFipsCerts, ExternalEntity{
+ Name: k,
+ Annotation: annotation,
+ Bundle: bundleBytes,
+ Checksum: "deleted",
+ CacheEntry: gateway.Name + "-" + string(gwUpdReq.bundleType) + "-" + k + "-deleted",
+ })
+ }
+ }
+
+ for _, fipsCert := range gateway.Spec.App.Otk.FipsCertificates {
+ if !fipsCert.Enabled {
+ continue
+ }
+
+ var sha1Sum string
+ var leafCerts []util.FipUserCert
+
+ switch strings.ToLower(fipsCert.Type) {
+ case "secret":
+ secret, err := getGatewaySecret(ctx, params, fipsCert.Name)
+ if err != nil {
+ return nil, err
+ }
+ leafCerts = util.ExtractLeafCertsFromSecret(secret)
+ dataBytes, _ := json.Marshal(&secret.Data)
+ h := sha1.New()
+ h.Write(dataBytes)
+ sha1Sum = fmt.Sprintf("%x", h.Sum(nil))
+ case "configmap":
+ cm, err := getGatewayConfigMap(ctx, params, fipsCert.Name)
+ if err != nil {
+ return nil, err
+ }
+ leafCerts = util.ExtractLeafCertsFromConfigMap(cm)
+ dataBytes, _ := json.Marshal(&cm.Data)
+ h := sha1.New()
+ h.Write(dataBytes)
+ sha1Sum = fmt.Sprintf("%x", h.Sum(nil))
+ default:
+ params.Log.V(2).Info("unsupported fips certificate source type", "type", fipsCert.Type, "name", fipsCert.Name)
+ continue
+ }
+
+ notFound := []string{}
+ if gateway.Status.LastAppliedOtkFipsCerts != nil && gateway.Status.LastAppliedOtkFipsCerts[fipsCert.Name] != nil {
+ for _, appliedCert := range gateway.Status.LastAppliedOtkFipsCerts[fipsCert.Name] {
+ found := false
+ for _, desired := range leafCerts {
+ if appliedCert == desired.SubjectDn {
+ found = true
+ }
+ }
+ if !found {
+ notFound = append(notFound, appliedCert)
+ }
+ }
+ }
+
+ if len(leafCerts) < 1 && len(notFound) < 1 {
+ continue
+ }
+
+ bundleBytes, err := util.BuildFipUserBundle(leafCerts, notFound)
+ if err != nil {
+ return nil, err
+ }
+
+ if sha1Sum == "" {
+ sha1Sum = "deleted"
+ }
+
+ annotation := "security.brcmlabs.com/otk-fips-certs-" + fipsCert.Name
+ otkFipsCerts = append(otkFipsCerts, ExternalEntity{
+ Name: fipsCert.Name,
+ Annotation: annotation,
+ Bundle: bundleBytes,
+ Checksum: sha1Sum,
+ CacheEntry: gateway.Name + "-" + string(gwUpdReq.bundleType) + "-" + fipsCert.Name + "-" + sha1Sum,
+ })
+ }
+
+ gwUpdReq.graphmanEncryptionPassphrase = ""
+ gwUpdReq.bundleName = string(gwUpdReq.bundleType)
+ gwUpdReq.externalEntities = otkFipsCerts
}
return gwUpdReq, nil
@@ -2607,6 +2713,48 @@ func updateEntityStatus(ctx context.Context, kind string, name string, bundleByt
if err := params.Client.Status().Update(ctx, params.Instance); err != nil {
return fmt.Errorf("failed to update external cert status: %w", err)
}
+ case "otk fips":
+ bundle := graphman.Bundle{}
+ err := json.Unmarshal(bundleBytes, &bundle)
+ if err != nil {
+ return err
+ }
+ fipUsers := []string{}
+ if params.Instance.Status.LastAppliedOtkFipsCerts == nil {
+ for _, fipUser := range bundle.FipUsers {
+ fipUsers = append(fipUsers, fipUser.SubjectDn)
+ }
+ } else {
+ for _, appliedFipUser := range bundle.FipUsers {
+ found := false
+ if bundle.Properties != nil {
+ for _, mapping := range bundle.Properties.Mappings.FipUsers {
+ mappingSource := MappingSource{}
+ sourceBytes, err := json.Marshal(mapping.Source)
+ if err != nil {
+ return err
+ }
+ err = json.Unmarshal(sourceBytes, &mappingSource)
+ if err != nil {
+ return err
+ }
+ if appliedFipUser.SubjectDn == mappingSource.Name && mapping.Action == graphman.MappingActionDelete {
+ found = true
+ }
+ }
+ }
+ if !found {
+ fipUsers = append(fipUsers, appliedFipUser.SubjectDn)
+ }
+ }
+ }
+ if params.Instance.Status.LastAppliedOtkFipsCerts == nil {
+ params.Instance.Status.LastAppliedOtkFipsCerts = map[string][]string{}
+ }
+ params.Instance.Status.LastAppliedOtkFipsCerts[name] = fipUsers
+ if err := params.Client.Status().Update(ctx, params.Instance); err != nil {
+ return fmt.Errorf("failed to update otk fips cert status: %w", err)
+ }
}
return nil
diff --git a/pkg/gateway/reconcile/l7otkcertificates.go b/pkg/gateway/reconcile/l7otkcertificates.go
deleted file mode 100644
index c290f3f5..00000000
--- a/pkg/gateway/reconcile/l7otkcertificates.go
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
-* Copyright (c) 2025 Broadcom. All rights reserved.
-* The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
-* All trademarks, trade names, service marks, and logos referenced
-* herein belong to their respective companies.
-*
-* This software and all information contained therein is confidential
-* and proprietary and shall not be duplicated, used, disclosed or
-* disseminated in any way except as authorized by the applicable
-* license agreement, without the express written permission of Broadcom.
-* All authorized reproductions must be marked with this language.
-*
-* EXCEPT AS SET FORTH IN THE APPLICABLE LICENSE AGREEMENT, TO THE
-* EXTENT PERMITTED BY APPLICABLE LAW OR AS AGREED BY BROADCOM IN ITS
-* APPLICABLE LICENSE AGREEMENT, BROADCOM PROVIDES THIS DOCUMENTATION
-* "AS IS" WITHOUT WARRANTY OF ANY KIND, INCLUDING WITHOUT LIMITATION,
-* ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-* PURPOSE, OR. NONINFRINGEMENT. IN NO EVENT WILL BROADCOM BE LIABLE TO
-* THE END USER OR ANY THIRD PARTY FOR ANY LOSS OR DAMAGE, DIRECT OR
-* INDIRECT, FROM THE USE OF THIS DOCUMENTATION, INCLUDING WITHOUT LIMITATION,
-* LOST PROFITS, LOST INVESTMENT, BUSINESS INTERRUPTION, GOODWILL, OR
-* LOST DATA, EVEN IF BROADCOM IS EXPRESSLY ADVISED IN ADVANCE OF THE
-* POSSIBILITY OF SUCH LOSS OR DAMAGE.
-*
- */
-package reconcile
-
-import (
- "context"
- "crypto/tls"
- "encoding/base64"
- "encoding/json"
- "strconv"
-
- securityv1 "github.com/caapim/layer7-operator/api/v1"
- "github.com/caapim/layer7-operator/internal/graphman"
- "github.com/caapim/layer7-operator/pkg/gateway"
- corev1 "k8s.io/api/core/v1"
- k8serrors "k8s.io/apimachinery/pkg/api/errors"
- "k8s.io/apimachinery/pkg/types"
-)
-
-func syncOtkCertificates(ctx context.Context, params Params) {
- gateway := &securityv1.Gateway{}
- err := params.Client.Get(ctx, types.NamespacedName{Name: params.Instance.Name, Namespace: params.Instance.Namespace}, gateway)
- if err != nil && k8serrors.IsNotFound(err) {
- params.Log.Error(err, "gateway not found", "name", params.Instance.Name, "namespace", params.Instance.Namespace)
- _ = removeJob(params.Instance.Name + "-" + params.Instance.Namespace + "-sync-otk-certificates")
- return
- }
-
- if !gateway.Spec.App.Otk.Enabled {
- _ = removeJob(params.Instance.Name + "-" + params.Instance.Namespace + "-sync-otk-certificates")
- return
- }
-
- err = applyOtkCertificates(ctx, params, gateway)
- if err != nil {
- params.Log.Info("failed to reconcile otk certificates", "name", gateway.Name, "namespace", gateway.Namespace, "error", err.Error())
- }
-}
-
-func applyOtkCertificates(ctx context.Context, params Params, gateway *securityv1.Gateway) error {
-
- bundle := graphman.Bundle{}
- annotation := ""
- sha1Sum := ""
-
- switch gateway.Spec.App.Otk.Type {
- case securityv1.OtkTypeDMZ:
- internalSecret, err := getGatewaySecret(ctx, params, gateway.Spec.App.Otk.InternalOtkGatewayReference+"-otk-internal-certificates")
- sha1Sum = internalSecret.ObjectMeta.Annotations["checksum/data"]
-
- if err != nil {
- return err
- }
- annotation = "security.brcmlabs.com/" + gateway.Name + "-" + string(gateway.Spec.App.Otk.Type) + "-certificates"
- for k, v := range internalSecret.Data {
- bundle.TrustedCerts = append(bundle.TrustedCerts, &graphman.TrustedCertInput{
- Name: k,
- CertBase64: base64.StdEncoding.EncodeToString(v),
- TrustAnchor: true,
- VerifyHostname: false,
- RevocationCheckPolicyType: "USE_DEFAULT",
- TrustedFor: []graphman.TrustedForType{
- "SSL",
- "SIGNING_SERVER_CERTS",
- },
- })
- }
-
- case securityv1.OtkTypeInternal:
- dmzSecret, err := getGatewaySecret(ctx, params, gateway.Spec.App.Otk.DmzOtkGatewayReference+"-otk-dmz-certificates")
- sha1Sum = dmzSecret.ObjectMeta.Annotations["checksum/data"]
- if err != nil {
- return err
- }
- annotation = "security.brcmlabs.com/" + gateway.Name + "-" + string(gateway.Spec.App.Otk.Type) + "-fips-users"
- for k, v := range dmzSecret.Data {
- bundle.FipUsers = append(bundle.FipUsers, &graphman.FipUserInput{
- Name: k,
- ProviderName: "otk-fips-provider",
- SubjectDn: "cn=" + k,
- CertBase64: base64.RawStdEncoding.EncodeToString(v),
- })
- }
- }
-
- bundleBytes, err := json.Marshal(bundle)
- if err != nil {
- return err
- }
-
- name := gateway.Name
- if gateway.Spec.App.Management.SecretName != "" {
- name = gateway.Spec.App.Management.SecretName
- }
- gwSecret, err := getGatewaySecret(ctx, params, name)
-
- if err != nil {
- return err
- }
-
- if !gateway.Spec.App.Management.Database.Enabled {
- podList, err := getGatewayPods(ctx, params)
- if err != nil {
- return err
- }
- err = ReconcileEphemeralGateway(ctx, params, "otk certificates", *podList, gateway, gwSecret, "", annotation, sha1Sum, true, "otk certificates", bundleBytes)
- if err != nil {
- return err
- }
- } else {
- gatewayDeployment, err := getGatewayDeployment(ctx, params)
- if err != nil {
- return err
- }
- err = ReconcileDBGateway(ctx, params, "otk certificates", *gatewayDeployment, gateway, gwSecret, "", annotation, sha1Sum, false, "otk certificates", bundleBytes)
- if err != nil {
- return err
- }
- }
-
- return nil
-}
-
-func manageCertificateSecrets(ctx context.Context, params Params) {
- gw := &securityv1.Gateway{}
- err := params.Client.Get(ctx, types.NamespacedName{Name: params.Instance.Name, Namespace: params.Instance.Namespace}, gw)
- if err != nil && k8serrors.IsNotFound(err) {
- params.Log.Error(err, "gateway not found", "name", params.Instance.Name, "namespace", params.Instance.Namespace)
- _ = removeJob(params.Instance.Name + "-sync-otk-certificate-secret")
- return
- }
-
- if !gw.Spec.App.Otk.Enabled {
- _ = removeJob(params.Instance.Name + "-sync-otk-certificate-secret")
- return
- }
- params.Instance = gw
- internalGatewayPort := 9443
- defaultOtkPort := 8443
- rawInternalCertList := map[string][]byte{}
- rawDMZCertList := map[string][]byte{}
- desiredSecrets := []*corev1.Secret{}
- if gw.Spec.App.Management.Graphman.DynamicSyncPort != 0 {
- internalGatewayPort = gw.Spec.App.Management.Graphman.DynamicSyncPort
-
- }
-
- if gw.Spec.App.Otk.InternalGatewayPort != 0 {
- internalGatewayPort = gw.Spec.App.Otk.InternalGatewayPort
- }
-
- if gw.Spec.App.Otk.OTKPort != 0 {
- defaultOtkPort = gw.Spec.App.Otk.OTKPort
- }
- podList, err := getGatewayPods(ctx, params)
- if err != nil {
- params.Log.Error(err, "failed to retrieve gateway pods", "name", params.Instance.Name, "namespace", params.Instance.Namespace)
- return
- }
-
- for _, pod := range podList.Items {
- for _, containerStatus := range pod.Status.ContainerStatuses {
- if containerStatus.Name == "gateway" {
- if !containerStatus.Ready {
- params.Log.V(2).Info("pod not ready", "pod", pod.Name, "name", params.Instance.Name, "namespace", params.Instance.Namespace)
- return
- }
- }
- }
-
- switch gw.Spec.App.Otk.Type {
- case securityv1.OtkTypeDMZ:
- rawCert, err := retrieveCertificate(pod.Status.PodIP, strconv.Itoa(defaultOtkPort))
- if err != nil {
- params.Log.Error(err, "failed to retrieve certificate", "pod", pod.Name, "name", params.Instance.Name, "namespace", params.Instance.Namespace)
- return
- }
- if len(rawDMZCertList) > 0 {
- for _, cert := range rawDMZCertList {
- if string(rawCert) != string(cert) {
- rawDMZCertList[pod.Name] = rawCert
- }
- }
- } else {
- rawDMZCertList[pod.Name] = rawCert
- }
- case securityv1.OtkTypeInternal:
- rawCert, err := retrieveCertificate(pod.Status.PodIP, strconv.Itoa(internalGatewayPort))
- if err != nil {
- params.Log.Error(err, "failed to retrieve certificate", "pod", pod.Name, "name", params.Instance.Name, "namespace", params.Instance.Namespace)
- return
- }
- if len(rawInternalCertList) > 0 {
- for _, cert := range rawInternalCertList {
- if string(rawCert) != string(cert) {
- rawInternalCertList[pod.Name] = rawCert
- }
- }
- } else {
- rawInternalCertList[pod.Name] = rawCert
- }
-
- }
- }
-
- if gw.Spec.App.Otk.Type == securityv1.OtkTypeDMZ && len(rawDMZCertList) > 0 {
- desiredSecrets = append(desiredSecrets, gateway.NewOtkCertificateSecret(gw, gw.Name+"-otk-dmz-certificates", rawDMZCertList))
- }
-
- if gw.Spec.App.Otk.Type == securityv1.OtkTypeInternal && len(rawInternalCertList) > 0 {
- desiredSecrets = append(desiredSecrets, gateway.NewOtkCertificateSecret(gw, gw.Name+"-otk-internal-certificates", rawInternalCertList))
- }
-
- err = reconcileSecrets(ctx, params, desiredSecrets)
- if err != nil {
- params.Log.Error(err, "failed to reconcile otk certificates", "Name", gw.Name, "namespace", gw.Namespace)
- return
- }
-
-}
-
-func retrieveCertificate(host string, port string) ([]byte, error) {
- conf := &tls.Config{
- InsecureSkipVerify: true,
- }
-
- conn, err := tls.Dial("tcp", host+":"+port, conf)
- if err != nil {
- return nil, err
- }
- defer conn.Close()
- cert := conn.ConnectionState().PeerCertificates[0].Raw
- return cert, nil
-}
diff --git a/pkg/gateway/reconcile/l7otkpolicies.go b/pkg/gateway/reconcile/l7otkpolicies.go
deleted file mode 100644
index 7e9b2f66..00000000
--- a/pkg/gateway/reconcile/l7otkpolicies.go
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
-* Copyright (c) 2025 Broadcom. All rights reserved.
-* The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
-* All trademarks, trade names, service marks, and logos referenced
-* herein belong to their respective companies.
-*
-* This software and all information contained therein is confidential
-* and proprietary and shall not be duplicated, used, disclosed or
-* disseminated in any way except as authorized by the applicable
-* license agreement, without the express written permission of Broadcom.
-* All authorized reproductions must be marked with this language.
-*
-* EXCEPT AS SET FORTH IN THE APPLICABLE LICENSE AGREEMENT, TO THE
-* EXTENT PERMITTED BY APPLICABLE LAW OR AS AGREED BY BROADCOM IN ITS
-* APPLICABLE LICENSE AGREEMENT, BROADCOM PROVIDES THIS DOCUMENTATION
-* "AS IS" WITHOUT WARRANTY OF ANY KIND, INCLUDING WITHOUT LIMITATION,
-* ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
-* PURPOSE, OR. NONINFRINGEMENT. IN NO EVENT WILL BROADCOM BE LIABLE TO
-* THE END USER OR ANY THIRD PARTY FOR ANY LOSS OR DAMAGE, DIRECT OR
-* INDIRECT, FROM THE USE OF THIS DOCUMENTATION, INCLUDING WITHOUT LIMITATION,
-* LOST PROFITS, LOST INVESTMENT, BUSINESS INTERRUPTION, GOODWILL, OR
-* LOST DATA, EVEN IF BROADCOM IS EXPRESSLY ADVISED IN ADVANCE OF THE
-* POSSIBILITY OF SUCH LOSS OR DAMAGE.
-*
- */
-package reconcile
-
-import (
- "context"
- "strconv"
- "strings"
-
- securityv1 "github.com/caapim/layer7-operator/api/v1"
- "github.com/caapim/layer7-operator/pkg/util"
- k8serrors "k8s.io/apimachinery/pkg/api/errors"
- "k8s.io/apimachinery/pkg/types"
-)
-
-func syncOtkPolicies(ctx context.Context, params Params) {
- gateway := &securityv1.Gateway{}
- err := params.Client.Get(ctx, types.NamespacedName{Name: params.Instance.Name, Namespace: params.Instance.Namespace}, gateway)
- if err != nil && k8serrors.IsNotFound(err) {
- params.Log.Error(err, "gateway not found", "name", params.Instance.Name, "namespace", params.Instance.Namespace)
- _ = removeJob(params.Instance.Name + "-" + params.Instance.Namespace + "-sync-otk-policies")
- return
- }
-
- if !gateway.Spec.App.Otk.Enabled {
- _ = removeJob(params.Instance.Name + "-" + params.Instance.Namespace + "-sync-otk-policies")
- return
- }
-
- params.Instance = gateway
-
- err = applyOtkPolicies(ctx, params, gateway)
- if err != nil {
- params.Log.Error(err, "failed to reconcile otk policies", "name", gateway.Name, "namespace", gateway.Namespace)
- }
-
-}
-
-func applyOtkPolicies(ctx context.Context, params Params, gateway *securityv1.Gateway) error {
- internalGatewayPort := 9443
- defaultOtkPort := 8443
- if gateway.Spec.App.Management.Graphman.DynamicSyncPort != 0 {
- internalGatewayPort = gateway.Spec.App.Management.Graphman.DynamicSyncPort
- }
-
- if gateway.Spec.App.Otk.OTKPort != 0 {
- defaultOtkPort = gateway.Spec.App.Otk.OTKPort
- }
-
- var gatewayHost string
- switch gateway.Spec.App.Otk.Type {
- case securityv1.OtkTypeDMZ:
- // TODO: open this to internal gateways that are fully external or in a different namespace
- // This routes via 9443 or the management port by default
- if gateway.Spec.App.Otk.InternalGatewayPort != 0 {
- internalGatewayPort = gateway.Spec.App.Otk.InternalGatewayPort
- }
- gatewayHost = "https://" + gateway.Spec.App.Otk.InternalOtkGatewayReference + ":" + strconv.Itoa(internalGatewayPort)
- case securityv1.OtkTypeInternal:
- gatewayHost = "https://" + gateway.Name + ":" + strconv.Itoa(defaultOtkPort)
- }
-
- bundle, sha1Sum, err := util.BuildOtkOverrideBundle(strings.ToUpper(string(gateway.Spec.App.Otk.Type)), gatewayHost, defaultOtkPort)
- if err != nil {
- return err
- }
-
- name := gateway.Name
- if gateway.Spec.App.Management.SecretName != "" {
- name = gateway.Spec.App.Management.SecretName
- }
- gwSecret, err := getGatewaySecret(ctx, params, name)
-
- if err != nil {
- return err
- }
-
- annotation := "security.brcmlabs.com/" + gateway.Name + "-" + string(gateway.Spec.App.Otk.Type) + "-policies"
-
- if !gateway.Spec.App.Management.Database.Enabled {
- podList, err := getGatewayPods(ctx, params)
- if err != nil {
- return err
- }
- err = ReconcileEphemeralGateway(ctx, params, "otk policies", *podList, gateway, gwSecret, "", annotation, sha1Sum, false, "otk policies", bundle)
- if err != nil {
- return err
- }
- } else {
- gatewayDeployment, err := getGatewayDeployment(ctx, params)
- if err != nil {
- return err
- }
- err = ReconcileDBGateway(ctx, params, "otk policies", *gatewayDeployment, gateway, gwSecret, "", annotation, sha1Sum, false, "otk policies", bundle)
- if err != nil {
- return err
- }
- }
-
- return nil
-}
diff --git a/pkg/gateway/reconcile/otkfipscerts.go b/pkg/gateway/reconcile/otkfipscerts.go
new file mode 100644
index 00000000..99aa7f42
--- /dev/null
+++ b/pkg/gateway/reconcile/otkfipscerts.go
@@ -0,0 +1,69 @@
+/*
+* Copyright (c) 2025 Broadcom. All rights reserved.
+* The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
+* All trademarks, trade names, service marks, and logos referenced
+* herein belong to their respective companies.
+*
+* This software and all information contained therein is confidential
+* and proprietary and shall not be duplicated, used, disclosed or
+* disseminated in any way except as authorized by the applicable
+* license agreement, without the express written permission of Broadcom.
+* All authorized reproductions must be marked with this language.
+*
+* EXCEPT AS SET FORTH IN THE APPLICABLE LICENSE AGREEMENT, TO THE
+* EXTENT PERMITTED BY APPLICABLE LAW OR AS AGREED BY BROADCOM IN ITS
+* APPLICABLE LICENSE AGREEMENT, BROADCOM PROVIDES THIS DOCUMENTATION
+* "AS IS" WITHOUT WARRANTY OF ANY KIND, INCLUDING WITHOUT LIMITATION,
+* ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+* PURPOSE, OR. NONINFRINGEMENT. IN NO EVENT WILL BROADCOM BE LIABLE TO
+* THE END USER OR ANY THIRD PARTY FOR ANY LOSS OR DAMAGE, DIRECT OR
+* INDIRECT, FROM THE USE OF THIS DOCUMENTATION, INCLUDING WITHOUT LIMITATION,
+* LOST PROFITS, LOST INVESTMENT, BUSINESS INTERRUPTION, GOODWILL, OR
+* LOST DATA, EVEN IF BROADCOM IS EXPRESSLY ADVISED IN ADVANCE OF THE
+* POSSIBILITY OF SUCH LOSS OR DAMAGE.
+*
+* AI assistance has been used to generate some or all contents of this file. That includes, but is not limited to, new code, modifying existing code, stylistic edits.
+ */
+package reconcile
+
+import (
+ "context"
+)
+
+func OtkFipsCerts(ctx context.Context, params Params) error {
+ gateway := params.Instance
+ if len(gateway.Spec.App.Otk.FipsCertificates) == 0 {
+ if len(gateway.Status.LastAppliedOtkFipsCerts) == 0 {
+ return nil
+ }
+ }
+
+ gwUpdReq, err := NewGwUpdateRequest(
+ ctx,
+ gateway,
+ params,
+ WithBundleType(BundleTypeOTKFips),
+ )
+
+ if err != nil {
+ return err
+ }
+
+ if gwUpdReq == nil {
+ return nil
+ }
+
+ for _, fipsCert := range gwUpdReq.externalEntities {
+ fipsCertUpdReq := gwUpdReq
+ fipsCertUpdReq.bundle = fipsCert.Bundle
+ fipsCertUpdReq.bundleName = fipsCert.Name
+ fipsCertUpdReq.checksum = fipsCert.Checksum
+ fipsCertUpdReq.cacheEntry = fipsCert.CacheEntry
+ fipsCertUpdReq.patchAnnotation = fipsCert.Annotation
+ err = SyncGateway(ctx, params, *fipsCertUpdReq)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/pkg/gateway/reconcile/secret.go b/pkg/gateway/reconcile/secret.go
index 14849c3e..abfe989c 100644
--- a/pkg/gateway/reconcile/secret.go
+++ b/pkg/gateway/reconcile/secret.go
@@ -1,3 +1,29 @@
+/*
+* Copyright (c) 2025 Broadcom. All rights reserved.
+* The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
+* All trademarks, trade names, service marks, and logos referenced
+* herein belong to their respective companies.
+*
+* This software and all information contained therein is confidential
+* and proprietary and shall not be duplicated, used, disclosed or
+* disseminated in any way except as authorized by the applicable
+* license agreement, without the express written permission of Broadcom.
+* All authorized reproductions must be marked with this language.
+*
+* EXCEPT AS SET FORTH IN THE APPLICABLE LICENSE AGREEMENT, TO THE
+* EXTENT PERMITTED BY APPLICABLE LAW OR AS AGREED BY BROADCOM IN ITS
+* APPLICABLE LICENSE AGREEMENT, BROADCOM PROVIDES THIS DOCUMENTATION
+* "AS IS" WITHOUT WARRANTY OF ANY KIND, INCLUDING WITHOUT LIMITATION,
+* ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+* PURPOSE, OR. NONINFRINGEMENT. IN NO EVENT WILL BROADCOM BE LIABLE TO
+* THE END USER OR ANY THIRD PARTY FOR ANY LOSS OR DAMAGE, DIRECT OR
+* INDIRECT, FROM THE USE OF THIS DOCUMENTATION, INCLUDING WITHOUT LIMITATION,
+* LOST PROFITS, LOST INVESTMENT, BUSINESS INTERRUPTION, GOODWILL, OR
+* LOST DATA, EVEN IF BROADCOM IS EXPRESSLY ADVISED IN ADVANCE OF THE
+* POSSIBILITY OF SUCH LOSS OR DAMAGE.
+*
+* AI assistance has been used to generate some or all contents of this file. That includes, but is not limited to, new code, modifying existing code, stylistic edits.
+ */
package reconcile
import (
@@ -45,6 +71,16 @@ func Secrets(ctx context.Context, params Params) error {
desiredSecrets = append(desiredSecrets, desiredSecret)
}
+ if gateway.OtkOverrideBundleRequired(params.Instance) {
+ desiredSecret, err := gateway.NewOtkOverrideBundleSecret(params.Instance)
+ if err != nil {
+ return err
+ }
+ if desiredSecret != nil {
+ desiredSecrets = append(desiredSecrets, desiredSecret)
+ }
+ }
+
if err := reconcileSecrets(ctx, params, desiredSecrets); err != nil {
return fmt.Errorf("failed to reconcile secrets: %w", err)
}
diff --git a/pkg/gateway/secrets.go b/pkg/gateway/secrets.go
index 9d4fb811..81d5f6ff 100644
--- a/pkg/gateway/secrets.go
+++ b/pkg/gateway/secrets.go
@@ -1,3 +1,29 @@
+/*
+* Copyright (c) 2025 Broadcom. All rights reserved.
+* The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
+* All trademarks, trade names, service marks, and logos referenced
+* herein belong to their respective companies.
+*
+* This software and all information contained therein is confidential
+* and proprietary and shall not be duplicated, used, disclosed or
+* disseminated in any way except as authorized by the applicable
+* license agreement, without the express written permission of Broadcom.
+* All authorized reproductions must be marked with this language.
+*
+* EXCEPT AS SET FORTH IN THE APPLICABLE LICENSE AGREEMENT, TO THE
+* EXTENT PERMITTED BY APPLICABLE LAW OR AS AGREED BY BROADCOM IN ITS
+* APPLICABLE LICENSE AGREEMENT, BROADCOM PROVIDES THIS DOCUMENTATION
+* "AS IS" WITHOUT WARRANTY OF ANY KIND, INCLUDING WITHOUT LIMITATION,
+* ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+* PURPOSE, OR. NONINFRINGEMENT. IN NO EVENT WILL BROADCOM BE LIABLE TO
+* THE END USER OR ANY THIRD PARTY FOR ANY LOSS OR DAMAGE, DIRECT OR
+* INDIRECT, FROM THE USE OF THIS DOCUMENTATION, INCLUDING WITHOUT LIMITATION,
+* LOST PROFITS, LOST INVESTMENT, BUSINESS INTERRUPTION, GOODWILL, OR
+* LOST DATA, EVEN IF BROADCOM IS EXPRESSLY ADVISED IN ADVANCE OF THE
+* POSSIBILITY OF SUCH LOSS OR DAMAGE.
+*
+* AI assistance has been used to generate some or all contents of this file. That includes, but is not limited to, new code, modifying existing code, stylistic edits.
+ */
package gateway
import (
@@ -5,6 +31,7 @@ import (
"encoding/json"
"fmt"
"regexp"
+ "strings"
securityv1 "github.com/caapim/layer7-operator/api/v1"
"github.com/caapim/layer7-operator/pkg/util"
@@ -253,6 +280,85 @@ func NewSecret(gw *securityv1.Gateway, name string) (*corev1.Secret, error) {
return secret, nil
}
+func OtkOverrideBundleRequired(gw *securityv1.Gateway) bool {
+ if !gw.Spec.App.Otk.Enabled {
+ return false
+ }
+ if gw.Spec.App.Otk.Type == securityv1.OtkTypeInternal || gw.Spec.App.Otk.Type == securityv1.OtkTypeDMZ {
+ return true
+ }
+ if gw.Spec.App.ClusterProperties.Enabled {
+ for _, p := range gw.Spec.App.ClusterProperties.Properties {
+ if p.Name == "otk.port" {
+ return false
+ }
+ }
+ }
+ return true
+}
+
+func NewOtkOverrideBundleSecret(gw *securityv1.Gateway) (*corev1.Secret, error) {
+ if !OtkOverrideBundleRequired(gw) {
+ return nil, nil
+ }
+
+ otkPort := 8443
+ if gw.Spec.App.Otk.OTKPort != 0 {
+ otkPort = gw.Spec.App.Otk.OTKPort
+ }
+
+ includeOtkPort := true
+ if gw.Spec.App.ClusterProperties.Enabled {
+ for _, p := range gw.Spec.App.ClusterProperties.Properties {
+ if p.Name == "otk.port" {
+ includeOtkPort = false
+ break
+ }
+ }
+ }
+
+ mode := strings.ToUpper(string(gw.Spec.App.Otk.Type))
+ gatewayHost := ""
+ switch gw.Spec.App.Otk.Type {
+ case securityv1.OtkTypeInternal:
+ gatewayHost = gw.Spec.App.Otk.DmzOTKGateway.Url
+ if gw.Spec.App.Otk.DmzOTKGateway.Port != 0 {
+ otkPort = gw.Spec.App.Otk.DmzOTKGateway.Port
+ }
+ case securityv1.OtkTypeDMZ:
+ gatewayHost = gw.Spec.App.Otk.InternalOTKGateway.Url
+ if gw.Spec.App.Otk.InternalOTKGateway.Port != 0 {
+ otkPort = gw.Spec.App.Otk.InternalOTKGateway.Port
+ }
+ }
+
+ bundleBytes, checksum, err := util.BuildOtkOverrideBundle(mode, gatewayHost, otkPort, includeOtkPort)
+ if err != nil {
+ return nil, err
+ }
+
+ data := map[string][]byte{
+ "otk-override-bundle.json": bundleBytes,
+ }
+
+ secret := &corev1.Secret{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: gw.Name + "-otk-override-bundle",
+ Namespace: gw.Namespace,
+ Labels: util.DefaultLabels(gw.Name, gw.Spec.App.Labels),
+ Annotations: map[string]string{"checksum/data": checksum},
+ },
+ TypeMeta: metav1.TypeMeta{
+ APIVersion: "v1",
+ Kind: "Secret",
+ },
+ Type: corev1.SecretTypeOpaque,
+ Data: data,
+ }
+
+ return secret, nil
+}
+
func NewOtkCertificateSecret(gw *securityv1.Gateway, name string, data map[string][]byte) *corev1.Secret {
dataBytes, _ := json.Marshal(data)
h := sha1.New()
diff --git a/pkg/util/graphman.go b/pkg/util/graphman.go
index cabd1049..ae807363 100644
--- a/pkg/util/graphman.go
+++ b/pkg/util/graphman.go
@@ -49,6 +49,7 @@ import (
"time"
graphman "github.com/caapim/layer7-operator/internal/graphman"
+ corev1 "k8s.io/api/core/v1"
)
const fipsProviderGuid = "41e5cacd15f86758f03ff2952616d4f3"
@@ -567,9 +568,20 @@ func BuildAndValidateBundle(path string, processNestedRepos bool) (bundleBytes [
return bundleBytes, nil
}
-func BuildOtkOverrideBundle(mode string, gatewayHost string, otkPort int) ([]byte, string, error) {
+func BuildOtkOverrideBundle(mode string, gatewayHost string, otkPort int, includeOtkPort bool) ([]byte, string, error) {
var bundle graphman.Bundle
var policyXml []byte
+
+ appendOtkPort := func() {
+ if includeOtkPort {
+ bundle.ClusterProperties = append(bundle.ClusterProperties, &graphman.ClusterPropertyInput{
+ Name: "otk.port",
+ Value: strconv.Itoa(otkPort),
+ Description: "OTK Port",
+ })
+ }
+ }
+
switch mode {
case "INTERNAL":
for _, internalPolicy := range internalPolicies {
@@ -596,6 +608,7 @@ func BuildOtkOverrideBundle(mode string, gatewayHost string, otkPort int) ([]byt
})
}
}
+ appendOtkPort()
bundle.FederatedIdps = append(bundle.FederatedIdps, &graphman.FederatedIdpInput{
Name: "otk-fips-provider",
@@ -630,12 +643,9 @@ func BuildOtkOverrideBundle(mode string, gatewayHost string, otkPort int) ([]byt
})
}
}
+ appendOtkPort()
case "SINGLE":
- bundle.ClusterProperties = append(bundle.ClusterProperties, &graphman.ClusterPropertyInput{
- Name: "otk.port",
- Value: strconv.Itoa(otkPort),
- Description: "OTK Port",
- })
+ appendOtkPort()
default:
return nil, "", fmt.Errorf("invalid otk installation type %s. Valid types are single, dmz and internal", mode)
}
@@ -809,3 +819,160 @@ func getSha1Thumbprint(rawCert []byte) (string, error) {
// bundle.Keys = append(bundle.Keys, &gmanKey)
// }
+
+type FipUserCert struct {
+ SubjectDn string
+ CertBase64 string
+ Name string
+}
+
+func ExtractLeafCertsFromSecret(secret *corev1.Secret) []FipUserCert {
+ var certs []FipUserCert
+
+ if secret.Type == corev1.SecretTypeTLS {
+ if tlsCrt, ok := secret.Data["tls.crt"]; ok {
+ if cert := extractFirstLeafCert(tlsCrt); cert != nil {
+ certs = append(certs, *cert)
+ }
+ }
+ return certs
+ }
+
+ for _, v := range secret.Data {
+ if !strings.Contains(string(v), "-----BEGIN CERTIFICATE-----") {
+ continue
+ }
+ if cert := extractFirstLeafCert(v); cert != nil {
+ certs = append(certs, *cert)
+ }
+ }
+ return certs
+}
+
+func ExtractLeafCertsFromConfigMap(cm *corev1.ConfigMap) []FipUserCert {
+ var certs []FipUserCert
+ for k, v := range cm.Data {
+ if !strings.HasSuffix(k, ".crt") {
+ continue
+ }
+ if !strings.Contains(v, "-----BEGIN CERTIFICATE-----") {
+ continue
+ }
+ certs = append(certs, extractAllCerts([]byte(v))...)
+ }
+ return certs
+}
+
+func extractFirstLeafCert(pemData []byte) *FipUserCert {
+ block, _ := pem.Decode(pemData)
+ if block == nil {
+ return nil
+ }
+ crtX509, err := x509.ParseCertificate(block.Bytes)
+ if err != nil {
+ return nil
+ }
+ return &FipUserCert{
+ SubjectDn: strings.ToLower(crtX509.Subject.String()),
+ CertBase64: base64.StdEncoding.EncodeToString(block.Bytes),
+ Name: crtX509.Subject.CommonName,
+ }
+}
+
+func extractAllCerts(pemData []byte) []FipUserCert {
+ var certs []FipUserCert
+ rest := pemData
+ for {
+ var block *pem.Block
+ block, rest = pem.Decode(rest)
+ if block == nil {
+ break
+ }
+ crtX509, err := x509.ParseCertificate(block.Bytes)
+ if err != nil {
+ continue
+ }
+ certs = append(certs, FipUserCert{
+ SubjectDn: strings.ToLower(crtX509.Subject.String()),
+ CertBase64: base64.StdEncoding.EncodeToString(block.Bytes),
+ Name: crtX509.Subject.CommonName,
+ })
+ }
+ return certs
+}
+
+func cnFromSubjectDn(dn string) string {
+ upper := strings.ToUpper(dn)
+ if strings.HasPrefix(upper, "CN=") {
+ return dn[3:]
+ }
+ for _, part := range strings.Split(dn, ",") {
+ part = strings.TrimSpace(part)
+ if strings.HasPrefix(strings.ToUpper(part), "CN=") {
+ return part[3:]
+ }
+ }
+ return dn
+}
+
+func BuildFipUserBundle(certs []FipUserCert, notFound []string) ([]byte, error) {
+ bundle := graphman.Bundle{}
+
+ for _, cert := range certs {
+ bundle.FipUsers = append(bundle.FipUsers, &graphman.FipUserInput{
+ Name: cert.Name,
+ ProviderName: "otk-fips-provider",
+ SubjectDn: cert.SubjectDn,
+ CertBase64: cert.CertBase64,
+ Login: cert.Name,
+ })
+ }
+
+ if len(notFound) > 0 {
+ bundle.Properties = &graphman.BundleProperties{}
+ for _, subjectDn := range notFound {
+ login := cnFromSubjectDn(subjectDn)
+ bundle.FipUsers = append(bundle.FipUsers, &graphman.FipUserInput{
+ Name: login,
+ ProviderName: "otk-fips-provider",
+ SubjectDn: subjectDn,
+ Login: login,
+ })
+ bundle.Properties.Mappings.FipUsers = append(bundle.Properties.Mappings.FipUsers, &graphman.MappingInstructionInput{
+ Action: graphman.MappingActionDelete,
+ Source: graphman.MappingSource{Name: login},
+ })
+ }
+ }
+
+ bundleBytes, err := json.Marshal(bundle)
+ if err != nil {
+ return nil, err
+ }
+ return bundleBytes, nil
+}
+
+func BuildFipUserDeleteBundle(subjectDns []string) ([]byte, error) {
+ bundle := graphman.Bundle{}
+ bundle.Properties = &graphman.BundleProperties{}
+
+ for _, subjectDn := range subjectDns {
+ login := cnFromSubjectDn(subjectDn)
+ bundle.FipUsers = append(bundle.FipUsers, &graphman.FipUserInput{
+ Name: login,
+ ProviderName: "otk-fips-provider",
+ SubjectDn: subjectDn,
+ Login: login,
+ })
+ bundle.Properties.Mappings.FipUsers = append(bundle.Properties.Mappings.FipUsers, &graphman.MappingInstructionInput{
+ Action: graphman.MappingActionDelete,
+ Source: graphman.MappingSource{Name: login},
+ })
+ }
+
+ bundleBytes, err := json.Marshal(bundle)
+ if err != nil {
+ return nil, err
+ }
+ return bundleBytes, nil
+}