From 30ad2bae7f511f4180985b2d88be7564f7a39c3f Mon Sep 17 00:00:00 2001 From: Elliott Baron Date: Tue, 13 Feb 2024 09:57:22 -0500 Subject: [PATCH] feat(api): combine Cryostat and ClusterCryostat CRDs (#721) * feat(api): combine Cryostat and ClusterCryostat CRDs * Make webhook internal, add tests * Add v1beta2 apiVersion with conversion webhook * Add conversion webhook tests * Run multi-namespace tests for Cryostat CRD * Formatting, generate bundle * Enable conversion webhooks * add conversion webhook to bundle, fixes * Remove log message * Update spec descriptors patch and initialization resource --------- Signed-off-by: Elliott Baron --- Dockerfile | 1 + PROJECT | 32 +- api/v1beta1/clustercryostat_conversion.go | 62 + api/v1beta1/clustercryostat_types.go | 1 - api/v1beta1/cryostat_conversion.go | 590 ++ api/v1beta1/cryostat_conversion_test.go | 146 + api/v1beta1/cryostat_suite_test.go | 27 + api/v1beta1/cryostat_types.go | 1 - api/v1beta2/clustercryostat_conversion.go | 24 + api/v1beta2/clustercryostat_types.go | 70 + api/v1beta2/cryostat_conversion.go | 22 + api/v1beta2/cryostat_types.go | 559 ++ api/v1beta2/groupversion_info.go | 34 + api/v1beta2/zz_generated.deepcopy.go | 893 ++++ ...t-operator-webhook-service_v1_service.yaml | 21 + ...yostat-operator.clusterserviceversion.yaml | 983 +++- ...operator.cryostat.io_clustercryostats.yaml | 4726 +++++++++++++++++ .../operator.cryostat.io_cryostats.yaml | 4721 ++++++++++++++++ ...operator.cryostat.io_clustercryostats.yaml | 4715 ++++++++++++++++ .../bases/operator.cryostat.io_cryostats.yaml | 4710 ++++++++++++++++ config/crd/kustomization.yaml | 8 +- config/crd/patches/webhook_in_cryostats.yaml | 2 + config/default/kustomization.yaml | 55 +- config/default/manager_webhook_patch.yaml | 23 + config/default/webhookcainjection_patch.yaml | 29 + ...yostat-operator.clusterserviceversion.yaml | 833 ++- config/manifests/targetNamespaces_patch.yaml | 32 + config/rbac/role.yaml | 6 + config/samples/kustomization.yaml | 2 + .../operator_v1beta2_clustercryostat.yaml | 16 + config/samples/operator_v1beta2_cryostat.yaml | 16 + config/webhook/kustomization.yaml | 6 + config/webhook/kustomizeconfig.yaml | 25 + config/webhook/manifests.yaml | 54 + config/webhook/service.yaml | 20 + internal/controllers/certmanager.go | 29 +- .../controllers/clustercryostat_controller.go | 6 +- .../clustercryostat_controller_test.go | 106 - internal/controllers/common/common_utils.go | 13 +- .../resource_definitions/certificates.go | 10 +- internal/controllers/cryostat_controller.go | 6 +- internal/controllers/ingresses.go | 24 +- internal/controllers/model/instance.go | 16 +- internal/controllers/pvc.go | 10 +- internal/controllers/rbac.go | 30 +- internal/controllers/reconciler_test.go | 223 +- internal/controllers/routes.go | 20 +- internal/controllers/services.go | 24 +- internal/main.go | 23 + internal/test/conversion.go | 638 +++ internal/test/resources.go | 161 +- internal/webhooks/cryostat_webhook.go | 44 + internal/webhooks/defaulter.go | 46 + internal/webhooks/test/resources.go | 72 + internal/webhooks/validator.go | 128 + internal/webhooks/validator_test.go | 199 + internal/webhooks/webhook_suite_test.go | 137 + 57 files changed, 25033 insertions(+), 397 deletions(-) create mode 100644 api/v1beta1/clustercryostat_conversion.go create mode 100644 api/v1beta1/cryostat_conversion.go create mode 100644 api/v1beta1/cryostat_conversion_test.go create mode 100644 api/v1beta1/cryostat_suite_test.go create mode 100644 api/v1beta2/clustercryostat_conversion.go create mode 100644 api/v1beta2/clustercryostat_types.go create mode 100644 api/v1beta2/cryostat_conversion.go create mode 100644 api/v1beta2/cryostat_types.go create mode 100644 api/v1beta2/groupversion_info.go create mode 100644 api/v1beta2/zz_generated.deepcopy.go create mode 100644 bundle/manifests/cryostat-operator-webhook-service_v1_service.yaml create mode 100644 config/default/manager_webhook_patch.yaml create mode 100644 config/default/webhookcainjection_patch.yaml create mode 100644 config/samples/operator_v1beta2_clustercryostat.yaml create mode 100644 config/samples/operator_v1beta2_cryostat.yaml create mode 100644 config/webhook/kustomization.yaml create mode 100644 config/webhook/kustomizeconfig.yaml create mode 100644 config/webhook/manifests.yaml create mode 100644 config/webhook/service.yaml create mode 100644 internal/test/conversion.go create mode 100644 internal/webhooks/cryostat_webhook.go create mode 100644 internal/webhooks/defaulter.go create mode 100644 internal/webhooks/test/resources.go create mode 100644 internal/webhooks/validator.go create mode 100644 internal/webhooks/validator_test.go create mode 100644 internal/webhooks/webhook_suite_test.go diff --git a/Dockerfile b/Dockerfile index a50eb94d6..d62951b64 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,6 +15,7 @@ RUN go mod download COPY internal/main.go internal/main.go COPY api/ api/ COPY internal/controllers/ internal/controllers/ +COPY internal/webhooks/ internal/webhooks/ # Build # the GOARCH has not a default value to allow the binary be built according to the host where the command diff --git a/PROJECT b/PROJECT index 79b5f32d3..9c30663a2 100644 --- a/PROJECT +++ b/PROJECT @@ -1,3 +1,7 @@ +# Code generated by tool. DO NOT EDIT. +# This file is used to track the info used to scaffold your project +# and allow the plugins properly work. +# More info: https://book.kubebuilder.io/reference/project-config.html domain: cryostat.io layout: - go.kubebuilder.io/v3 @@ -10,7 +14,6 @@ resources: - api: crdVersion: v1 namespaced: true - controller: true domain: cryostat.io group: operator kind: Cryostat @@ -19,10 +22,35 @@ resources: - api: crdVersion: v1 namespaced: false - controller: true domain: cryostat.io group: operator kind: ClusterCryostat path: github.com/cryostatio/cryostat-operator/api/v1beta1 version: v1beta1 +- api: + crdVersion: v1 + namespaced: true + controller: true + domain: cryostat.io + group: operator + kind: Cryostat + path: github.com/cryostatio/cryostat-operator/api/v1beta2 + version: v1beta2 + webhooks: + conversion: true + defaulting: true + validation: true + webhookVersion: v1 +- api: + crdVersion: v1 + namespaced: false + controller: true + domain: cryostat.io + group: operator + kind: ClusterCryostat + path: github.com/cryostatio/cryostat-operator/api/v1beta2 + version: v1beta2 + webhooks: + conversion: true + webhookVersion: v1 version: "3" diff --git a/api/v1beta1/clustercryostat_conversion.go b/api/v1beta1/clustercryostat_conversion.go new file mode 100644 index 000000000..cb7cb194c --- /dev/null +++ b/api/v1beta1/clustercryostat_conversion.go @@ -0,0 +1,62 @@ +// Copyright The Cryostat Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1beta1 + +import ( + operatorv1beta2 "github.com/cryostatio/cryostat-operator/api/v1beta2" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +// TODO Remove this file with ClusterCryostat CRD + +var _ conversion.Convertible = &ClusterCryostat{} + +// ConvertTo converts this ClusterCryostat to the Hub version (v1beta2). +func (src *ClusterCryostat) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*operatorv1beta2.ClusterCryostat) + + // Copy ObjectMeta as-is + dst.ObjectMeta = src.ObjectMeta + + // Convert existing Spec fields + convertSpecTo(&src.Spec.CryostatSpec, &dst.Spec.CryostatSpec) + dst.Spec.InstallNamespace = src.Spec.InstallNamespace + dst.Spec.TargetNamespaces = src.Spec.TargetNamespaces + + // Convert existing Status fields + convertStatusTo(&src.Status.CryostatStatus, &dst.Status.CryostatStatus) + dst.Status.TargetNamespaces = src.Spec.TargetNamespaces + + return nil +} + +// ConvertFrom converts from the Hub version (v1beta2) to this version. +func (dst *ClusterCryostat) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*operatorv1beta2.ClusterCryostat) + + // Copy ObjectMeta as-is + dst.ObjectMeta = src.ObjectMeta + + // Convert existing Spec fields + convertSpecFrom(&src.Spec.CryostatSpec, &dst.Spec.CryostatSpec) + dst.Spec.InstallNamespace = src.Spec.InstallNamespace + dst.Spec.TargetNamespaces = src.Spec.TargetNamespaces + + // Convert existing Status fields + convertStatusFrom(&src.Status.CryostatStatus, &dst.Status.CryostatStatus) + dst.Status.TargetNamespaces = src.Spec.TargetNamespaces + + return nil +} diff --git a/api/v1beta1/clustercryostat_types.go b/api/v1beta1/clustercryostat_types.go index 39190d9b4..6628164a5 100644 --- a/api/v1beta1/clustercryostat_types.go +++ b/api/v1beta1/clustercryostat_types.go @@ -49,7 +49,6 @@ type ClusterCryostatStatus struct { // +kubebuilder:object:root=true // +kubebuilder:subresource:status -// +kubebuilder:storageversion // +kubebuilder:resource:path=clustercryostats,scope=Cluster // ClusterCryostat allows you to install Cryostat for multiple namespaces or cluster-wide. diff --git a/api/v1beta1/cryostat_conversion.go b/api/v1beta1/cryostat_conversion.go new file mode 100644 index 000000000..bf6a7d73d --- /dev/null +++ b/api/v1beta1/cryostat_conversion.go @@ -0,0 +1,590 @@ +// Copyright The Cryostat Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1beta1 + +import ( + operatorv1beta2 "github.com/cryostatio/cryostat-operator/api/v1beta2" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +var _ conversion.Convertible = &Cryostat{} + +// ConvertTo converts this Cryostat to the Hub version (v1beta2). +func (src *Cryostat) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*operatorv1beta2.Cryostat) + + // Copy ObjectMeta as-is + dst.ObjectMeta = src.ObjectMeta + + // Convert existing Spec fields + convertSpecTo(&src.Spec, &dst.Spec) + + // Convert existing Status fields + convertStatusTo(&src.Status, &dst.Status) + + // Maintain the previous behaviour by using the CR's namespace as the sole target namespace + dst.Spec.TargetNamespaces = []string{src.Namespace} + dst.Status.TargetNamespaces = []string{src.Namespace} + + return nil +} + +func convertSpecTo(src *CryostatSpec, dst *operatorv1beta2.CryostatSpec) { + dst.Minimal = src.Minimal + dst.EnableCertManager = src.EnableCertManager + dst.TrustedCertSecrets = convertCertSecretsTo(src.TrustedCertSecrets) + dst.EventTemplates = convertEventTemplatesTo(src.EventTemplates) + dst.StorageOptions = convertStorageOptionsTo(src.StorageOptions) + dst.ServiceOptions = convertServiceOptionsTo(src.ServiceOptions) + dst.NetworkOptions = convertNetworkOptionsTo(src.NetworkOptions) + dst.ReportOptions = convertReportOptionsTo(src.ReportOptions) + dst.MaxWsConnections = src.MaxWsConnections + dst.JmxCacheOptions = convertJmxCacheOptionsTo(src.JmxCacheOptions) + dst.Resources = convertResourceOptionsTo(src.Resources) + dst.AuthProperties = convertAuthPropertiesTo(src.AuthProperties) + dst.SecurityOptions = convertSecurityOptionsTo(src.SecurityOptions) + dst.SchedulingOptions = convertSchedulingOptionsTo(src.SchedulingOptions) + dst.TargetDiscoveryOptions = convertTargetDiscoveryTo(src.TargetDiscoveryOptions) + dst.JmxCredentialsDatabaseOptions = convertDatabaseOptionsTo(src.JmxCredentialsDatabaseOptions) + dst.OperandMetadata = convertOperandMetadataTo(src.OperandMetadata) +} + +func convertStatusTo(src *CryostatStatus, dst *operatorv1beta2.CryostatStatus) { + dst.ApplicationURL = src.ApplicationURL + dst.Conditions = src.Conditions + dst.GrafanaSecret = src.GrafanaSecret +} + +func convertCertSecretsTo(srcCerts []CertificateSecret) []operatorv1beta2.CertificateSecret { + var dstCerts []operatorv1beta2.CertificateSecret + if srcCerts != nil { + dstCerts = make([]operatorv1beta2.CertificateSecret, 0, len(srcCerts)) + for _, cert := range srcCerts { + dstCerts = append(dstCerts, operatorv1beta2.CertificateSecret{ + SecretName: cert.SecretName, + CertificateKey: cert.CertificateKey, + }) + } + } + return dstCerts +} + +func convertEventTemplatesTo(srcTemplates []TemplateConfigMap) []operatorv1beta2.TemplateConfigMap { + var dstTemplates []operatorv1beta2.TemplateConfigMap + if srcTemplates != nil { + dstTemplates = make([]operatorv1beta2.TemplateConfigMap, 0, len(srcTemplates)) + for _, template := range srcTemplates { + dstTemplates = append(dstTemplates, operatorv1beta2.TemplateConfigMap{ + ConfigMapName: template.ConfigMapName, + Filename: template.Filename, + }) + } + } + return dstTemplates +} + +func convertStorageOptionsTo(srcOpts *StorageConfiguration) *operatorv1beta2.StorageConfiguration { + var dstOpts *operatorv1beta2.StorageConfiguration + if srcOpts != nil { + dstOpts = &operatorv1beta2.StorageConfiguration{} + if srcOpts.PVC != nil { + dstOpts.PVC = &operatorv1beta2.PersistentVolumeClaimConfig{ + Annotations: srcOpts.PVC.Annotations, + Labels: srcOpts.PVC.Labels, + Spec: srcOpts.PVC.Spec, + } + } + if srcOpts.EmptyDir != nil { + dstOpts.EmptyDir = &operatorv1beta2.EmptyDirConfig{ + Enabled: srcOpts.EmptyDir.Enabled, + Medium: srcOpts.EmptyDir.Medium, + SizeLimit: srcOpts.EmptyDir.SizeLimit, + } + } + } + return dstOpts +} + +func convertServiceOptionsTo(srcOpts *ServiceConfigList) *operatorv1beta2.ServiceConfigList { + var dstOpts *operatorv1beta2.ServiceConfigList + if srcOpts != nil { + dstOpts = &operatorv1beta2.ServiceConfigList{} + if srcOpts.CoreConfig != nil { + dstOpts.CoreConfig = &operatorv1beta2.CoreServiceConfig{ + HTTPPort: srcOpts.CoreConfig.HTTPPort, + JMXPort: srcOpts.CoreConfig.JMXPort, + ServiceConfig: convertServiceConfigTo(srcOpts.CoreConfig.ServiceConfig), + } + } + if srcOpts.GrafanaConfig != nil { + dstOpts.GrafanaConfig = &operatorv1beta2.GrafanaServiceConfig{ + HTTPPort: srcOpts.GrafanaConfig.HTTPPort, + ServiceConfig: convertServiceConfigTo(srcOpts.GrafanaConfig.ServiceConfig), + } + } + if srcOpts.ReportsConfig != nil { + dstOpts.ReportsConfig = &operatorv1beta2.ReportsServiceConfig{ + HTTPPort: srcOpts.ReportsConfig.HTTPPort, + ServiceConfig: convertServiceConfigTo(srcOpts.ReportsConfig.ServiceConfig), + } + } + } + return dstOpts +} + +func convertServiceConfigTo(srcConfig ServiceConfig) operatorv1beta2.ServiceConfig { + return operatorv1beta2.ServiceConfig{ + ServiceType: srcConfig.ServiceType, + Annotations: srcConfig.Annotations, + Labels: srcConfig.Labels, + } +} + +func convertNetworkOptionsTo(srcOpts *NetworkConfigurationList) *operatorv1beta2.NetworkConfigurationList { + var dstOpts *operatorv1beta2.NetworkConfigurationList + if srcOpts != nil { + dstOpts = &operatorv1beta2.NetworkConfigurationList{ + CoreConfig: convertNetworkConfigTo(srcOpts.CoreConfig), + GrafanaConfig: convertNetworkConfigTo(srcOpts.GrafanaConfig), + CommandConfig: convertNetworkConfigTo(srcOpts.CommandConfig), // TODO Remove this from v1beta2 API + } + } + return dstOpts +} + +func convertNetworkConfigTo(srcConfig *NetworkConfiguration) *operatorv1beta2.NetworkConfiguration { + var dstConfig *operatorv1beta2.NetworkConfiguration + if srcConfig != nil { + dstConfig = &operatorv1beta2.NetworkConfiguration{ + IngressSpec: srcConfig.IngressSpec, + Annotations: srcConfig.Annotations, + Labels: srcConfig.Labels, + } + } + return dstConfig +} + +func convertReportOptionsTo(srcOpts *ReportConfiguration) *operatorv1beta2.ReportConfiguration { + var dstOpts *operatorv1beta2.ReportConfiguration + if srcOpts != nil { + var dstSecurityOpts *operatorv1beta2.ReportsSecurityOptions + if srcOpts.SecurityOptions != nil { + dstSecurityOpts = &operatorv1beta2.ReportsSecurityOptions{ + PodSecurityContext: srcOpts.SecurityOptions.PodSecurityContext, + ReportsSecurityContext: srcOpts.SecurityOptions.ReportsSecurityContext, + } + } + dstOpts = &operatorv1beta2.ReportConfiguration{ + Replicas: srcOpts.Replicas, + Resources: srcOpts.Resources, + SubProcessMaxHeapSize: srcOpts.SubProcessMaxHeapSize, + SecurityOptions: dstSecurityOpts, + SchedulingOptions: convertSchedulingOptionsTo(srcOpts.SchedulingOptions), + } + } + return dstOpts +} + +func convertSchedulingOptionsTo(srcOpts *SchedulingConfiguration) *operatorv1beta2.SchedulingConfiguration { + var dstOpts *operatorv1beta2.SchedulingConfiguration + if srcOpts != nil { + var dstAffinity *operatorv1beta2.Affinity + if srcOpts.Affinity != nil { + dstAffinity = &operatorv1beta2.Affinity{ + NodeAffinity: srcOpts.Affinity.NodeAffinity, + PodAffinity: srcOpts.Affinity.PodAffinity, + PodAntiAffinity: srcOpts.Affinity.PodAntiAffinity, + } + } + dstOpts = &operatorv1beta2.SchedulingConfiguration{ + NodeSelector: srcOpts.NodeSelector, + Affinity: dstAffinity, + Tolerations: srcOpts.Tolerations, + } + } + return dstOpts +} + +func convertJmxCacheOptionsTo(srcOpts *JmxCacheOptions) *operatorv1beta2.JmxCacheOptions { + var dstOpts *operatorv1beta2.JmxCacheOptions + if srcOpts != nil { + dstOpts = &operatorv1beta2.JmxCacheOptions{ + TargetCacheSize: srcOpts.TargetCacheSize, + TargetCacheTTL: srcOpts.TargetCacheTTL, + } + } + return dstOpts +} + +func convertResourceOptionsTo(srcOpts *ResourceConfigList) *operatorv1beta2.ResourceConfigList { + var dstOpts *operatorv1beta2.ResourceConfigList + if srcOpts != nil { + dstOpts = &operatorv1beta2.ResourceConfigList{ + CoreResources: srcOpts.CoreResources, + DataSourceResources: srcOpts.DataSourceResources, + GrafanaResources: srcOpts.GrafanaResources, + } + } + return dstOpts +} + +func convertAuthPropertiesTo(srcProps *AuthorizationProperties) *operatorv1beta2.AuthorizationProperties { + var dstProps *operatorv1beta2.AuthorizationProperties + if srcProps != nil { + dstProps = &operatorv1beta2.AuthorizationProperties{ + ClusterRoleName: srcProps.ClusterRoleName, + ConfigMapName: srcProps.ConfigMapName, + Filename: srcProps.Filename, + } + } + return dstProps +} + +func convertSecurityOptionsTo(srcOpts *SecurityOptions) *operatorv1beta2.SecurityOptions { + var dstOpts *operatorv1beta2.SecurityOptions + if srcOpts != nil { + dstOpts = &operatorv1beta2.SecurityOptions{ + PodSecurityContext: srcOpts.PodSecurityContext, + CoreSecurityContext: srcOpts.CoreSecurityContext, + DataSourceSecurityContext: srcOpts.DataSourceSecurityContext, + GrafanaSecurityContext: srcOpts.GrafanaSecurityContext, + } + } + return dstOpts +} + +func convertTargetDiscoveryTo(srcOpts *TargetDiscoveryOptions) *operatorv1beta2.TargetDiscoveryOptions { + var dstOpts *operatorv1beta2.TargetDiscoveryOptions + if srcOpts != nil { + dstOpts = &operatorv1beta2.TargetDiscoveryOptions{ + BuiltInDiscoveryDisabled: srcOpts.BuiltInDiscoveryDisabled, + } + } + return dstOpts +} + +func convertDatabaseOptionsTo(srcOpts *JmxCredentialsDatabaseOptions) *operatorv1beta2.JmxCredentialsDatabaseOptions { + var dstOpts *operatorv1beta2.JmxCredentialsDatabaseOptions + if srcOpts != nil { + dstOpts = &operatorv1beta2.JmxCredentialsDatabaseOptions{ + DatabaseSecretName: srcOpts.DatabaseSecretName, + } + } + return dstOpts +} + +func convertOperandMetadataTo(srcOpts *OperandMetadata) *operatorv1beta2.OperandMetadata { + var dstOpts *operatorv1beta2.OperandMetadata + if srcOpts != nil { + dstOpts = &operatorv1beta2.OperandMetadata{ + DeploymentMetadata: convertResourceMetadataTo(srcOpts.DeploymentMetadata), + PodMetadata: convertResourceMetadataTo(srcOpts.PodMetadata), + } + } + return dstOpts +} + +func convertResourceMetadataTo(srcMeta *ResourceMetadata) *operatorv1beta2.ResourceMetadata { + var dstMeta *operatorv1beta2.ResourceMetadata + if srcMeta != nil { + dstMeta = &operatorv1beta2.ResourceMetadata{ + Annotations: srcMeta.Annotations, + Labels: srcMeta.Labels, + } + } + return dstMeta +} + +// ConvertFrom converts from the Hub version (v1beta2) to this version. +func (dst *Cryostat) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*operatorv1beta2.Cryostat) + + // Copy ObjectMeta as-is + dst.ObjectMeta = src.ObjectMeta + + // Convert existing Spec fields + convertSpecFrom(&src.Spec, &dst.Spec) + + // Convert existing Status fields + convertStatusFrom(&src.Status, &dst.Status) + + return nil +} + +func convertSpecFrom(src *operatorv1beta2.CryostatSpec, dst *CryostatSpec) { + dst.Minimal = src.Minimal + dst.EnableCertManager = src.EnableCertManager + dst.TrustedCertSecrets = convertCertSecretsFrom(src.TrustedCertSecrets) + dst.EventTemplates = convertEventTemplatesFrom(src.EventTemplates) + dst.StorageOptions = convertStorageOptionsFrom(src.StorageOptions) + dst.ServiceOptions = convertServiceOptionsFrom(src.ServiceOptions) + dst.NetworkOptions = convertNetworkOptionsFrom(src.NetworkOptions) + dst.ReportOptions = convertReportOptionsFrom(src.ReportOptions) + dst.MaxWsConnections = src.MaxWsConnections + dst.JmxCacheOptions = convertJmxCacheOptionsFrom(src.JmxCacheOptions) + dst.Resources = convertResourceOptionsFrom(src.Resources) + dst.AuthProperties = convertAuthPropertiesFrom(src.AuthProperties) + dst.SecurityOptions = convertSecurityOptionsFrom(src.SecurityOptions) + dst.SchedulingOptions = convertSchedulingOptionsFrom(src.SchedulingOptions) + dst.TargetDiscoveryOptions = convertTargetDiscoveryFrom(src.TargetDiscoveryOptions) + dst.JmxCredentialsDatabaseOptions = convertDatabaseOptionsFrom(src.JmxCredentialsDatabaseOptions) + dst.OperandMetadata = convertOperandMetadataFrom(src.OperandMetadata) +} + +func convertStatusFrom(src *operatorv1beta2.CryostatStatus, dst *CryostatStatus) { + dst.ApplicationURL = src.ApplicationURL + dst.Conditions = src.Conditions + dst.GrafanaSecret = src.GrafanaSecret +} + +func convertCertSecretsFrom(srcCerts []operatorv1beta2.CertificateSecret) []CertificateSecret { + var dstCerts []CertificateSecret + if srcCerts != nil { + dstCerts = make([]CertificateSecret, 0, len(srcCerts)) + for _, cert := range srcCerts { + dstCerts = append(dstCerts, CertificateSecret{ + SecretName: cert.SecretName, + CertificateKey: cert.CertificateKey, + }) + } + } + return dstCerts +} + +func convertEventTemplatesFrom(srcTemplates []operatorv1beta2.TemplateConfigMap) []TemplateConfigMap { + var dstTemplates []TemplateConfigMap + if srcTemplates != nil { + dstTemplates = make([]TemplateConfigMap, 0, len(srcTemplates)) + for _, template := range srcTemplates { + dstTemplates = append(dstTemplates, TemplateConfigMap{ + ConfigMapName: template.ConfigMapName, + Filename: template.Filename, + }) + } + } + return dstTemplates +} + +func convertStorageOptionsFrom(srcOpts *operatorv1beta2.StorageConfiguration) *StorageConfiguration { + var dstOpts *StorageConfiguration + if srcOpts != nil { + dstOpts = &StorageConfiguration{} + if srcOpts.PVC != nil { + dstOpts.PVC = &PersistentVolumeClaimConfig{ + Annotations: srcOpts.PVC.Annotations, + Labels: srcOpts.PVC.Labels, + Spec: srcOpts.PVC.Spec, + } + } + if srcOpts.EmptyDir != nil { + dstOpts.EmptyDir = &EmptyDirConfig{ + Enabled: srcOpts.EmptyDir.Enabled, + Medium: srcOpts.EmptyDir.Medium, + SizeLimit: srcOpts.EmptyDir.SizeLimit, + } + } + } + return dstOpts +} + +func convertServiceOptionsFrom(srcOpts *operatorv1beta2.ServiceConfigList) *ServiceConfigList { + var dstOpts *ServiceConfigList + if srcOpts != nil { + dstOpts = &ServiceConfigList{} + if srcOpts.CoreConfig != nil { + dstOpts.CoreConfig = &CoreServiceConfig{ + HTTPPort: srcOpts.CoreConfig.HTTPPort, + JMXPort: srcOpts.CoreConfig.JMXPort, + ServiceConfig: convertServiceConfigFrom(srcOpts.CoreConfig.ServiceConfig), + } + } + if srcOpts.GrafanaConfig != nil { + dstOpts.GrafanaConfig = &GrafanaServiceConfig{ + HTTPPort: srcOpts.GrafanaConfig.HTTPPort, + ServiceConfig: convertServiceConfigFrom(srcOpts.GrafanaConfig.ServiceConfig), + } + } + if srcOpts.ReportsConfig != nil { + dstOpts.ReportsConfig = &ReportsServiceConfig{ + HTTPPort: srcOpts.ReportsConfig.HTTPPort, + ServiceConfig: convertServiceConfigFrom(srcOpts.ReportsConfig.ServiceConfig), + } + } + } + return dstOpts +} + +func convertServiceConfigFrom(srcConfig operatorv1beta2.ServiceConfig) ServiceConfig { + return ServiceConfig{ + ServiceType: srcConfig.ServiceType, + Annotations: srcConfig.Annotations, + Labels: srcConfig.Labels, + } +} + +func convertNetworkOptionsFrom(srcOpts *operatorv1beta2.NetworkConfigurationList) *NetworkConfigurationList { + var dstOpts *NetworkConfigurationList + if srcOpts != nil { + dstOpts = &NetworkConfigurationList{ + CoreConfig: convertNetworkConfigFrom(srcOpts.CoreConfig), + GrafanaConfig: convertNetworkConfigFrom(srcOpts.GrafanaConfig), + CommandConfig: convertNetworkConfigFrom(srcOpts.CommandConfig), // TODO Remove this from v1beta2 API + } + } + return dstOpts +} + +func convertNetworkConfigFrom(srcConfig *operatorv1beta2.NetworkConfiguration) *NetworkConfiguration { + var dstConfig *NetworkConfiguration + if srcConfig != nil { + dstConfig = &NetworkConfiguration{ + IngressSpec: srcConfig.IngressSpec, + Annotations: srcConfig.Annotations, + Labels: srcConfig.Labels, + } + } + return dstConfig +} + +func convertReportOptionsFrom(srcOpts *operatorv1beta2.ReportConfiguration) *ReportConfiguration { + var dstOpts *ReportConfiguration + if srcOpts != nil { + var dstSecurityOpts *ReportsSecurityOptions + if srcOpts.SecurityOptions != nil { + dstSecurityOpts = &ReportsSecurityOptions{ + PodSecurityContext: srcOpts.SecurityOptions.PodSecurityContext, + ReportsSecurityContext: srcOpts.SecurityOptions.ReportsSecurityContext, + } + } + dstOpts = &ReportConfiguration{ + Replicas: srcOpts.Replicas, + Resources: srcOpts.Resources, + SubProcessMaxHeapSize: srcOpts.SubProcessMaxHeapSize, + SecurityOptions: dstSecurityOpts, + SchedulingOptions: convertSchedulingOptionsFrom(srcOpts.SchedulingOptions), + } + } + return dstOpts +} + +func convertSchedulingOptionsFrom(srcOpts *operatorv1beta2.SchedulingConfiguration) *SchedulingConfiguration { + var dstOpts *SchedulingConfiguration + if srcOpts != nil { + var dstAffinity *Affinity + if srcOpts.Affinity != nil { + dstAffinity = &Affinity{ + NodeAffinity: srcOpts.Affinity.NodeAffinity, + PodAffinity: srcOpts.Affinity.PodAffinity, + PodAntiAffinity: srcOpts.Affinity.PodAntiAffinity, + } + } + dstOpts = &SchedulingConfiguration{ + NodeSelector: srcOpts.NodeSelector, + Affinity: dstAffinity, + Tolerations: srcOpts.Tolerations, + } + } + return dstOpts +} + +func convertJmxCacheOptionsFrom(srcOpts *operatorv1beta2.JmxCacheOptions) *JmxCacheOptions { + var dstOpts *JmxCacheOptions + if srcOpts != nil { + dstOpts = &JmxCacheOptions{ + TargetCacheSize: srcOpts.TargetCacheSize, + TargetCacheTTL: srcOpts.TargetCacheTTL, + } + } + return dstOpts +} + +func convertResourceOptionsFrom(srcOpts *operatorv1beta2.ResourceConfigList) *ResourceConfigList { + var dstOpts *ResourceConfigList + if srcOpts != nil { + dstOpts = &ResourceConfigList{ + CoreResources: srcOpts.CoreResources, + DataSourceResources: srcOpts.DataSourceResources, + GrafanaResources: srcOpts.GrafanaResources, + } + } + return dstOpts +} + +func convertAuthPropertiesFrom(srcProps *operatorv1beta2.AuthorizationProperties) *AuthorizationProperties { + var dstProps *AuthorizationProperties + if srcProps != nil { + dstProps = &AuthorizationProperties{ + ClusterRoleName: srcProps.ClusterRoleName, + ConfigMapName: srcProps.ConfigMapName, + Filename: srcProps.Filename, + } + } + return dstProps +} + +func convertSecurityOptionsFrom(srcOpts *operatorv1beta2.SecurityOptions) *SecurityOptions { + var dstOpts *SecurityOptions + if srcOpts != nil { + dstOpts = &SecurityOptions{ + PodSecurityContext: srcOpts.PodSecurityContext, + CoreSecurityContext: srcOpts.CoreSecurityContext, + DataSourceSecurityContext: srcOpts.DataSourceSecurityContext, + GrafanaSecurityContext: srcOpts.GrafanaSecurityContext, + } + } + return dstOpts +} + +func convertTargetDiscoveryFrom(srcOpts *operatorv1beta2.TargetDiscoveryOptions) *TargetDiscoveryOptions { + var dstOpts *TargetDiscoveryOptions + if srcOpts != nil { + dstOpts = &TargetDiscoveryOptions{ + BuiltInDiscoveryDisabled: srcOpts.BuiltInDiscoveryDisabled, + } + } + return dstOpts +} + +func convertDatabaseOptionsFrom(srcOpts *operatorv1beta2.JmxCredentialsDatabaseOptions) *JmxCredentialsDatabaseOptions { + var dstOpts *JmxCredentialsDatabaseOptions + if srcOpts != nil { + dstOpts = &JmxCredentialsDatabaseOptions{ + DatabaseSecretName: srcOpts.DatabaseSecretName, + } + } + return dstOpts +} + +func convertOperandMetadataFrom(srcOpts *operatorv1beta2.OperandMetadata) *OperandMetadata { + var dstOpts *OperandMetadata + if srcOpts != nil { + dstOpts = &OperandMetadata{ + DeploymentMetadata: convertResourceMetadataFrom(srcOpts.DeploymentMetadata), + PodMetadata: convertResourceMetadataFrom(srcOpts.PodMetadata), + } + } + return dstOpts +} + +func convertResourceMetadataFrom(srcMeta *operatorv1beta2.ResourceMetadata) *ResourceMetadata { + var dstMeta *ResourceMetadata + if srcMeta != nil { + dstMeta = &ResourceMetadata{ + Annotations: srcMeta.Annotations, + Labels: srcMeta.Labels, + } + } + return dstMeta +} diff --git a/api/v1beta1/cryostat_conversion_test.go b/api/v1beta1/cryostat_conversion_test.go new file mode 100644 index 000000000..37b78304c --- /dev/null +++ b/api/v1beta1/cryostat_conversion_test.go @@ -0,0 +1,146 @@ +// Copyright The Cryostat Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1beta1_test + +import ( + operatorv1beta1 "github.com/cryostatio/cryostat-operator/api/v1beta1" + operatorv1beta2 "github.com/cryostatio/cryostat-operator/api/v1beta2" + "github.com/cryostatio/cryostat-operator/internal/controllers/model" + "github.com/cryostatio/cryostat-operator/internal/test" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +type conversionTestInput struct { + *test.TestResources +} + +var _ = Describe("Cryostat", func() { + var t *conversionTestInput + + BeforeEach(func() { + t = &conversionTestInput{ + TestResources: &test.TestResources{ + Name: "cryostat", + Namespace: "test", + TargetNamespaces: []string{"test"}, + }, + } + }) + + DescribeTable("converting from v1beta1 to v1beta2", + func(oldFunc func(*test.TestResources) *operatorv1beta1.Cryostat, newFunc func(*test.TestResources) *model.CryostatInstance) { + oldCR := oldFunc(t.TestResources) + newCRModel := newFunc(t.TestResources) + Expect(newCRModel.Object).To(BeAssignableToTypeOf(&operatorv1beta2.Cryostat{})) + newCR := newCRModel.Object.(*operatorv1beta2.Cryostat) + // Fill in Status.TargetNamespaces + newCR.Status.TargetNamespaces = newCR.Spec.TargetNamespaces + + converted := &operatorv1beta2.Cryostat{} + err := oldCR.ConvertTo(converted) + Expect(err).ToNot(HaveOccurred()) + + Expect(converted).To(Equal(newCR)) + }, + tableEntries(), + ) + + DescribeTable("converting from v1beta2 to v1beta1", + func(oldFunc func(*test.TestResources) *operatorv1beta1.Cryostat, newFunc func(*test.TestResources) *model.CryostatInstance) { + oldCR := oldFunc(t.TestResources) + newCRModel := newFunc(t.TestResources) + Expect(newCRModel.Object).To(BeAssignableToTypeOf(&operatorv1beta2.Cryostat{})) + newCR := newCRModel.Object.(*operatorv1beta2.Cryostat) + + converted := &operatorv1beta1.Cryostat{} + err := converted.ConvertFrom(newCR) + Expect(err).ToNot(HaveOccurred()) + + Expect(converted).To(Equal(oldCR)) + }, + tableEntries(), + ) + +}) + +func tableEntries() []TableEntry { + return []TableEntry{ + Entry("defaults", (*test.TestResources).NewCryostatV1Beta1, + (*test.TestResources).NewCryostat), + Entry("secrets", (*test.TestResources).NewCryostatWithSecretsV1Beta1, + (*test.TestResources).NewCryostatWithSecrets), + Entry("templates", (*test.TestResources).NewCryostatWithTemplatesV1Beta1, + (*test.TestResources).NewCryostatWithTemplates), + Entry("ingress", (*test.TestResources).NewCryostatWithIngressV1Beta1, + (*test.TestResources).NewCryostatWithIngress), + Entry("ingress with cert-manager disabled", (*test.TestResources).NewCryostatWithIngressCertManagerDisabledV1Beta1, + (*test.TestResources).NewCryostatWithIngressCertManagerDisabled), + Entry("PVC spec", (*test.TestResources).NewCryostatWithPVCSpecV1Beta1, + (*test.TestResources).NewCryostatWithPVCSpec), + Entry("PVC spec with some defaults", (*test.TestResources).NewCryostatWithPVCSpecSomeDefaultV1Beta1, + (*test.TestResources).NewCryostatWithPVCSpecSomeDefault), + Entry("PVC spec with labels only", (*test.TestResources).NewCryostatWithPVCLabelsOnlyV1Beta1, + (*test.TestResources).NewCryostatWithPVCLabelsOnly), + Entry("default emptyDir", (*test.TestResources).NewCryostatWithDefaultEmptyDirV1Beta1, + (*test.TestResources).NewCryostatWithDefaultEmptyDir), + Entry("custom emptyDir", (*test.TestResources).NewCryostatWithEmptyDirSpecV1Beta1, + (*test.TestResources).NewCryostatWithEmptyDirSpec), + Entry("core service", (*test.TestResources).NewCryostatWithCoreSvcV1Beta1, + (*test.TestResources).NewCryostatWithCoreSvc), + Entry("Grafana service", (*test.TestResources).NewCryostatWithGrafanaSvcV1Beta1, + (*test.TestResources).NewCryostatWithGrafanaSvc), + Entry("reports service", (*test.TestResources).NewCryostatWithReportsSvcV1Beta1, + (*test.TestResources).NewCryostatWithReportsSvc), + Entry("core ingress", (*test.TestResources).NewCryostatWithCoreNetworkOptionsV1Beta1, + (*test.TestResources).NewCryostatWithCoreNetworkOptions), + Entry("Grafana ingress", (*test.TestResources).NewCryostatWithGrafanaNetworkOptionsV1Beta1, + (*test.TestResources).NewCryostatWithGrafanaNetworkOptions), + Entry("reports resources", (*test.TestResources).NewCryostatWithReportsResourcesV1Beta1, + (*test.TestResources).NewCryostatWithReportsResources), + Entry("reports low resource limit", (*test.TestResources).NewCryostatWithReportLowResourceLimitV1Beta1, + (*test.TestResources).NewCryostatWithReportLowResourceLimit), + Entry("scheduling", (*test.TestResources).NewCryostatWithSchedulingV1Beta1, + (*test.TestResources).NewCryostatWithScheduling), + Entry("reports scheduling", (*test.TestResources).NewCryostatWithReportsSchedulingV1Beta1, + (*test.TestResources).NewCryostatWithReportsScheduling), + Entry("cert-manager disabled", (*test.TestResources).NewCryostatCertManagerDisabledV1Beta1, + (*test.TestResources).NewCryostatCertManagerDisabled), + Entry("cert-manager undefined", (*test.TestResources).NewCryostatCertManagerUndefinedV1Beta1, + (*test.TestResources).NewCryostatCertManagerUndefined), + Entry("resources", (*test.TestResources).NewCryostatWithResourcesV1Beta1, + (*test.TestResources).NewCryostatWithResources), + Entry("low resource limit", (*test.TestResources).NewCryostatWithLowResourceLimitV1Beta1, + (*test.TestResources).NewCryostatWithLowResourceLimit), + Entry("auth properties", (*test.TestResources).NewCryostatWithAuthPropertiesV1Beta1, + (*test.TestResources).NewCryostatWithAuthProperties), + Entry("built-in discovery disabled", (*test.TestResources).NewCryostatWithBuiltInDiscoveryDisabledV1Beta1, + (*test.TestResources).NewCryostatWithBuiltInDiscoveryDisabled), + Entry("JMX cache options", (*test.TestResources).NewCryostatWithJmxCacheOptionsSpecV1Beta1, + (*test.TestResources).NewCryostatWithJmxCacheOptionsSpec), + Entry("WS connections", (*test.TestResources).NewCryostatWithWsConnectionsSpecV1Beta1, + (*test.TestResources).NewCryostatWithWsConnectionsSpec), + Entry("subprocess heap", (*test.TestResources).NewCryostatWithReportSubprocessHeapSpecV1Beta1, + (*test.TestResources).NewCryostatWithReportSubprocessHeapSpec), + Entry("security", (*test.TestResources).NewCryostatWithSecurityOptionsV1Beta1, + (*test.TestResources).NewCryostatWithSecurityOptions), + Entry("reports security", (*test.TestResources).NewCryostatWithReportSecurityOptionsV1Beta1, + (*test.TestResources).NewCryostatWithReportSecurityOptions), + Entry("database secret", (*test.TestResources).NewCryostatWithDatabaseSecretProvidedV1Beta1, + (*test.TestResources).NewCryostatWithDatabaseSecretProvided), + Entry("metadata", (*test.TestResources).NewCryostatWithAdditionalMetadataV1Beta1, + (*test.TestResources).NewCryostatWithAdditionalMetadata), + } +} diff --git a/api/v1beta1/cryostat_suite_test.go b/api/v1beta1/cryostat_suite_test.go new file mode 100644 index 000000000..b16274daa --- /dev/null +++ b/api/v1beta1/cryostat_suite_test.go @@ -0,0 +1,27 @@ +// Copyright The Cryostat Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1beta1_test + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestBooks(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Cryostat Suite") +} diff --git a/api/v1beta1/cryostat_types.go b/api/v1beta1/cryostat_types.go index 1270866a6..a480a28c6 100644 --- a/api/v1beta1/cryostat_types.go +++ b/api/v1beta1/cryostat_types.go @@ -414,7 +414,6 @@ type JmxCacheOptions struct { // +kubebuilder:object:root=true // +kubebuilder:subresource:status -// +kubebuilder:storageversion // +kubebuilder:resource:path=cryostats,scope=Namespaced // Cryostat allows you to install Cryostat for a single namespace. diff --git a/api/v1beta2/clustercryostat_conversion.go b/api/v1beta2/clustercryostat_conversion.go new file mode 100644 index 000000000..2f1604627 --- /dev/null +++ b/api/v1beta2/clustercryostat_conversion.go @@ -0,0 +1,24 @@ +// Copyright The Cryostat Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1beta2 + +import "sigs.k8s.io/controller-runtime/pkg/conversion" + +// TODO Remove this file with ClusterCryostat CRD + +var _ conversion.Hub = &ClusterCryostat{} + +// Hub marks this type as a conversion hub. +func (*ClusterCryostat) Hub() {} diff --git a/api/v1beta2/clustercryostat_types.go b/api/v1beta2/clustercryostat_types.go new file mode 100644 index 000000000..686a970fa --- /dev/null +++ b/api/v1beta2/clustercryostat_types.go @@ -0,0 +1,70 @@ +// Copyright The Cryostat Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1beta2 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// ClusterCryostatSpec defines the desired state of ClusterCryostat. +type ClusterCryostatSpec struct { + // Namespace where Cryostat should be installed. + // On multi-tenant clusters, we strongly suggest installing Cryostat into + // its own namespace. + // +operator-sdk:csv:customresourcedefinitions:type=spec,order=1,xDescriptors={"urn:alm:descriptor:io.kubernetes:Namespace"} + InstallNamespace string `json:"installNamespace"` + // +operator-sdk:csv:customresourcedefinitions:type=spec + CryostatSpec `json:",inline"` +} + +// ClusterCryostatStatus defines the observed state of ClusterCryostat. +type ClusterCryostatStatus struct { + // +operator-sdk:csv:customresourcedefinitions:type=status + CryostatStatus `json:",inline"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:storageversion +// +kubebuilder:resource:path=clustercryostats,scope=Cluster + +// ClusterCryostat allows you to install Cryostat for multiple namespaces or cluster-wide. +// It contains configuration options for controlling the Deployment of the Cryostat +// application and its related components. +// A ClusterCryostat or Cryostat instance must be created to instruct the operator +// to deploy the Cryostat application. +// +operator-sdk:csv:customresourcedefinitions:resources={{Deployment,v1},{Ingress,v1},{PersistentVolumeClaim,v1},{Secret,v1},{Service,v1},{Route,v1},{ConsoleLink,v1}} +// +kubebuilder:printcolumn:name="Application URL",type=string,JSONPath=`.status.applicationUrl` +// +kubebuilder:printcolumn:name="Grafana Secret",type=string,JSONPath=`.status.grafanaSecret` +type ClusterCryostat struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ClusterCryostatSpec `json:"spec,omitempty"` + Status ClusterCryostatStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// ClusterCryostatList contains a list of ClusterCryostat +type ClusterCryostatList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ClusterCryostat `json:"items"` +} + +func init() { + SchemeBuilder.Register(&ClusterCryostat{}, &ClusterCryostatList{}) +} diff --git a/api/v1beta2/cryostat_conversion.go b/api/v1beta2/cryostat_conversion.go new file mode 100644 index 000000000..8086d775c --- /dev/null +++ b/api/v1beta2/cryostat_conversion.go @@ -0,0 +1,22 @@ +// Copyright The Cryostat Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1beta2 + +import "sigs.k8s.io/controller-runtime/pkg/conversion" + +var _ conversion.Hub = &Cryostat{} + +// Hub marks this type as a conversion hub. +func (*Cryostat) Hub() {} diff --git a/api/v1beta2/cryostat_types.go b/api/v1beta2/cryostat_types.go new file mode 100644 index 000000000..1fc0d947d --- /dev/null +++ b/api/v1beta2/cryostat_types.go @@ -0,0 +1,559 @@ +// Copyright The Cryostat Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1beta2 + +import ( + corev1 "k8s.io/api/core/v1" + netv1 "k8s.io/api/networking/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/conversion" +) + +// CryostatSpec defines the desired state of Cryostat. +type CryostatSpec struct { + // List of namespaces whose workloads Cryostat should be + // permitted to access and profile. Defaults to this Cryostat's namespace. + // Warning: All Cryostat users will be able to create and manage + // recordings for workloads in the listed namespaces. + // More details: https://github.com/cryostatio/cryostat-operator/blob/v2.4.0/docs/multi-namespace.md#data-isolation + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,order=2 + TargetNamespaces []string `json:"targetNamespaces,omitempty"` + // Deploy a pared-down Cryostat instance with no Grafana Dashboard or JFR Data Source. + // +operator-sdk:csv:customresourcedefinitions:type=spec,order=4,displayName="Minimal Deployment",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:booleanSwitch"} + Minimal bool `json:"minimal"` + // List of TLS certificates to trust when connecting to targets. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Trusted TLS Certificates" + TrustedCertSecrets []CertificateSecret `json:"trustedCertSecrets,omitempty"` + // List of Flight Recorder Event Templates to preconfigure in Cryostat. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Event Templates" + EventTemplates []TemplateConfigMap `json:"eventTemplates,omitempty"` + // Use cert-manager to secure in-cluster communication between Cryostat components. + // Requires cert-manager to be installed. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,order=3,displayName="Enable cert-manager Integration",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:booleanSwitch"} + EnableCertManager *bool `json:"enableCertManager"` + // Options to customize the storage for Flight Recordings and Templates. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + StorageOptions *StorageConfiguration `json:"storageOptions,omitempty"` + // Options to customize the services created for the Cryostat application and Grafana dashboard. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + ServiceOptions *ServiceConfigList `json:"serviceOptions,omitempty"` + // Options to control how the operator exposes the application outside of the cluster, + // such as using an Ingress or Route. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + NetworkOptions *NetworkConfigurationList `json:"networkOptions,omitempty"` + // Options to configure Cryostat Automated Report Analysis. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + ReportOptions *ReportConfiguration `json:"reportOptions,omitempty"` + // The maximum number of WebSocket client connections allowed (minimum 1, default unlimited). + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Max WebSocket Connections",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:number"} + // +kubebuilder:validation:Minimum=1 + MaxWsConnections int32 `json:"maxWsConnections,omitempty"` + // Options to customize the JMX target connections cache for the Cryostat application. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="JMX Connections Cache Options" + JmxCacheOptions *JmxCacheOptions `json:"jmxCacheOptions,omitempty"` + // Resource requirements for the Cryostat deployment. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + Resources *ResourceConfigList `json:"resources,omitempty"` + // Override default authorization properties for Cryostat on OpenShift. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Authorization Properties",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced"} + AuthProperties *AuthorizationProperties `json:"authProperties,omitempty"` + // Options to configure the Security Contexts for the Cryostat application. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced"} + SecurityOptions *SecurityOptions `json:"securityOptions,omitempty"` + // Options to configure scheduling for the Cryostat deployment + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + SchedulingOptions *SchedulingConfiguration `json:"schedulingOptions,omitempty"` + // Options to configure the Cryostat application's target discovery mechanisms. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + TargetDiscoveryOptions *TargetDiscoveryOptions `json:"targetDiscoveryOptions,omitempty"` + // Options to configure the Cryostat application's credentials database. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Credentials Database Options" + JmxCredentialsDatabaseOptions *JmxCredentialsDatabaseOptions `json:"jmxCredentialsDatabaseOptions,omitempty"` + // Options to configure the Cryostat deployments and pods metadata + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Operand metadata" + OperandMetadata *OperandMetadata `json:"operandMetadata,omitempty"` +} + +type OperandMetadata struct { + // Options to configure the Cryostat deployments metadata + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Deployments metadata" + DeploymentMetadata *ResourceMetadata `json:"deploymentMetadata,omitempty"` + // Options to configure the Cryostat pods metadata + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Pods metadata" + PodMetadata *ResourceMetadata `json:"podMetadata,omitempty"` +} + +type ResourceMetadata struct { + // Annotations to add to the resources during its creation. + // +optional + Annotations map[string]string `json:"annotations,omitempty"` + // Labels to add to the resources during its creation. + // The labels with keys "app" and "component" are reserved + // for use by the operator. + // +optional + Labels map[string]string `json:"labels,omitempty"` +} + +type ResourceConfigList struct { + // Resource requirements for the Cryostat application. If specifying a memory limit, at least 768MiB is recommended. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:resourceRequirements"} + CoreResources corev1.ResourceRequirements `json:"coreResources,omitempty"` + // Resource requirements for the JFR Data Source container. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:resourceRequirements"} + DataSourceResources corev1.ResourceRequirements `json:"dataSourceResources,omitempty"` + // Resource requirements for the Grafana container. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:resourceRequirements"} + GrafanaResources corev1.ResourceRequirements `json:"grafanaResources,omitempty"` +} + +// CryostatStatus defines the observed state of Cryostat. +type CryostatStatus struct { + // List of namespaces that Cryostat has been configured + // and authorized to access and profile. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=status,order=3 + TargetNamespaces []string `json:"targetNamespaces,omitempty"` + // Conditions of the components managed by the Cryostat Operator. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=status,displayName="Cryostat Conditions",xDescriptors={"urn:alm:descriptor:io.kubernetes.conditions"} + Conditions []metav1.Condition `json:"conditions,omitempty"` + // Name of the Secret containing the generated Grafana credentials. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=status,order=2,xDescriptors={"urn:alm:descriptor:io.kubernetes:Secret"} + GrafanaSecret string `json:"grafanaSecret,omitempty"` + // Address of the deployed Cryostat web application. + // +operator-sdk:csv:customresourcedefinitions:type=status,order=1,xDescriptors={"urn:alm:descriptor:org.w3:link"} + ApplicationURL string `json:"applicationUrl"` +} + +// CryostatConditionType refers to a Condition type that may be used in status.conditions +type CryostatConditionType string + +const ( + // Whether the main Cryostat deployment is available. + ConditionTypeMainDeploymentAvailable CryostatConditionType = "MainDeploymentAvailable" + // Whether the main Cryostat deployment is progressing. + ConditionTypeMainDeploymentProgressing CryostatConditionType = "MainDeploymentProgressing" + // If pods within the main Cryostat deployment failed to be created or destroyed. + ConditionTypeMainDeploymentReplicaFailure CryostatConditionType = "MainDeploymentReplicaFailure" + // If enabled, whether the reports deployment is available. + ConditionTypeReportsDeploymentAvailable CryostatConditionType = "ReportsDeploymentAvailable" + // If enabled, whether the reports deployment is progressing. + ConditionTypeReportsDeploymentProgressing CryostatConditionType = "ReportsDeploymentProgressing" + // If enabled, whether pods in the reports deployment failed to be created or destroyed. + ConditionTypeReportsDeploymentReplicaFailure CryostatConditionType = "ReportsDeploymentReplicaFailure" + // If enabled, whether TLS setup is complete for the Cryostat components. + ConditionTypeTLSSetupComplete CryostatConditionType = "TLSSetupComplete" +) + +// StorageConfiguration provides customization to the storage created by +// the operator to hold Flight Recordings and Recording Templates. If no +// configurations are specified, a PVC will be created by default. +type StorageConfiguration struct { + // Configuration for the Persistent Volume Claim to be created + // by the operator. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + PVC *PersistentVolumeClaimConfig `json:"pvc,omitempty"` + // Configuration for an EmptyDir to be created + // by the operator instead of a PVC. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + EmptyDir *EmptyDirConfig `json:"emptyDir,omitempty"` +} + +// ReportConfiguration is used to determine how many replicas of cryostat-reports +// the operator should create and what the resource limits of those containers +// should be. If no replicas are created then Cryostat is configured to use basic +// subprocess report generation. If at least one replica is created then Cryostat +// is configured to use remote report generation, pointed at a load balancer service +// in front of the cryostat-reports replicas. +type ReportConfiguration struct { + // The number of report sidecar replica containers to deploy. + // Each replica can service one report generation request at a time. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:podCount"} + Replicas int32 `json:"replicas,omitempty"` + // The resources allocated to each sidecar replica. + // A replica with more resources can handle larger input recordings and will process them faster. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:resourceRequirements"} + Resources corev1.ResourceRequirements `json:"resources,omitempty"` + // When zero report sidecar replicas are requested, SubProcessMaxHeapSize configures + // the maximum heap size of the basic subprocess report generator in MiB. + // The default heap size is `200` (MiB). + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:number"} + SubProcessMaxHeapSize int32 `json:"subProcessMaxHeapSize,omitempty"` + // Options to configure the Security Contexts for the Cryostat report generator. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:advanced"} + SecurityOptions *ReportsSecurityOptions `json:"securityOptions,omitempty"` + // Options to configure scheduling for the reports deployment + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + SchedulingOptions *SchedulingConfiguration `json:"schedulingOptions,omitempty"` +} + +// SchedulingConfiguration contains multiple choices to control scheduling of Cryostat pods +type SchedulingConfiguration struct { + // Label selector used to schedule a Cryostat pod to a node. See: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:selector:core:v1:Node"} + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + // Affinity rules for scheduling Cryostat pods. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + Affinity *Affinity `json:"affinity,omitempty"` + // Tolerations to allow scheduling of Cryostat pods to tainted nodes. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` +} + +// Affinity groups different kinds of affinity configurations for Cryostat pods +type Affinity struct { + // Node affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#NodeAffinity + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:nodeAffinity"} + NodeAffinity *corev1.NodeAffinity `json:"nodeAffinity,omitempty"` + // Pod affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAffinity + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:podAffinity"} + PodAffinity *corev1.PodAffinity `json:"podAffinity,omitempty"` + // Pod anti-affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAntiAffinity + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:podAntiAffinity"} + PodAntiAffinity *corev1.PodAntiAffinity `json:"podAntiAffinity,omitempty"` +} + +// ServiceConfig provides customization for a service created +// by the operator. +type ServiceConfig struct { + // Type of service to create. Defaults to "ClusterIP". + // +optional + ServiceType *corev1.ServiceType `json:"serviceType,omitempty"` + // Annotations to add to the service during its creation. + // +optional + Annotations map[string]string `json:"annotations,omitempty"` + // Labels to add to the service during its creation. + // The labels with keys "app" and "component" are reserved + // for use by the operator. + // +optional + Labels map[string]string `json:"labels,omitempty"` +} + +// CoreServiceConfig provides customization for the service handling +// traffic for the Cryostat application. +type CoreServiceConfig struct { + // HTTP port number for the Cryostat application service. + // Defaults to 8181. + // +optional + HTTPPort *int32 `json:"httpPort,omitempty"` + // Remote JMX port number for the Cryostat application service. + // Defaults to 9091. + // +optional + JMXPort *int32 `json:"jmxPort,omitempty"` + ServiceConfig `json:",inline"` +} + +// GrafanaServiceConfig provides customization for the service handling +// traffic for the Grafana dashboard. +type GrafanaServiceConfig struct { + // HTTP port number for the Grafana dashboard service. + // Defaults to 3000. + // +optional + HTTPPort *int32 `json:"httpPort,omitempty"` + ServiceConfig `json:",inline"` +} + +// ReportsServiceConfig provides customization for the service handling +// traffic for the cryostat-reports sidecars. +type ReportsServiceConfig struct { + // HTTP port number for the cryostat-reports service. + // Defaults to 10000. + // +optional + HTTPPort *int32 `json:"httpPort,omitempty"` + ServiceConfig `json:",inline"` +} + +// ServiceConfigList holds the service configuration for each +// service created by the operator. +type ServiceConfigList struct { + // Specification for the service responsible for the Cryostat application. + // +optional + CoreConfig *CoreServiceConfig `json:"coreConfig,omitempty"` + // Specification for the service responsible for the Cryostat Grafana dashboard. + // +optional + GrafanaConfig *GrafanaServiceConfig `json:"grafanaConfig,omitempty"` + // Specification for the service responsible for the cryostat-reports sidecars. + // +optional + ReportsConfig *ReportsServiceConfig `json:"reportsConfig,omitempty"` +} + +// NetworkConfiguration provides customization for how to expose a Cryostat +// service, so that it can be reached from outside the cluster. +// On OpenShift, a Route is created by default. On Kubernetes, an Ingress will +// be created if the IngressSpec is defined within this NetworkConfiguration. +type NetworkConfiguration struct { + // Configuration for an Ingress object. + // Currently subpaths are not supported, so unique hosts must be specified + // (if a single external IP is being used) to differentiate between ingresses/services. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + IngressSpec *netv1.IngressSpec `json:"ingressSpec,omitempty"` + // Annotations to add to the Ingress or Route during its creation. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + Annotations map[string]string `json:"annotations,omitempty"` + // Labels to add to the Ingress or Route during its creation. + // The label with key "app" is reserved for use by the operator. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + Labels map[string]string `json:"labels,omitempty"` +} + +// NetworkConfigurationList holds NetworkConfiguration objects that specify +// how to expose the services created by the operator for the main Cryostat +// deployment. +type NetworkConfigurationList struct { + // Specifications for how to expose the Cryostat service, + // which serves the Cryostat application. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + CoreConfig *NetworkConfiguration `json:"coreConfig,omitempty"` + // Specifications for how to expose the Cryostat command service, + // which serves the WebSocket command channel. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:hidden"} + // + // Deprecated: CommandConfig is no longer used. + CommandConfig *NetworkConfiguration `json:"commandConfig,omitempty"` + // Specifications for how to expose Cryostat's Grafana service, + // which serves the Grafana dashboard. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + GrafanaConfig *NetworkConfiguration `json:"grafanaConfig,omitempty"` +} + +// PersistentVolumeClaimConfig holds all customization options to +// configure a Persistent Volume Claim to be created and managed +// by the operator. +type PersistentVolumeClaimConfig struct { + // Annotations to add to the Persistent Volume Claim during its creation. + // +optional + Annotations map[string]string `json:"annotations,omitempty"` + // Labels to add to the Persistent Volume Claim during its creation. + // The label with key "app" is reserved for use by the operator. + // +optional + Labels map[string]string `json:"labels,omitempty"` + // Spec for a Persistent Volume Claim, whose options will override the + // defaults used by the operator. Unless overriden, the PVC will be + // created with the default Storage Class and 500MiB of storage. + // Once the operator has created the PVC, changes to this field have + // no effect. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + Spec *corev1.PersistentVolumeClaimSpec `json:"spec,omitempty"` +} + +// EmptyDirConfig holds all customization options to +// configure an EmptyDir to be created and managed +// by the operator. +type EmptyDirConfig struct { + // When enabled, Cryostat will use EmptyDir volumes instead of a Persistent Volume Claim. Any PVC configurations will be ignored. + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:booleanSwitch"} + Enabled bool `json:"enabled,omitempty"` + // Unless specified, the emptyDir volume will be mounted on + // the same storage medium backing the node. Setting this field to + // "Memory" will mount the emptyDir on a tmpfs (RAM-backed filesystem). + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:fieldDependency:storageOptions.emptyDir.enabled:true"} + Medium corev1.StorageMedium `json:"medium,omitempty"` + // The maximum memory limit for the emptyDir. Default is unbounded. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:fieldDependency:storageOptions.emptyDir.enabled:true"} + // +kubebuilder:validation:Pattern=^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + SizeLimit string `json:"sizeLimit,omitempty"` +} + +// JmxCacheConfig provides customization for the JMX target connections +// cache for the Cryostat application. +type JmxCacheOptions struct { + // The maximum number of JMX connections to cache. Use `-1` for an unlimited cache size (TTL expiration only). Defaults to `-1`. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:number"} + // +kubebuilder:validation:Minimum=-1 + TargetCacheSize int32 `json:"targetCacheSize,omitempty"` + // The time to live (in seconds) for cached JMX connections. Defaults to `10`. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:number"} + // +kubebuilder:validation:Minimum=1 + TargetCacheTTL int32 `json:"targetCacheTTL,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:storageversion +// +kubebuilder:resource:path=cryostats,scope=Namespaced + +// Cryostat allows you to install Cryostat for a single namespace. +// It contains configuration options for controlling the Deployment of the Cryostat +// application and its related components. +// A ClusterCryostat or Cryostat instance must be created to instruct the operator +// to deploy the Cryostat application. +// +operator-sdk:csv:customresourcedefinitions:resources={{Deployment,v1},{Ingress,v1},{PersistentVolumeClaim,v1},{Secret,v1},{Service,v1},{Route,v1},{ConsoleLink,v1}} +// +kubebuilder:printcolumn:name="Application URL",type=string,JSONPath=`.status.applicationUrl` +// +kubebuilder:printcolumn:name="Grafana Secret",type=string,JSONPath=`.status.grafanaSecret` +type Cryostat struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec CryostatSpec `json:"spec,omitempty"` + Status CryostatStatus `json:"status,omitempty"` +} + +// ConvertFrom implements conversion.Convertible. +func (*Cryostat) ConvertFrom(src conversion.Hub) error { + panic("unimplemented") +} + +// ConvertTo implements conversion.Convertible. +func (*Cryostat) ConvertTo(dst conversion.Hub) error { + panic("unimplemented") +} + +// +kubebuilder:object:root=true + +// CryostatList contains a list of Cryostat +type CryostatList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Cryostat `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Cryostat{}, &CryostatList{}) +} + +// DefaultCertificateKey will be used when looking up the certificate within a secret, +// if a key is not manually specified. +const DefaultCertificateKey = corev1.TLSCertKey + +type CertificateSecret struct { + // Name of secret in the local namespace. + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:io.kubernetes:Secret"} + SecretName string `json:"secretName"` + // Key within secret containing the certificate. + // +optional + CertificateKey *string `json:"certificateKey,omitempty"` +} + +// A ConfigMap containing a .jfc template file. +type TemplateConfigMap struct { + // Name of config map in the local namespace. + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:io.kubernetes:ConfigMap"} + ConfigMapName string `json:"configMapName"` + // Filename within config map containing the template file. + Filename string `json:"filename"` +} + +// Authorization properties provide custom permission mapping between Cryostat resources to Kubernetes resources. +// If the mapping is updated, Cryostat must be manually restarted. +type AuthorizationProperties struct { + // Name of the ClusterRole to use when Cryostat requests a role-scoped OAuth token. + // This ClusterRole should contain permissions for all Kubernetes objects listed in custom permission mapping. + // More details: https://docs.openshift.com/container-platform/4.11/authentication/tokens-scoping.html#scoping-tokens-role-scope_configuring-internal-oauth + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="ClusterRole Name",xDescriptors={"urn:alm:descriptor:io.kubernetes:ClusterRole"} + ClusterRoleName string `json:"clusterRoleName"` + // Name of config map in the local namespace. + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="ConfigMap Name",xDescriptors={"urn:alm:descriptor:io.kubernetes:ConfigMap"} + ConfigMapName string `json:"configMapName"` + // Filename within config map containing the resource mapping. + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:text"} + Filename string `json:"filename"` +} + +// SecurityOptions contains Security Context customizations for the +// main Cryostat application at both the pod and container level. +type SecurityOptions struct { + // Security Context to apply to the Cryostat pod. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"` + // Security Context to apply to the Cryostat application container. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + CoreSecurityContext *corev1.SecurityContext `json:"coreSecurityContext,omitempty"` + // Security Context to apply to the JFR Data Source container. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + DataSourceSecurityContext *corev1.SecurityContext `json:"dataSourceSecurityContext,omitempty"` + // Security Context to apply to the Grafana container. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + GrafanaSecurityContext *corev1.SecurityContext `json:"grafanaSecurityContext,omitempty"` +} + +// ReportsSecurityOptions contains Security Context customizations for the +// Cryostat report generator at both the pod and container level. +type ReportsSecurityOptions struct { + // Security Context to apply to the Cryostat report generator pod. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"` + // Security Context to apply to the Cryostat report generator container. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + ReportsSecurityContext *corev1.SecurityContext `json:"reportsSecurityContext,omitempty"` +} + +// TargetDiscoveryOptions provides configuration options to the Cryostat application's target discovery mechanisms. +type TargetDiscoveryOptions struct { + // When true, the Cryostat application will disable the built-in discovery mechanisms. Defaults to false + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Disable Built-in Discovery",xDescriptors={"urn:alm:descriptor:com.tectonic.ui:booleanSwitch"} + BuiltInDiscoveryDisabled bool `json:"builtInDiscoveryDisabled,omitempty"` +} + +// JmxCredentialsDatabaseOptions provides configuration options to the Cryostat application's credentials database. +type JmxCredentialsDatabaseOptions struct { + // Name of the secret containing the password to encrypt credentials database. + // +optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:io.kubernetes:Secret"} + DatabaseSecretName *string `json:"databaseSecretName,omitempty"` +} diff --git a/api/v1beta2/groupversion_info.go b/api/v1beta2/groupversion_info.go new file mode 100644 index 000000000..79f19b264 --- /dev/null +++ b/api/v1beta2/groupversion_info.go @@ -0,0 +1,34 @@ +// Copyright The Cryostat Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package v1beta2 contains API Schema definitions for the operator v1beta2 API group +// +kubebuilder:object:generate=true +// +groupName=operator.cryostat.io +package v1beta2 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "operator.cryostat.io", Version: "v1beta2"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/api/v1beta2/zz_generated.deepcopy.go b/api/v1beta2/zz_generated.deepcopy.go new file mode 100644 index 000000000..c1850c2d1 --- /dev/null +++ b/api/v1beta2/zz_generated.deepcopy.go @@ -0,0 +1,893 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright The Cryostat Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by controller-gen. DO NOT EDIT. + +package v1beta2 + +import ( + corev1 "k8s.io/api/core/v1" + networkingv1 "k8s.io/api/networking/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Affinity) DeepCopyInto(out *Affinity) { + *out = *in + if in.NodeAffinity != nil { + in, out := &in.NodeAffinity, &out.NodeAffinity + *out = new(corev1.NodeAffinity) + (*in).DeepCopyInto(*out) + } + if in.PodAffinity != nil { + in, out := &in.PodAffinity, &out.PodAffinity + *out = new(corev1.PodAffinity) + (*in).DeepCopyInto(*out) + } + if in.PodAntiAffinity != nil { + in, out := &in.PodAntiAffinity, &out.PodAntiAffinity + *out = new(corev1.PodAntiAffinity) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Affinity. +func (in *Affinity) DeepCopy() *Affinity { + if in == nil { + return nil + } + out := new(Affinity) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AuthorizationProperties) DeepCopyInto(out *AuthorizationProperties) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AuthorizationProperties. +func (in *AuthorizationProperties) DeepCopy() *AuthorizationProperties { + if in == nil { + return nil + } + out := new(AuthorizationProperties) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CertificateSecret) DeepCopyInto(out *CertificateSecret) { + *out = *in + if in.CertificateKey != nil { + in, out := &in.CertificateKey, &out.CertificateKey + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertificateSecret. +func (in *CertificateSecret) DeepCopy() *CertificateSecret { + if in == nil { + return nil + } + out := new(CertificateSecret) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterCryostat) DeepCopyInto(out *ClusterCryostat) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterCryostat. +func (in *ClusterCryostat) DeepCopy() *ClusterCryostat { + if in == nil { + return nil + } + out := new(ClusterCryostat) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterCryostat) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterCryostatList) DeepCopyInto(out *ClusterCryostatList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterCryostat, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterCryostatList. +func (in *ClusterCryostatList) DeepCopy() *ClusterCryostatList { + if in == nil { + return nil + } + out := new(ClusterCryostatList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterCryostatList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterCryostatSpec) DeepCopyInto(out *ClusterCryostatSpec) { + *out = *in + in.CryostatSpec.DeepCopyInto(&out.CryostatSpec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterCryostatSpec. +func (in *ClusterCryostatSpec) DeepCopy() *ClusterCryostatSpec { + if in == nil { + return nil + } + out := new(ClusterCryostatSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterCryostatStatus) DeepCopyInto(out *ClusterCryostatStatus) { + *out = *in + in.CryostatStatus.DeepCopyInto(&out.CryostatStatus) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterCryostatStatus. +func (in *ClusterCryostatStatus) DeepCopy() *ClusterCryostatStatus { + if in == nil { + return nil + } + out := new(ClusterCryostatStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CoreServiceConfig) DeepCopyInto(out *CoreServiceConfig) { + *out = *in + if in.HTTPPort != nil { + in, out := &in.HTTPPort, &out.HTTPPort + *out = new(int32) + **out = **in + } + if in.JMXPort != nil { + in, out := &in.JMXPort, &out.JMXPort + *out = new(int32) + **out = **in + } + in.ServiceConfig.DeepCopyInto(&out.ServiceConfig) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CoreServiceConfig. +func (in *CoreServiceConfig) DeepCopy() *CoreServiceConfig { + if in == nil { + return nil + } + out := new(CoreServiceConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Cryostat) DeepCopyInto(out *Cryostat) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Cryostat. +func (in *Cryostat) DeepCopy() *Cryostat { + if in == nil { + return nil + } + out := new(Cryostat) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Cryostat) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CryostatList) DeepCopyInto(out *CryostatList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Cryostat, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CryostatList. +func (in *CryostatList) DeepCopy() *CryostatList { + if in == nil { + return nil + } + out := new(CryostatList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CryostatList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CryostatSpec) DeepCopyInto(out *CryostatSpec) { + *out = *in + if in.TargetNamespaces != nil { + in, out := &in.TargetNamespaces, &out.TargetNamespaces + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.TrustedCertSecrets != nil { + in, out := &in.TrustedCertSecrets, &out.TrustedCertSecrets + *out = make([]CertificateSecret, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.EventTemplates != nil { + in, out := &in.EventTemplates, &out.EventTemplates + *out = make([]TemplateConfigMap, len(*in)) + copy(*out, *in) + } + if in.EnableCertManager != nil { + in, out := &in.EnableCertManager, &out.EnableCertManager + *out = new(bool) + **out = **in + } + if in.StorageOptions != nil { + in, out := &in.StorageOptions, &out.StorageOptions + *out = new(StorageConfiguration) + (*in).DeepCopyInto(*out) + } + if in.ServiceOptions != nil { + in, out := &in.ServiceOptions, &out.ServiceOptions + *out = new(ServiceConfigList) + (*in).DeepCopyInto(*out) + } + if in.NetworkOptions != nil { + in, out := &in.NetworkOptions, &out.NetworkOptions + *out = new(NetworkConfigurationList) + (*in).DeepCopyInto(*out) + } + if in.ReportOptions != nil { + in, out := &in.ReportOptions, &out.ReportOptions + *out = new(ReportConfiguration) + (*in).DeepCopyInto(*out) + } + if in.JmxCacheOptions != nil { + in, out := &in.JmxCacheOptions, &out.JmxCacheOptions + *out = new(JmxCacheOptions) + **out = **in + } + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = new(ResourceConfigList) + (*in).DeepCopyInto(*out) + } + if in.AuthProperties != nil { + in, out := &in.AuthProperties, &out.AuthProperties + *out = new(AuthorizationProperties) + **out = **in + } + if in.SecurityOptions != nil { + in, out := &in.SecurityOptions, &out.SecurityOptions + *out = new(SecurityOptions) + (*in).DeepCopyInto(*out) + } + if in.SchedulingOptions != nil { + in, out := &in.SchedulingOptions, &out.SchedulingOptions + *out = new(SchedulingConfiguration) + (*in).DeepCopyInto(*out) + } + if in.TargetDiscoveryOptions != nil { + in, out := &in.TargetDiscoveryOptions, &out.TargetDiscoveryOptions + *out = new(TargetDiscoveryOptions) + **out = **in + } + if in.JmxCredentialsDatabaseOptions != nil { + in, out := &in.JmxCredentialsDatabaseOptions, &out.JmxCredentialsDatabaseOptions + *out = new(JmxCredentialsDatabaseOptions) + (*in).DeepCopyInto(*out) + } + if in.OperandMetadata != nil { + in, out := &in.OperandMetadata, &out.OperandMetadata + *out = new(OperandMetadata) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CryostatSpec. +func (in *CryostatSpec) DeepCopy() *CryostatSpec { + if in == nil { + return nil + } + out := new(CryostatSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CryostatStatus) DeepCopyInto(out *CryostatStatus) { + *out = *in + if in.TargetNamespaces != nil { + in, out := &in.TargetNamespaces, &out.TargetNamespaces + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CryostatStatus. +func (in *CryostatStatus) DeepCopy() *CryostatStatus { + if in == nil { + return nil + } + out := new(CryostatStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EmptyDirConfig) DeepCopyInto(out *EmptyDirConfig) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EmptyDirConfig. +func (in *EmptyDirConfig) DeepCopy() *EmptyDirConfig { + if in == nil { + return nil + } + out := new(EmptyDirConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GrafanaServiceConfig) DeepCopyInto(out *GrafanaServiceConfig) { + *out = *in + if in.HTTPPort != nil { + in, out := &in.HTTPPort, &out.HTTPPort + *out = new(int32) + **out = **in + } + in.ServiceConfig.DeepCopyInto(&out.ServiceConfig) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GrafanaServiceConfig. +func (in *GrafanaServiceConfig) DeepCopy() *GrafanaServiceConfig { + if in == nil { + return nil + } + out := new(GrafanaServiceConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JmxCacheOptions) DeepCopyInto(out *JmxCacheOptions) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JmxCacheOptions. +func (in *JmxCacheOptions) DeepCopy() *JmxCacheOptions { + if in == nil { + return nil + } + out := new(JmxCacheOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *JmxCredentialsDatabaseOptions) DeepCopyInto(out *JmxCredentialsDatabaseOptions) { + *out = *in + if in.DatabaseSecretName != nil { + in, out := &in.DatabaseSecretName, &out.DatabaseSecretName + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JmxCredentialsDatabaseOptions. +func (in *JmxCredentialsDatabaseOptions) DeepCopy() *JmxCredentialsDatabaseOptions { + if in == nil { + return nil + } + out := new(JmxCredentialsDatabaseOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkConfiguration) DeepCopyInto(out *NetworkConfiguration) { + *out = *in + if in.IngressSpec != nil { + in, out := &in.IngressSpec, &out.IngressSpec + *out = new(networkingv1.IngressSpec) + (*in).DeepCopyInto(*out) + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkConfiguration. +func (in *NetworkConfiguration) DeepCopy() *NetworkConfiguration { + if in == nil { + return nil + } + out := new(NetworkConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NetworkConfigurationList) DeepCopyInto(out *NetworkConfigurationList) { + *out = *in + if in.CoreConfig != nil { + in, out := &in.CoreConfig, &out.CoreConfig + *out = new(NetworkConfiguration) + (*in).DeepCopyInto(*out) + } + if in.CommandConfig != nil { + in, out := &in.CommandConfig, &out.CommandConfig + *out = new(NetworkConfiguration) + (*in).DeepCopyInto(*out) + } + if in.GrafanaConfig != nil { + in, out := &in.GrafanaConfig, &out.GrafanaConfig + *out = new(NetworkConfiguration) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkConfigurationList. +func (in *NetworkConfigurationList) DeepCopy() *NetworkConfigurationList { + if in == nil { + return nil + } + out := new(NetworkConfigurationList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OperandMetadata) DeepCopyInto(out *OperandMetadata) { + *out = *in + if in.DeploymentMetadata != nil { + in, out := &in.DeploymentMetadata, &out.DeploymentMetadata + *out = new(ResourceMetadata) + (*in).DeepCopyInto(*out) + } + if in.PodMetadata != nil { + in, out := &in.PodMetadata, &out.PodMetadata + *out = new(ResourceMetadata) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OperandMetadata. +func (in *OperandMetadata) DeepCopy() *OperandMetadata { + if in == nil { + return nil + } + out := new(OperandMetadata) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PersistentVolumeClaimConfig) DeepCopyInto(out *PersistentVolumeClaimConfig) { + *out = *in + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Spec != nil { + in, out := &in.Spec, &out.Spec + *out = new(corev1.PersistentVolumeClaimSpec) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PersistentVolumeClaimConfig. +func (in *PersistentVolumeClaimConfig) DeepCopy() *PersistentVolumeClaimConfig { + if in == nil { + return nil + } + out := new(PersistentVolumeClaimConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReportConfiguration) DeepCopyInto(out *ReportConfiguration) { + *out = *in + in.Resources.DeepCopyInto(&out.Resources) + if in.SecurityOptions != nil { + in, out := &in.SecurityOptions, &out.SecurityOptions + *out = new(ReportsSecurityOptions) + (*in).DeepCopyInto(*out) + } + if in.SchedulingOptions != nil { + in, out := &in.SchedulingOptions, &out.SchedulingOptions + *out = new(SchedulingConfiguration) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReportConfiguration. +func (in *ReportConfiguration) DeepCopy() *ReportConfiguration { + if in == nil { + return nil + } + out := new(ReportConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReportsSecurityOptions) DeepCopyInto(out *ReportsSecurityOptions) { + *out = *in + if in.PodSecurityContext != nil { + in, out := &in.PodSecurityContext, &out.PodSecurityContext + *out = new(corev1.PodSecurityContext) + (*in).DeepCopyInto(*out) + } + if in.ReportsSecurityContext != nil { + in, out := &in.ReportsSecurityContext, &out.ReportsSecurityContext + *out = new(corev1.SecurityContext) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReportsSecurityOptions. +func (in *ReportsSecurityOptions) DeepCopy() *ReportsSecurityOptions { + if in == nil { + return nil + } + out := new(ReportsSecurityOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReportsServiceConfig) DeepCopyInto(out *ReportsServiceConfig) { + *out = *in + if in.HTTPPort != nil { + in, out := &in.HTTPPort, &out.HTTPPort + *out = new(int32) + **out = **in + } + in.ServiceConfig.DeepCopyInto(&out.ServiceConfig) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReportsServiceConfig. +func (in *ReportsServiceConfig) DeepCopy() *ReportsServiceConfig { + if in == nil { + return nil + } + out := new(ReportsServiceConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceConfigList) DeepCopyInto(out *ResourceConfigList) { + *out = *in + in.CoreResources.DeepCopyInto(&out.CoreResources) + in.DataSourceResources.DeepCopyInto(&out.DataSourceResources) + in.GrafanaResources.DeepCopyInto(&out.GrafanaResources) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceConfigList. +func (in *ResourceConfigList) DeepCopy() *ResourceConfigList { + if in == nil { + return nil + } + out := new(ResourceConfigList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceMetadata) DeepCopyInto(out *ResourceMetadata) { + *out = *in + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceMetadata. +func (in *ResourceMetadata) DeepCopy() *ResourceMetadata { + if in == nil { + return nil + } + out := new(ResourceMetadata) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SchedulingConfiguration) DeepCopyInto(out *SchedulingConfiguration) { + *out = *in + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Affinity != nil { + in, out := &in.Affinity, &out.Affinity + *out = new(Affinity) + (*in).DeepCopyInto(*out) + } + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]corev1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SchedulingConfiguration. +func (in *SchedulingConfiguration) DeepCopy() *SchedulingConfiguration { + if in == nil { + return nil + } + out := new(SchedulingConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecurityOptions) DeepCopyInto(out *SecurityOptions) { + *out = *in + if in.PodSecurityContext != nil { + in, out := &in.PodSecurityContext, &out.PodSecurityContext + *out = new(corev1.PodSecurityContext) + (*in).DeepCopyInto(*out) + } + if in.CoreSecurityContext != nil { + in, out := &in.CoreSecurityContext, &out.CoreSecurityContext + *out = new(corev1.SecurityContext) + (*in).DeepCopyInto(*out) + } + if in.DataSourceSecurityContext != nil { + in, out := &in.DataSourceSecurityContext, &out.DataSourceSecurityContext + *out = new(corev1.SecurityContext) + (*in).DeepCopyInto(*out) + } + if in.GrafanaSecurityContext != nil { + in, out := &in.GrafanaSecurityContext, &out.GrafanaSecurityContext + *out = new(corev1.SecurityContext) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecurityOptions. +func (in *SecurityOptions) DeepCopy() *SecurityOptions { + if in == nil { + return nil + } + out := new(SecurityOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceConfig) DeepCopyInto(out *ServiceConfig) { + *out = *in + if in.ServiceType != nil { + in, out := &in.ServiceType, &out.ServiceType + *out = new(corev1.ServiceType) + **out = **in + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceConfig. +func (in *ServiceConfig) DeepCopy() *ServiceConfig { + if in == nil { + return nil + } + out := new(ServiceConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ServiceConfigList) DeepCopyInto(out *ServiceConfigList) { + *out = *in + if in.CoreConfig != nil { + in, out := &in.CoreConfig, &out.CoreConfig + *out = new(CoreServiceConfig) + (*in).DeepCopyInto(*out) + } + if in.GrafanaConfig != nil { + in, out := &in.GrafanaConfig, &out.GrafanaConfig + *out = new(GrafanaServiceConfig) + (*in).DeepCopyInto(*out) + } + if in.ReportsConfig != nil { + in, out := &in.ReportsConfig, &out.ReportsConfig + *out = new(ReportsServiceConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceConfigList. +func (in *ServiceConfigList) DeepCopy() *ServiceConfigList { + if in == nil { + return nil + } + out := new(ServiceConfigList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *StorageConfiguration) DeepCopyInto(out *StorageConfiguration) { + *out = *in + if in.PVC != nil { + in, out := &in.PVC, &out.PVC + *out = new(PersistentVolumeClaimConfig) + (*in).DeepCopyInto(*out) + } + if in.EmptyDir != nil { + in, out := &in.EmptyDir, &out.EmptyDir + *out = new(EmptyDirConfig) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageConfiguration. +func (in *StorageConfiguration) DeepCopy() *StorageConfiguration { + if in == nil { + return nil + } + out := new(StorageConfiguration) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TargetDiscoveryOptions) DeepCopyInto(out *TargetDiscoveryOptions) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TargetDiscoveryOptions. +func (in *TargetDiscoveryOptions) DeepCopy() *TargetDiscoveryOptions { + if in == nil { + return nil + } + out := new(TargetDiscoveryOptions) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TemplateConfigMap) DeepCopyInto(out *TemplateConfigMap) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TemplateConfigMap. +func (in *TemplateConfigMap) DeepCopy() *TemplateConfigMap { + if in == nil { + return nil + } + out := new(TemplateConfigMap) + in.DeepCopyInto(out) + return out +} diff --git a/bundle/manifests/cryostat-operator-webhook-service_v1_service.yaml b/bundle/manifests/cryostat-operator-webhook-service_v1_service.yaml new file mode 100644 index 000000000..0e7a3b06a --- /dev/null +++ b/bundle/manifests/cryostat-operator-webhook-service_v1_service.yaml @@ -0,0 +1,21 @@ +apiVersion: v1 +kind: Service +metadata: + creationTimestamp: null + labels: + app.kubernetes.io/component: webhook + app.kubernetes.io/created-by: cryostat-operator + app.kubernetes.io/instance: webhook-service + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: service + app.kubernetes.io/part-of: cryostat-operator + name: cryostat-operator-webhook-service +spec: + ports: + - port: 443 + protocol: TCP + targetPort: 9443 + selector: + control-plane: controller-manager +status: + loadBalancer: {} diff --git a/bundle/manifests/cryostat-operator.clusterserviceversion.yaml b/bundle/manifests/cryostat-operator.clusterserviceversion.yaml index 6cfe13ae4..83d78572a 100644 --- a/bundle/manifests/cryostat-operator.clusterserviceversion.yaml +++ b/bundle/manifests/cryostat-operator.clusterserviceversion.yaml @@ -49,16 +49,62 @@ metadata: }, "trustedCertSecrets": [] } + }, + { + "apiVersion": "operator.cryostat.io/v1beta2", + "kind": "ClusterCryostat", + "metadata": { + "name": "clustercryostat-sample" + }, + "spec": { + "enableCertManager": true, + "eventTemplates": [], + "minimal": false, + "reportOptions": { + "replicas": 0 + }, + "storageOptions": { + "pvc": { + "annotations": {}, + "labels": {}, + "spec": {} + } + }, + "trustedCertSecrets": [] + } + }, + { + "apiVersion": "operator.cryostat.io/v1beta2", + "kind": "Cryostat", + "metadata": { + "name": "cryostat-sample" + }, + "spec": { + "enableCertManager": true, + "eventTemplates": [], + "minimal": false, + "reportOptions": { + "replicas": 0 + }, + "storageOptions": { + "pvc": { + "annotations": {}, + "labels": {}, + "spec": {} + } + }, + "trustedCertSecrets": [] + } } ] capabilities: Seamless Upgrades categories: Monitoring, Developer Tools containerImage: quay.io/cryostat/cryostat-operator:2.5.0-dev - createdAt: "2024-02-12T21:32:06Z" + createdAt: "2024-02-12T22:09:00Z" description: JVM monitoring and profiling tool operatorframework.io/initialization-resource: |- { - "apiVersion": "operator.cryostat.io/v1beta1", + "apiVersion": "operator.cryostat.io/v1beta2", "kind": "Cryostat", "metadata": { "name": "cryostat-sample" @@ -116,18 +162,815 @@ spec: name: "" version: v1 specDescriptors: - - description: Namespace where Cryostat should be installed. On multi-tenant - clusters, we strongly suggest installing Cryostat into its own namespace. - displayName: Install Namespace - path: installNamespace - x-descriptors: - - urn:alm:descriptor:io.kubernetes:Namespace - - description: 'List of namespaces whose workloads Cryostat should be permitted - to access and profile. Warning: All Cryostat users will be able to create - and manage recordings for workloads in the listed namespaces. More details: - https://github.com/cryostatio/cryostat-operator/blob/v2.3.0/docs/multi-namespace.md#data-isolation' - displayName: Target Namespaces - path: targetNamespaces + - description: Namespace where Cryostat should be installed. On multi-tenant + clusters, we strongly suggest installing Cryostat into its own namespace. + displayName: Install Namespace + path: installNamespace + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Namespace + - description: 'List of namespaces whose workloads Cryostat should be permitted + to access and profile. Warning: All Cryostat users will be able to create + and manage recordings for workloads in the listed namespaces. More details: + https://github.com/cryostatio/cryostat-operator/blob/v2.3.0/docs/multi-namespace.md#data-isolation' + displayName: Target Namespaces + path: targetNamespaces + - description: Use cert-manager to secure in-cluster communication between Cryostat + components. Requires cert-manager to be installed. + displayName: Enable cert-manager Integration + path: enableCertManager + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Deploy a pared-down Cryostat instance with no Grafana Dashboard + or JFR Data Source. + displayName: Minimal Deployment + path: minimal + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Override default authorization properties for Cryostat on OpenShift. + displayName: Authorization Properties + path: authProperties + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - description: 'Name of the ClusterRole to use when Cryostat requests a role-scoped + OAuth token. This ClusterRole should contain permissions for all Kubernetes + objects listed in custom permission mapping. More details: https://docs.openshift.com/container-platform/4.11/authentication/tokens-scoping.html#scoping-tokens-role-scope_configuring-internal-oauth' + displayName: ClusterRole Name + path: authProperties.clusterRoleName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:ClusterRole + - description: Name of config map in the local namespace. + displayName: ConfigMap Name + path: authProperties.configMapName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:ConfigMap + - description: Filename within config map containing the resource mapping. + displayName: Filename + path: authProperties.filename + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:text + - description: List of Flight Recorder Event Templates to preconfigure in Cryostat. + displayName: Event Templates + path: eventTemplates + - description: Name of config map in the local namespace. + displayName: Config Map Name + path: eventTemplates[0].configMapName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:ConfigMap + - description: Options to customize the JMX target connections cache for the + Cryostat application. + displayName: JMX Connections Cache Options + path: jmxCacheOptions + - description: The maximum number of JMX connections to cache. Use `-1` for + an unlimited cache size (TTL expiration only). Defaults to `-1`. + displayName: Target Cache Size + path: jmxCacheOptions.targetCacheSize + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: The time to live (in seconds) for cached JMX connections. Defaults + to `10`. + displayName: Target Cache TTL + path: jmxCacheOptions.targetCacheTTL + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: Options to configure the Cryostat application's credentials database. + displayName: Credentials Database Options + path: jmxCredentialsDatabaseOptions + - description: Name of the secret containing the password to encrypt credentials + database. + displayName: Database Secret Name + path: jmxCredentialsDatabaseOptions.databaseSecretName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + - description: The maximum number of WebSocket client connections allowed (minimum + 1, default unlimited). + displayName: Max WebSocket Connections + path: maxWsConnections + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: Options to control how the operator exposes the application outside + of the cluster, such as using an Ingress or Route. + displayName: Network Options + path: networkOptions + - description: "Specifications for how to expose the Cryostat command service, + which serves the WebSocket command channel. \n Deprecated: CommandConfig + is no longer used." + displayName: Command Config + path: networkOptions.commandConfig + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:hidden + - description: Annotations to add to the Ingress or Route during its creation. + displayName: Annotations + path: networkOptions.commandConfig.annotations + - description: Configuration for an Ingress object. Currently subpaths are not + supported, so unique hosts must be specified (if a single external IP is + being used) to differentiate between ingresses/services. + displayName: Ingress Spec + path: networkOptions.commandConfig.ingressSpec + - description: Labels to add to the Ingress or Route during its creation. The + label with key "app" is reserved for use by the operator. + displayName: Labels + path: networkOptions.commandConfig.labels + - description: Specifications for how to expose the Cryostat service, which + serves the Cryostat application. + displayName: Core Config + path: networkOptions.coreConfig + - description: Annotations to add to the Ingress or Route during its creation. + displayName: Annotations + path: networkOptions.coreConfig.annotations + - description: Configuration for an Ingress object. Currently subpaths are not + supported, so unique hosts must be specified (if a single external IP is + being used) to differentiate between ingresses/services. + displayName: Ingress Spec + path: networkOptions.coreConfig.ingressSpec + - description: Labels to add to the Ingress or Route during its creation. The + label with key "app" is reserved for use by the operator. + displayName: Labels + path: networkOptions.coreConfig.labels + - description: Specifications for how to expose Cryostat's Grafana service, + which serves the Grafana dashboard. + displayName: Grafana Config + path: networkOptions.grafanaConfig + - description: Annotations to add to the Ingress or Route during its creation. + displayName: Annotations + path: networkOptions.grafanaConfig.annotations + - description: Configuration for an Ingress object. Currently subpaths are not + supported, so unique hosts must be specified (if a single external IP is + being used) to differentiate between ingresses/services. + displayName: Ingress Spec + path: networkOptions.grafanaConfig.ingressSpec + - description: Labels to add to the Ingress or Route during its creation. The + label with key "app" is reserved for use by the operator. + displayName: Labels + path: networkOptions.grafanaConfig.labels + - description: Options to configure the Cryostat deployments and pods metadata + displayName: Operand metadata + path: operandMetadata + - description: Options to configure the Cryostat deployments metadata + displayName: Deployments metadata + path: operandMetadata.deploymentMetadata + - description: Options to configure the Cryostat pods metadata + displayName: Pods metadata + path: operandMetadata.podMetadata + - description: Options to configure Cryostat Automated Report Analysis. + displayName: Report Options + path: reportOptions + - description: The number of report sidecar replica containers to deploy. Each + replica can service one report generation request at a time. + displayName: Replicas + path: reportOptions.replicas + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podCount + - description: The resources allocated to each sidecar replica. A replica with + more resources can handle larger input recordings and will process them + faster. + displayName: Resources + path: reportOptions.resources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + - description: Options to configure scheduling for the reports deployment + displayName: Scheduling Options + path: reportOptions.schedulingOptions + - description: Affinity rules for scheduling Cryostat pods. + displayName: Affinity + path: reportOptions.schedulingOptions.affinity + - description: 'Node affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#NodeAffinity' + displayName: Node Affinity + path: reportOptions.schedulingOptions.affinity.nodeAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:nodeAffinity + - description: 'Pod affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAffinity' + displayName: Pod Affinity + path: reportOptions.schedulingOptions.affinity.podAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podAffinity + - description: 'Pod anti-affinity scheduling rules for a Cryostat pod. See: + https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAntiAffinity' + displayName: Pod Anti Affinity + path: reportOptions.schedulingOptions.affinity.podAntiAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podAntiAffinity + - description: 'Label selector used to schedule a Cryostat pod to a node. See: + https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + displayName: Node Selector + path: reportOptions.schedulingOptions.nodeSelector + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:selector:core:v1:Node + - description: 'Tolerations to allow scheduling of Cryostat pods to tainted + nodes. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/' + displayName: Tolerations + path: reportOptions.schedulingOptions.tolerations + - description: Options to configure the Security Contexts for the Cryostat report + generator. + displayName: Security Options + path: reportOptions.securityOptions + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - description: Security Context to apply to the Cryostat report generator pod. + displayName: Pod Security Context + path: reportOptions.securityOptions.podSecurityContext + - description: Security Context to apply to the Cryostat report generator container. + displayName: Reports Security Context + path: reportOptions.securityOptions.reportsSecurityContext + - description: When zero report sidecar replicas are requested, SubProcessMaxHeapSize + configures the maximum heap size of the basic subprocess report generator + in MiB. The default heap size is `200` (MiB). + displayName: Sub Process Max Heap Size + path: reportOptions.subProcessMaxHeapSize + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: Resource requirements for the Cryostat deployment. + displayName: Resources + path: resources + - description: Resource requirements for the Cryostat application. If specifying + a memory limit, at least 768MiB is recommended. + displayName: Core Resources + path: resources.coreResources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + - description: Resource requirements for the JFR Data Source container. + displayName: Data Source Resources + path: resources.dataSourceResources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + - description: Resource requirements for the Grafana container. + displayName: Grafana Resources + path: resources.grafanaResources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + - description: Options to configure scheduling for the Cryostat deployment + displayName: Scheduling Options + path: schedulingOptions + - description: Affinity rules for scheduling Cryostat pods. + displayName: Affinity + path: schedulingOptions.affinity + - description: 'Node affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#NodeAffinity' + displayName: Node Affinity + path: schedulingOptions.affinity.nodeAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:nodeAffinity + - description: 'Pod affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAffinity' + displayName: Pod Affinity + path: schedulingOptions.affinity.podAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podAffinity + - description: 'Pod anti-affinity scheduling rules for a Cryostat pod. See: + https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAntiAffinity' + displayName: Pod Anti Affinity + path: schedulingOptions.affinity.podAntiAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podAntiAffinity + - description: 'Label selector used to schedule a Cryostat pod to a node. See: + https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + displayName: Node Selector + path: schedulingOptions.nodeSelector + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:selector:core:v1:Node + - description: 'Tolerations to allow scheduling of Cryostat pods to tainted + nodes. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/' + displayName: Tolerations + path: schedulingOptions.tolerations + - description: Options to configure the Security Contexts for the Cryostat application. + displayName: Security Options + path: securityOptions + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - description: Security Context to apply to the Cryostat application container. + displayName: Core Security Context + path: securityOptions.coreSecurityContext + - description: Security Context to apply to the JFR Data Source container. + displayName: Data Source Security Context + path: securityOptions.dataSourceSecurityContext + - description: Security Context to apply to the Grafana container. + displayName: Grafana Security Context + path: securityOptions.grafanaSecurityContext + - description: Security Context to apply to the Cryostat pod. + displayName: Pod Security Context + path: securityOptions.podSecurityContext + - description: Options to customize the services created for the Cryostat application + and Grafana dashboard. + displayName: Service Options + path: serviceOptions + - description: Options to customize the storage for Flight Recordings and Templates. + displayName: Storage Options + path: storageOptions + - description: Configuration for an EmptyDir to be created by the operator instead + of a PVC. + displayName: Empty Dir + path: storageOptions.emptyDir + - description: When enabled, Cryostat will use EmptyDir volumes instead of a + Persistent Volume Claim. Any PVC configurations will be ignored. + displayName: Enabled + path: storageOptions.emptyDir.enabled + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Unless specified, the emptyDir volume will be mounted on the + same storage medium backing the node. Setting this field to "Memory" will + mount the emptyDir on a tmpfs (RAM-backed filesystem). + displayName: Medium + path: storageOptions.emptyDir.medium + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:fieldDependency:storageOptions.emptyDir.enabled:true + - description: The maximum memory limit for the emptyDir. Default is unbounded. + displayName: Size Limit + path: storageOptions.emptyDir.sizeLimit + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:fieldDependency:storageOptions.emptyDir.enabled:true + - description: Configuration for the Persistent Volume Claim to be created by + the operator. + displayName: PVC + path: storageOptions.pvc + - description: Spec for a Persistent Volume Claim, whose options will override + the defaults used by the operator. Unless overriden, the PVC will be created + with the default Storage Class and 500MiB of storage. Once the operator + has created the PVC, changes to this field have no effect. + displayName: Spec + path: storageOptions.pvc.spec + - description: Options to configure the Cryostat application's target discovery + mechanisms. + displayName: Target Discovery Options + path: targetDiscoveryOptions + - description: When true, the Cryostat application will disable the built-in + discovery mechanisms. Defaults to false + displayName: Disable Built-in Discovery + path: targetDiscoveryOptions.builtInDiscoveryDisabled + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: List of TLS certificates to trust when connecting to targets. + displayName: Trusted TLS Certificates + path: trustedCertSecrets + - description: Name of secret in the local namespace. + displayName: Secret Name + path: trustedCertSecrets[0].secretName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + - description: A namespace whose workloads Cryostat should be able to connect + and record + displayName: Target Namespace + path: targetNamespaces[0] + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Namespace + statusDescriptors: + - description: Address of the deployed Cryostat web application. + displayName: Application URL + path: applicationUrl + x-descriptors: + - urn:alm:descriptor:org.w3:link + - description: Name of the Secret containing the generated Grafana credentials. + displayName: Grafana Secret + path: grafanaSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + - description: List of namespaces that Cryostat has been configured and authorized + to access and profile. + displayName: Target Namespaces + path: targetNamespaces + - description: Conditions of the components managed by the Cryostat Operator. + displayName: Cryostat Conditions + path: conditions + x-descriptors: + - urn:alm:descriptor:io.kubernetes.conditions + - description: A namespace whose workloads Cryostat should be able to connect + and record + displayName: Target Namespace + path: targetNamespaces[0] + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Namespace + version: v1beta1 + - description: ClusterCryostat allows you to install Cryostat for multiple namespaces + or cluster-wide. It contains configuration options for controlling the Deployment + of the Cryostat application and its related components. A ClusterCryostat + or Cryostat instance must be created to instruct the operator to deploy the + Cryostat application. + displayName: Cluster Cryostat + kind: ClusterCryostat + name: clustercryostats.operator.cryostat.io + resources: + - kind: ConsoleLink + name: "" + version: v1 + - kind: Deployment + name: "" + version: v1 + - kind: Ingress + name: "" + version: v1 + - kind: PersistentVolumeClaim + name: "" + version: v1 + - kind: Route + name: "" + version: v1 + - kind: Secret + name: "" + version: v1 + - kind: Service + name: "" + version: v1 + specDescriptors: + - description: Namespace where Cryostat should be installed. On multi-tenant + clusters, we strongly suggest installing Cryostat into its own namespace. + displayName: Install Namespace + path: installNamespace + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Namespace + - description: 'List of namespaces whose workloads Cryostat should be permitted + to access and profile. Defaults to this Cryostat''s namespace. Warning: + All Cryostat users will be able to create and manage recordings for workloads + in the listed namespaces. More details: https://github.com/cryostatio/cryostat-operator/blob/v2.4.0/docs/multi-namespace.md#data-isolation' + displayName: Target Namespaces + path: targetNamespaces + - description: Use cert-manager to secure in-cluster communication between Cryostat + components. Requires cert-manager to be installed. + displayName: Enable cert-manager Integration + path: enableCertManager + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Deploy a pared-down Cryostat instance with no Grafana Dashboard + or JFR Data Source. + displayName: Minimal Deployment + path: minimal + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Override default authorization properties for Cryostat on OpenShift. + displayName: Authorization Properties + path: authProperties + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - description: 'Name of the ClusterRole to use when Cryostat requests a role-scoped + OAuth token. This ClusterRole should contain permissions for all Kubernetes + objects listed in custom permission mapping. More details: https://docs.openshift.com/container-platform/4.11/authentication/tokens-scoping.html#scoping-tokens-role-scope_configuring-internal-oauth' + displayName: ClusterRole Name + path: authProperties.clusterRoleName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:ClusterRole + - description: Name of config map in the local namespace. + displayName: ConfigMap Name + path: authProperties.configMapName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:ConfigMap + - description: Filename within config map containing the resource mapping. + displayName: Filename + path: authProperties.filename + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:text + - description: List of Flight Recorder Event Templates to preconfigure in Cryostat. + displayName: Event Templates + path: eventTemplates + - description: Name of config map in the local namespace. + displayName: Config Map Name + path: eventTemplates[0].configMapName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:ConfigMap + - description: Options to customize the JMX target connections cache for the + Cryostat application. + displayName: JMX Connections Cache Options + path: jmxCacheOptions + - description: The maximum number of JMX connections to cache. Use `-1` for + an unlimited cache size (TTL expiration only). Defaults to `-1`. + displayName: Target Cache Size + path: jmxCacheOptions.targetCacheSize + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: The time to live (in seconds) for cached JMX connections. Defaults + to `10`. + displayName: Target Cache TTL + path: jmxCacheOptions.targetCacheTTL + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: Options to configure the Cryostat application's credentials database. + displayName: Credentials Database Options + path: jmxCredentialsDatabaseOptions + - description: Name of the secret containing the password to encrypt credentials + database. + displayName: Database Secret Name + path: jmxCredentialsDatabaseOptions.databaseSecretName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + - description: The maximum number of WebSocket client connections allowed (minimum + 1, default unlimited). + displayName: Max WebSocket Connections + path: maxWsConnections + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: Options to control how the operator exposes the application outside + of the cluster, such as using an Ingress or Route. + displayName: Network Options + path: networkOptions + - description: "Specifications for how to expose the Cryostat command service, + which serves the WebSocket command channel. \n Deprecated: CommandConfig + is no longer used." + displayName: Command Config + path: networkOptions.commandConfig + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:hidden + - description: Annotations to add to the Ingress or Route during its creation. + displayName: Annotations + path: networkOptions.commandConfig.annotations + - description: Configuration for an Ingress object. Currently subpaths are not + supported, so unique hosts must be specified (if a single external IP is + being used) to differentiate between ingresses/services. + displayName: Ingress Spec + path: networkOptions.commandConfig.ingressSpec + - description: Labels to add to the Ingress or Route during its creation. The + label with key "app" is reserved for use by the operator. + displayName: Labels + path: networkOptions.commandConfig.labels + - description: Specifications for how to expose the Cryostat service, which + serves the Cryostat application. + displayName: Core Config + path: networkOptions.coreConfig + - description: Annotations to add to the Ingress or Route during its creation. + displayName: Annotations + path: networkOptions.coreConfig.annotations + - description: Configuration for an Ingress object. Currently subpaths are not + supported, so unique hosts must be specified (if a single external IP is + being used) to differentiate between ingresses/services. + displayName: Ingress Spec + path: networkOptions.coreConfig.ingressSpec + - description: Labels to add to the Ingress or Route during its creation. The + label with key "app" is reserved for use by the operator. + displayName: Labels + path: networkOptions.coreConfig.labels + - description: Specifications for how to expose Cryostat's Grafana service, + which serves the Grafana dashboard. + displayName: Grafana Config + path: networkOptions.grafanaConfig + - description: Annotations to add to the Ingress or Route during its creation. + displayName: Annotations + path: networkOptions.grafanaConfig.annotations + - description: Configuration for an Ingress object. Currently subpaths are not + supported, so unique hosts must be specified (if a single external IP is + being used) to differentiate between ingresses/services. + displayName: Ingress Spec + path: networkOptions.grafanaConfig.ingressSpec + - description: Labels to add to the Ingress or Route during its creation. The + label with key "app" is reserved for use by the operator. + displayName: Labels + path: networkOptions.grafanaConfig.labels + - description: Options to configure the Cryostat deployments and pods metadata + displayName: Operand metadata + path: operandMetadata + - description: Options to configure the Cryostat deployments metadata + displayName: Deployments metadata + path: operandMetadata.deploymentMetadata + - description: Options to configure the Cryostat pods metadata + displayName: Pods metadata + path: operandMetadata.podMetadata + - description: Options to configure Cryostat Automated Report Analysis. + displayName: Report Options + path: reportOptions + - description: The number of report sidecar replica containers to deploy. Each + replica can service one report generation request at a time. + displayName: Replicas + path: reportOptions.replicas + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podCount + - description: The resources allocated to each sidecar replica. A replica with + more resources can handle larger input recordings and will process them + faster. + displayName: Resources + path: reportOptions.resources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + - description: Options to configure scheduling for the reports deployment + displayName: Scheduling Options + path: reportOptions.schedulingOptions + - description: Affinity rules for scheduling Cryostat pods. + displayName: Affinity + path: reportOptions.schedulingOptions.affinity + - description: 'Node affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#NodeAffinity' + displayName: Node Affinity + path: reportOptions.schedulingOptions.affinity.nodeAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:nodeAffinity + - description: 'Pod affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAffinity' + displayName: Pod Affinity + path: reportOptions.schedulingOptions.affinity.podAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podAffinity + - description: 'Pod anti-affinity scheduling rules for a Cryostat pod. See: + https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAntiAffinity' + displayName: Pod Anti Affinity + path: reportOptions.schedulingOptions.affinity.podAntiAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podAntiAffinity + - description: 'Label selector used to schedule a Cryostat pod to a node. See: + https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + displayName: Node Selector + path: reportOptions.schedulingOptions.nodeSelector + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:selector:core:v1:Node + - description: 'Tolerations to allow scheduling of Cryostat pods to tainted + nodes. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/' + displayName: Tolerations + path: reportOptions.schedulingOptions.tolerations + - description: Options to configure the Security Contexts for the Cryostat report + generator. + displayName: Security Options + path: reportOptions.securityOptions + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - description: Security Context to apply to the Cryostat report generator pod. + displayName: Pod Security Context + path: reportOptions.securityOptions.podSecurityContext + - description: Security Context to apply to the Cryostat report generator container. + displayName: Reports Security Context + path: reportOptions.securityOptions.reportsSecurityContext + - description: When zero report sidecar replicas are requested, SubProcessMaxHeapSize + configures the maximum heap size of the basic subprocess report generator + in MiB. The default heap size is `200` (MiB). + displayName: Sub Process Max Heap Size + path: reportOptions.subProcessMaxHeapSize + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: Resource requirements for the Cryostat deployment. + displayName: Resources + path: resources + - description: Resource requirements for the Cryostat application. If specifying + a memory limit, at least 768MiB is recommended. + displayName: Core Resources + path: resources.coreResources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + - description: Resource requirements for the JFR Data Source container. + displayName: Data Source Resources + path: resources.dataSourceResources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + - description: Resource requirements for the Grafana container. + displayName: Grafana Resources + path: resources.grafanaResources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + - description: Options to configure scheduling for the Cryostat deployment + displayName: Scheduling Options + path: schedulingOptions + - description: Affinity rules for scheduling Cryostat pods. + displayName: Affinity + path: schedulingOptions.affinity + - description: 'Node affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#NodeAffinity' + displayName: Node Affinity + path: schedulingOptions.affinity.nodeAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:nodeAffinity + - description: 'Pod affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAffinity' + displayName: Pod Affinity + path: schedulingOptions.affinity.podAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podAffinity + - description: 'Pod anti-affinity scheduling rules for a Cryostat pod. See: + https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAntiAffinity' + displayName: Pod Anti Affinity + path: schedulingOptions.affinity.podAntiAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podAntiAffinity + - description: 'Label selector used to schedule a Cryostat pod to a node. See: + https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + displayName: Node Selector + path: schedulingOptions.nodeSelector + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:selector:core:v1:Node + - description: 'Tolerations to allow scheduling of Cryostat pods to tainted + nodes. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/' + displayName: Tolerations + path: schedulingOptions.tolerations + - description: Options to configure the Security Contexts for the Cryostat application. + displayName: Security Options + path: securityOptions + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - description: Security Context to apply to the Cryostat application container. + displayName: Core Security Context + path: securityOptions.coreSecurityContext + - description: Security Context to apply to the JFR Data Source container. + displayName: Data Source Security Context + path: securityOptions.dataSourceSecurityContext + - description: Security Context to apply to the Grafana container. + displayName: Grafana Security Context + path: securityOptions.grafanaSecurityContext + - description: Security Context to apply to the Cryostat pod. + displayName: Pod Security Context + path: securityOptions.podSecurityContext + - description: Options to customize the services created for the Cryostat application + and Grafana dashboard. + displayName: Service Options + path: serviceOptions + - description: Options to customize the storage for Flight Recordings and Templates. + displayName: Storage Options + path: storageOptions + - description: Configuration for an EmptyDir to be created by the operator instead + of a PVC. + displayName: Empty Dir + path: storageOptions.emptyDir + - description: When enabled, Cryostat will use EmptyDir volumes instead of a + Persistent Volume Claim. Any PVC configurations will be ignored. + displayName: Enabled + path: storageOptions.emptyDir.enabled + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Unless specified, the emptyDir volume will be mounted on the + same storage medium backing the node. Setting this field to "Memory" will + mount the emptyDir on a tmpfs (RAM-backed filesystem). + displayName: Medium + path: storageOptions.emptyDir.medium + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:fieldDependency:storageOptions.emptyDir.enabled:true + - description: The maximum memory limit for the emptyDir. Default is unbounded. + displayName: Size Limit + path: storageOptions.emptyDir.sizeLimit + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:fieldDependency:storageOptions.emptyDir.enabled:true + - description: Configuration for the Persistent Volume Claim to be created by + the operator. + displayName: PVC + path: storageOptions.pvc + - description: Spec for a Persistent Volume Claim, whose options will override + the defaults used by the operator. Unless overriden, the PVC will be created + with the default Storage Class and 500MiB of storage. Once the operator + has created the PVC, changes to this field have no effect. + displayName: Spec + path: storageOptions.pvc.spec + - description: Options to configure the Cryostat application's target discovery + mechanisms. + displayName: Target Discovery Options + path: targetDiscoveryOptions + - description: When true, the Cryostat application will disable the built-in + discovery mechanisms. Defaults to false + displayName: Disable Built-in Discovery + path: targetDiscoveryOptions.builtInDiscoveryDisabled + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: List of TLS certificates to trust when connecting to targets. + displayName: Trusted TLS Certificates + path: trustedCertSecrets + - description: Name of secret in the local namespace. + displayName: Secret Name + path: trustedCertSecrets[0].secretName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + - description: A namespace whose workloads Cryostat should be able to connect + and record + displayName: Target Namespace + path: targetNamespaces[0] + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Namespace + statusDescriptors: + - description: Address of the deployed Cryostat web application. + displayName: Application URL + path: applicationUrl + x-descriptors: + - urn:alm:descriptor:org.w3:link + - description: Name of the Secret containing the generated Grafana credentials. + displayName: Grafana Secret + path: grafanaSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + - description: List of namespaces that Cryostat has been configured and authorized + to access and profile. + displayName: Target Namespaces + path: targetNamespaces + - description: Conditions of the components managed by the Cryostat Operator. + displayName: Cryostat Conditions + path: conditions + x-descriptors: + - urn:alm:descriptor:io.kubernetes.conditions + - description: A namespace whose workloads Cryostat should be able to connect + and record + displayName: Target Namespace + path: targetNamespaces[0] + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Namespace + version: v1beta2 + - description: Cryostat allows you to install Cryostat for a single namespace. + It contains configuration options for controlling the Deployment of the Cryostat + application and its related components. A ClusterCryostat or Cryostat instance + must be created to instruct the operator to deploy the Cryostat application. + displayName: Cryostat + kind: Cryostat + name: cryostats.operator.cryostat.io + resources: + - kind: ConsoleLink + name: "" + version: v1 + - kind: Deployment + name: "" + version: v1 + - kind: Ingress + name: "" + version: v1 + - kind: PersistentVolumeClaim + name: "" + version: v1 + - kind: Route + name: "" + version: v1 + - kind: Secret + name: "" + version: v1 + - kind: Service + name: "" + version: v1 + specDescriptors: - description: Use cert-manager to secure in-cluster communication between Cryostat components. Requires cert-manager to be installed. displayName: Enable cert-manager Integration @@ -481,12 +1324,6 @@ spec: path: trustedCertSecrets[0].secretName x-descriptors: - urn:alm:descriptor:io.kubernetes:Secret - - description: A namespace whose workloads Cryostat should be able to connect - and record - displayName: Target Namespace - path: targetNamespaces[0] - x-descriptors: - - urn:alm:descriptor:io.kubernetes:Namespace statusDescriptors: - description: Address of the deployed Cryostat web application. displayName: Application URL @@ -498,21 +1335,11 @@ spec: path: grafanaSecret x-descriptors: - urn:alm:descriptor:io.kubernetes:Secret - - description: List of namespaces that Cryostat has been configured and authorized - to access and profile. - displayName: Target Namespaces - path: targetNamespaces - description: Conditions of the components managed by the Cryostat Operator. displayName: Cryostat Conditions path: conditions x-descriptors: - urn:alm:descriptor:io.kubernetes.conditions - - description: A namespace whose workloads Cryostat should be able to connect - and record - displayName: Target Namespace - path: targetNamespaces[0] - x-descriptors: - - urn:alm:descriptor:io.kubernetes:Namespace version: v1beta1 - description: Cryostat allows you to install Cryostat for a single namespace. It contains configuration options for controlling the Deployment of the Cryostat @@ -544,6 +1371,12 @@ spec: name: "" version: v1 specDescriptors: + - description: 'List of namespaces whose workloads Cryostat should be permitted + to access and profile. Defaults to this Cryostat''s namespace. Warning: + All Cryostat users will be able to create and manage recordings for workloads + in the listed namespaces. More details: https://github.com/cryostatio/cryostat-operator/blob/v2.4.0/docs/multi-namespace.md#data-isolation' + displayName: Target Namespaces + path: targetNamespaces - description: Use cert-manager to secure in-cluster communication between Cryostat components. Requires cert-manager to be installed. displayName: Enable cert-manager Integration @@ -897,6 +1730,12 @@ spec: path: trustedCertSecrets[0].secretName x-descriptors: - urn:alm:descriptor:io.kubernetes:Secret + - description: A namespace whose workloads Cryostat should be able to connect + and record + displayName: Target Namespace + path: targetNamespaces[0] + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Namespace statusDescriptors: - description: Address of the deployed Cryostat web application. displayName: Application URL @@ -908,12 +1747,22 @@ spec: path: grafanaSecret x-descriptors: - urn:alm:descriptor:io.kubernetes:Secret + - description: List of namespaces that Cryostat has been configured and authorized + to access and profile. + displayName: Target Namespaces + path: targetNamespaces - description: Conditions of the components managed by the Cryostat Operator. displayName: Cryostat Conditions path: conditions x-descriptors: - urn:alm:descriptor:io.kubernetes.conditions - version: v1beta1 + - description: A namespace whose workloads Cryostat should be able to connect + and record + displayName: Target Namespace + path: targetNamespaces[0] + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Namespace + version: v1beta2 description: | Cryostat provides a cloud-based solution for interacting with the JDK Flight Recorder already present in OpenJDK 11+ JVMs. With Cryostat, users can remotely start, stop, retrieve, and even analyze JFR event data, providing the capability to easily take advantage of Flight Recorder's extremely low runtime cost and overhead and the flexibility to monitor applications and analyze recording data without transferring data outside of the cluster the application runs within. ##Prerequisites @@ -998,6 +1847,12 @@ spec: - selfsubjectaccessreviews verbs: - create + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create - apiGroups: - cert-manager.io resources: @@ -1169,6 +2024,10 @@ spec: initialDelaySeconds: 15 periodSeconds: 20 name: manager + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP readinessProbe: httpGet: path: /readyz @@ -1187,12 +2046,21 @@ spec: capabilities: drop: - ALL + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true securityContext: runAsNonRoot: true seccompProfile: type: RuntimeDefault serviceAccountName: cryostat-operator-service-account terminationGracePeriodSeconds: 10 + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: webhook-server-cert permissions: - rules: - apiGroups: @@ -1276,3 +2144,56 @@ spec: - image: quay.io/cryostat/cryostat-reports:latest name: reports version: 2.5.0-dev + webhookdefinitions: + - admissionReviewVersions: + - v1 + containerPort: 443 + conversionCRDs: + - clustercryostats.operator.cryostat.io + - cryostats.operator.cryostat.io + deploymentName: cryostat-operator-controller-manager + generateName: cclustercryostatscryostats.kb.io + sideEffects: None + targetPort: 9443 + type: ConversionWebhook + webhookPath: /convert + - admissionReviewVersions: + - v1 + containerPort: 443 + deploymentName: cryostat-operator-controller-manager + failurePolicy: Fail + generateName: mcryostat.kb.io + rules: + - apiGroups: + - operator.cryostat.io + apiVersions: + - v1beta2 + operations: + - CREATE + - UPDATE + resources: + - cryostats + sideEffects: None + targetPort: 9443 + type: MutatingAdmissionWebhook + webhookPath: /mutate-operator-cryostat-io-v1beta2-cryostat + - admissionReviewVersions: + - v1 + containerPort: 443 + deploymentName: cryostat-operator-controller-manager + failurePolicy: Fail + generateName: vcryostat.kb.io + rules: + - apiGroups: + - operator.cryostat.io + apiVersions: + - v1beta2 + operations: + - CREATE + - UPDATE + resources: + - cryostats + sideEffects: None + targetPort: 9443 + type: ValidatingAdmissionWebhook + webhookPath: /validate-operator-cryostat-io-v1beta2-cryostat diff --git a/bundle/manifests/operator.cryostat.io_clustercryostats.yaml b/bundle/manifests/operator.cryostat.io_clustercryostats.yaml index 383979ab7..b117234a9 100644 --- a/bundle/manifests/operator.cryostat.io_clustercryostats.yaml +++ b/bundle/manifests/operator.cryostat.io_clustercryostats.yaml @@ -2,10 +2,21 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: + cert-manager.io/inject-ca-from: cryostat-operator-system/cryostat-operator-serving-cert controller-gen.kubebuilder.io/version: v0.11.1 creationTimestamp: null name: clustercryostats.operator.cryostat.io spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + name: cryostat-operator-webhook-service + namespace: cryostat-operator-system + path: /convert + conversionReviewVersions: + - v1 group: operator.cryostat.io names: kind: ClusterCryostat @@ -4747,6 +4758,4721 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.applicationUrl + name: Application URL + type: string + - jsonPath: .status.grafanaSecret + name: Grafana Secret + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: ClusterCryostat allows you to install Cryostat for multiple namespaces + or cluster-wide. It contains configuration options for controlling the Deployment + of the Cryostat application and its related components. A ClusterCryostat + or Cryostat instance must be created to instruct the operator to deploy + the Cryostat application. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ClusterCryostatSpec defines the desired state of ClusterCryostat. + properties: + authProperties: + description: Override default authorization properties for Cryostat + on OpenShift. + properties: + clusterRoleName: + description: 'Name of the ClusterRole to use when Cryostat requests + a role-scoped OAuth token. This ClusterRole should contain permissions + for all Kubernetes objects listed in custom permission mapping. + More details: https://docs.openshift.com/container-platform/4.11/authentication/tokens-scoping.html#scoping-tokens-role-scope_configuring-internal-oauth' + type: string + configMapName: + description: Name of config map in the local namespace. + type: string + filename: + description: Filename within config map containing the resource + mapping. + type: string + required: + - clusterRoleName + - configMapName + - filename + type: object + enableCertManager: + description: Use cert-manager to secure in-cluster communication between + Cryostat components. Requires cert-manager to be installed. + type: boolean + eventTemplates: + description: List of Flight Recorder Event Templates to preconfigure + in Cryostat. + items: + description: A ConfigMap containing a .jfc template file. + properties: + configMapName: + description: Name of config map in the local namespace. + type: string + filename: + description: Filename within config map containing the template + file. + type: string + required: + - configMapName + - filename + type: object + type: array + installNamespace: + description: Namespace where Cryostat should be installed. On multi-tenant + clusters, we strongly suggest installing Cryostat into its own namespace. + type: string + jmxCacheOptions: + description: Options to customize the JMX target connections cache + for the Cryostat application. + properties: + targetCacheSize: + description: The maximum number of JMX connections to cache. Use + `-1` for an unlimited cache size (TTL expiration only). Defaults + to `-1`. + format: int32 + minimum: -1 + type: integer + targetCacheTTL: + description: The time to live (in seconds) for cached JMX connections. + Defaults to `10`. + format: int32 + minimum: 1 + type: integer + type: object + jmxCredentialsDatabaseOptions: + description: Options to configure the Cryostat application's credentials + database. + properties: + databaseSecretName: + description: Name of the secret containing the password to encrypt + credentials database. + type: string + type: object + maxWsConnections: + description: The maximum number of WebSocket client connections allowed + (minimum 1, default unlimited). + format: int32 + minimum: 1 + type: integer + minimal: + description: Deploy a pared-down Cryostat instance with no Grafana + Dashboard or JFR Data Source. + type: boolean + networkOptions: + description: Options to control how the operator exposes the application + outside of the cluster, such as using an Ingress or Route. + properties: + commandConfig: + description: "Specifications for how to expose the Cryostat command + service, which serves the WebSocket command channel. \n Deprecated: + CommandConfig is no longer used." + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the Ingress or Route during + its creation. + type: object + ingressSpec: + description: Configuration for an Ingress object. Currently + subpaths are not supported, so unique hosts must be specified + (if a single external IP is being used) to differentiate + between ingresses/services. + properties: + defaultBackend: + description: DefaultBackend is the backend that should + handle requests that don't match any rule. If Rules + are not specified, DefaultBackend must be specified. + If DefaultBackend is not set, the handling of requests + that do not match any of the rules will be up to the + Ingress controller. + properties: + resource: + description: Resource is an ObjectRef to another Kubernetes + resource in the namespace of the Ingress object. + If resource is specified, a service.Name and service.Port + must not be specified. This is a mutually exclusive + setting with "Service". + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a Service as a Backend. + This is a mutually exclusive setting with "Resource". + properties: + name: + description: Name is the referenced service. The + service must exist in the same namespace as + the Ingress object. + type: string + port: + description: Port of the referenced service. A + port name or port number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name of the port + on the Service. This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the numerical port + number (e.g. 80) on the Service. This is + a mutually exclusive setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + ingressClassName: + description: IngressClassName is the name of an IngressClass + cluster resource. Ingress controller implementations + use this field to know whether they should be serving + this Ingress resource, by a transitive connection (controller + -> IngressClass -> Ingress resource). Although the `kubernetes.io/ingress.class` + annotation (simple constant name) was never formally + defined, it was widely supported by Ingress controllers + to create a direct binding between Ingress controller + and Ingress resources. Newly created Ingress resources + should prefer using the field. However, even though + the annotation is officially deprecated, for backwards + compatibility reasons, ingress controllers should still + honor that annotation if present. + type: string + rules: + description: A list of host rules used to configure the + Ingress. If unspecified, or no rule matches, all traffic + is sent to the default backend. + items: + description: IngressRule represents the rules mapping + the paths under a specified host to the related backend + services. Incoming requests are first evaluated for + a host match, then routed to the backend associated + with the matching IngressRuleValue. + properties: + host: + description: "Host is the fully qualified domain + name of a network host, as defined by RFC 3986. + Note the following deviations from the \"host\" + part of the URI as defined in RFC 3986: 1. IPs + are not allowed. Currently an IngressRuleValue + can only apply to the IP in the Spec of the parent + Ingress. 2. The `:` delimiter is not respected + because ports are not allowed. Currently the port + of an Ingress is implicitly :80 for http and :443 + for https. Both these may change in the future. + Incoming requests are matched against the host + before the IngressRuleValue. If the host is unspecified, + the Ingress routes all traffic based on the specified + IngressRuleValue. \n Host can be \"precise\" which + is a domain name without the terminating dot of + a network host (e.g. \"foo.bar.com\") or \"wildcard\", + which is a domain name prefixed with a single + wildcard label (e.g. \"*.foo.com\"). The wildcard + character '*' must appear by itself as the first + DNS label and matches only a single label. You + cannot have a wildcard label by itself (e.g. Host + == \"*\"). Requests will be matched against the + Host field in the following way: 1. If Host is + precise, the request matches this rule if the + http host header is equal to Host. 2. If Host + is a wildcard, then the request matches this rule + if the http host header is to equal to the suffix + (removing the first label) of the wildcard rule." + type: string + http: + description: 'HTTPIngressRuleValue is a list of + http selectors pointing to backends. In the example: + http:///? -> backend where + where parts of the url correspond to RFC 3986, + this resource will be used to match against everything + after the last ''/'' and before the first ''?'' + or ''#''.' + properties: + paths: + description: A collection of paths that map + requests to backends. + items: + description: HTTPIngressPath associates a + path with a backend. Incoming urls matching + the path are forwarded to the backend. + properties: + backend: + description: Backend defines the referenced + service endpoint to which the traffic + will be forwarded to. + properties: + resource: + description: Resource is an ObjectRef + to another Kubernetes resource in + the namespace of the Ingress object. + If resource is specified, a service.Name + and service.Port must not be specified. + This is a mutually exclusive setting + with "Service". + properties: + apiGroup: + description: APIGroup is the group + for the resource being referenced. + If APIGroup is not specified, + the specified Kind must be in + the core API group. For any + other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type + of resource being referenced + type: string + name: + description: Name is the name + of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a + Service as a Backend. This is a + mutually exclusive setting with + "Resource". + properties: + name: + description: Name is the referenced + service. The service must exist + in the same namespace as the + Ingress object. + type: string + port: + description: Port of the referenced + service. A port name or port + number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name + of the port on the Service. + This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the + numerical port number (e.g. + 80) on the Service. This + is a mutually exclusive + setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + path: + description: Path is matched against the + path of an incoming request. Currently + it can contain characters disallowed + from the conventional "path" part of + a URL as defined by RFC 3986. Paths + must begin with a '/' and must be present + when using PathType with value "Exact" + or "Prefix". + type: string + pathType: + description: 'PathType determines the + interpretation of the Path matching. + PathType can be one of the following + values: * Exact: Matches the URL path + exactly. * Prefix: Matches based on + a URL path prefix split by ''/''. Matching + is done on a path element by element + basis. A path element refers is the + list of labels in the path split by + the ''/'' separator. A request is a + match for path p if every p is an element-wise + prefix of p of the request path. Note + that if the last element of the path + is a substring of the last element in + request path, it is not a match (e.g. + /foo/bar matches /foo/bar/baz, but does + not match /foo/barbaz). * ImplementationSpecific: + Interpretation of the Path matching + is up to the IngressClass. Implementations + can treat this as a separate PathType + or treat it identically to Prefix or + Exact path types. Implementations are + required to support all path types.' + type: string + required: + - backend + - pathType + type: object + type: array + x-kubernetes-list-type: atomic + required: + - paths + type: object + type: object + type: array + x-kubernetes-list-type: atomic + tls: + description: TLS configuration. Currently the Ingress + only supports a single TLS port, 443. If multiple members + of this list specify different hosts, they will be multiplexed + on the same port according to the hostname specified + through the SNI TLS extension, if the ingress controller + fulfilling the ingress supports SNI. + items: + description: IngressTLS describes the transport layer + security associated with an Ingress. + properties: + hosts: + description: Hosts are a list of hosts included + in the TLS certificate. The values in this list + must match the name/s used in the tlsSecret. Defaults + to the wildcard host setting for the loadbalancer + controller fulfilling this Ingress, if left unspecified. + items: + type: string + type: array + x-kubernetes-list-type: atomic + secretName: + description: SecretName is the name of the secret + used to terminate TLS traffic on port 443. Field + is left optional to allow TLS routing based on + SNI hostname alone. If the SNI host in a listener + conflicts with the "Host" header field used by + an IngressRule, the SNI host is used for termination + and value of the Host header is used for routing. + type: string + type: object + type: array + x-kubernetes-list-type: atomic + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the Ingress or Route during + its creation. The label with key "app" is reserved for use + by the operator. + type: object + type: object + coreConfig: + description: Specifications for how to expose the Cryostat service, + which serves the Cryostat application. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the Ingress or Route during + its creation. + type: object + ingressSpec: + description: Configuration for an Ingress object. Currently + subpaths are not supported, so unique hosts must be specified + (if a single external IP is being used) to differentiate + between ingresses/services. + properties: + defaultBackend: + description: DefaultBackend is the backend that should + handle requests that don't match any rule. If Rules + are not specified, DefaultBackend must be specified. + If DefaultBackend is not set, the handling of requests + that do not match any of the rules will be up to the + Ingress controller. + properties: + resource: + description: Resource is an ObjectRef to another Kubernetes + resource in the namespace of the Ingress object. + If resource is specified, a service.Name and service.Port + must not be specified. This is a mutually exclusive + setting with "Service". + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a Service as a Backend. + This is a mutually exclusive setting with "Resource". + properties: + name: + description: Name is the referenced service. The + service must exist in the same namespace as + the Ingress object. + type: string + port: + description: Port of the referenced service. A + port name or port number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name of the port + on the Service. This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the numerical port + number (e.g. 80) on the Service. This is + a mutually exclusive setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + ingressClassName: + description: IngressClassName is the name of an IngressClass + cluster resource. Ingress controller implementations + use this field to know whether they should be serving + this Ingress resource, by a transitive connection (controller + -> IngressClass -> Ingress resource). Although the `kubernetes.io/ingress.class` + annotation (simple constant name) was never formally + defined, it was widely supported by Ingress controllers + to create a direct binding between Ingress controller + and Ingress resources. Newly created Ingress resources + should prefer using the field. However, even though + the annotation is officially deprecated, for backwards + compatibility reasons, ingress controllers should still + honor that annotation if present. + type: string + rules: + description: A list of host rules used to configure the + Ingress. If unspecified, or no rule matches, all traffic + is sent to the default backend. + items: + description: IngressRule represents the rules mapping + the paths under a specified host to the related backend + services. Incoming requests are first evaluated for + a host match, then routed to the backend associated + with the matching IngressRuleValue. + properties: + host: + description: "Host is the fully qualified domain + name of a network host, as defined by RFC 3986. + Note the following deviations from the \"host\" + part of the URI as defined in RFC 3986: 1. IPs + are not allowed. Currently an IngressRuleValue + can only apply to the IP in the Spec of the parent + Ingress. 2. The `:` delimiter is not respected + because ports are not allowed. Currently the port + of an Ingress is implicitly :80 for http and :443 + for https. Both these may change in the future. + Incoming requests are matched against the host + before the IngressRuleValue. If the host is unspecified, + the Ingress routes all traffic based on the specified + IngressRuleValue. \n Host can be \"precise\" which + is a domain name without the terminating dot of + a network host (e.g. \"foo.bar.com\") or \"wildcard\", + which is a domain name prefixed with a single + wildcard label (e.g. \"*.foo.com\"). The wildcard + character '*' must appear by itself as the first + DNS label and matches only a single label. You + cannot have a wildcard label by itself (e.g. Host + == \"*\"). Requests will be matched against the + Host field in the following way: 1. If Host is + precise, the request matches this rule if the + http host header is equal to Host. 2. If Host + is a wildcard, then the request matches this rule + if the http host header is to equal to the suffix + (removing the first label) of the wildcard rule." + type: string + http: + description: 'HTTPIngressRuleValue is a list of + http selectors pointing to backends. In the example: + http:///? -> backend where + where parts of the url correspond to RFC 3986, + this resource will be used to match against everything + after the last ''/'' and before the first ''?'' + or ''#''.' + properties: + paths: + description: A collection of paths that map + requests to backends. + items: + description: HTTPIngressPath associates a + path with a backend. Incoming urls matching + the path are forwarded to the backend. + properties: + backend: + description: Backend defines the referenced + service endpoint to which the traffic + will be forwarded to. + properties: + resource: + description: Resource is an ObjectRef + to another Kubernetes resource in + the namespace of the Ingress object. + If resource is specified, a service.Name + and service.Port must not be specified. + This is a mutually exclusive setting + with "Service". + properties: + apiGroup: + description: APIGroup is the group + for the resource being referenced. + If APIGroup is not specified, + the specified Kind must be in + the core API group. For any + other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type + of resource being referenced + type: string + name: + description: Name is the name + of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a + Service as a Backend. This is a + mutually exclusive setting with + "Resource". + properties: + name: + description: Name is the referenced + service. The service must exist + in the same namespace as the + Ingress object. + type: string + port: + description: Port of the referenced + service. A port name or port + number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name + of the port on the Service. + This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the + numerical port number (e.g. + 80) on the Service. This + is a mutually exclusive + setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + path: + description: Path is matched against the + path of an incoming request. Currently + it can contain characters disallowed + from the conventional "path" part of + a URL as defined by RFC 3986. Paths + must begin with a '/' and must be present + when using PathType with value "Exact" + or "Prefix". + type: string + pathType: + description: 'PathType determines the + interpretation of the Path matching. + PathType can be one of the following + values: * Exact: Matches the URL path + exactly. * Prefix: Matches based on + a URL path prefix split by ''/''. Matching + is done on a path element by element + basis. A path element refers is the + list of labels in the path split by + the ''/'' separator. A request is a + match for path p if every p is an element-wise + prefix of p of the request path. Note + that if the last element of the path + is a substring of the last element in + request path, it is not a match (e.g. + /foo/bar matches /foo/bar/baz, but does + not match /foo/barbaz). * ImplementationSpecific: + Interpretation of the Path matching + is up to the IngressClass. Implementations + can treat this as a separate PathType + or treat it identically to Prefix or + Exact path types. Implementations are + required to support all path types.' + type: string + required: + - backend + - pathType + type: object + type: array + x-kubernetes-list-type: atomic + required: + - paths + type: object + type: object + type: array + x-kubernetes-list-type: atomic + tls: + description: TLS configuration. Currently the Ingress + only supports a single TLS port, 443. If multiple members + of this list specify different hosts, they will be multiplexed + on the same port according to the hostname specified + through the SNI TLS extension, if the ingress controller + fulfilling the ingress supports SNI. + items: + description: IngressTLS describes the transport layer + security associated with an Ingress. + properties: + hosts: + description: Hosts are a list of hosts included + in the TLS certificate. The values in this list + must match the name/s used in the tlsSecret. Defaults + to the wildcard host setting for the loadbalancer + controller fulfilling this Ingress, if left unspecified. + items: + type: string + type: array + x-kubernetes-list-type: atomic + secretName: + description: SecretName is the name of the secret + used to terminate TLS traffic on port 443. Field + is left optional to allow TLS routing based on + SNI hostname alone. If the SNI host in a listener + conflicts with the "Host" header field used by + an IngressRule, the SNI host is used for termination + and value of the Host header is used for routing. + type: string + type: object + type: array + x-kubernetes-list-type: atomic + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the Ingress or Route during + its creation. The label with key "app" is reserved for use + by the operator. + type: object + type: object + grafanaConfig: + description: Specifications for how to expose Cryostat's Grafana + service, which serves the Grafana dashboard. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the Ingress or Route during + its creation. + type: object + ingressSpec: + description: Configuration for an Ingress object. Currently + subpaths are not supported, so unique hosts must be specified + (if a single external IP is being used) to differentiate + between ingresses/services. + properties: + defaultBackend: + description: DefaultBackend is the backend that should + handle requests that don't match any rule. If Rules + are not specified, DefaultBackend must be specified. + If DefaultBackend is not set, the handling of requests + that do not match any of the rules will be up to the + Ingress controller. + properties: + resource: + description: Resource is an ObjectRef to another Kubernetes + resource in the namespace of the Ingress object. + If resource is specified, a service.Name and service.Port + must not be specified. This is a mutually exclusive + setting with "Service". + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a Service as a Backend. + This is a mutually exclusive setting with "Resource". + properties: + name: + description: Name is the referenced service. The + service must exist in the same namespace as + the Ingress object. + type: string + port: + description: Port of the referenced service. A + port name or port number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name of the port + on the Service. This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the numerical port + number (e.g. 80) on the Service. This is + a mutually exclusive setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + ingressClassName: + description: IngressClassName is the name of an IngressClass + cluster resource. Ingress controller implementations + use this field to know whether they should be serving + this Ingress resource, by a transitive connection (controller + -> IngressClass -> Ingress resource). Although the `kubernetes.io/ingress.class` + annotation (simple constant name) was never formally + defined, it was widely supported by Ingress controllers + to create a direct binding between Ingress controller + and Ingress resources. Newly created Ingress resources + should prefer using the field. However, even though + the annotation is officially deprecated, for backwards + compatibility reasons, ingress controllers should still + honor that annotation if present. + type: string + rules: + description: A list of host rules used to configure the + Ingress. If unspecified, or no rule matches, all traffic + is sent to the default backend. + items: + description: IngressRule represents the rules mapping + the paths under a specified host to the related backend + services. Incoming requests are first evaluated for + a host match, then routed to the backend associated + with the matching IngressRuleValue. + properties: + host: + description: "Host is the fully qualified domain + name of a network host, as defined by RFC 3986. + Note the following deviations from the \"host\" + part of the URI as defined in RFC 3986: 1. IPs + are not allowed. Currently an IngressRuleValue + can only apply to the IP in the Spec of the parent + Ingress. 2. The `:` delimiter is not respected + because ports are not allowed. Currently the port + of an Ingress is implicitly :80 for http and :443 + for https. Both these may change in the future. + Incoming requests are matched against the host + before the IngressRuleValue. If the host is unspecified, + the Ingress routes all traffic based on the specified + IngressRuleValue. \n Host can be \"precise\" which + is a domain name without the terminating dot of + a network host (e.g. \"foo.bar.com\") or \"wildcard\", + which is a domain name prefixed with a single + wildcard label (e.g. \"*.foo.com\"). The wildcard + character '*' must appear by itself as the first + DNS label and matches only a single label. You + cannot have a wildcard label by itself (e.g. Host + == \"*\"). Requests will be matched against the + Host field in the following way: 1. If Host is + precise, the request matches this rule if the + http host header is equal to Host. 2. If Host + is a wildcard, then the request matches this rule + if the http host header is to equal to the suffix + (removing the first label) of the wildcard rule." + type: string + http: + description: 'HTTPIngressRuleValue is a list of + http selectors pointing to backends. In the example: + http:///? -> backend where + where parts of the url correspond to RFC 3986, + this resource will be used to match against everything + after the last ''/'' and before the first ''?'' + or ''#''.' + properties: + paths: + description: A collection of paths that map + requests to backends. + items: + description: HTTPIngressPath associates a + path with a backend. Incoming urls matching + the path are forwarded to the backend. + properties: + backend: + description: Backend defines the referenced + service endpoint to which the traffic + will be forwarded to. + properties: + resource: + description: Resource is an ObjectRef + to another Kubernetes resource in + the namespace of the Ingress object. + If resource is specified, a service.Name + and service.Port must not be specified. + This is a mutually exclusive setting + with "Service". + properties: + apiGroup: + description: APIGroup is the group + for the resource being referenced. + If APIGroup is not specified, + the specified Kind must be in + the core API group. For any + other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type + of resource being referenced + type: string + name: + description: Name is the name + of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a + Service as a Backend. This is a + mutually exclusive setting with + "Resource". + properties: + name: + description: Name is the referenced + service. The service must exist + in the same namespace as the + Ingress object. + type: string + port: + description: Port of the referenced + service. A port name or port + number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name + of the port on the Service. + This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the + numerical port number (e.g. + 80) on the Service. This + is a mutually exclusive + setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + path: + description: Path is matched against the + path of an incoming request. Currently + it can contain characters disallowed + from the conventional "path" part of + a URL as defined by RFC 3986. Paths + must begin with a '/' and must be present + when using PathType with value "Exact" + or "Prefix". + type: string + pathType: + description: 'PathType determines the + interpretation of the Path matching. + PathType can be one of the following + values: * Exact: Matches the URL path + exactly. * Prefix: Matches based on + a URL path prefix split by ''/''. Matching + is done on a path element by element + basis. A path element refers is the + list of labels in the path split by + the ''/'' separator. A request is a + match for path p if every p is an element-wise + prefix of p of the request path. Note + that if the last element of the path + is a substring of the last element in + request path, it is not a match (e.g. + /foo/bar matches /foo/bar/baz, but does + not match /foo/barbaz). * ImplementationSpecific: + Interpretation of the Path matching + is up to the IngressClass. Implementations + can treat this as a separate PathType + or treat it identically to Prefix or + Exact path types. Implementations are + required to support all path types.' + type: string + required: + - backend + - pathType + type: object + type: array + x-kubernetes-list-type: atomic + required: + - paths + type: object + type: object + type: array + x-kubernetes-list-type: atomic + tls: + description: TLS configuration. Currently the Ingress + only supports a single TLS port, 443. If multiple members + of this list specify different hosts, they will be multiplexed + on the same port according to the hostname specified + through the SNI TLS extension, if the ingress controller + fulfilling the ingress supports SNI. + items: + description: IngressTLS describes the transport layer + security associated with an Ingress. + properties: + hosts: + description: Hosts are a list of hosts included + in the TLS certificate. The values in this list + must match the name/s used in the tlsSecret. Defaults + to the wildcard host setting for the loadbalancer + controller fulfilling this Ingress, if left unspecified. + items: + type: string + type: array + x-kubernetes-list-type: atomic + secretName: + description: SecretName is the name of the secret + used to terminate TLS traffic on port 443. Field + is left optional to allow TLS routing based on + SNI hostname alone. If the SNI host in a listener + conflicts with the "Host" header field used by + an IngressRule, the SNI host is used for termination + and value of the Host header is used for routing. + type: string + type: object + type: array + x-kubernetes-list-type: atomic + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the Ingress or Route during + its creation. The label with key "app" is reserved for use + by the operator. + type: object + type: object + type: object + operandMetadata: + description: Options to configure the Cryostat deployments and pods + metadata + properties: + deploymentMetadata: + description: Options to configure the Cryostat deployments metadata + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the resources during its + creation. + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the resources during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + type: object + podMetadata: + description: Options to configure the Cryostat pods metadata + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the resources during its + creation. + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the resources during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + type: object + type: object + reportOptions: + description: Options to configure Cryostat Automated Report Analysis. + properties: + replicas: + description: The number of report sidecar replica containers to + deploy. Each replica can service one report generation request + at a time. + format: int32 + type: integer + resources: + description: The resources allocated to each sidecar replica. + A replica with more resources can handle larger input recordings + and will process them faster. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + schedulingOptions: + description: Options to configure scheduling for the reports deployment + properties: + affinity: + description: Affinity rules for scheduling Cryostat pods. + properties: + nodeAffinity: + description: 'Node affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#NodeAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term + matches all objects with implicit weight 0 (i.e. + it's a no-op). A null preferred scheduling term + matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to an update), the system may or may not try + to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them + are ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: 'Pod affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to a pod label update), the system may or may + not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: 'Pod anti-affinity scheduling rules for a + Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAntiAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by iterating through + the elements of this field and adding "weight" to + the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + anti-affinity requirements specified by this field + cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may + or may not try to eventually evict the pod from + its node. When there are multiple elements, the + lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + nodeSelector: + additionalProperties: + type: string + description: 'Label selector used to schedule a Cryostat pod + to a node. See: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + tolerations: + description: 'Tolerations to allow scheduling of Cryostat + pods to tainted nodes. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/' + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, + allowed values are NoSchedule, PreferNoSchedule and + NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. If the + key is empty, operator must be Exists; this combination + means to match all values and all keys. + type: string + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and Equal. + Defaults to Equal. Exists is equivalent to wildcard + for value, so that a pod can tolerate all taints of + a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period + of time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the + taint forever (do not evict). Zero and negative values + will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration + matches to. If the operator is Exists, the value should + be empty, otherwise just a regular string. + type: string + type: object + type: array + type: object + securityOptions: + description: Options to configure the Security Contexts for the + Cryostat report generator. + properties: + podSecurityContext: + description: Security Context to apply to the Cryostat report + generator pod. + properties: + fsGroup: + description: "A special supplemental group that applies + to all containers in a pod. Some volume types allow + the Kubelet to change the ownership of that volume to + be owned by the pod: \n 1. The owning GID will be the + FSGroup 2. The setgid bit is set (new files created + in the volume will be owned by FSGroup) 3. The permission + bits are OR'd with rw-rw---- \n If unset, the Kubelet + will not modify the ownership and permissions of any + volume. Note that this field cannot be set when spec.os.name + is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of + changing ownership and permission of the volume before + being exposed inside Pod. This field will only apply + to volume types which support fsGroup based ownership(and + permissions). It will have no effect on ephemeral volume + types such as: secret, configmaps and emptydir. Valid + values are "OnRootMismatch" and "Always". If not specified, + "Always" is used. Note that this field cannot be set + when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if it + does. If unset or false, no such validation will be + performed. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence + for that container. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all + containers. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this + field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers + in this pod. Note that this field cannot be set when + spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process + run in each container, in addition to the container's + primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container + process. If unspecified, no additional groups are added + to any container. Note that group memberships defined + in the container image for the uid of the container + process are still effective, even if they are not included + in this list. Note that this field cannot be set when + spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls + used for the pod. Pods with unsupported sysctls (by + the container runtime) might fail to launch. Note that + this field cannot be set when spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be + set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options within a + container's SecurityContext will be used. If set in + both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + reportsSecurityContext: + description: Security Context to apply to the Cryostat report + generator container. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag + will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if it + does. If unset or false, no such validation will be + performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + type: object + subProcessMaxHeapSize: + description: When zero report sidecar replicas are requested, + SubProcessMaxHeapSize configures the maximum heap size of the + basic subprocess report generator in MiB. The default heap size + is `200` (MiB). + format: int32 + type: integer + type: object + resources: + description: Resource requirements for the Cryostat deployment. + properties: + coreResources: + description: Resource requirements for the Cryostat application. + If specifying a memory limit, at least 768MiB is recommended. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + dataSourceResources: + description: Resource requirements for the JFR Data Source container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + grafanaResources: + description: Resource requirements for the Grafana container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + type: object + schedulingOptions: + description: Options to configure scheduling for the Cryostat deployment + properties: + affinity: + description: Affinity rules for scheduling Cryostat pods. + properties: + nodeAffinity: + description: 'Node affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#NodeAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: 'Pod affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: 'Pod anti-affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAntiAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + nodeSelector: + additionalProperties: + type: string + description: 'Label selector used to schedule a Cryostat pod to + a node. See: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + tolerations: + description: 'Tolerations to allow scheduling of Cryostat pods + to tainted nodes. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/' + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, allowed + values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match + all values and all keys. + type: string + operator: + description: Operator represents a key's relationship to + the value. Valid operators are Exists and Equal. Defaults + to Equal. Exists is equivalent to wildcard for value, + so that a pod can tolerate all taints of a particular + category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of + time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the taint + forever (do not evict). Zero and negative values will + be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + type: object + securityOptions: + description: Options to configure the Security Contexts for the Cryostat + application. + properties: + coreSecurityContext: + description: Security Context to apply to the Cryostat application + container. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + dataSourceSecurityContext: + description: Security Context to apply to the JFR Data Source + container. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + grafanaSecurityContext: + description: Security Context to apply to the Grafana container. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + podSecurityContext: + description: Security Context to apply to the Cryostat pod. + properties: + fsGroup: + description: "A special supplemental group that applies to + all containers in a pod. Some volume types allow the Kubelet + to change the ownership of that volume to be owned by the + pod: \n 1. The owning GID will be the FSGroup 2. The setgid + bit is set (new files created in the volume will be owned + by FSGroup) 3. The permission bits are OR'd with rw-rw---- + \n If unset, the Kubelet will not modify the ownership and + permissions of any volume. Note that this field cannot be + set when spec.os.name is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will + have no effect on ephemeral volume types such as: secret, + configmaps and emptydir. Valid values are "OnRootMismatch" + and "Always". If not specified, "Always" is used. Note that + this field cannot be set when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this field + cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is + windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + SecurityContext. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence + for that container. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers + in this pod. Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process + run in each container, in addition to the container's primary + GID, the fsGroup (if specified), and group memberships defined + in the container image for the uid of the container process. + If unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image + for the uid of the container process are still effective, + even if they are not included in this list. Note that this + field cannot be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used + for the pod. Pods with unsupported sysctls (by the container + runtime) might fail to launch. Note that this field cannot + be set when spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options within a container's + SecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + type: object + serviceOptions: + description: Options to customize the services created for the Cryostat + application and Grafana dashboard. + properties: + coreConfig: + description: Specification for the service responsible for the + Cryostat application. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the service during its + creation. + type: object + httpPort: + description: HTTP port number for the Cryostat application + service. Defaults to 8181. + format: int32 + type: integer + jmxPort: + description: Remote JMX port number for the Cryostat application + service. Defaults to 9091. + format: int32 + type: integer + labels: + additionalProperties: + type: string + description: Labels to add to the service during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + serviceType: + description: Type of service to create. Defaults to "ClusterIP". + type: string + type: object + grafanaConfig: + description: Specification for the service responsible for the + Cryostat Grafana dashboard. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the service during its + creation. + type: object + httpPort: + description: HTTP port number for the Grafana dashboard service. + Defaults to 3000. + format: int32 + type: integer + labels: + additionalProperties: + type: string + description: Labels to add to the service during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + serviceType: + description: Type of service to create. Defaults to "ClusterIP". + type: string + type: object + reportsConfig: + description: Specification for the service responsible for the + cryostat-reports sidecars. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the service during its + creation. + type: object + httpPort: + description: HTTP port number for the cryostat-reports service. + Defaults to 10000. + format: int32 + type: integer + labels: + additionalProperties: + type: string + description: Labels to add to the service during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + serviceType: + description: Type of service to create. Defaults to "ClusterIP". + type: string + type: object + type: object + storageOptions: + description: Options to customize the storage for Flight Recordings + and Templates. + properties: + emptyDir: + description: Configuration for an EmptyDir to be created by the + operator instead of a PVC. + properties: + enabled: + description: When enabled, Cryostat will use EmptyDir volumes + instead of a Persistent Volume Claim. Any PVC configurations + will be ignored. + type: boolean + medium: + description: Unless specified, the emptyDir volume will be + mounted on the same storage medium backing the node. Setting + this field to "Memory" will mount the emptyDir on a tmpfs + (RAM-backed filesystem). + type: string + sizeLimit: + description: The maximum memory limit for the emptyDir. Default + is unbounded. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + type: string + type: object + pvc: + description: Configuration for the Persistent Volume Claim to + be created by the operator. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the Persistent Volume Claim + during its creation. + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the Persistent Volume Claim + during its creation. The label with key "app" is reserved + for use by the operator. + type: object + spec: + description: Spec for a Persistent Volume Claim, whose options + will override the defaults used by the operator. Unless + overriden, the PVC will be created with the default Storage + Class and 500MiB of storage. Once the operator has created + the PVC, changes to this field have no effect. + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified + data source, it will create a new volume based on the + contents of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then + dataSourceRef will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the dataSource + field and as such if both fields are non-empty, they + must have the same value. For backwards compatibility, + when namespace isn''t specified in dataSourceRef, both + fields (dataSource and dataSourceRef) will be set to + the same value automatically if one of them is empty + and the other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the same + value and must be empty. There are three important differences + between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef + allows any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + * While dataSource only allows local objects, dataSourceRef + allows objects in any namespaces. (Beta) Using this + field requires the AnyVolumeDataSource feature gate + to be enabled. (Alpha) Using the namespace field of + dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the + ReferenceGrant documentation for details. (Alpha) + This field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify resource + requirements that are lower than previous value but + must still be higher than capacity recorded in the status + field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n This field is immutable. It can only be set for + containers." + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one + entry in pod.spec.resourceClaims of the Pod + where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes to + consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values + array must be non-empty. If the operator is + Exists or DoesNotExist, the values array must + be empty. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is + required by the claim. Value of Filesystem is implied + when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + type: object + type: object + targetDiscoveryOptions: + description: Options to configure the Cryostat application's target + discovery mechanisms. + properties: + builtInDiscoveryDisabled: + description: When true, the Cryostat application will disable + the built-in discovery mechanisms. Defaults to false + type: boolean + type: object + targetNamespaces: + description: 'List of namespaces whose workloads Cryostat should be + permitted to access and profile. Defaults to this Cryostat''s namespace. + Warning: All Cryostat users will be able to create and manage recordings + for workloads in the listed namespaces. More details: https://github.com/cryostatio/cryostat-operator/blob/v2.4.0/docs/multi-namespace.md#data-isolation' + items: + type: string + type: array + trustedCertSecrets: + description: List of TLS certificates to trust when connecting to + targets. + items: + properties: + certificateKey: + description: Key within secret containing the certificate. + type: string + secretName: + description: Name of secret in the local namespace. + type: string + required: + - secretName + type: object + type: array + required: + - installNamespace + - minimal + type: object + status: + description: ClusterCryostatStatus defines the observed state of ClusterCryostat. + properties: + applicationUrl: + description: Address of the deployed Cryostat web application. + type: string + conditions: + description: Conditions of the components managed by the Cryostat + Operator. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + grafanaSecret: + description: Name of the Secret containing the generated Grafana credentials. + type: string + targetNamespaces: + description: List of namespaces that Cryostat has been configured + and authorized to access and profile. + items: + type: string + type: array + required: + - applicationUrl + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/bundle/manifests/operator.cryostat.io_cryostats.yaml b/bundle/manifests/operator.cryostat.io_cryostats.yaml index b465c8459..25ebf2503 100644 --- a/bundle/manifests/operator.cryostat.io_cryostats.yaml +++ b/bundle/manifests/operator.cryostat.io_cryostats.yaml @@ -2,10 +2,21 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: + cert-manager.io/inject-ca-from: cryostat-operator-system/cryostat-operator-serving-cert controller-gen.kubebuilder.io/version: v0.11.1 creationTimestamp: null name: cryostats.operator.cryostat.io spec: + conversion: + strategy: Webhook + webhook: + clientConfig: + service: + name: cryostat-operator-webhook-service + namespace: cryostat-operator-system + path: /convert + conversionReviewVersions: + - v1 group: operator.cryostat.io names: kind: Cryostat @@ -4728,6 +4739,4716 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.applicationUrl + name: Application URL + type: string + - jsonPath: .status.grafanaSecret + name: Grafana Secret + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: Cryostat allows you to install Cryostat for a single namespace. + It contains configuration options for controlling the Deployment of the + Cryostat application and its related components. A ClusterCryostat or Cryostat + instance must be created to instruct the operator to deploy the Cryostat + application. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: CryostatSpec defines the desired state of Cryostat. + properties: + authProperties: + description: Override default authorization properties for Cryostat + on OpenShift. + properties: + clusterRoleName: + description: 'Name of the ClusterRole to use when Cryostat requests + a role-scoped OAuth token. This ClusterRole should contain permissions + for all Kubernetes objects listed in custom permission mapping. + More details: https://docs.openshift.com/container-platform/4.11/authentication/tokens-scoping.html#scoping-tokens-role-scope_configuring-internal-oauth' + type: string + configMapName: + description: Name of config map in the local namespace. + type: string + filename: + description: Filename within config map containing the resource + mapping. + type: string + required: + - clusterRoleName + - configMapName + - filename + type: object + enableCertManager: + description: Use cert-manager to secure in-cluster communication between + Cryostat components. Requires cert-manager to be installed. + type: boolean + eventTemplates: + description: List of Flight Recorder Event Templates to preconfigure + in Cryostat. + items: + description: A ConfigMap containing a .jfc template file. + properties: + configMapName: + description: Name of config map in the local namespace. + type: string + filename: + description: Filename within config map containing the template + file. + type: string + required: + - configMapName + - filename + type: object + type: array + jmxCacheOptions: + description: Options to customize the JMX target connections cache + for the Cryostat application. + properties: + targetCacheSize: + description: The maximum number of JMX connections to cache. Use + `-1` for an unlimited cache size (TTL expiration only). Defaults + to `-1`. + format: int32 + minimum: -1 + type: integer + targetCacheTTL: + description: The time to live (in seconds) for cached JMX connections. + Defaults to `10`. + format: int32 + minimum: 1 + type: integer + type: object + jmxCredentialsDatabaseOptions: + description: Options to configure the Cryostat application's credentials + database. + properties: + databaseSecretName: + description: Name of the secret containing the password to encrypt + credentials database. + type: string + type: object + maxWsConnections: + description: The maximum number of WebSocket client connections allowed + (minimum 1, default unlimited). + format: int32 + minimum: 1 + type: integer + minimal: + description: Deploy a pared-down Cryostat instance with no Grafana + Dashboard or JFR Data Source. + type: boolean + networkOptions: + description: Options to control how the operator exposes the application + outside of the cluster, such as using an Ingress or Route. + properties: + commandConfig: + description: "Specifications for how to expose the Cryostat command + service, which serves the WebSocket command channel. \n Deprecated: + CommandConfig is no longer used." + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the Ingress or Route during + its creation. + type: object + ingressSpec: + description: Configuration for an Ingress object. Currently + subpaths are not supported, so unique hosts must be specified + (if a single external IP is being used) to differentiate + between ingresses/services. + properties: + defaultBackend: + description: DefaultBackend is the backend that should + handle requests that don't match any rule. If Rules + are not specified, DefaultBackend must be specified. + If DefaultBackend is not set, the handling of requests + that do not match any of the rules will be up to the + Ingress controller. + properties: + resource: + description: Resource is an ObjectRef to another Kubernetes + resource in the namespace of the Ingress object. + If resource is specified, a service.Name and service.Port + must not be specified. This is a mutually exclusive + setting with "Service". + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a Service as a Backend. + This is a mutually exclusive setting with "Resource". + properties: + name: + description: Name is the referenced service. The + service must exist in the same namespace as + the Ingress object. + type: string + port: + description: Port of the referenced service. A + port name or port number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name of the port + on the Service. This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the numerical port + number (e.g. 80) on the Service. This is + a mutually exclusive setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + ingressClassName: + description: IngressClassName is the name of an IngressClass + cluster resource. Ingress controller implementations + use this field to know whether they should be serving + this Ingress resource, by a transitive connection (controller + -> IngressClass -> Ingress resource). Although the `kubernetes.io/ingress.class` + annotation (simple constant name) was never formally + defined, it was widely supported by Ingress controllers + to create a direct binding between Ingress controller + and Ingress resources. Newly created Ingress resources + should prefer using the field. However, even though + the annotation is officially deprecated, for backwards + compatibility reasons, ingress controllers should still + honor that annotation if present. + type: string + rules: + description: A list of host rules used to configure the + Ingress. If unspecified, or no rule matches, all traffic + is sent to the default backend. + items: + description: IngressRule represents the rules mapping + the paths under a specified host to the related backend + services. Incoming requests are first evaluated for + a host match, then routed to the backend associated + with the matching IngressRuleValue. + properties: + host: + description: "Host is the fully qualified domain + name of a network host, as defined by RFC 3986. + Note the following deviations from the \"host\" + part of the URI as defined in RFC 3986: 1. IPs + are not allowed. Currently an IngressRuleValue + can only apply to the IP in the Spec of the parent + Ingress. 2. The `:` delimiter is not respected + because ports are not allowed. Currently the port + of an Ingress is implicitly :80 for http and :443 + for https. Both these may change in the future. + Incoming requests are matched against the host + before the IngressRuleValue. If the host is unspecified, + the Ingress routes all traffic based on the specified + IngressRuleValue. \n Host can be \"precise\" which + is a domain name without the terminating dot of + a network host (e.g. \"foo.bar.com\") or \"wildcard\", + which is a domain name prefixed with a single + wildcard label (e.g. \"*.foo.com\"). The wildcard + character '*' must appear by itself as the first + DNS label and matches only a single label. You + cannot have a wildcard label by itself (e.g. Host + == \"*\"). Requests will be matched against the + Host field in the following way: 1. If Host is + precise, the request matches this rule if the + http host header is equal to Host. 2. If Host + is a wildcard, then the request matches this rule + if the http host header is to equal to the suffix + (removing the first label) of the wildcard rule." + type: string + http: + description: 'HTTPIngressRuleValue is a list of + http selectors pointing to backends. In the example: + http:///? -> backend where + where parts of the url correspond to RFC 3986, + this resource will be used to match against everything + after the last ''/'' and before the first ''?'' + or ''#''.' + properties: + paths: + description: A collection of paths that map + requests to backends. + items: + description: HTTPIngressPath associates a + path with a backend. Incoming urls matching + the path are forwarded to the backend. + properties: + backend: + description: Backend defines the referenced + service endpoint to which the traffic + will be forwarded to. + properties: + resource: + description: Resource is an ObjectRef + to another Kubernetes resource in + the namespace of the Ingress object. + If resource is specified, a service.Name + and service.Port must not be specified. + This is a mutually exclusive setting + with "Service". + properties: + apiGroup: + description: APIGroup is the group + for the resource being referenced. + If APIGroup is not specified, + the specified Kind must be in + the core API group. For any + other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type + of resource being referenced + type: string + name: + description: Name is the name + of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a + Service as a Backend. This is a + mutually exclusive setting with + "Resource". + properties: + name: + description: Name is the referenced + service. The service must exist + in the same namespace as the + Ingress object. + type: string + port: + description: Port of the referenced + service. A port name or port + number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name + of the port on the Service. + This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the + numerical port number (e.g. + 80) on the Service. This + is a mutually exclusive + setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + path: + description: Path is matched against the + path of an incoming request. Currently + it can contain characters disallowed + from the conventional "path" part of + a URL as defined by RFC 3986. Paths + must begin with a '/' and must be present + when using PathType with value "Exact" + or "Prefix". + type: string + pathType: + description: 'PathType determines the + interpretation of the Path matching. + PathType can be one of the following + values: * Exact: Matches the URL path + exactly. * Prefix: Matches based on + a URL path prefix split by ''/''. Matching + is done on a path element by element + basis. A path element refers is the + list of labels in the path split by + the ''/'' separator. A request is a + match for path p if every p is an element-wise + prefix of p of the request path. Note + that if the last element of the path + is a substring of the last element in + request path, it is not a match (e.g. + /foo/bar matches /foo/bar/baz, but does + not match /foo/barbaz). * ImplementationSpecific: + Interpretation of the Path matching + is up to the IngressClass. Implementations + can treat this as a separate PathType + or treat it identically to Prefix or + Exact path types. Implementations are + required to support all path types.' + type: string + required: + - backend + - pathType + type: object + type: array + x-kubernetes-list-type: atomic + required: + - paths + type: object + type: object + type: array + x-kubernetes-list-type: atomic + tls: + description: TLS configuration. Currently the Ingress + only supports a single TLS port, 443. If multiple members + of this list specify different hosts, they will be multiplexed + on the same port according to the hostname specified + through the SNI TLS extension, if the ingress controller + fulfilling the ingress supports SNI. + items: + description: IngressTLS describes the transport layer + security associated with an Ingress. + properties: + hosts: + description: Hosts are a list of hosts included + in the TLS certificate. The values in this list + must match the name/s used in the tlsSecret. Defaults + to the wildcard host setting for the loadbalancer + controller fulfilling this Ingress, if left unspecified. + items: + type: string + type: array + x-kubernetes-list-type: atomic + secretName: + description: SecretName is the name of the secret + used to terminate TLS traffic on port 443. Field + is left optional to allow TLS routing based on + SNI hostname alone. If the SNI host in a listener + conflicts with the "Host" header field used by + an IngressRule, the SNI host is used for termination + and value of the Host header is used for routing. + type: string + type: object + type: array + x-kubernetes-list-type: atomic + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the Ingress or Route during + its creation. The label with key "app" is reserved for use + by the operator. + type: object + type: object + coreConfig: + description: Specifications for how to expose the Cryostat service, + which serves the Cryostat application. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the Ingress or Route during + its creation. + type: object + ingressSpec: + description: Configuration for an Ingress object. Currently + subpaths are not supported, so unique hosts must be specified + (if a single external IP is being used) to differentiate + between ingresses/services. + properties: + defaultBackend: + description: DefaultBackend is the backend that should + handle requests that don't match any rule. If Rules + are not specified, DefaultBackend must be specified. + If DefaultBackend is not set, the handling of requests + that do not match any of the rules will be up to the + Ingress controller. + properties: + resource: + description: Resource is an ObjectRef to another Kubernetes + resource in the namespace of the Ingress object. + If resource is specified, a service.Name and service.Port + must not be specified. This is a mutually exclusive + setting with "Service". + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a Service as a Backend. + This is a mutually exclusive setting with "Resource". + properties: + name: + description: Name is the referenced service. The + service must exist in the same namespace as + the Ingress object. + type: string + port: + description: Port of the referenced service. A + port name or port number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name of the port + on the Service. This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the numerical port + number (e.g. 80) on the Service. This is + a mutually exclusive setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + ingressClassName: + description: IngressClassName is the name of an IngressClass + cluster resource. Ingress controller implementations + use this field to know whether they should be serving + this Ingress resource, by a transitive connection (controller + -> IngressClass -> Ingress resource). Although the `kubernetes.io/ingress.class` + annotation (simple constant name) was never formally + defined, it was widely supported by Ingress controllers + to create a direct binding between Ingress controller + and Ingress resources. Newly created Ingress resources + should prefer using the field. However, even though + the annotation is officially deprecated, for backwards + compatibility reasons, ingress controllers should still + honor that annotation if present. + type: string + rules: + description: A list of host rules used to configure the + Ingress. If unspecified, or no rule matches, all traffic + is sent to the default backend. + items: + description: IngressRule represents the rules mapping + the paths under a specified host to the related backend + services. Incoming requests are first evaluated for + a host match, then routed to the backend associated + with the matching IngressRuleValue. + properties: + host: + description: "Host is the fully qualified domain + name of a network host, as defined by RFC 3986. + Note the following deviations from the \"host\" + part of the URI as defined in RFC 3986: 1. IPs + are not allowed. Currently an IngressRuleValue + can only apply to the IP in the Spec of the parent + Ingress. 2. The `:` delimiter is not respected + because ports are not allowed. Currently the port + of an Ingress is implicitly :80 for http and :443 + for https. Both these may change in the future. + Incoming requests are matched against the host + before the IngressRuleValue. If the host is unspecified, + the Ingress routes all traffic based on the specified + IngressRuleValue. \n Host can be \"precise\" which + is a domain name without the terminating dot of + a network host (e.g. \"foo.bar.com\") or \"wildcard\", + which is a domain name prefixed with a single + wildcard label (e.g. \"*.foo.com\"). The wildcard + character '*' must appear by itself as the first + DNS label and matches only a single label. You + cannot have a wildcard label by itself (e.g. Host + == \"*\"). Requests will be matched against the + Host field in the following way: 1. If Host is + precise, the request matches this rule if the + http host header is equal to Host. 2. If Host + is a wildcard, then the request matches this rule + if the http host header is to equal to the suffix + (removing the first label) of the wildcard rule." + type: string + http: + description: 'HTTPIngressRuleValue is a list of + http selectors pointing to backends. In the example: + http:///? -> backend where + where parts of the url correspond to RFC 3986, + this resource will be used to match against everything + after the last ''/'' and before the first ''?'' + or ''#''.' + properties: + paths: + description: A collection of paths that map + requests to backends. + items: + description: HTTPIngressPath associates a + path with a backend. Incoming urls matching + the path are forwarded to the backend. + properties: + backend: + description: Backend defines the referenced + service endpoint to which the traffic + will be forwarded to. + properties: + resource: + description: Resource is an ObjectRef + to another Kubernetes resource in + the namespace of the Ingress object. + If resource is specified, a service.Name + and service.Port must not be specified. + This is a mutually exclusive setting + with "Service". + properties: + apiGroup: + description: APIGroup is the group + for the resource being referenced. + If APIGroup is not specified, + the specified Kind must be in + the core API group. For any + other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type + of resource being referenced + type: string + name: + description: Name is the name + of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a + Service as a Backend. This is a + mutually exclusive setting with + "Resource". + properties: + name: + description: Name is the referenced + service. The service must exist + in the same namespace as the + Ingress object. + type: string + port: + description: Port of the referenced + service. A port name or port + number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name + of the port on the Service. + This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the + numerical port number (e.g. + 80) on the Service. This + is a mutually exclusive + setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + path: + description: Path is matched against the + path of an incoming request. Currently + it can contain characters disallowed + from the conventional "path" part of + a URL as defined by RFC 3986. Paths + must begin with a '/' and must be present + when using PathType with value "Exact" + or "Prefix". + type: string + pathType: + description: 'PathType determines the + interpretation of the Path matching. + PathType can be one of the following + values: * Exact: Matches the URL path + exactly. * Prefix: Matches based on + a URL path prefix split by ''/''. Matching + is done on a path element by element + basis. A path element refers is the + list of labels in the path split by + the ''/'' separator. A request is a + match for path p if every p is an element-wise + prefix of p of the request path. Note + that if the last element of the path + is a substring of the last element in + request path, it is not a match (e.g. + /foo/bar matches /foo/bar/baz, but does + not match /foo/barbaz). * ImplementationSpecific: + Interpretation of the Path matching + is up to the IngressClass. Implementations + can treat this as a separate PathType + or treat it identically to Prefix or + Exact path types. Implementations are + required to support all path types.' + type: string + required: + - backend + - pathType + type: object + type: array + x-kubernetes-list-type: atomic + required: + - paths + type: object + type: object + type: array + x-kubernetes-list-type: atomic + tls: + description: TLS configuration. Currently the Ingress + only supports a single TLS port, 443. If multiple members + of this list specify different hosts, they will be multiplexed + on the same port according to the hostname specified + through the SNI TLS extension, if the ingress controller + fulfilling the ingress supports SNI. + items: + description: IngressTLS describes the transport layer + security associated with an Ingress. + properties: + hosts: + description: Hosts are a list of hosts included + in the TLS certificate. The values in this list + must match the name/s used in the tlsSecret. Defaults + to the wildcard host setting for the loadbalancer + controller fulfilling this Ingress, if left unspecified. + items: + type: string + type: array + x-kubernetes-list-type: atomic + secretName: + description: SecretName is the name of the secret + used to terminate TLS traffic on port 443. Field + is left optional to allow TLS routing based on + SNI hostname alone. If the SNI host in a listener + conflicts with the "Host" header field used by + an IngressRule, the SNI host is used for termination + and value of the Host header is used for routing. + type: string + type: object + type: array + x-kubernetes-list-type: atomic + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the Ingress or Route during + its creation. The label with key "app" is reserved for use + by the operator. + type: object + type: object + grafanaConfig: + description: Specifications for how to expose Cryostat's Grafana + service, which serves the Grafana dashboard. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the Ingress or Route during + its creation. + type: object + ingressSpec: + description: Configuration for an Ingress object. Currently + subpaths are not supported, so unique hosts must be specified + (if a single external IP is being used) to differentiate + between ingresses/services. + properties: + defaultBackend: + description: DefaultBackend is the backend that should + handle requests that don't match any rule. If Rules + are not specified, DefaultBackend must be specified. + If DefaultBackend is not set, the handling of requests + that do not match any of the rules will be up to the + Ingress controller. + properties: + resource: + description: Resource is an ObjectRef to another Kubernetes + resource in the namespace of the Ingress object. + If resource is specified, a service.Name and service.Port + must not be specified. This is a mutually exclusive + setting with "Service". + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a Service as a Backend. + This is a mutually exclusive setting with "Resource". + properties: + name: + description: Name is the referenced service. The + service must exist in the same namespace as + the Ingress object. + type: string + port: + description: Port of the referenced service. A + port name or port number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name of the port + on the Service. This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the numerical port + number (e.g. 80) on the Service. This is + a mutually exclusive setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + ingressClassName: + description: IngressClassName is the name of an IngressClass + cluster resource. Ingress controller implementations + use this field to know whether they should be serving + this Ingress resource, by a transitive connection (controller + -> IngressClass -> Ingress resource). Although the `kubernetes.io/ingress.class` + annotation (simple constant name) was never formally + defined, it was widely supported by Ingress controllers + to create a direct binding between Ingress controller + and Ingress resources. Newly created Ingress resources + should prefer using the field. However, even though + the annotation is officially deprecated, for backwards + compatibility reasons, ingress controllers should still + honor that annotation if present. + type: string + rules: + description: A list of host rules used to configure the + Ingress. If unspecified, or no rule matches, all traffic + is sent to the default backend. + items: + description: IngressRule represents the rules mapping + the paths under a specified host to the related backend + services. Incoming requests are first evaluated for + a host match, then routed to the backend associated + with the matching IngressRuleValue. + properties: + host: + description: "Host is the fully qualified domain + name of a network host, as defined by RFC 3986. + Note the following deviations from the \"host\" + part of the URI as defined in RFC 3986: 1. IPs + are not allowed. Currently an IngressRuleValue + can only apply to the IP in the Spec of the parent + Ingress. 2. The `:` delimiter is not respected + because ports are not allowed. Currently the port + of an Ingress is implicitly :80 for http and :443 + for https. Both these may change in the future. + Incoming requests are matched against the host + before the IngressRuleValue. If the host is unspecified, + the Ingress routes all traffic based on the specified + IngressRuleValue. \n Host can be \"precise\" which + is a domain name without the terminating dot of + a network host (e.g. \"foo.bar.com\") or \"wildcard\", + which is a domain name prefixed with a single + wildcard label (e.g. \"*.foo.com\"). The wildcard + character '*' must appear by itself as the first + DNS label and matches only a single label. You + cannot have a wildcard label by itself (e.g. Host + == \"*\"). Requests will be matched against the + Host field in the following way: 1. If Host is + precise, the request matches this rule if the + http host header is equal to Host. 2. If Host + is a wildcard, then the request matches this rule + if the http host header is to equal to the suffix + (removing the first label) of the wildcard rule." + type: string + http: + description: 'HTTPIngressRuleValue is a list of + http selectors pointing to backends. In the example: + http:///? -> backend where + where parts of the url correspond to RFC 3986, + this resource will be used to match against everything + after the last ''/'' and before the first ''?'' + or ''#''.' + properties: + paths: + description: A collection of paths that map + requests to backends. + items: + description: HTTPIngressPath associates a + path with a backend. Incoming urls matching + the path are forwarded to the backend. + properties: + backend: + description: Backend defines the referenced + service endpoint to which the traffic + will be forwarded to. + properties: + resource: + description: Resource is an ObjectRef + to another Kubernetes resource in + the namespace of the Ingress object. + If resource is specified, a service.Name + and service.Port must not be specified. + This is a mutually exclusive setting + with "Service". + properties: + apiGroup: + description: APIGroup is the group + for the resource being referenced. + If APIGroup is not specified, + the specified Kind must be in + the core API group. For any + other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type + of resource being referenced + type: string + name: + description: Name is the name + of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a + Service as a Backend. This is a + mutually exclusive setting with + "Resource". + properties: + name: + description: Name is the referenced + service. The service must exist + in the same namespace as the + Ingress object. + type: string + port: + description: Port of the referenced + service. A port name or port + number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name + of the port on the Service. + This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the + numerical port number (e.g. + 80) on the Service. This + is a mutually exclusive + setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + path: + description: Path is matched against the + path of an incoming request. Currently + it can contain characters disallowed + from the conventional "path" part of + a URL as defined by RFC 3986. Paths + must begin with a '/' and must be present + when using PathType with value "Exact" + or "Prefix". + type: string + pathType: + description: 'PathType determines the + interpretation of the Path matching. + PathType can be one of the following + values: * Exact: Matches the URL path + exactly. * Prefix: Matches based on + a URL path prefix split by ''/''. Matching + is done on a path element by element + basis. A path element refers is the + list of labels in the path split by + the ''/'' separator. A request is a + match for path p if every p is an element-wise + prefix of p of the request path. Note + that if the last element of the path + is a substring of the last element in + request path, it is not a match (e.g. + /foo/bar matches /foo/bar/baz, but does + not match /foo/barbaz). * ImplementationSpecific: + Interpretation of the Path matching + is up to the IngressClass. Implementations + can treat this as a separate PathType + or treat it identically to Prefix or + Exact path types. Implementations are + required to support all path types.' + type: string + required: + - backend + - pathType + type: object + type: array + x-kubernetes-list-type: atomic + required: + - paths + type: object + type: object + type: array + x-kubernetes-list-type: atomic + tls: + description: TLS configuration. Currently the Ingress + only supports a single TLS port, 443. If multiple members + of this list specify different hosts, they will be multiplexed + on the same port according to the hostname specified + through the SNI TLS extension, if the ingress controller + fulfilling the ingress supports SNI. + items: + description: IngressTLS describes the transport layer + security associated with an Ingress. + properties: + hosts: + description: Hosts are a list of hosts included + in the TLS certificate. The values in this list + must match the name/s used in the tlsSecret. Defaults + to the wildcard host setting for the loadbalancer + controller fulfilling this Ingress, if left unspecified. + items: + type: string + type: array + x-kubernetes-list-type: atomic + secretName: + description: SecretName is the name of the secret + used to terminate TLS traffic on port 443. Field + is left optional to allow TLS routing based on + SNI hostname alone. If the SNI host in a listener + conflicts with the "Host" header field used by + an IngressRule, the SNI host is used for termination + and value of the Host header is used for routing. + type: string + type: object + type: array + x-kubernetes-list-type: atomic + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the Ingress or Route during + its creation. The label with key "app" is reserved for use + by the operator. + type: object + type: object + type: object + operandMetadata: + description: Options to configure the Cryostat deployments and pods + metadata + properties: + deploymentMetadata: + description: Options to configure the Cryostat deployments metadata + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the resources during its + creation. + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the resources during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + type: object + podMetadata: + description: Options to configure the Cryostat pods metadata + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the resources during its + creation. + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the resources during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + type: object + type: object + reportOptions: + description: Options to configure Cryostat Automated Report Analysis. + properties: + replicas: + description: The number of report sidecar replica containers to + deploy. Each replica can service one report generation request + at a time. + format: int32 + type: integer + resources: + description: The resources allocated to each sidecar replica. + A replica with more resources can handle larger input recordings + and will process them faster. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + schedulingOptions: + description: Options to configure scheduling for the reports deployment + properties: + affinity: + description: Affinity rules for scheduling Cryostat pods. + properties: + nodeAffinity: + description: 'Node affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#NodeAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term + matches all objects with implicit weight 0 (i.e. + it's a no-op). A null preferred scheduling term + matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to an update), the system may or may not try + to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them + are ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: 'Pod affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to a pod label update), the system may or may + not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: 'Pod anti-affinity scheduling rules for a + Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAntiAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by iterating through + the elements of this field and adding "weight" to + the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + anti-affinity requirements specified by this field + cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may + or may not try to eventually evict the pod from + its node. When there are multiple elements, the + lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + nodeSelector: + additionalProperties: + type: string + description: 'Label selector used to schedule a Cryostat pod + to a node. See: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + tolerations: + description: 'Tolerations to allow scheduling of Cryostat + pods to tainted nodes. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/' + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, + allowed values are NoSchedule, PreferNoSchedule and + NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. If the + key is empty, operator must be Exists; this combination + means to match all values and all keys. + type: string + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and Equal. + Defaults to Equal. Exists is equivalent to wildcard + for value, so that a pod can tolerate all taints of + a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period + of time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the + taint forever (do not evict). Zero and negative values + will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration + matches to. If the operator is Exists, the value should + be empty, otherwise just a regular string. + type: string + type: object + type: array + type: object + securityOptions: + description: Options to configure the Security Contexts for the + Cryostat report generator. + properties: + podSecurityContext: + description: Security Context to apply to the Cryostat report + generator pod. + properties: + fsGroup: + description: "A special supplemental group that applies + to all containers in a pod. Some volume types allow + the Kubelet to change the ownership of that volume to + be owned by the pod: \n 1. The owning GID will be the + FSGroup 2. The setgid bit is set (new files created + in the volume will be owned by FSGroup) 3. The permission + bits are OR'd with rw-rw---- \n If unset, the Kubelet + will not modify the ownership and permissions of any + volume. Note that this field cannot be set when spec.os.name + is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of + changing ownership and permission of the volume before + being exposed inside Pod. This field will only apply + to volume types which support fsGroup based ownership(and + permissions). It will have no effect on ephemeral volume + types such as: secret, configmaps and emptydir. Valid + values are "OnRootMismatch" and "Always". If not specified, + "Always" is used. Note that this field cannot be set + when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if it + does. If unset or false, no such validation will be + performed. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence + for that container. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all + containers. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this + field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers + in this pod. Note that this field cannot be set when + spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process + run in each container, in addition to the container's + primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container + process. If unspecified, no additional groups are added + to any container. Note that group memberships defined + in the container image for the uid of the container + process are still effective, even if they are not included + in this list. Note that this field cannot be set when + spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls + used for the pod. Pods with unsupported sysctls (by + the container runtime) might fail to launch. Note that + this field cannot be set when spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be + set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options within a + container's SecurityContext will be used. If set in + both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + reportsSecurityContext: + description: Security Context to apply to the Cryostat report + generator container. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag + will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if it + does. If unset or false, no such validation will be + performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + type: object + subProcessMaxHeapSize: + description: When zero report sidecar replicas are requested, + SubProcessMaxHeapSize configures the maximum heap size of the + basic subprocess report generator in MiB. The default heap size + is `200` (MiB). + format: int32 + type: integer + type: object + resources: + description: Resource requirements for the Cryostat deployment. + properties: + coreResources: + description: Resource requirements for the Cryostat application. + If specifying a memory limit, at least 768MiB is recommended. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + dataSourceResources: + description: Resource requirements for the JFR Data Source container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + grafanaResources: + description: Resource requirements for the Grafana container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + type: object + schedulingOptions: + description: Options to configure scheduling for the Cryostat deployment + properties: + affinity: + description: Affinity rules for scheduling Cryostat pods. + properties: + nodeAffinity: + description: 'Node affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#NodeAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: 'Pod affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: 'Pod anti-affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAntiAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + nodeSelector: + additionalProperties: + type: string + description: 'Label selector used to schedule a Cryostat pod to + a node. See: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + tolerations: + description: 'Tolerations to allow scheduling of Cryostat pods + to tainted nodes. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/' + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, allowed + values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match + all values and all keys. + type: string + operator: + description: Operator represents a key's relationship to + the value. Valid operators are Exists and Equal. Defaults + to Equal. Exists is equivalent to wildcard for value, + so that a pod can tolerate all taints of a particular + category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of + time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the taint + forever (do not evict). Zero and negative values will + be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + type: object + securityOptions: + description: Options to configure the Security Contexts for the Cryostat + application. + properties: + coreSecurityContext: + description: Security Context to apply to the Cryostat application + container. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + dataSourceSecurityContext: + description: Security Context to apply to the JFR Data Source + container. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + grafanaSecurityContext: + description: Security Context to apply to the Grafana container. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + podSecurityContext: + description: Security Context to apply to the Cryostat pod. + properties: + fsGroup: + description: "A special supplemental group that applies to + all containers in a pod. Some volume types allow the Kubelet + to change the ownership of that volume to be owned by the + pod: \n 1. The owning GID will be the FSGroup 2. The setgid + bit is set (new files created in the volume will be owned + by FSGroup) 3. The permission bits are OR'd with rw-rw---- + \n If unset, the Kubelet will not modify the ownership and + permissions of any volume. Note that this field cannot be + set when spec.os.name is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will + have no effect on ephemeral volume types such as: secret, + configmaps and emptydir. Valid values are "OnRootMismatch" + and "Always". If not specified, "Always" is used. Note that + this field cannot be set when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this field + cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is + windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + SecurityContext. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence + for that container. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers + in this pod. Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process + run in each container, in addition to the container's primary + GID, the fsGroup (if specified), and group memberships defined + in the container image for the uid of the container process. + If unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image + for the uid of the container process are still effective, + even if they are not included in this list. Note that this + field cannot be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used + for the pod. Pods with unsupported sysctls (by the container + runtime) might fail to launch. Note that this field cannot + be set when spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options within a container's + SecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + type: object + serviceOptions: + description: Options to customize the services created for the Cryostat + application and Grafana dashboard. + properties: + coreConfig: + description: Specification for the service responsible for the + Cryostat application. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the service during its + creation. + type: object + httpPort: + description: HTTP port number for the Cryostat application + service. Defaults to 8181. + format: int32 + type: integer + jmxPort: + description: Remote JMX port number for the Cryostat application + service. Defaults to 9091. + format: int32 + type: integer + labels: + additionalProperties: + type: string + description: Labels to add to the service during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + serviceType: + description: Type of service to create. Defaults to "ClusterIP". + type: string + type: object + grafanaConfig: + description: Specification for the service responsible for the + Cryostat Grafana dashboard. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the service during its + creation. + type: object + httpPort: + description: HTTP port number for the Grafana dashboard service. + Defaults to 3000. + format: int32 + type: integer + labels: + additionalProperties: + type: string + description: Labels to add to the service during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + serviceType: + description: Type of service to create. Defaults to "ClusterIP". + type: string + type: object + reportsConfig: + description: Specification for the service responsible for the + cryostat-reports sidecars. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the service during its + creation. + type: object + httpPort: + description: HTTP port number for the cryostat-reports service. + Defaults to 10000. + format: int32 + type: integer + labels: + additionalProperties: + type: string + description: Labels to add to the service during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + serviceType: + description: Type of service to create. Defaults to "ClusterIP". + type: string + type: object + type: object + storageOptions: + description: Options to customize the storage for Flight Recordings + and Templates. + properties: + emptyDir: + description: Configuration for an EmptyDir to be created by the + operator instead of a PVC. + properties: + enabled: + description: When enabled, Cryostat will use EmptyDir volumes + instead of a Persistent Volume Claim. Any PVC configurations + will be ignored. + type: boolean + medium: + description: Unless specified, the emptyDir volume will be + mounted on the same storage medium backing the node. Setting + this field to "Memory" will mount the emptyDir on a tmpfs + (RAM-backed filesystem). + type: string + sizeLimit: + description: The maximum memory limit for the emptyDir. Default + is unbounded. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + type: string + type: object + pvc: + description: Configuration for the Persistent Volume Claim to + be created by the operator. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the Persistent Volume Claim + during its creation. + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the Persistent Volume Claim + during its creation. The label with key "app" is reserved + for use by the operator. + type: object + spec: + description: Spec for a Persistent Volume Claim, whose options + will override the defaults used by the operator. Unless + overriden, the PVC will be created with the default Storage + Class and 500MiB of storage. Once the operator has created + the PVC, changes to this field have no effect. + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified + data source, it will create a new volume based on the + contents of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then + dataSourceRef will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the dataSource + field and as such if both fields are non-empty, they + must have the same value. For backwards compatibility, + when namespace isn''t specified in dataSourceRef, both + fields (dataSource and dataSourceRef) will be set to + the same value automatically if one of them is empty + and the other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the same + value and must be empty. There are three important differences + between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef + allows any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + * While dataSource only allows local objects, dataSourceRef + allows objects in any namespaces. (Beta) Using this + field requires the AnyVolumeDataSource feature gate + to be enabled. (Alpha) Using the namespace field of + dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the + ReferenceGrant documentation for details. (Alpha) + This field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify resource + requirements that are lower than previous value but + must still be higher than capacity recorded in the status + field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n This field is immutable. It can only be set for + containers." + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one + entry in pod.spec.resourceClaims of the Pod + where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes to + consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values + array must be non-empty. If the operator is + Exists or DoesNotExist, the values array must + be empty. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is + required by the claim. Value of Filesystem is implied + when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + type: object + type: object + targetDiscoveryOptions: + description: Options to configure the Cryostat application's target + discovery mechanisms. + properties: + builtInDiscoveryDisabled: + description: When true, the Cryostat application will disable + the built-in discovery mechanisms. Defaults to false + type: boolean + type: object + targetNamespaces: + description: 'List of namespaces whose workloads Cryostat should be + permitted to access and profile. Defaults to this Cryostat''s namespace. + Warning: All Cryostat users will be able to create and manage recordings + for workloads in the listed namespaces. More details: https://github.com/cryostatio/cryostat-operator/blob/v2.4.0/docs/multi-namespace.md#data-isolation' + items: + type: string + type: array + trustedCertSecrets: + description: List of TLS certificates to trust when connecting to + targets. + items: + properties: + certificateKey: + description: Key within secret containing the certificate. + type: string + secretName: + description: Name of secret in the local namespace. + type: string + required: + - secretName + type: object + type: array + required: + - minimal + type: object + status: + description: CryostatStatus defines the observed state of Cryostat. + properties: + applicationUrl: + description: Address of the deployed Cryostat web application. + type: string + conditions: + description: Conditions of the components managed by the Cryostat + Operator. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + grafanaSecret: + description: Name of the Secret containing the generated Grafana credentials. + type: string + targetNamespaces: + description: List of namespaces that Cryostat has been configured + and authorized to access and profile. + items: + type: string + type: array + required: + - applicationUrl + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/config/crd/bases/operator.cryostat.io_clustercryostats.yaml b/config/crd/bases/operator.cryostat.io_clustercryostats.yaml index 9d606b91f..d92d831dc 100644 --- a/config/crd/bases/operator.cryostat.io_clustercryostats.yaml +++ b/config/crd/bases/operator.cryostat.io_clustercryostats.yaml @@ -4748,6 +4748,4721 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.applicationUrl + name: Application URL + type: string + - jsonPath: .status.grafanaSecret + name: Grafana Secret + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: ClusterCryostat allows you to install Cryostat for multiple namespaces + or cluster-wide. It contains configuration options for controlling the Deployment + of the Cryostat application and its related components. A ClusterCryostat + or Cryostat instance must be created to instruct the operator to deploy + the Cryostat application. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ClusterCryostatSpec defines the desired state of ClusterCryostat. + properties: + authProperties: + description: Override default authorization properties for Cryostat + on OpenShift. + properties: + clusterRoleName: + description: 'Name of the ClusterRole to use when Cryostat requests + a role-scoped OAuth token. This ClusterRole should contain permissions + for all Kubernetes objects listed in custom permission mapping. + More details: https://docs.openshift.com/container-platform/4.11/authentication/tokens-scoping.html#scoping-tokens-role-scope_configuring-internal-oauth' + type: string + configMapName: + description: Name of config map in the local namespace. + type: string + filename: + description: Filename within config map containing the resource + mapping. + type: string + required: + - clusterRoleName + - configMapName + - filename + type: object + enableCertManager: + description: Use cert-manager to secure in-cluster communication between + Cryostat components. Requires cert-manager to be installed. + type: boolean + eventTemplates: + description: List of Flight Recorder Event Templates to preconfigure + in Cryostat. + items: + description: A ConfigMap containing a .jfc template file. + properties: + configMapName: + description: Name of config map in the local namespace. + type: string + filename: + description: Filename within config map containing the template + file. + type: string + required: + - configMapName + - filename + type: object + type: array + installNamespace: + description: Namespace where Cryostat should be installed. On multi-tenant + clusters, we strongly suggest installing Cryostat into its own namespace. + type: string + jmxCacheOptions: + description: Options to customize the JMX target connections cache + for the Cryostat application. + properties: + targetCacheSize: + description: The maximum number of JMX connections to cache. Use + `-1` for an unlimited cache size (TTL expiration only). Defaults + to `-1`. + format: int32 + minimum: -1 + type: integer + targetCacheTTL: + description: The time to live (in seconds) for cached JMX connections. + Defaults to `10`. + format: int32 + minimum: 1 + type: integer + type: object + jmxCredentialsDatabaseOptions: + description: Options to configure the Cryostat application's credentials + database. + properties: + databaseSecretName: + description: Name of the secret containing the password to encrypt + credentials database. + type: string + type: object + maxWsConnections: + description: The maximum number of WebSocket client connections allowed + (minimum 1, default unlimited). + format: int32 + minimum: 1 + type: integer + minimal: + description: Deploy a pared-down Cryostat instance with no Grafana + Dashboard or JFR Data Source. + type: boolean + networkOptions: + description: Options to control how the operator exposes the application + outside of the cluster, such as using an Ingress or Route. + properties: + commandConfig: + description: "Specifications for how to expose the Cryostat command + service, which serves the WebSocket command channel. \n Deprecated: + CommandConfig is no longer used." + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the Ingress or Route during + its creation. + type: object + ingressSpec: + description: Configuration for an Ingress object. Currently + subpaths are not supported, so unique hosts must be specified + (if a single external IP is being used) to differentiate + between ingresses/services. + properties: + defaultBackend: + description: DefaultBackend is the backend that should + handle requests that don't match any rule. If Rules + are not specified, DefaultBackend must be specified. + If DefaultBackend is not set, the handling of requests + that do not match any of the rules will be up to the + Ingress controller. + properties: + resource: + description: Resource is an ObjectRef to another Kubernetes + resource in the namespace of the Ingress object. + If resource is specified, a service.Name and service.Port + must not be specified. This is a mutually exclusive + setting with "Service". + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a Service as a Backend. + This is a mutually exclusive setting with "Resource". + properties: + name: + description: Name is the referenced service. The + service must exist in the same namespace as + the Ingress object. + type: string + port: + description: Port of the referenced service. A + port name or port number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name of the port + on the Service. This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the numerical port + number (e.g. 80) on the Service. This is + a mutually exclusive setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + ingressClassName: + description: IngressClassName is the name of an IngressClass + cluster resource. Ingress controller implementations + use this field to know whether they should be serving + this Ingress resource, by a transitive connection (controller + -> IngressClass -> Ingress resource). Although the `kubernetes.io/ingress.class` + annotation (simple constant name) was never formally + defined, it was widely supported by Ingress controllers + to create a direct binding between Ingress controller + and Ingress resources. Newly created Ingress resources + should prefer using the field. However, even though + the annotation is officially deprecated, for backwards + compatibility reasons, ingress controllers should still + honor that annotation if present. + type: string + rules: + description: A list of host rules used to configure the + Ingress. If unspecified, or no rule matches, all traffic + is sent to the default backend. + items: + description: IngressRule represents the rules mapping + the paths under a specified host to the related backend + services. Incoming requests are first evaluated for + a host match, then routed to the backend associated + with the matching IngressRuleValue. + properties: + host: + description: "Host is the fully qualified domain + name of a network host, as defined by RFC 3986. + Note the following deviations from the \"host\" + part of the URI as defined in RFC 3986: 1. IPs + are not allowed. Currently an IngressRuleValue + can only apply to the IP in the Spec of the parent + Ingress. 2. The `:` delimiter is not respected + because ports are not allowed. Currently the port + of an Ingress is implicitly :80 for http and :443 + for https. Both these may change in the future. + Incoming requests are matched against the host + before the IngressRuleValue. If the host is unspecified, + the Ingress routes all traffic based on the specified + IngressRuleValue. \n Host can be \"precise\" which + is a domain name without the terminating dot of + a network host (e.g. \"foo.bar.com\") or \"wildcard\", + which is a domain name prefixed with a single + wildcard label (e.g. \"*.foo.com\"). The wildcard + character '*' must appear by itself as the first + DNS label and matches only a single label. You + cannot have a wildcard label by itself (e.g. Host + == \"*\"). Requests will be matched against the + Host field in the following way: 1. If Host is + precise, the request matches this rule if the + http host header is equal to Host. 2. If Host + is a wildcard, then the request matches this rule + if the http host header is to equal to the suffix + (removing the first label) of the wildcard rule." + type: string + http: + description: 'HTTPIngressRuleValue is a list of + http selectors pointing to backends. In the example: + http:///? -> backend where + where parts of the url correspond to RFC 3986, + this resource will be used to match against everything + after the last ''/'' and before the first ''?'' + or ''#''.' + properties: + paths: + description: A collection of paths that map + requests to backends. + items: + description: HTTPIngressPath associates a + path with a backend. Incoming urls matching + the path are forwarded to the backend. + properties: + backend: + description: Backend defines the referenced + service endpoint to which the traffic + will be forwarded to. + properties: + resource: + description: Resource is an ObjectRef + to another Kubernetes resource in + the namespace of the Ingress object. + If resource is specified, a service.Name + and service.Port must not be specified. + This is a mutually exclusive setting + with "Service". + properties: + apiGroup: + description: APIGroup is the group + for the resource being referenced. + If APIGroup is not specified, + the specified Kind must be in + the core API group. For any + other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type + of resource being referenced + type: string + name: + description: Name is the name + of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a + Service as a Backend. This is a + mutually exclusive setting with + "Resource". + properties: + name: + description: Name is the referenced + service. The service must exist + in the same namespace as the + Ingress object. + type: string + port: + description: Port of the referenced + service. A port name or port + number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name + of the port on the Service. + This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the + numerical port number (e.g. + 80) on the Service. This + is a mutually exclusive + setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + path: + description: Path is matched against the + path of an incoming request. Currently + it can contain characters disallowed + from the conventional "path" part of + a URL as defined by RFC 3986. Paths + must begin with a '/' and must be present + when using PathType with value "Exact" + or "Prefix". + type: string + pathType: + description: 'PathType determines the + interpretation of the Path matching. + PathType can be one of the following + values: * Exact: Matches the URL path + exactly. * Prefix: Matches based on + a URL path prefix split by ''/''. Matching + is done on a path element by element + basis. A path element refers is the + list of labels in the path split by + the ''/'' separator. A request is a + match for path p if every p is an element-wise + prefix of p of the request path. Note + that if the last element of the path + is a substring of the last element in + request path, it is not a match (e.g. + /foo/bar matches /foo/bar/baz, but does + not match /foo/barbaz). * ImplementationSpecific: + Interpretation of the Path matching + is up to the IngressClass. Implementations + can treat this as a separate PathType + or treat it identically to Prefix or + Exact path types. Implementations are + required to support all path types.' + type: string + required: + - backend + - pathType + type: object + type: array + x-kubernetes-list-type: atomic + required: + - paths + type: object + type: object + type: array + x-kubernetes-list-type: atomic + tls: + description: TLS configuration. Currently the Ingress + only supports a single TLS port, 443. If multiple members + of this list specify different hosts, they will be multiplexed + on the same port according to the hostname specified + through the SNI TLS extension, if the ingress controller + fulfilling the ingress supports SNI. + items: + description: IngressTLS describes the transport layer + security associated with an Ingress. + properties: + hosts: + description: Hosts are a list of hosts included + in the TLS certificate. The values in this list + must match the name/s used in the tlsSecret. Defaults + to the wildcard host setting for the loadbalancer + controller fulfilling this Ingress, if left unspecified. + items: + type: string + type: array + x-kubernetes-list-type: atomic + secretName: + description: SecretName is the name of the secret + used to terminate TLS traffic on port 443. Field + is left optional to allow TLS routing based on + SNI hostname alone. If the SNI host in a listener + conflicts with the "Host" header field used by + an IngressRule, the SNI host is used for termination + and value of the Host header is used for routing. + type: string + type: object + type: array + x-kubernetes-list-type: atomic + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the Ingress or Route during + its creation. The label with key "app" is reserved for use + by the operator. + type: object + type: object + coreConfig: + description: Specifications for how to expose the Cryostat service, + which serves the Cryostat application. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the Ingress or Route during + its creation. + type: object + ingressSpec: + description: Configuration for an Ingress object. Currently + subpaths are not supported, so unique hosts must be specified + (if a single external IP is being used) to differentiate + between ingresses/services. + properties: + defaultBackend: + description: DefaultBackend is the backend that should + handle requests that don't match any rule. If Rules + are not specified, DefaultBackend must be specified. + If DefaultBackend is not set, the handling of requests + that do not match any of the rules will be up to the + Ingress controller. + properties: + resource: + description: Resource is an ObjectRef to another Kubernetes + resource in the namespace of the Ingress object. + If resource is specified, a service.Name and service.Port + must not be specified. This is a mutually exclusive + setting with "Service". + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a Service as a Backend. + This is a mutually exclusive setting with "Resource". + properties: + name: + description: Name is the referenced service. The + service must exist in the same namespace as + the Ingress object. + type: string + port: + description: Port of the referenced service. A + port name or port number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name of the port + on the Service. This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the numerical port + number (e.g. 80) on the Service. This is + a mutually exclusive setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + ingressClassName: + description: IngressClassName is the name of an IngressClass + cluster resource. Ingress controller implementations + use this field to know whether they should be serving + this Ingress resource, by a transitive connection (controller + -> IngressClass -> Ingress resource). Although the `kubernetes.io/ingress.class` + annotation (simple constant name) was never formally + defined, it was widely supported by Ingress controllers + to create a direct binding between Ingress controller + and Ingress resources. Newly created Ingress resources + should prefer using the field. However, even though + the annotation is officially deprecated, for backwards + compatibility reasons, ingress controllers should still + honor that annotation if present. + type: string + rules: + description: A list of host rules used to configure the + Ingress. If unspecified, or no rule matches, all traffic + is sent to the default backend. + items: + description: IngressRule represents the rules mapping + the paths under a specified host to the related backend + services. Incoming requests are first evaluated for + a host match, then routed to the backend associated + with the matching IngressRuleValue. + properties: + host: + description: "Host is the fully qualified domain + name of a network host, as defined by RFC 3986. + Note the following deviations from the \"host\" + part of the URI as defined in RFC 3986: 1. IPs + are not allowed. Currently an IngressRuleValue + can only apply to the IP in the Spec of the parent + Ingress. 2. The `:` delimiter is not respected + because ports are not allowed. Currently the port + of an Ingress is implicitly :80 for http and :443 + for https. Both these may change in the future. + Incoming requests are matched against the host + before the IngressRuleValue. If the host is unspecified, + the Ingress routes all traffic based on the specified + IngressRuleValue. \n Host can be \"precise\" which + is a domain name without the terminating dot of + a network host (e.g. \"foo.bar.com\") or \"wildcard\", + which is a domain name prefixed with a single + wildcard label (e.g. \"*.foo.com\"). The wildcard + character '*' must appear by itself as the first + DNS label and matches only a single label. You + cannot have a wildcard label by itself (e.g. Host + == \"*\"). Requests will be matched against the + Host field in the following way: 1. If Host is + precise, the request matches this rule if the + http host header is equal to Host. 2. If Host + is a wildcard, then the request matches this rule + if the http host header is to equal to the suffix + (removing the first label) of the wildcard rule." + type: string + http: + description: 'HTTPIngressRuleValue is a list of + http selectors pointing to backends. In the example: + http:///? -> backend where + where parts of the url correspond to RFC 3986, + this resource will be used to match against everything + after the last ''/'' and before the first ''?'' + or ''#''.' + properties: + paths: + description: A collection of paths that map + requests to backends. + items: + description: HTTPIngressPath associates a + path with a backend. Incoming urls matching + the path are forwarded to the backend. + properties: + backend: + description: Backend defines the referenced + service endpoint to which the traffic + will be forwarded to. + properties: + resource: + description: Resource is an ObjectRef + to another Kubernetes resource in + the namespace of the Ingress object. + If resource is specified, a service.Name + and service.Port must not be specified. + This is a mutually exclusive setting + with "Service". + properties: + apiGroup: + description: APIGroup is the group + for the resource being referenced. + If APIGroup is not specified, + the specified Kind must be in + the core API group. For any + other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type + of resource being referenced + type: string + name: + description: Name is the name + of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a + Service as a Backend. This is a + mutually exclusive setting with + "Resource". + properties: + name: + description: Name is the referenced + service. The service must exist + in the same namespace as the + Ingress object. + type: string + port: + description: Port of the referenced + service. A port name or port + number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name + of the port on the Service. + This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the + numerical port number (e.g. + 80) on the Service. This + is a mutually exclusive + setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + path: + description: Path is matched against the + path of an incoming request. Currently + it can contain characters disallowed + from the conventional "path" part of + a URL as defined by RFC 3986. Paths + must begin with a '/' and must be present + when using PathType with value "Exact" + or "Prefix". + type: string + pathType: + description: 'PathType determines the + interpretation of the Path matching. + PathType can be one of the following + values: * Exact: Matches the URL path + exactly. * Prefix: Matches based on + a URL path prefix split by ''/''. Matching + is done on a path element by element + basis. A path element refers is the + list of labels in the path split by + the ''/'' separator. A request is a + match for path p if every p is an element-wise + prefix of p of the request path. Note + that if the last element of the path + is a substring of the last element in + request path, it is not a match (e.g. + /foo/bar matches /foo/bar/baz, but does + not match /foo/barbaz). * ImplementationSpecific: + Interpretation of the Path matching + is up to the IngressClass. Implementations + can treat this as a separate PathType + or treat it identically to Prefix or + Exact path types. Implementations are + required to support all path types.' + type: string + required: + - backend + - pathType + type: object + type: array + x-kubernetes-list-type: atomic + required: + - paths + type: object + type: object + type: array + x-kubernetes-list-type: atomic + tls: + description: TLS configuration. Currently the Ingress + only supports a single TLS port, 443. If multiple members + of this list specify different hosts, they will be multiplexed + on the same port according to the hostname specified + through the SNI TLS extension, if the ingress controller + fulfilling the ingress supports SNI. + items: + description: IngressTLS describes the transport layer + security associated with an Ingress. + properties: + hosts: + description: Hosts are a list of hosts included + in the TLS certificate. The values in this list + must match the name/s used in the tlsSecret. Defaults + to the wildcard host setting for the loadbalancer + controller fulfilling this Ingress, if left unspecified. + items: + type: string + type: array + x-kubernetes-list-type: atomic + secretName: + description: SecretName is the name of the secret + used to terminate TLS traffic on port 443. Field + is left optional to allow TLS routing based on + SNI hostname alone. If the SNI host in a listener + conflicts with the "Host" header field used by + an IngressRule, the SNI host is used for termination + and value of the Host header is used for routing. + type: string + type: object + type: array + x-kubernetes-list-type: atomic + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the Ingress or Route during + its creation. The label with key "app" is reserved for use + by the operator. + type: object + type: object + grafanaConfig: + description: Specifications for how to expose Cryostat's Grafana + service, which serves the Grafana dashboard. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the Ingress or Route during + its creation. + type: object + ingressSpec: + description: Configuration for an Ingress object. Currently + subpaths are not supported, so unique hosts must be specified + (if a single external IP is being used) to differentiate + between ingresses/services. + properties: + defaultBackend: + description: DefaultBackend is the backend that should + handle requests that don't match any rule. If Rules + are not specified, DefaultBackend must be specified. + If DefaultBackend is not set, the handling of requests + that do not match any of the rules will be up to the + Ingress controller. + properties: + resource: + description: Resource is an ObjectRef to another Kubernetes + resource in the namespace of the Ingress object. + If resource is specified, a service.Name and service.Port + must not be specified. This is a mutually exclusive + setting with "Service". + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a Service as a Backend. + This is a mutually exclusive setting with "Resource". + properties: + name: + description: Name is the referenced service. The + service must exist in the same namespace as + the Ingress object. + type: string + port: + description: Port of the referenced service. A + port name or port number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name of the port + on the Service. This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the numerical port + number (e.g. 80) on the Service. This is + a mutually exclusive setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + ingressClassName: + description: IngressClassName is the name of an IngressClass + cluster resource. Ingress controller implementations + use this field to know whether they should be serving + this Ingress resource, by a transitive connection (controller + -> IngressClass -> Ingress resource). Although the `kubernetes.io/ingress.class` + annotation (simple constant name) was never formally + defined, it was widely supported by Ingress controllers + to create a direct binding between Ingress controller + and Ingress resources. Newly created Ingress resources + should prefer using the field. However, even though + the annotation is officially deprecated, for backwards + compatibility reasons, ingress controllers should still + honor that annotation if present. + type: string + rules: + description: A list of host rules used to configure the + Ingress. If unspecified, or no rule matches, all traffic + is sent to the default backend. + items: + description: IngressRule represents the rules mapping + the paths under a specified host to the related backend + services. Incoming requests are first evaluated for + a host match, then routed to the backend associated + with the matching IngressRuleValue. + properties: + host: + description: "Host is the fully qualified domain + name of a network host, as defined by RFC 3986. + Note the following deviations from the \"host\" + part of the URI as defined in RFC 3986: 1. IPs + are not allowed. Currently an IngressRuleValue + can only apply to the IP in the Spec of the parent + Ingress. 2. The `:` delimiter is not respected + because ports are not allowed. Currently the port + of an Ingress is implicitly :80 for http and :443 + for https. Both these may change in the future. + Incoming requests are matched against the host + before the IngressRuleValue. If the host is unspecified, + the Ingress routes all traffic based on the specified + IngressRuleValue. \n Host can be \"precise\" which + is a domain name without the terminating dot of + a network host (e.g. \"foo.bar.com\") or \"wildcard\", + which is a domain name prefixed with a single + wildcard label (e.g. \"*.foo.com\"). The wildcard + character '*' must appear by itself as the first + DNS label and matches only a single label. You + cannot have a wildcard label by itself (e.g. Host + == \"*\"). Requests will be matched against the + Host field in the following way: 1. If Host is + precise, the request matches this rule if the + http host header is equal to Host. 2. If Host + is a wildcard, then the request matches this rule + if the http host header is to equal to the suffix + (removing the first label) of the wildcard rule." + type: string + http: + description: 'HTTPIngressRuleValue is a list of + http selectors pointing to backends. In the example: + http:///? -> backend where + where parts of the url correspond to RFC 3986, + this resource will be used to match against everything + after the last ''/'' and before the first ''?'' + or ''#''.' + properties: + paths: + description: A collection of paths that map + requests to backends. + items: + description: HTTPIngressPath associates a + path with a backend. Incoming urls matching + the path are forwarded to the backend. + properties: + backend: + description: Backend defines the referenced + service endpoint to which the traffic + will be forwarded to. + properties: + resource: + description: Resource is an ObjectRef + to another Kubernetes resource in + the namespace of the Ingress object. + If resource is specified, a service.Name + and service.Port must not be specified. + This is a mutually exclusive setting + with "Service". + properties: + apiGroup: + description: APIGroup is the group + for the resource being referenced. + If APIGroup is not specified, + the specified Kind must be in + the core API group. For any + other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type + of resource being referenced + type: string + name: + description: Name is the name + of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a + Service as a Backend. This is a + mutually exclusive setting with + "Resource". + properties: + name: + description: Name is the referenced + service. The service must exist + in the same namespace as the + Ingress object. + type: string + port: + description: Port of the referenced + service. A port name or port + number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name + of the port on the Service. + This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the + numerical port number (e.g. + 80) on the Service. This + is a mutually exclusive + setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + path: + description: Path is matched against the + path of an incoming request. Currently + it can contain characters disallowed + from the conventional "path" part of + a URL as defined by RFC 3986. Paths + must begin with a '/' and must be present + when using PathType with value "Exact" + or "Prefix". + type: string + pathType: + description: 'PathType determines the + interpretation of the Path matching. + PathType can be one of the following + values: * Exact: Matches the URL path + exactly. * Prefix: Matches based on + a URL path prefix split by ''/''. Matching + is done on a path element by element + basis. A path element refers is the + list of labels in the path split by + the ''/'' separator. A request is a + match for path p if every p is an element-wise + prefix of p of the request path. Note + that if the last element of the path + is a substring of the last element in + request path, it is not a match (e.g. + /foo/bar matches /foo/bar/baz, but does + not match /foo/barbaz). * ImplementationSpecific: + Interpretation of the Path matching + is up to the IngressClass. Implementations + can treat this as a separate PathType + or treat it identically to Prefix or + Exact path types. Implementations are + required to support all path types.' + type: string + required: + - backend + - pathType + type: object + type: array + x-kubernetes-list-type: atomic + required: + - paths + type: object + type: object + type: array + x-kubernetes-list-type: atomic + tls: + description: TLS configuration. Currently the Ingress + only supports a single TLS port, 443. If multiple members + of this list specify different hosts, they will be multiplexed + on the same port according to the hostname specified + through the SNI TLS extension, if the ingress controller + fulfilling the ingress supports SNI. + items: + description: IngressTLS describes the transport layer + security associated with an Ingress. + properties: + hosts: + description: Hosts are a list of hosts included + in the TLS certificate. The values in this list + must match the name/s used in the tlsSecret. Defaults + to the wildcard host setting for the loadbalancer + controller fulfilling this Ingress, if left unspecified. + items: + type: string + type: array + x-kubernetes-list-type: atomic + secretName: + description: SecretName is the name of the secret + used to terminate TLS traffic on port 443. Field + is left optional to allow TLS routing based on + SNI hostname alone. If the SNI host in a listener + conflicts with the "Host" header field used by + an IngressRule, the SNI host is used for termination + and value of the Host header is used for routing. + type: string + type: object + type: array + x-kubernetes-list-type: atomic + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the Ingress or Route during + its creation. The label with key "app" is reserved for use + by the operator. + type: object + type: object + type: object + operandMetadata: + description: Options to configure the Cryostat deployments and pods + metadata + properties: + deploymentMetadata: + description: Options to configure the Cryostat deployments metadata + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the resources during its + creation. + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the resources during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + type: object + podMetadata: + description: Options to configure the Cryostat pods metadata + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the resources during its + creation. + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the resources during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + type: object + type: object + reportOptions: + description: Options to configure Cryostat Automated Report Analysis. + properties: + replicas: + description: The number of report sidecar replica containers to + deploy. Each replica can service one report generation request + at a time. + format: int32 + type: integer + resources: + description: The resources allocated to each sidecar replica. + A replica with more resources can handle larger input recordings + and will process them faster. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + schedulingOptions: + description: Options to configure scheduling for the reports deployment + properties: + affinity: + description: Affinity rules for scheduling Cryostat pods. + properties: + nodeAffinity: + description: 'Node affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#NodeAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term + matches all objects with implicit weight 0 (i.e. + it's a no-op). A null preferred scheduling term + matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to an update), the system may or may not try + to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them + are ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: 'Pod affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to a pod label update), the system may or may + not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: 'Pod anti-affinity scheduling rules for a + Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAntiAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by iterating through + the elements of this field and adding "weight" to + the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + anti-affinity requirements specified by this field + cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may + or may not try to eventually evict the pod from + its node. When there are multiple elements, the + lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + nodeSelector: + additionalProperties: + type: string + description: 'Label selector used to schedule a Cryostat pod + to a node. See: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + tolerations: + description: 'Tolerations to allow scheduling of Cryostat + pods to tainted nodes. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/' + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, + allowed values are NoSchedule, PreferNoSchedule and + NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. If the + key is empty, operator must be Exists; this combination + means to match all values and all keys. + type: string + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and Equal. + Defaults to Equal. Exists is equivalent to wildcard + for value, so that a pod can tolerate all taints of + a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period + of time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the + taint forever (do not evict). Zero and negative values + will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration + matches to. If the operator is Exists, the value should + be empty, otherwise just a regular string. + type: string + type: object + type: array + type: object + securityOptions: + description: Options to configure the Security Contexts for the + Cryostat report generator. + properties: + podSecurityContext: + description: Security Context to apply to the Cryostat report + generator pod. + properties: + fsGroup: + description: "A special supplemental group that applies + to all containers in a pod. Some volume types allow + the Kubelet to change the ownership of that volume to + be owned by the pod: \n 1. The owning GID will be the + FSGroup 2. The setgid bit is set (new files created + in the volume will be owned by FSGroup) 3. The permission + bits are OR'd with rw-rw---- \n If unset, the Kubelet + will not modify the ownership and permissions of any + volume. Note that this field cannot be set when spec.os.name + is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of + changing ownership and permission of the volume before + being exposed inside Pod. This field will only apply + to volume types which support fsGroup based ownership(and + permissions). It will have no effect on ephemeral volume + types such as: secret, configmaps and emptydir. Valid + values are "OnRootMismatch" and "Always". If not specified, + "Always" is used. Note that this field cannot be set + when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if it + does. If unset or false, no such validation will be + performed. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence + for that container. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all + containers. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this + field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers + in this pod. Note that this field cannot be set when + spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process + run in each container, in addition to the container's + primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container + process. If unspecified, no additional groups are added + to any container. Note that group memberships defined + in the container image for the uid of the container + process are still effective, even if they are not included + in this list. Note that this field cannot be set when + spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls + used for the pod. Pods with unsupported sysctls (by + the container runtime) might fail to launch. Note that + this field cannot be set when spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be + set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options within a + container's SecurityContext will be used. If set in + both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + reportsSecurityContext: + description: Security Context to apply to the Cryostat report + generator container. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag + will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if it + does. If unset or false, no such validation will be + performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + type: object + subProcessMaxHeapSize: + description: When zero report sidecar replicas are requested, + SubProcessMaxHeapSize configures the maximum heap size of the + basic subprocess report generator in MiB. The default heap size + is `200` (MiB). + format: int32 + type: integer + type: object + resources: + description: Resource requirements for the Cryostat deployment. + properties: + coreResources: + description: Resource requirements for the Cryostat application. + If specifying a memory limit, at least 768MiB is recommended. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + dataSourceResources: + description: Resource requirements for the JFR Data Source container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + grafanaResources: + description: Resource requirements for the Grafana container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + type: object + schedulingOptions: + description: Options to configure scheduling for the Cryostat deployment + properties: + affinity: + description: Affinity rules for scheduling Cryostat pods. + properties: + nodeAffinity: + description: 'Node affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#NodeAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: 'Pod affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: 'Pod anti-affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAntiAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + nodeSelector: + additionalProperties: + type: string + description: 'Label selector used to schedule a Cryostat pod to + a node. See: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + tolerations: + description: 'Tolerations to allow scheduling of Cryostat pods + to tainted nodes. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/' + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, allowed + values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match + all values and all keys. + type: string + operator: + description: Operator represents a key's relationship to + the value. Valid operators are Exists and Equal. Defaults + to Equal. Exists is equivalent to wildcard for value, + so that a pod can tolerate all taints of a particular + category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of + time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the taint + forever (do not evict). Zero and negative values will + be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + type: object + securityOptions: + description: Options to configure the Security Contexts for the Cryostat + application. + properties: + coreSecurityContext: + description: Security Context to apply to the Cryostat application + container. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + dataSourceSecurityContext: + description: Security Context to apply to the JFR Data Source + container. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + grafanaSecurityContext: + description: Security Context to apply to the Grafana container. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + podSecurityContext: + description: Security Context to apply to the Cryostat pod. + properties: + fsGroup: + description: "A special supplemental group that applies to + all containers in a pod. Some volume types allow the Kubelet + to change the ownership of that volume to be owned by the + pod: \n 1. The owning GID will be the FSGroup 2. The setgid + bit is set (new files created in the volume will be owned + by FSGroup) 3. The permission bits are OR'd with rw-rw---- + \n If unset, the Kubelet will not modify the ownership and + permissions of any volume. Note that this field cannot be + set when spec.os.name is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will + have no effect on ephemeral volume types such as: secret, + configmaps and emptydir. Valid values are "OnRootMismatch" + and "Always". If not specified, "Always" is used. Note that + this field cannot be set when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this field + cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is + windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + SecurityContext. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence + for that container. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers + in this pod. Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process + run in each container, in addition to the container's primary + GID, the fsGroup (if specified), and group memberships defined + in the container image for the uid of the container process. + If unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image + for the uid of the container process are still effective, + even if they are not included in this list. Note that this + field cannot be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used + for the pod. Pods with unsupported sysctls (by the container + runtime) might fail to launch. Note that this field cannot + be set when spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options within a container's + SecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + type: object + serviceOptions: + description: Options to customize the services created for the Cryostat + application and Grafana dashboard. + properties: + coreConfig: + description: Specification for the service responsible for the + Cryostat application. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the service during its + creation. + type: object + httpPort: + description: HTTP port number for the Cryostat application + service. Defaults to 8181. + format: int32 + type: integer + jmxPort: + description: Remote JMX port number for the Cryostat application + service. Defaults to 9091. + format: int32 + type: integer + labels: + additionalProperties: + type: string + description: Labels to add to the service during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + serviceType: + description: Type of service to create. Defaults to "ClusterIP". + type: string + type: object + grafanaConfig: + description: Specification for the service responsible for the + Cryostat Grafana dashboard. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the service during its + creation. + type: object + httpPort: + description: HTTP port number for the Grafana dashboard service. + Defaults to 3000. + format: int32 + type: integer + labels: + additionalProperties: + type: string + description: Labels to add to the service during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + serviceType: + description: Type of service to create. Defaults to "ClusterIP". + type: string + type: object + reportsConfig: + description: Specification for the service responsible for the + cryostat-reports sidecars. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the service during its + creation. + type: object + httpPort: + description: HTTP port number for the cryostat-reports service. + Defaults to 10000. + format: int32 + type: integer + labels: + additionalProperties: + type: string + description: Labels to add to the service during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + serviceType: + description: Type of service to create. Defaults to "ClusterIP". + type: string + type: object + type: object + storageOptions: + description: Options to customize the storage for Flight Recordings + and Templates. + properties: + emptyDir: + description: Configuration for an EmptyDir to be created by the + operator instead of a PVC. + properties: + enabled: + description: When enabled, Cryostat will use EmptyDir volumes + instead of a Persistent Volume Claim. Any PVC configurations + will be ignored. + type: boolean + medium: + description: Unless specified, the emptyDir volume will be + mounted on the same storage medium backing the node. Setting + this field to "Memory" will mount the emptyDir on a tmpfs + (RAM-backed filesystem). + type: string + sizeLimit: + description: The maximum memory limit for the emptyDir. Default + is unbounded. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + type: string + type: object + pvc: + description: Configuration for the Persistent Volume Claim to + be created by the operator. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the Persistent Volume Claim + during its creation. + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the Persistent Volume Claim + during its creation. The label with key "app" is reserved + for use by the operator. + type: object + spec: + description: Spec for a Persistent Volume Claim, whose options + will override the defaults used by the operator. Unless + overriden, the PVC will be created with the default Storage + Class and 500MiB of storage. Once the operator has created + the PVC, changes to this field have no effect. + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified + data source, it will create a new volume based on the + contents of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then + dataSourceRef will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the dataSource + field and as such if both fields are non-empty, they + must have the same value. For backwards compatibility, + when namespace isn''t specified in dataSourceRef, both + fields (dataSource and dataSourceRef) will be set to + the same value automatically if one of them is empty + and the other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the same + value and must be empty. There are three important differences + between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef + allows any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + * While dataSource only allows local objects, dataSourceRef + allows objects in any namespaces. (Beta) Using this + field requires the AnyVolumeDataSource feature gate + to be enabled. (Alpha) Using the namespace field of + dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the + ReferenceGrant documentation for details. (Alpha) + This field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify resource + requirements that are lower than previous value but + must still be higher than capacity recorded in the status + field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n This field is immutable. It can only be set for + containers." + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one + entry in pod.spec.resourceClaims of the Pod + where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes to + consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values + array must be non-empty. If the operator is + Exists or DoesNotExist, the values array must + be empty. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is + required by the claim. Value of Filesystem is implied + when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + type: object + type: object + targetDiscoveryOptions: + description: Options to configure the Cryostat application's target + discovery mechanisms. + properties: + builtInDiscoveryDisabled: + description: When true, the Cryostat application will disable + the built-in discovery mechanisms. Defaults to false + type: boolean + type: object + targetNamespaces: + description: 'List of namespaces whose workloads Cryostat should be + permitted to access and profile. Defaults to this Cryostat''s namespace. + Warning: All Cryostat users will be able to create and manage recordings + for workloads in the listed namespaces. More details: https://github.com/cryostatio/cryostat-operator/blob/v2.4.0/docs/multi-namespace.md#data-isolation' + items: + type: string + type: array + trustedCertSecrets: + description: List of TLS certificates to trust when connecting to + targets. + items: + properties: + certificateKey: + description: Key within secret containing the certificate. + type: string + secretName: + description: Name of secret in the local namespace. + type: string + required: + - secretName + type: object + type: array + required: + - installNamespace + - minimal + type: object + status: + description: ClusterCryostatStatus defines the observed state of ClusterCryostat. + properties: + applicationUrl: + description: Address of the deployed Cryostat web application. + type: string + conditions: + description: Conditions of the components managed by the Cryostat + Operator. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + grafanaSecret: + description: Name of the Secret containing the generated Grafana credentials. + type: string + targetNamespaces: + description: List of namespaces that Cryostat has been configured + and authorized to access and profile. + items: + type: string + type: array + required: + - applicationUrl + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/config/crd/bases/operator.cryostat.io_cryostats.yaml b/config/crd/bases/operator.cryostat.io_cryostats.yaml index 6cce048fb..5de7ef336 100644 --- a/config/crd/bases/operator.cryostat.io_cryostats.yaml +++ b/config/crd/bases/operator.cryostat.io_cryostats.yaml @@ -4729,6 +4729,4716 @@ spec: type: object type: object served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .status.applicationUrl + name: Application URL + type: string + - jsonPath: .status.grafanaSecret + name: Grafana Secret + type: string + name: v1beta2 + schema: + openAPIV3Schema: + description: Cryostat allows you to install Cryostat for a single namespace. + It contains configuration options for controlling the Deployment of the + Cryostat application and its related components. A ClusterCryostat or Cryostat + instance must be created to instruct the operator to deploy the Cryostat + application. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: CryostatSpec defines the desired state of Cryostat. + properties: + authProperties: + description: Override default authorization properties for Cryostat + on OpenShift. + properties: + clusterRoleName: + description: 'Name of the ClusterRole to use when Cryostat requests + a role-scoped OAuth token. This ClusterRole should contain permissions + for all Kubernetes objects listed in custom permission mapping. + More details: https://docs.openshift.com/container-platform/4.11/authentication/tokens-scoping.html#scoping-tokens-role-scope_configuring-internal-oauth' + type: string + configMapName: + description: Name of config map in the local namespace. + type: string + filename: + description: Filename within config map containing the resource + mapping. + type: string + required: + - clusterRoleName + - configMapName + - filename + type: object + enableCertManager: + description: Use cert-manager to secure in-cluster communication between + Cryostat components. Requires cert-manager to be installed. + type: boolean + eventTemplates: + description: List of Flight Recorder Event Templates to preconfigure + in Cryostat. + items: + description: A ConfigMap containing a .jfc template file. + properties: + configMapName: + description: Name of config map in the local namespace. + type: string + filename: + description: Filename within config map containing the template + file. + type: string + required: + - configMapName + - filename + type: object + type: array + jmxCacheOptions: + description: Options to customize the JMX target connections cache + for the Cryostat application. + properties: + targetCacheSize: + description: The maximum number of JMX connections to cache. Use + `-1` for an unlimited cache size (TTL expiration only). Defaults + to `-1`. + format: int32 + minimum: -1 + type: integer + targetCacheTTL: + description: The time to live (in seconds) for cached JMX connections. + Defaults to `10`. + format: int32 + minimum: 1 + type: integer + type: object + jmxCredentialsDatabaseOptions: + description: Options to configure the Cryostat application's credentials + database. + properties: + databaseSecretName: + description: Name of the secret containing the password to encrypt + credentials database. + type: string + type: object + maxWsConnections: + description: The maximum number of WebSocket client connections allowed + (minimum 1, default unlimited). + format: int32 + minimum: 1 + type: integer + minimal: + description: Deploy a pared-down Cryostat instance with no Grafana + Dashboard or JFR Data Source. + type: boolean + networkOptions: + description: Options to control how the operator exposes the application + outside of the cluster, such as using an Ingress or Route. + properties: + commandConfig: + description: "Specifications for how to expose the Cryostat command + service, which serves the WebSocket command channel. \n Deprecated: + CommandConfig is no longer used." + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the Ingress or Route during + its creation. + type: object + ingressSpec: + description: Configuration for an Ingress object. Currently + subpaths are not supported, so unique hosts must be specified + (if a single external IP is being used) to differentiate + between ingresses/services. + properties: + defaultBackend: + description: DefaultBackend is the backend that should + handle requests that don't match any rule. If Rules + are not specified, DefaultBackend must be specified. + If DefaultBackend is not set, the handling of requests + that do not match any of the rules will be up to the + Ingress controller. + properties: + resource: + description: Resource is an ObjectRef to another Kubernetes + resource in the namespace of the Ingress object. + If resource is specified, a service.Name and service.Port + must not be specified. This is a mutually exclusive + setting with "Service". + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a Service as a Backend. + This is a mutually exclusive setting with "Resource". + properties: + name: + description: Name is the referenced service. The + service must exist in the same namespace as + the Ingress object. + type: string + port: + description: Port of the referenced service. A + port name or port number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name of the port + on the Service. This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the numerical port + number (e.g. 80) on the Service. This is + a mutually exclusive setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + ingressClassName: + description: IngressClassName is the name of an IngressClass + cluster resource. Ingress controller implementations + use this field to know whether they should be serving + this Ingress resource, by a transitive connection (controller + -> IngressClass -> Ingress resource). Although the `kubernetes.io/ingress.class` + annotation (simple constant name) was never formally + defined, it was widely supported by Ingress controllers + to create a direct binding between Ingress controller + and Ingress resources. Newly created Ingress resources + should prefer using the field. However, even though + the annotation is officially deprecated, for backwards + compatibility reasons, ingress controllers should still + honor that annotation if present. + type: string + rules: + description: A list of host rules used to configure the + Ingress. If unspecified, or no rule matches, all traffic + is sent to the default backend. + items: + description: IngressRule represents the rules mapping + the paths under a specified host to the related backend + services. Incoming requests are first evaluated for + a host match, then routed to the backend associated + with the matching IngressRuleValue. + properties: + host: + description: "Host is the fully qualified domain + name of a network host, as defined by RFC 3986. + Note the following deviations from the \"host\" + part of the URI as defined in RFC 3986: 1. IPs + are not allowed. Currently an IngressRuleValue + can only apply to the IP in the Spec of the parent + Ingress. 2. The `:` delimiter is not respected + because ports are not allowed. Currently the port + of an Ingress is implicitly :80 for http and :443 + for https. Both these may change in the future. + Incoming requests are matched against the host + before the IngressRuleValue. If the host is unspecified, + the Ingress routes all traffic based on the specified + IngressRuleValue. \n Host can be \"precise\" which + is a domain name without the terminating dot of + a network host (e.g. \"foo.bar.com\") or \"wildcard\", + which is a domain name prefixed with a single + wildcard label (e.g. \"*.foo.com\"). The wildcard + character '*' must appear by itself as the first + DNS label and matches only a single label. You + cannot have a wildcard label by itself (e.g. Host + == \"*\"). Requests will be matched against the + Host field in the following way: 1. If Host is + precise, the request matches this rule if the + http host header is equal to Host. 2. If Host + is a wildcard, then the request matches this rule + if the http host header is to equal to the suffix + (removing the first label) of the wildcard rule." + type: string + http: + description: 'HTTPIngressRuleValue is a list of + http selectors pointing to backends. In the example: + http:///? -> backend where + where parts of the url correspond to RFC 3986, + this resource will be used to match against everything + after the last ''/'' and before the first ''?'' + or ''#''.' + properties: + paths: + description: A collection of paths that map + requests to backends. + items: + description: HTTPIngressPath associates a + path with a backend. Incoming urls matching + the path are forwarded to the backend. + properties: + backend: + description: Backend defines the referenced + service endpoint to which the traffic + will be forwarded to. + properties: + resource: + description: Resource is an ObjectRef + to another Kubernetes resource in + the namespace of the Ingress object. + If resource is specified, a service.Name + and service.Port must not be specified. + This is a mutually exclusive setting + with "Service". + properties: + apiGroup: + description: APIGroup is the group + for the resource being referenced. + If APIGroup is not specified, + the specified Kind must be in + the core API group. For any + other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type + of resource being referenced + type: string + name: + description: Name is the name + of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a + Service as a Backend. This is a + mutually exclusive setting with + "Resource". + properties: + name: + description: Name is the referenced + service. The service must exist + in the same namespace as the + Ingress object. + type: string + port: + description: Port of the referenced + service. A port name or port + number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name + of the port on the Service. + This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the + numerical port number (e.g. + 80) on the Service. This + is a mutually exclusive + setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + path: + description: Path is matched against the + path of an incoming request. Currently + it can contain characters disallowed + from the conventional "path" part of + a URL as defined by RFC 3986. Paths + must begin with a '/' and must be present + when using PathType with value "Exact" + or "Prefix". + type: string + pathType: + description: 'PathType determines the + interpretation of the Path matching. + PathType can be one of the following + values: * Exact: Matches the URL path + exactly. * Prefix: Matches based on + a URL path prefix split by ''/''. Matching + is done on a path element by element + basis. A path element refers is the + list of labels in the path split by + the ''/'' separator. A request is a + match for path p if every p is an element-wise + prefix of p of the request path. Note + that if the last element of the path + is a substring of the last element in + request path, it is not a match (e.g. + /foo/bar matches /foo/bar/baz, but does + not match /foo/barbaz). * ImplementationSpecific: + Interpretation of the Path matching + is up to the IngressClass. Implementations + can treat this as a separate PathType + or treat it identically to Prefix or + Exact path types. Implementations are + required to support all path types.' + type: string + required: + - backend + - pathType + type: object + type: array + x-kubernetes-list-type: atomic + required: + - paths + type: object + type: object + type: array + x-kubernetes-list-type: atomic + tls: + description: TLS configuration. Currently the Ingress + only supports a single TLS port, 443. If multiple members + of this list specify different hosts, they will be multiplexed + on the same port according to the hostname specified + through the SNI TLS extension, if the ingress controller + fulfilling the ingress supports SNI. + items: + description: IngressTLS describes the transport layer + security associated with an Ingress. + properties: + hosts: + description: Hosts are a list of hosts included + in the TLS certificate. The values in this list + must match the name/s used in the tlsSecret. Defaults + to the wildcard host setting for the loadbalancer + controller fulfilling this Ingress, if left unspecified. + items: + type: string + type: array + x-kubernetes-list-type: atomic + secretName: + description: SecretName is the name of the secret + used to terminate TLS traffic on port 443. Field + is left optional to allow TLS routing based on + SNI hostname alone. If the SNI host in a listener + conflicts with the "Host" header field used by + an IngressRule, the SNI host is used for termination + and value of the Host header is used for routing. + type: string + type: object + type: array + x-kubernetes-list-type: atomic + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the Ingress or Route during + its creation. The label with key "app" is reserved for use + by the operator. + type: object + type: object + coreConfig: + description: Specifications for how to expose the Cryostat service, + which serves the Cryostat application. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the Ingress or Route during + its creation. + type: object + ingressSpec: + description: Configuration for an Ingress object. Currently + subpaths are not supported, so unique hosts must be specified + (if a single external IP is being used) to differentiate + between ingresses/services. + properties: + defaultBackend: + description: DefaultBackend is the backend that should + handle requests that don't match any rule. If Rules + are not specified, DefaultBackend must be specified. + If DefaultBackend is not set, the handling of requests + that do not match any of the rules will be up to the + Ingress controller. + properties: + resource: + description: Resource is an ObjectRef to another Kubernetes + resource in the namespace of the Ingress object. + If resource is specified, a service.Name and service.Port + must not be specified. This is a mutually exclusive + setting with "Service". + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a Service as a Backend. + This is a mutually exclusive setting with "Resource". + properties: + name: + description: Name is the referenced service. The + service must exist in the same namespace as + the Ingress object. + type: string + port: + description: Port of the referenced service. A + port name or port number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name of the port + on the Service. This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the numerical port + number (e.g. 80) on the Service. This is + a mutually exclusive setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + ingressClassName: + description: IngressClassName is the name of an IngressClass + cluster resource. Ingress controller implementations + use this field to know whether they should be serving + this Ingress resource, by a transitive connection (controller + -> IngressClass -> Ingress resource). Although the `kubernetes.io/ingress.class` + annotation (simple constant name) was never formally + defined, it was widely supported by Ingress controllers + to create a direct binding between Ingress controller + and Ingress resources. Newly created Ingress resources + should prefer using the field. However, even though + the annotation is officially deprecated, for backwards + compatibility reasons, ingress controllers should still + honor that annotation if present. + type: string + rules: + description: A list of host rules used to configure the + Ingress. If unspecified, or no rule matches, all traffic + is sent to the default backend. + items: + description: IngressRule represents the rules mapping + the paths under a specified host to the related backend + services. Incoming requests are first evaluated for + a host match, then routed to the backend associated + with the matching IngressRuleValue. + properties: + host: + description: "Host is the fully qualified domain + name of a network host, as defined by RFC 3986. + Note the following deviations from the \"host\" + part of the URI as defined in RFC 3986: 1. IPs + are not allowed. Currently an IngressRuleValue + can only apply to the IP in the Spec of the parent + Ingress. 2. The `:` delimiter is not respected + because ports are not allowed. Currently the port + of an Ingress is implicitly :80 for http and :443 + for https. Both these may change in the future. + Incoming requests are matched against the host + before the IngressRuleValue. If the host is unspecified, + the Ingress routes all traffic based on the specified + IngressRuleValue. \n Host can be \"precise\" which + is a domain name without the terminating dot of + a network host (e.g. \"foo.bar.com\") or \"wildcard\", + which is a domain name prefixed with a single + wildcard label (e.g. \"*.foo.com\"). The wildcard + character '*' must appear by itself as the first + DNS label and matches only a single label. You + cannot have a wildcard label by itself (e.g. Host + == \"*\"). Requests will be matched against the + Host field in the following way: 1. If Host is + precise, the request matches this rule if the + http host header is equal to Host. 2. If Host + is a wildcard, then the request matches this rule + if the http host header is to equal to the suffix + (removing the first label) of the wildcard rule." + type: string + http: + description: 'HTTPIngressRuleValue is a list of + http selectors pointing to backends. In the example: + http:///? -> backend where + where parts of the url correspond to RFC 3986, + this resource will be used to match against everything + after the last ''/'' and before the first ''?'' + or ''#''.' + properties: + paths: + description: A collection of paths that map + requests to backends. + items: + description: HTTPIngressPath associates a + path with a backend. Incoming urls matching + the path are forwarded to the backend. + properties: + backend: + description: Backend defines the referenced + service endpoint to which the traffic + will be forwarded to. + properties: + resource: + description: Resource is an ObjectRef + to another Kubernetes resource in + the namespace of the Ingress object. + If resource is specified, a service.Name + and service.Port must not be specified. + This is a mutually exclusive setting + with "Service". + properties: + apiGroup: + description: APIGroup is the group + for the resource being referenced. + If APIGroup is not specified, + the specified Kind must be in + the core API group. For any + other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type + of resource being referenced + type: string + name: + description: Name is the name + of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a + Service as a Backend. This is a + mutually exclusive setting with + "Resource". + properties: + name: + description: Name is the referenced + service. The service must exist + in the same namespace as the + Ingress object. + type: string + port: + description: Port of the referenced + service. A port name or port + number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name + of the port on the Service. + This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the + numerical port number (e.g. + 80) on the Service. This + is a mutually exclusive + setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + path: + description: Path is matched against the + path of an incoming request. Currently + it can contain characters disallowed + from the conventional "path" part of + a URL as defined by RFC 3986. Paths + must begin with a '/' and must be present + when using PathType with value "Exact" + or "Prefix". + type: string + pathType: + description: 'PathType determines the + interpretation of the Path matching. + PathType can be one of the following + values: * Exact: Matches the URL path + exactly. * Prefix: Matches based on + a URL path prefix split by ''/''. Matching + is done on a path element by element + basis. A path element refers is the + list of labels in the path split by + the ''/'' separator. A request is a + match for path p if every p is an element-wise + prefix of p of the request path. Note + that if the last element of the path + is a substring of the last element in + request path, it is not a match (e.g. + /foo/bar matches /foo/bar/baz, but does + not match /foo/barbaz). * ImplementationSpecific: + Interpretation of the Path matching + is up to the IngressClass. Implementations + can treat this as a separate PathType + or treat it identically to Prefix or + Exact path types. Implementations are + required to support all path types.' + type: string + required: + - backend + - pathType + type: object + type: array + x-kubernetes-list-type: atomic + required: + - paths + type: object + type: object + type: array + x-kubernetes-list-type: atomic + tls: + description: TLS configuration. Currently the Ingress + only supports a single TLS port, 443. If multiple members + of this list specify different hosts, they will be multiplexed + on the same port according to the hostname specified + through the SNI TLS extension, if the ingress controller + fulfilling the ingress supports SNI. + items: + description: IngressTLS describes the transport layer + security associated with an Ingress. + properties: + hosts: + description: Hosts are a list of hosts included + in the TLS certificate. The values in this list + must match the name/s used in the tlsSecret. Defaults + to the wildcard host setting for the loadbalancer + controller fulfilling this Ingress, if left unspecified. + items: + type: string + type: array + x-kubernetes-list-type: atomic + secretName: + description: SecretName is the name of the secret + used to terminate TLS traffic on port 443. Field + is left optional to allow TLS routing based on + SNI hostname alone. If the SNI host in a listener + conflicts with the "Host" header field used by + an IngressRule, the SNI host is used for termination + and value of the Host header is used for routing. + type: string + type: object + type: array + x-kubernetes-list-type: atomic + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the Ingress or Route during + its creation. The label with key "app" is reserved for use + by the operator. + type: object + type: object + grafanaConfig: + description: Specifications for how to expose Cryostat's Grafana + service, which serves the Grafana dashboard. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the Ingress or Route during + its creation. + type: object + ingressSpec: + description: Configuration for an Ingress object. Currently + subpaths are not supported, so unique hosts must be specified + (if a single external IP is being used) to differentiate + between ingresses/services. + properties: + defaultBackend: + description: DefaultBackend is the backend that should + handle requests that don't match any rule. If Rules + are not specified, DefaultBackend must be specified. + If DefaultBackend is not set, the handling of requests + that do not match any of the rules will be up to the + Ingress controller. + properties: + resource: + description: Resource is an ObjectRef to another Kubernetes + resource in the namespace of the Ingress object. + If resource is specified, a service.Name and service.Port + must not be specified. This is a mutually exclusive + setting with "Service". + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is + required. + type: string + kind: + description: Kind is the type of resource being + referenced + type: string + name: + description: Name is the name of resource being + referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a Service as a Backend. + This is a mutually exclusive setting with "Resource". + properties: + name: + description: Name is the referenced service. The + service must exist in the same namespace as + the Ingress object. + type: string + port: + description: Port of the referenced service. A + port name or port number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name of the port + on the Service. This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the numerical port + number (e.g. 80) on the Service. This is + a mutually exclusive setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + ingressClassName: + description: IngressClassName is the name of an IngressClass + cluster resource. Ingress controller implementations + use this field to know whether they should be serving + this Ingress resource, by a transitive connection (controller + -> IngressClass -> Ingress resource). Although the `kubernetes.io/ingress.class` + annotation (simple constant name) was never formally + defined, it was widely supported by Ingress controllers + to create a direct binding between Ingress controller + and Ingress resources. Newly created Ingress resources + should prefer using the field. However, even though + the annotation is officially deprecated, for backwards + compatibility reasons, ingress controllers should still + honor that annotation if present. + type: string + rules: + description: A list of host rules used to configure the + Ingress. If unspecified, or no rule matches, all traffic + is sent to the default backend. + items: + description: IngressRule represents the rules mapping + the paths under a specified host to the related backend + services. Incoming requests are first evaluated for + a host match, then routed to the backend associated + with the matching IngressRuleValue. + properties: + host: + description: "Host is the fully qualified domain + name of a network host, as defined by RFC 3986. + Note the following deviations from the \"host\" + part of the URI as defined in RFC 3986: 1. IPs + are not allowed. Currently an IngressRuleValue + can only apply to the IP in the Spec of the parent + Ingress. 2. The `:` delimiter is not respected + because ports are not allowed. Currently the port + of an Ingress is implicitly :80 for http and :443 + for https. Both these may change in the future. + Incoming requests are matched against the host + before the IngressRuleValue. If the host is unspecified, + the Ingress routes all traffic based on the specified + IngressRuleValue. \n Host can be \"precise\" which + is a domain name without the terminating dot of + a network host (e.g. \"foo.bar.com\") or \"wildcard\", + which is a domain name prefixed with a single + wildcard label (e.g. \"*.foo.com\"). The wildcard + character '*' must appear by itself as the first + DNS label and matches only a single label. You + cannot have a wildcard label by itself (e.g. Host + == \"*\"). Requests will be matched against the + Host field in the following way: 1. If Host is + precise, the request matches this rule if the + http host header is equal to Host. 2. If Host + is a wildcard, then the request matches this rule + if the http host header is to equal to the suffix + (removing the first label) of the wildcard rule." + type: string + http: + description: 'HTTPIngressRuleValue is a list of + http selectors pointing to backends. In the example: + http:///? -> backend where + where parts of the url correspond to RFC 3986, + this resource will be used to match against everything + after the last ''/'' and before the first ''?'' + or ''#''.' + properties: + paths: + description: A collection of paths that map + requests to backends. + items: + description: HTTPIngressPath associates a + path with a backend. Incoming urls matching + the path are forwarded to the backend. + properties: + backend: + description: Backend defines the referenced + service endpoint to which the traffic + will be forwarded to. + properties: + resource: + description: Resource is an ObjectRef + to another Kubernetes resource in + the namespace of the Ingress object. + If resource is specified, a service.Name + and service.Port must not be specified. + This is a mutually exclusive setting + with "Service". + properties: + apiGroup: + description: APIGroup is the group + for the resource being referenced. + If APIGroup is not specified, + the specified Kind must be in + the core API group. For any + other third-party types, APIGroup + is required. + type: string + kind: + description: Kind is the type + of resource being referenced + type: string + name: + description: Name is the name + of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + service: + description: Service references a + Service as a Backend. This is a + mutually exclusive setting with + "Resource". + properties: + name: + description: Name is the referenced + service. The service must exist + in the same namespace as the + Ingress object. + type: string + port: + description: Port of the referenced + service. A port name or port + number is required for a IngressServiceBackend. + properties: + name: + description: Name is the name + of the port on the Service. + This is a mutually exclusive + setting with "Number". + type: string + number: + description: Number is the + numerical port number (e.g. + 80) on the Service. This + is a mutually exclusive + setting with "Name". + format: int32 + type: integer + type: object + required: + - name + type: object + type: object + path: + description: Path is matched against the + path of an incoming request. Currently + it can contain characters disallowed + from the conventional "path" part of + a URL as defined by RFC 3986. Paths + must begin with a '/' and must be present + when using PathType with value "Exact" + or "Prefix". + type: string + pathType: + description: 'PathType determines the + interpretation of the Path matching. + PathType can be one of the following + values: * Exact: Matches the URL path + exactly. * Prefix: Matches based on + a URL path prefix split by ''/''. Matching + is done on a path element by element + basis. A path element refers is the + list of labels in the path split by + the ''/'' separator. A request is a + match for path p if every p is an element-wise + prefix of p of the request path. Note + that if the last element of the path + is a substring of the last element in + request path, it is not a match (e.g. + /foo/bar matches /foo/bar/baz, but does + not match /foo/barbaz). * ImplementationSpecific: + Interpretation of the Path matching + is up to the IngressClass. Implementations + can treat this as a separate PathType + or treat it identically to Prefix or + Exact path types. Implementations are + required to support all path types.' + type: string + required: + - backend + - pathType + type: object + type: array + x-kubernetes-list-type: atomic + required: + - paths + type: object + type: object + type: array + x-kubernetes-list-type: atomic + tls: + description: TLS configuration. Currently the Ingress + only supports a single TLS port, 443. If multiple members + of this list specify different hosts, they will be multiplexed + on the same port according to the hostname specified + through the SNI TLS extension, if the ingress controller + fulfilling the ingress supports SNI. + items: + description: IngressTLS describes the transport layer + security associated with an Ingress. + properties: + hosts: + description: Hosts are a list of hosts included + in the TLS certificate. The values in this list + must match the name/s used in the tlsSecret. Defaults + to the wildcard host setting for the loadbalancer + controller fulfilling this Ingress, if left unspecified. + items: + type: string + type: array + x-kubernetes-list-type: atomic + secretName: + description: SecretName is the name of the secret + used to terminate TLS traffic on port 443. Field + is left optional to allow TLS routing based on + SNI hostname alone. If the SNI host in a listener + conflicts with the "Host" header field used by + an IngressRule, the SNI host is used for termination + and value of the Host header is used for routing. + type: string + type: object + type: array + x-kubernetes-list-type: atomic + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the Ingress or Route during + its creation. The label with key "app" is reserved for use + by the operator. + type: object + type: object + type: object + operandMetadata: + description: Options to configure the Cryostat deployments and pods + metadata + properties: + deploymentMetadata: + description: Options to configure the Cryostat deployments metadata + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the resources during its + creation. + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the resources during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + type: object + podMetadata: + description: Options to configure the Cryostat pods metadata + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the resources during its + creation. + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the resources during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + type: object + type: object + reportOptions: + description: Options to configure Cryostat Automated Report Analysis. + properties: + replicas: + description: The number of report sidecar replica containers to + deploy. Each replica can service one report generation request + at a time. + format: int32 + type: integer + resources: + description: The resources allocated to each sidecar replica. + A replica with more resources can handle larger input recordings + and will process them faster. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + schedulingOptions: + description: Options to configure scheduling for the reports deployment + properties: + affinity: + description: Affinity rules for scheduling Cryostat pods. + properties: + nodeAffinity: + description: 'Node affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#NodeAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term + matches all objects with implicit weight 0 (i.e. + it's a no-op). A null preferred scheduling term + matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated + with the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching + the corresponding nodeSelectorTerm, in the + range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to an update), the system may or may not try + to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector + terms. The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them + are ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: The label key that the + selector applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. + If the operator is Gt or Lt, the + values array must have a single + element, which will be interpreted + as an integer. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: 'Pod affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, + etc.), compute a sum by iterating through the elements + of this field and adding "weight" to the sum if + the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + affinity requirements specified by this field cease + to be met at some point during pod execution (e.g. + due to a pod label update), the system may or may + not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes + corresponding to each podAffinityTerm are intersected, + i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: 'Pod anti-affinity scheduling rules for a + Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAntiAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule + pods to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node + that violates one or more of the expressions. The + node that is most preferred is the one with the + greatest sum of weights, i.e. for each node that + meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity + expressions, etc.), compute a sum by iterating through + the elements of this field and adding "weight" to + the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum + are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, + associated with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of + resources, in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set + of namespaces that the term applies to. + The term is applied to the union of the + namespaces selected by this field and + the ones listed in the namespaces field. + null selector and null or empty namespaces + list means "this pod's namespace". An + empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The + requirements are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label + key that the selector applies + to. + type: string + operator: + description: operator represents + a key's relationship to a set + of values. Valid operators are + In, NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array + of string values. If the operator + is In or NotIn, the values array + must be non-empty. If the operator + is Exists or DoesNotExist, the + values array must be empty. + This array is replaced during + a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of + {key,value} pairs. A single {key,value} + in the matchLabels map is equivalent + to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are + ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static + list of namespace names that the term + applies to. The term is applied to the + union of the namespaces listed in this + field and the ones selected by namespaceSelector. + null or empty namespaces list and null + namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located + (affinity) or not co-located (anti-affinity) + with the pods matching the labelSelector + in the specified namespaces, where co-located + is defined as running on a node whose + value of the label with key topologyKey + matches that of any node on which any + of the selected pods is running. Empty + topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching + the corresponding podAffinityTerm, in the + range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the + pod will not be scheduled onto the node. If the + anti-affinity requirements specified by this field + cease to be met at some point during pod execution + (e.g. due to a pod label update), the system may + or may not try to eventually evict the pod from + its node. When there are multiple elements, the + lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those + matching the labelSelector relative to the given + namespace(s)) that this pod should be co-located + (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node + whose value of the label with key + matches that of any node on which a pod of the + set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + nodeSelector: + additionalProperties: + type: string + description: 'Label selector used to schedule a Cryostat pod + to a node. See: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + tolerations: + description: 'Tolerations to allow scheduling of Cryostat + pods to tainted nodes. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/' + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, + allowed values are NoSchedule, PreferNoSchedule and + NoExecute. + type: string + key: + description: Key is the taint key that the toleration + applies to. Empty means match all taint keys. If the + key is empty, operator must be Exists; this combination + means to match all values and all keys. + type: string + operator: + description: Operator represents a key's relationship + to the value. Valid operators are Exists and Equal. + Defaults to Equal. Exists is equivalent to wildcard + for value, so that a pod can tolerate all taints of + a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period + of time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the + taint forever (do not evict). Zero and negative values + will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration + matches to. If the operator is Exists, the value should + be empty, otherwise just a regular string. + type: string + type: object + type: array + type: object + securityOptions: + description: Options to configure the Security Contexts for the + Cryostat report generator. + properties: + podSecurityContext: + description: Security Context to apply to the Cryostat report + generator pod. + properties: + fsGroup: + description: "A special supplemental group that applies + to all containers in a pod. Some volume types allow + the Kubelet to change the ownership of that volume to + be owned by the pod: \n 1. The owning GID will be the + FSGroup 2. The setgid bit is set (new files created + in the volume will be owned by FSGroup) 3. The permission + bits are OR'd with rw-rw---- \n If unset, the Kubelet + will not modify the ownership and permissions of any + volume. Note that this field cannot be set when spec.os.name + is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of + changing ownership and permission of the volume before + being exposed inside Pod. This field will only apply + to volume types which support fsGroup based ownership(and + permissions). It will have no effect on ephemeral volume + types such as: secret, configmaps and emptydir. Valid + values are "OnRootMismatch" and "Always". If not specified, + "Always" is used. Note that this field cannot be set + when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this + field cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if it + does. If unset or false, no such validation will be + performed. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence + for that container. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all + containers. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in SecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this + field cannot be set when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers + in this pod. Note that this field cannot be set when + spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process + run in each container, in addition to the container's + primary GID, the fsGroup (if specified), and group memberships + defined in the container image for the uid of the container + process. If unspecified, no additional groups are added + to any container. Note that group memberships defined + in the container image for the uid of the container + process are still effective, even if they are not included + in this list. Note that this field cannot be set when + spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls + used for the pod. Pods with unsupported sysctls (by + the container runtime) might fail to launch. Note that + this field cannot be set when spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be + set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options within a + container's SecurityContext will be used. If set in + both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + reportsSecurityContext: + description: Security Context to apply to the Cryostat report + generator container. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether + a process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag + will be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be + set when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running + containers. Defaults to the default set of capabilities + granted by the container runtime. Note that this field + cannot be set when spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes + in privileged containers are essentially equivalent + to root on the host. Defaults to false. Note that this + field cannot be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount + to use for the containers. The default is DefaultProcMount + which uses the container runtime defaults for readonly + paths and masked paths. This requires the ProcMountType + feature flag to be enabled. Note that this field cannot + be set when spec.os.name is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root + filesystem. Default is false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be + set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as + a non-root user. If true, the Kubelet will validate + the image at runtime to ensure that it does not run + as UID 0 (root) and fail to start the container if it + does. If unset or false, no such validation will be + performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata + if unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name + is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the + container. If unspecified, the container runtime will + allocate a random SELinux context for each container. May + also be set in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. + Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile + defined in a file on the node should be used. The + profile must be preconfigured on the node to work. + Must be a descending path, relative to the kubelet's + configured seccomp profile location. Must only be + set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp + profile will be applied. Valid options are: \n Localhost + - a profile defined in a file on the node should + be used. RuntimeDefault - the container runtime + default profile should be used. Unconfined - no + profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to + all containers. If unspecified, the options from the + PodSecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set + when spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA + admission webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec + named by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of + the GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container + should be run as a 'Host Process' container. This + field is alpha-level and will only be honored by + components that enable the WindowsHostProcessContainers + feature flag. Setting this field without the feature + flag will result in errors when validating the Pod. + All of a Pod's containers must have the same effective + HostProcess value (it is not allowed to have a mix + of HostProcess containers and non-HostProcess containers). In + addition, if HostProcess is true then HostNetwork + must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set + in PodSecurityContext. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + type: object + subProcessMaxHeapSize: + description: When zero report sidecar replicas are requested, + SubProcessMaxHeapSize configures the maximum heap size of the + basic subprocess report generator in MiB. The default heap size + is `200` (MiB). + format: int32 + type: integer + type: object + resources: + description: Resource requirements for the Cryostat deployment. + properties: + coreResources: + description: Resource requirements for the Cryostat application. + If specifying a memory limit, at least 768MiB is recommended. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + dataSourceResources: + description: Resource requirements for the JFR Data Source container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + grafanaResources: + description: Resource requirements for the Grafana container. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only be + set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in + pod.spec.resourceClaims of the Pod where this field + is used. It makes that resource available inside a + container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, otherwise + to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + type: object + schedulingOptions: + description: Options to configure scheduling for the Cryostat deployment + properties: + affinity: + description: Affinity rules for scheduling Cryostat pods. + properties: + nodeAffinity: + description: 'Node affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#NodeAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node matches the corresponding matchExpressions; + the node(s) with the highest sum are the most preferred. + items: + description: An empty preferred scheduling term matches + all objects with implicit weight 0 (i.e. it's a no-op). + A null preferred scheduling term matches no objects + (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from + its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: A null or empty node selector term + matches no objects. The requirements of them are + ANDed. The TopologySelectorTerm type implements + a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: A node selector requirement is + a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: Represents a key's relationship + to a set of values. Valid operators + are In, NotIn, Exists, DoesNotExist. + Gt, and Lt. + type: string + values: + description: An array of string values. + If the operator is In or NotIn, the + values array must be non-empty. If the + operator is Exists or DoesNotExist, + the values array must be empty. If the + operator is Gt or Lt, the values array + must have a single element, which will + be interpreted as an integer. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + type: object + x-kubernetes-map-type: atomic + type: array + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: 'Pod affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the affinity expressions specified + by this field, but it may choose a node that violates + one or more of the expressions. The node that is most + preferred is the one with the greatest sum of weights, + i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the affinity requirements specified by + this field are not met at scheduling time, the pod will + not be scheduled onto the node. If the affinity requirements + specified by this field cease to be met at some point + during pod execution (e.g. due to a pod label update), + the system may or may not try to eventually evict the + pod from its node. When there are multiple elements, + the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + podAntiAffinity: + description: 'Pod anti-affinity scheduling rules for a Cryostat + pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAntiAffinity' + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: The scheduler will prefer to schedule pods + to nodes that satisfy the anti-affinity expressions + specified by this field, but it may choose a node that + violates one or more of the expressions. The node that + is most preferred is the one with the greatest sum of + weights, i.e. for each node that meets all of the scheduling + requirements (resource request, requiredDuringScheduling + anti-affinity expressions, etc.), compute a sum by iterating + through the elements of this field and adding "weight" + to the sum if the node has pods which matches the corresponding + podAffinityTerm; the node(s) with the highest sum are + the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by + this field and the ones listed in the namespaces + field. null selector and null or empty namespaces + list means "this pod's namespace". An empty + selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: A label selector requirement + is a selector that contains values, + a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: operator represents a + key's relationship to a set of values. + Valid operators are In, NotIn, Exists + and DoesNotExist. + type: string + values: + description: values is an array of + string values. If the operator is + In or NotIn, the values array must + be non-empty. If the operator is + Exists or DoesNotExist, the values + array must be empty. This array + is replaced during a strategic merge + patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator + is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. + The term is applied to the union of the namespaces + listed in this field and the ones selected + by namespaceSelector. null or empty namespaces + list and null namespaceSelector means "this + pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the + pods matching the labelSelector in the specified + namespaces, where co-located is defined as + running on a node whose value of the label + with key topologyKey matches that of any node + on which any of the selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: weight associated with matching the + corresponding podAffinityTerm, in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + requiredDuringSchedulingIgnoredDuringExecution: + description: If the anti-affinity requirements specified + by this field are not met at scheduling time, the pod + will not be scheduled onto the node. If the anti-affinity + requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod + label update), the system may or may not try to eventually + evict the pod from its node. When there are multiple + elements, the lists of nodes corresponding to each podAffinityTerm + are intersected, i.e. all terms must be satisfied. + items: + description: Defines a set of pods (namely those matching + the labelSelector relative to the given namespace(s)) + that this pod should be co-located (affinity) or not + co-located (anti-affinity) with, where co-located + is defined as running on a node whose value of the + label with key matches that of any node + on which a pod of the set of pods is running + properties: + labelSelector: + description: A label query over a set of resources, + in this case pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaceSelector: + description: A label query over the set of namespaces + that the term applies to. The term is applied + to the union of the namespaces selected by this + field and the ones listed in the namespaces field. + null selector and null or empty namespaces list + means "this pod's namespace". An empty selector + ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: A label selector requirement + is a selector that contains values, a key, + and an operator that relates the key and + values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: operator represents a key's + relationship to a set of values. Valid + operators are In, NotIn, Exists and + DoesNotExist. + type: string + values: + description: values is an array of string + values. If the operator is In or NotIn, + the values array must be non-empty. + If the operator is Exists or DoesNotExist, + the values array must be empty. This + array is replaced during a strategic + merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} + pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, + whose key field is "key", the operator is + "In", and the values array contains only "value". + The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: namespaces specifies a static list + of namespace names that the term applies to. The + term is applied to the union of the namespaces + listed in this field and the ones selected by + namespaceSelector. null or empty namespaces list + and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + topologyKey: + description: This pod should be co-located (affinity) + or not co-located (anti-affinity) with the pods + matching the labelSelector in the specified namespaces, + where co-located is defined as running on a node + whose value of the label with key topologyKey + matches that of any node on which any of the selected + pods is running. Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + type: object + type: object + nodeSelector: + additionalProperties: + type: string + description: 'Label selector used to schedule a Cryostat pod to + a node. See: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + tolerations: + description: 'Tolerations to allow scheduling of Cryostat pods + to tainted nodes. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/' + items: + description: The pod this Toleration is attached to tolerates + any taint that matches the triple using + the matching operator . + properties: + effect: + description: Effect indicates the taint effect to match. + Empty means match all taint effects. When specified, allowed + values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match + all values and all keys. + type: string + operator: + description: Operator represents a key's relationship to + the value. Valid operators are Exists and Equal. Defaults + to Equal. Exists is equivalent to wildcard for value, + so that a pod can tolerate all taints of a particular + category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of + time the toleration (which must be of effect NoExecute, + otherwise this field is ignored) tolerates the taint. + By default, it is not set, which means tolerate the taint + forever (do not evict). Zero and negative values will + be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + type: object + securityOptions: + description: Options to configure the Security Contexts for the Cryostat + application. + properties: + coreSecurityContext: + description: Security Context to apply to the Cryostat application + container. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + dataSourceSecurityContext: + description: Security Context to apply to the JFR Data Source + container. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + grafanaSecurityContext: + description: Security Context to apply to the Grafana container. + properties: + allowPrivilegeEscalation: + description: 'AllowPrivilegeEscalation controls whether a + process can gain more privileges than its parent process. + This bool directly controls if the no_new_privs flag will + be set on the container process. AllowPrivilegeEscalation + is true always when the container is: 1) run as Privileged + 2) has CAP_SYS_ADMIN Note that this field cannot be set + when spec.os.name is windows.' + type: boolean + capabilities: + description: The capabilities to add/drop when running containers. + Defaults to the default set of capabilities granted by the + container runtime. Note that this field cannot be set when + spec.os.name is windows. + properties: + add: + description: Added capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + drop: + description: Removed capabilities + items: + description: Capability represent POSIX capabilities + type + type: string + type: array + type: object + privileged: + description: Run container in privileged mode. Processes in + privileged containers are essentially equivalent to root + on the host. Defaults to false. Note that this field cannot + be set when spec.os.name is windows. + type: boolean + procMount: + description: procMount denotes the type of proc mount to use + for the containers. The default is DefaultProcMount which + uses the container runtime defaults for readonly paths and + masked paths. This requires the ProcMountType feature flag + to be enabled. Note that this field cannot be set when spec.os.name + is windows. + type: string + readOnlyRootFilesystem: + description: Whether this container has a read-only root filesystem. + Default is false. Note that this field cannot be set when + spec.os.name is windows. + type: boolean + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in PodSecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. Note + that this field cannot be set when spec.os.name is windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to the container. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by this container. + If seccomp options are provided at both the pod & container + level, the container options override the pod options. Note + that this field cannot be set when spec.os.name is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options from the PodSecurityContext + will be used. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence. + Note that this field cannot be set when spec.os.name is + linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + podSecurityContext: + description: Security Context to apply to the Cryostat pod. + properties: + fsGroup: + description: "A special supplemental group that applies to + all containers in a pod. Some volume types allow the Kubelet + to change the ownership of that volume to be owned by the + pod: \n 1. The owning GID will be the FSGroup 2. The setgid + bit is set (new files created in the volume will be owned + by FSGroup) 3. The permission bits are OR'd with rw-rw---- + \n If unset, the Kubelet will not modify the ownership and + permissions of any volume. Note that this field cannot be + set when spec.os.name is windows." + format: int64 + type: integer + fsGroupChangePolicy: + description: 'fsGroupChangePolicy defines behavior of changing + ownership and permission of the volume before being exposed + inside Pod. This field will only apply to volume types which + support fsGroup based ownership(and permissions). It will + have no effect on ephemeral volume types such as: secret, + configmaps and emptydir. Valid values are "OnRootMismatch" + and "Always". If not specified, "Always" is used. Note that + this field cannot be set when spec.os.name is windows.' + type: string + runAsGroup: + description: The GID to run the entrypoint of the container + process. Uses runtime default if unset. May also be set + in SecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence for that container. Note that this field + cannot be set when spec.os.name is windows. + format: int64 + type: integer + runAsNonRoot: + description: Indicates that the container must run as a non-root + user. If true, the Kubelet will validate the image at runtime + to ensure that it does not run as UID 0 (root) and fail + to start the container if it does. If unset or false, no + such validation will be performed. May also be set in SecurityContext. If + set in both SecurityContext and PodSecurityContext, the + value specified in SecurityContext takes precedence. + type: boolean + runAsUser: + description: The UID to run the entrypoint of the container + process. Defaults to user specified in image metadata if + unspecified. May also be set in SecurityContext. If set + in both SecurityContext and PodSecurityContext, the value + specified in SecurityContext takes precedence for that container. + Note that this field cannot be set when spec.os.name is + windows. + format: int64 + type: integer + seLinuxOptions: + description: The SELinux context to be applied to all containers. + If unspecified, the container runtime will allocate a random + SELinux context for each container. May also be set in + SecurityContext. If set in both SecurityContext and PodSecurityContext, + the value specified in SecurityContext takes precedence + for that container. Note that this field cannot be set when + spec.os.name is windows. + properties: + level: + description: Level is SELinux level label that applies + to the container. + type: string + role: + description: Role is a SELinux role label that applies + to the container. + type: string + type: + description: Type is a SELinux type label that applies + to the container. + type: string + user: + description: User is a SELinux user label that applies + to the container. + type: string + type: object + seccompProfile: + description: The seccomp options to use by the containers + in this pod. Note that this field cannot be set when spec.os.name + is windows. + properties: + localhostProfile: + description: localhostProfile indicates a profile defined + in a file on the node should be used. The profile must + be preconfigured on the node to work. Must be a descending + path, relative to the kubelet's configured seccomp profile + location. Must only be set if type is "Localhost". + type: string + type: + description: "type indicates which kind of seccomp profile + will be applied. Valid options are: \n Localhost - a + profile defined in a file on the node should be used. + RuntimeDefault - the container runtime default profile + should be used. Unconfined - no profile should be applied." + type: string + required: + - type + type: object + supplementalGroups: + description: A list of groups applied to the first process + run in each container, in addition to the container's primary + GID, the fsGroup (if specified), and group memberships defined + in the container image for the uid of the container process. + If unspecified, no additional groups are added to any container. + Note that group memberships defined in the container image + for the uid of the container process are still effective, + even if they are not included in this list. Note that this + field cannot be set when spec.os.name is windows. + items: + format: int64 + type: integer + type: array + sysctls: + description: Sysctls hold a list of namespaced sysctls used + for the pod. Pods with unsupported sysctls (by the container + runtime) might fail to launch. Note that this field cannot + be set when spec.os.name is windows. + items: + description: Sysctl defines a kernel parameter to be set + properties: + name: + description: Name of a property to set + type: string + value: + description: Value of a property to set + type: string + required: + - name + - value + type: object + type: array + windowsOptions: + description: The Windows specific settings applied to all + containers. If unspecified, the options within a container's + SecurityContext will be used. If set in both SecurityContext + and PodSecurityContext, the value specified in SecurityContext + takes precedence. Note that this field cannot be set when + spec.os.name is linux. + properties: + gmsaCredentialSpec: + description: GMSACredentialSpec is where the GMSA admission + webhook (https://github.com/kubernetes-sigs/windows-gmsa) + inlines the contents of the GMSA credential spec named + by the GMSACredentialSpecName field. + type: string + gmsaCredentialSpecName: + description: GMSACredentialSpecName is the name of the + GMSA credential spec to use. + type: string + hostProcess: + description: HostProcess determines if a container should + be run as a 'Host Process' container. This field is + alpha-level and will only be honored by components that + enable the WindowsHostProcessContainers feature flag. + Setting this field without the feature flag will result + in errors when validating the Pod. All of a Pod's containers + must have the same effective HostProcess value (it is + not allowed to have a mix of HostProcess containers + and non-HostProcess containers). In addition, if HostProcess + is true then HostNetwork must also be set to true. + type: boolean + runAsUserName: + description: The UserName in Windows to run the entrypoint + of the container process. Defaults to the user specified + in image metadata if unspecified. May also be set in + PodSecurityContext. If set in both SecurityContext and + PodSecurityContext, the value specified in SecurityContext + takes precedence. + type: string + type: object + type: object + type: object + serviceOptions: + description: Options to customize the services created for the Cryostat + application and Grafana dashboard. + properties: + coreConfig: + description: Specification for the service responsible for the + Cryostat application. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the service during its + creation. + type: object + httpPort: + description: HTTP port number for the Cryostat application + service. Defaults to 8181. + format: int32 + type: integer + jmxPort: + description: Remote JMX port number for the Cryostat application + service. Defaults to 9091. + format: int32 + type: integer + labels: + additionalProperties: + type: string + description: Labels to add to the service during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + serviceType: + description: Type of service to create. Defaults to "ClusterIP". + type: string + type: object + grafanaConfig: + description: Specification for the service responsible for the + Cryostat Grafana dashboard. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the service during its + creation. + type: object + httpPort: + description: HTTP port number for the Grafana dashboard service. + Defaults to 3000. + format: int32 + type: integer + labels: + additionalProperties: + type: string + description: Labels to add to the service during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + serviceType: + description: Type of service to create. Defaults to "ClusterIP". + type: string + type: object + reportsConfig: + description: Specification for the service responsible for the + cryostat-reports sidecars. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the service during its + creation. + type: object + httpPort: + description: HTTP port number for the cryostat-reports service. + Defaults to 10000. + format: int32 + type: integer + labels: + additionalProperties: + type: string + description: Labels to add to the service during its creation. + The labels with keys "app" and "component" are reserved + for use by the operator. + type: object + serviceType: + description: Type of service to create. Defaults to "ClusterIP". + type: string + type: object + type: object + storageOptions: + description: Options to customize the storage for Flight Recordings + and Templates. + properties: + emptyDir: + description: Configuration for an EmptyDir to be created by the + operator instead of a PVC. + properties: + enabled: + description: When enabled, Cryostat will use EmptyDir volumes + instead of a Persistent Volume Claim. Any PVC configurations + will be ignored. + type: boolean + medium: + description: Unless specified, the emptyDir volume will be + mounted on the same storage medium backing the node. Setting + this field to "Memory" will mount the emptyDir on a tmpfs + (RAM-backed filesystem). + type: string + sizeLimit: + description: The maximum memory limit for the emptyDir. Default + is unbounded. + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + type: string + type: object + pvc: + description: Configuration for the Persistent Volume Claim to + be created by the operator. + properties: + annotations: + additionalProperties: + type: string + description: Annotations to add to the Persistent Volume Claim + during its creation. + type: object + labels: + additionalProperties: + type: string + description: Labels to add to the Persistent Volume Claim + during its creation. The label with key "app" is reserved + for use by the operator. + type: object + spec: + description: Spec for a Persistent Volume Claim, whose options + will override the defaults used by the operator. Unless + overriden, the PVC will be created with the default Storage + Class and 500MiB of storage. Once the operator has created + the PVC, changes to this field have no effect. + properties: + accessModes: + description: 'accessModes contains the desired access + modes the volume should have. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#access-modes-1' + items: + type: string + type: array + dataSource: + description: 'dataSource field can be used to specify + either: * An existing VolumeSnapshot object (snapshot.storage.k8s.io/VolumeSnapshot) + * An existing PVC (PersistentVolumeClaim) If the provisioner + or an external controller can support the specified + data source, it will create a new volume based on the + contents of the specified data source. When the AnyVolumeDataSource + feature gate is enabled, dataSource contents will be + copied to dataSourceRef, and dataSourceRef contents + will be copied to dataSource when dataSourceRef.namespace + is not specified. If the namespace is specified, then + dataSourceRef will not be copied to dataSource.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + required: + - kind + - name + type: object + x-kubernetes-map-type: atomic + dataSourceRef: + description: 'dataSourceRef specifies the object from + which to populate the volume with data, if a non-empty + volume is desired. This may be any object from a non-empty + API group (non core object) or a PersistentVolumeClaim + object. When this field is specified, volume binding + will only succeed if the type of the specified object + matches some installed volume populator or dynamic provisioner. + This field will replace the functionality of the dataSource + field and as such if both fields are non-empty, they + must have the same value. For backwards compatibility, + when namespace isn''t specified in dataSourceRef, both + fields (dataSource and dataSourceRef) will be set to + the same value automatically if one of them is empty + and the other is non-empty. When namespace is specified + in dataSourceRef, dataSource isn''t set to the same + value and must be empty. There are three important differences + between dataSource and dataSourceRef: * While dataSource + only allows two specific types of objects, dataSourceRef + allows any non-core object, as well as PersistentVolumeClaim + objects. * While dataSource ignores disallowed values + (dropping them), dataSourceRef preserves all values, + and generates an error if a disallowed value is specified. + * While dataSource only allows local objects, dataSourceRef + allows objects in any namespaces. (Beta) Using this + field requires the AnyVolumeDataSource feature gate + to be enabled. (Alpha) Using the namespace field of + dataSourceRef requires the CrossNamespaceVolumeDataSource + feature gate to be enabled.' + properties: + apiGroup: + description: APIGroup is the group for the resource + being referenced. If APIGroup is not specified, + the specified Kind must be in the core API group. + For any other third-party types, APIGroup is required. + type: string + kind: + description: Kind is the type of resource being referenced + type: string + name: + description: Name is the name of resource being referenced + type: string + namespace: + description: Namespace is the namespace of resource + being referenced Note that when a namespace is specified, + a gateway.networking.k8s.io/ReferenceGrant object + is required in the referent namespace to allow that + namespace's owner to accept the reference. See the + ReferenceGrant documentation for details. (Alpha) + This field requires the CrossNamespaceVolumeDataSource + feature gate to be enabled. + type: string + required: + - kind + - name + type: object + resources: + description: 'resources represents the minimum resources + the volume should have. If RecoverVolumeExpansionFailure + feature is enabled users are allowed to specify resource + requirements that are lower than previous value but + must still be higher than capacity recorded in the status + field of the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#resources' + properties: + claims: + description: "Claims lists the names of resources, + defined in spec.resourceClaims, that are used by + this container. \n This is an alpha field and requires + enabling the DynamicResourceAllocation feature gate. + \n This field is immutable. It can only be set for + containers." + items: + description: ResourceClaim references one entry + in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one + entry in pod.spec.resourceClaims of the Pod + where this field is used. It makes that resource + available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount + of compute resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount + of compute resources required. If Requests is omitted + for a container, it defaults to Limits if that is + explicitly specified, otherwise to an implementation-defined + value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + selector: + description: selector is a label query over volumes to + consider for binding. + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, + NotIn, Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values + array must be non-empty. If the operator is + Exists or DoesNotExist, the values array must + be empty. This array is replaced during a + strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field + is "key", the operator is "In", and the values array + contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + storageClassName: + description: 'storageClassName is the name of the StorageClass + required by the claim. More info: https://kubernetes.io/docs/concepts/storage/persistent-volumes#class-1' + type: string + volumeMode: + description: volumeMode defines what type of volume is + required by the claim. Value of Filesystem is implied + when not included in claim spec. + type: string + volumeName: + description: volumeName is the binding reference to the + PersistentVolume backing this claim. + type: string + type: object + type: object + type: object + targetDiscoveryOptions: + description: Options to configure the Cryostat application's target + discovery mechanisms. + properties: + builtInDiscoveryDisabled: + description: When true, the Cryostat application will disable + the built-in discovery mechanisms. Defaults to false + type: boolean + type: object + targetNamespaces: + description: 'List of namespaces whose workloads Cryostat should be + permitted to access and profile. Defaults to this Cryostat''s namespace. + Warning: All Cryostat users will be able to create and manage recordings + for workloads in the listed namespaces. More details: https://github.com/cryostatio/cryostat-operator/blob/v2.4.0/docs/multi-namespace.md#data-isolation' + items: + type: string + type: array + trustedCertSecrets: + description: List of TLS certificates to trust when connecting to + targets. + items: + properties: + certificateKey: + description: Key within secret containing the certificate. + type: string + secretName: + description: Name of secret in the local namespace. + type: string + required: + - secretName + type: object + type: array + required: + - minimal + type: object + status: + description: CryostatStatus defines the observed state of Cryostat. + properties: + applicationUrl: + description: Address of the deployed Cryostat web application. + type: string + conditions: + description: Conditions of the components managed by the Cryostat + Operator. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + grafanaSecret: + description: Name of the Secret containing the generated Grafana credentials. + type: string + targetNamespaces: + description: List of namespaces that Cryostat has been configured + and authorized to access and profile. + items: + type: string + type: array + required: + - applicationUrl + type: object + type: object + served: true storage: true subresources: status: {} diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index 153a06d7c..bd3981702 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -9,14 +9,14 @@ resources: patchesStrategicMerge: # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. # patches here are for enabling the conversion webhook for each CRD -#- patches/webhook_in_cryostats.yaml -#- patches/webhook_in_clustercryostats.yaml +- patches/webhook_in_cryostats.yaml +- patches/webhook_in_clustercryostats.yaml # +kubebuilder:scaffold:crdkustomizewebhookpatch # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. # patches here are for enabling the CA injection for each CRD -#- patches/cainjection_in_cryostats.yaml -#- patches/cainjection_in_clustercryostats.yaml +- patches/cainjection_in_cryostats.yaml +- patches/cainjection_in_clustercryostats.yaml # +kubebuilder:scaffold:crdkustomizecainjectionpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/config/crd/patches/webhook_in_cryostats.yaml b/config/crd/patches/webhook_in_cryostats.yaml index d8bd2b812..f90b447e8 100644 --- a/config/crd/patches/webhook_in_cryostats.yaml +++ b/config/crd/patches/webhook_in_cryostats.yaml @@ -12,3 +12,5 @@ spec: namespace: system name: webhook-service path: /convert + conversionReviewVersions: + - v1 diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index e50ac282b..6f4957f46 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -12,17 +12,6 @@ namePrefix: cryostat-operator- #commonLabels: # someName: someValue -# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in -# crd/kustomization.yaml -#- ../webhook -# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. -#- ../certmanager -# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. -#- ../prometheus - -patchesStrategicMerge: -- image_tag_patch.yaml -- image_pull_patch.yaml # Protect the /metrics endpoint by putting it behind auth. # If you want your controller-manager to expose the /metrics # endpoint w/o any authn/z, please comment the following line. @@ -37,17 +26,57 @@ patchesStrategicMerge: # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in # crd/kustomization.yaml -#- manager_webhook_patch.yaml # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. # Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. # 'CERTMANAGER' needs to be enabled to use ca injection -#- webhookcainjection_patch.yaml +patchesStrategicMerge: +- image_tag_patch.yaml +- image_pull_patch.yaml +- manager_webhook_patch.yaml +- webhookcainjection_patch.yaml # the following config is for teaching kustomize how to do var substitution apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization +# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in +# crd/kustomization.yaml +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. resources: - ../crd - ../rbac - ../manager +- ../webhook +- ../certmanager + +# the following config is for teaching kustomize how to do var substitution +# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. +vars: +- fieldref: + fieldPath: metadata.namespace + name: CERTIFICATE_NAMESPACE + objref: + group: cert-manager.io + kind: Certificate + name: serving-cert + version: v1 +- fieldref: {} + name: CERTIFICATE_NAME + objref: + group: cert-manager.io + kind: Certificate + name: serving-cert + version: v1 +- fieldref: + fieldPath: metadata.namespace + name: SERVICE_NAMESPACE + objref: + kind: Service + name: webhook-service + version: v1 +- fieldref: {} + name: SERVICE_NAME + objref: + kind: Service + name: webhook-service + version: v1 diff --git a/config/default/manager_webhook_patch.yaml b/config/default/manager_webhook_patch.yaml new file mode 100644 index 000000000..738de350b --- /dev/null +++ b/config/default/manager_webhook_patch.yaml @@ -0,0 +1,23 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + ports: + - containerPort: 9443 + name: webhook-server + protocol: TCP + volumeMounts: + - mountPath: /tmp/k8s-webhook-server/serving-certs + name: cert + readOnly: true + volumes: + - name: cert + secret: + defaultMode: 420 + secretName: webhook-server-cert diff --git a/config/default/webhookcainjection_patch.yaml b/config/default/webhookcainjection_patch.yaml new file mode 100644 index 000000000..fc7a98333 --- /dev/null +++ b/config/default/webhookcainjection_patch.yaml @@ -0,0 +1,29 @@ +# This patch add annotation to admission webhook config and +# the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize. +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + labels: + app.kubernetes.io/name: mutatingwebhookconfiguration + app.kubernetes.io/instance: mutating-webhook-configuration + app.kubernetes.io/component: webhook + app.kubernetes.io/created-by: cryostat-operator + app.kubernetes.io/part-of: cryostat-operator + app.kubernetes.io/managed-by: kustomize + name: mutating-webhook-configuration + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + labels: + app.kubernetes.io/name: validatingwebhookconfiguration + app.kubernetes.io/instance: validating-webhook-configuration + app.kubernetes.io/component: webhook + app.kubernetes.io/created-by: cryostat-operator + app.kubernetes.io/part-of: cryostat-operator + app.kubernetes.io/managed-by: kustomize + name: validating-webhook-configuration + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) diff --git a/config/manifests/bases/cryostat-operator.clusterserviceversion.yaml b/config/manifests/bases/cryostat-operator.clusterserviceversion.yaml index 760d31451..3c3207178 100644 --- a/config/manifests/bases/cryostat-operator.clusterserviceversion.yaml +++ b/config/manifests/bases/cryostat-operator.clusterserviceversion.yaml @@ -8,7 +8,7 @@ metadata: description: JVM monitoring and profiling tool operatorframework.io/initialization-resource: |- { - "apiVersion": "operator.cryostat.io/v1beta1", + "apiVersion": "operator.cryostat.io/v1beta2", "kind": "Cryostat", "metadata": { "name": "cryostat-sample" @@ -35,6 +35,399 @@ spec: apiservicedefinitions: {} customresourcedefinitions: owned: + - description: ClusterCryostat allows you to install Cryostat for multiple namespaces + or cluster-wide. It contains configuration options for controlling the Deployment + of the Cryostat application and its related components. A ClusterCryostat + or Cryostat instance must be created to instruct the operator to deploy the + Cryostat application. + displayName: Cluster Cryostat + kind: ClusterCryostat + name: clustercryostats.operator.cryostat.io + resources: + - kind: ConsoleLink + name: "" + version: v1 + - kind: Deployment + name: "" + version: v1 + - kind: Ingress + name: "" + version: v1 + - kind: PersistentVolumeClaim + name: "" + version: v1 + - kind: Route + name: "" + version: v1 + - kind: Secret + name: "" + version: v1 + - kind: Service + name: "" + version: v1 + specDescriptors: + - description: Namespace where Cryostat should be installed. On multi-tenant + clusters, we strongly suggest installing Cryostat into its own namespace. + displayName: Install Namespace + path: installNamespace + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Namespace + - description: 'List of namespaces whose workloads Cryostat should be permitted + to access and profile. Defaults to this Cryostat''s namespace. Warning: + All Cryostat users will be able to create and manage recordings for workloads + in the listed namespaces. More details: https://github.com/cryostatio/cryostat-operator/blob/v2.4.0/docs/multi-namespace.md#data-isolation' + displayName: Target Namespaces + path: targetNamespaces + - description: Use cert-manager to secure in-cluster communication between Cryostat + components. Requires cert-manager to be installed. + displayName: Enable cert-manager Integration + path: enableCertManager + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Deploy a pared-down Cryostat instance with no Grafana Dashboard + or JFR Data Source. + displayName: Minimal Deployment + path: minimal + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Override default authorization properties for Cryostat on OpenShift. + displayName: Authorization Properties + path: authProperties + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - description: 'Name of the ClusterRole to use when Cryostat requests a role-scoped + OAuth token. This ClusterRole should contain permissions for all Kubernetes + objects listed in custom permission mapping. More details: https://docs.openshift.com/container-platform/4.11/authentication/tokens-scoping.html#scoping-tokens-role-scope_configuring-internal-oauth' + displayName: ClusterRole Name + path: authProperties.clusterRoleName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:ClusterRole + - description: Name of config map in the local namespace. + displayName: ConfigMap Name + path: authProperties.configMapName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:ConfigMap + - description: Filename within config map containing the resource mapping. + displayName: Filename + path: authProperties.filename + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:text + - description: List of Flight Recorder Event Templates to preconfigure in Cryostat. + displayName: Event Templates + path: eventTemplates + - description: Name of config map in the local namespace. + displayName: Config Map Name + path: eventTemplates[0].configMapName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:ConfigMap + - description: Options to customize the JMX target connections cache for the + Cryostat application. + displayName: JMX Connections Cache Options + path: jmxCacheOptions + - description: The maximum number of JMX connections to cache. Use `-1` for + an unlimited cache size (TTL expiration only). Defaults to `-1`. + displayName: Target Cache Size + path: jmxCacheOptions.targetCacheSize + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: The time to live (in seconds) for cached JMX connections. Defaults + to `10`. + displayName: Target Cache TTL + path: jmxCacheOptions.targetCacheTTL + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: Options to configure the Cryostat application's credentials database. + displayName: Credentials Database Options + path: jmxCredentialsDatabaseOptions + - description: Name of the secret containing the password to encrypt credentials + database. + displayName: Database Secret Name + path: jmxCredentialsDatabaseOptions.databaseSecretName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + - description: The maximum number of WebSocket client connections allowed (minimum + 1, default unlimited). + displayName: Max WebSocket Connections + path: maxWsConnections + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: Options to control how the operator exposes the application outside + of the cluster, such as using an Ingress or Route. + displayName: Network Options + path: networkOptions + - description: "Specifications for how to expose the Cryostat command service, + which serves the WebSocket command channel. \n Deprecated: CommandConfig + is no longer used." + displayName: Command Config + path: networkOptions.commandConfig + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:hidden + - description: Annotations to add to the Ingress or Route during its creation. + displayName: Annotations + path: networkOptions.commandConfig.annotations + - description: Configuration for an Ingress object. Currently subpaths are not + supported, so unique hosts must be specified (if a single external IP is + being used) to differentiate between ingresses/services. + displayName: Ingress Spec + path: networkOptions.commandConfig.ingressSpec + - description: Labels to add to the Ingress or Route during its creation. The + label with key "app" is reserved for use by the operator. + displayName: Labels + path: networkOptions.commandConfig.labels + - description: Specifications for how to expose the Cryostat service, which + serves the Cryostat application. + displayName: Core Config + path: networkOptions.coreConfig + - description: Annotations to add to the Ingress or Route during its creation. + displayName: Annotations + path: networkOptions.coreConfig.annotations + - description: Configuration for an Ingress object. Currently subpaths are not + supported, so unique hosts must be specified (if a single external IP is + being used) to differentiate between ingresses/services. + displayName: Ingress Spec + path: networkOptions.coreConfig.ingressSpec + - description: Labels to add to the Ingress or Route during its creation. The + label with key "app" is reserved for use by the operator. + displayName: Labels + path: networkOptions.coreConfig.labels + - description: Specifications for how to expose Cryostat's Grafana service, + which serves the Grafana dashboard. + displayName: Grafana Config + path: networkOptions.grafanaConfig + - description: Annotations to add to the Ingress or Route during its creation. + displayName: Annotations + path: networkOptions.grafanaConfig.annotations + - description: Configuration for an Ingress object. Currently subpaths are not + supported, so unique hosts must be specified (if a single external IP is + being used) to differentiate between ingresses/services. + displayName: Ingress Spec + path: networkOptions.grafanaConfig.ingressSpec + - description: Labels to add to the Ingress or Route during its creation. The + label with key "app" is reserved for use by the operator. + displayName: Labels + path: networkOptions.grafanaConfig.labels + - description: Options to configure the Cryostat deployments and pods metadata + displayName: Operand metadata + path: operandMetadata + - description: Options to configure the Cryostat deployments metadata + displayName: Deployments metadata + path: operandMetadata.deploymentMetadata + - description: Options to configure the Cryostat pods metadata + displayName: Pods metadata + path: operandMetadata.podMetadata + - description: Options to configure Cryostat Automated Report Analysis. + displayName: Report Options + path: reportOptions + - description: The number of report sidecar replica containers to deploy. Each + replica can service one report generation request at a time. + displayName: Replicas + path: reportOptions.replicas + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podCount + - description: The resources allocated to each sidecar replica. A replica with + more resources can handle larger input recordings and will process them + faster. + displayName: Resources + path: reportOptions.resources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + - description: Options to configure scheduling for the reports deployment + displayName: Scheduling Options + path: reportOptions.schedulingOptions + - description: Affinity rules for scheduling Cryostat pods. + displayName: Affinity + path: reportOptions.schedulingOptions.affinity + - description: 'Node affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#NodeAffinity' + displayName: Node Affinity + path: reportOptions.schedulingOptions.affinity.nodeAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:nodeAffinity + - description: 'Pod affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAffinity' + displayName: Pod Affinity + path: reportOptions.schedulingOptions.affinity.podAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podAffinity + - description: 'Pod anti-affinity scheduling rules for a Cryostat pod. See: + https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAntiAffinity' + displayName: Pod Anti Affinity + path: reportOptions.schedulingOptions.affinity.podAntiAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podAntiAffinity + - description: 'Label selector used to schedule a Cryostat pod to a node. See: + https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + displayName: Node Selector + path: reportOptions.schedulingOptions.nodeSelector + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:selector:core:v1:Node + - description: 'Tolerations to allow scheduling of Cryostat pods to tainted + nodes. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/' + displayName: Tolerations + path: reportOptions.schedulingOptions.tolerations + - description: Options to configure the Security Contexts for the Cryostat report + generator. + displayName: Security Options + path: reportOptions.securityOptions + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - description: Security Context to apply to the Cryostat report generator pod. + displayName: Pod Security Context + path: reportOptions.securityOptions.podSecurityContext + - description: Security Context to apply to the Cryostat report generator container. + displayName: Reports Security Context + path: reportOptions.securityOptions.reportsSecurityContext + - description: When zero report sidecar replicas are requested, SubProcessMaxHeapSize + configures the maximum heap size of the basic subprocess report generator + in MiB. The default heap size is `200` (MiB). + displayName: Sub Process Max Heap Size + path: reportOptions.subProcessMaxHeapSize + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: Resource requirements for the Cryostat deployment. + displayName: Resources + path: resources + - description: Resource requirements for the Cryostat application. If specifying + a memory limit, at least 768MiB is recommended. + displayName: Core Resources + path: resources.coreResources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + - description: Resource requirements for the JFR Data Source container. + displayName: Data Source Resources + path: resources.dataSourceResources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + - description: Resource requirements for the Grafana container. + displayName: Grafana Resources + path: resources.grafanaResources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + - description: Options to configure scheduling for the Cryostat deployment + displayName: Scheduling Options + path: schedulingOptions + - description: Affinity rules for scheduling Cryostat pods. + displayName: Affinity + path: schedulingOptions.affinity + - description: 'Node affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#NodeAffinity' + displayName: Node Affinity + path: schedulingOptions.affinity.nodeAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:nodeAffinity + - description: 'Pod affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAffinity' + displayName: Pod Affinity + path: schedulingOptions.affinity.podAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podAffinity + - description: 'Pod anti-affinity scheduling rules for a Cryostat pod. See: + https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAntiAffinity' + displayName: Pod Anti Affinity + path: schedulingOptions.affinity.podAntiAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podAntiAffinity + - description: 'Label selector used to schedule a Cryostat pod to a node. See: + https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + displayName: Node Selector + path: schedulingOptions.nodeSelector + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:selector:core:v1:Node + - description: 'Tolerations to allow scheduling of Cryostat pods to tainted + nodes. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/' + displayName: Tolerations + path: schedulingOptions.tolerations + - description: Options to configure the Security Contexts for the Cryostat application. + displayName: Security Options + path: securityOptions + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - description: Security Context to apply to the Cryostat application container. + displayName: Core Security Context + path: securityOptions.coreSecurityContext + - description: Security Context to apply to the JFR Data Source container. + displayName: Data Source Security Context + path: securityOptions.dataSourceSecurityContext + - description: Security Context to apply to the Grafana container. + displayName: Grafana Security Context + path: securityOptions.grafanaSecurityContext + - description: Security Context to apply to the Cryostat pod. + displayName: Pod Security Context + path: securityOptions.podSecurityContext + - description: Options to customize the services created for the Cryostat application + and Grafana dashboard. + displayName: Service Options + path: serviceOptions + - description: Options to customize the storage for Flight Recordings and Templates. + displayName: Storage Options + path: storageOptions + - description: Configuration for an EmptyDir to be created by the operator instead + of a PVC. + displayName: Empty Dir + path: storageOptions.emptyDir + - description: When enabled, Cryostat will use EmptyDir volumes instead of a + Persistent Volume Claim. Any PVC configurations will be ignored. + displayName: Enabled + path: storageOptions.emptyDir.enabled + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Unless specified, the emptyDir volume will be mounted on the + same storage medium backing the node. Setting this field to "Memory" will + mount the emptyDir on a tmpfs (RAM-backed filesystem). + displayName: Medium + path: storageOptions.emptyDir.medium + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:fieldDependency:storageOptions.emptyDir.enabled:true + - description: The maximum memory limit for the emptyDir. Default is unbounded. + displayName: Size Limit + path: storageOptions.emptyDir.sizeLimit + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:fieldDependency:storageOptions.emptyDir.enabled:true + - description: Configuration for the Persistent Volume Claim to be created by + the operator. + displayName: PVC + path: storageOptions.pvc + - description: Spec for a Persistent Volume Claim, whose options will override + the defaults used by the operator. Unless overriden, the PVC will be created + with the default Storage Class and 500MiB of storage. Once the operator + has created the PVC, changes to this field have no effect. + displayName: Spec + path: storageOptions.pvc.spec + - description: Options to configure the Cryostat application's target discovery + mechanisms. + displayName: Target Discovery Options + path: targetDiscoveryOptions + - description: When true, the Cryostat application will disable the built-in + discovery mechanisms. Defaults to false + displayName: Disable Built-in Discovery + path: targetDiscoveryOptions.builtInDiscoveryDisabled + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: List of TLS certificates to trust when connecting to targets. + displayName: Trusted TLS Certificates + path: trustedCertSecrets + - description: Name of secret in the local namespace. + displayName: Secret Name + path: trustedCertSecrets[0].secretName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Address of the deployed Cryostat web application. + displayName: Application URL + path: applicationUrl + x-descriptors: + - urn:alm:descriptor:org.w3:link + - description: Name of the Secret containing the generated Grafana credentials. + displayName: Grafana Secret + path: grafanaSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + - description: List of namespaces that Cryostat has been configured and authorized + to access and profile. + displayName: Target Namespaces + path: targetNamespaces + - description: Conditions of the components managed by the Cryostat Operator. + displayName: Cryostat Conditions + path: conditions + x-descriptors: + - urn:alm:descriptor:io.kubernetes.conditions + version: v1beta2 - description: ClusterCryostat allows you to install Cryostat for multiple namespaces or cluster-wide. It contains configuration options for controlling the Deployment of the Cryostat application and its related components. A ClusterCryostat @@ -394,35 +787,421 @@ spec: displayName: Target Discovery Options path: targetDiscoveryOptions - description: When true, the Cryostat application will disable the built-in - discovery mechanisms. Defaults to false. + discovery mechanisms. Defaults to false. + displayName: Disable Built-in Discovery + path: targetDiscoveryOptions.builtInDiscoveryDisabled + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: When true, the Cryostat application will use the default port + name jfr-jmx to look for JMX connectable targets. + displayName: Disable Built-in Port Names + path: targetDiscoveryOptions.disableBuiltInPortNames + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: When true, the Cryostat application will use the default port + number 9091 to look for JMX connectable targets. + displayName: Disable Built-in Port Numbers + path: targetDiscoveryOptions.disableBuiltInPortNumbers + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: List of port names that the Cryostat application should look + for in order to consider a target as JMX connectable. + displayName: Discovery Port Names + path: targetDiscoveryOptions.discoveryPortNames + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:fieldDependency:targetDiscoveryOptions.disableBuiltInPortNames:true + - description: List of port numbers that the Cryostat application should look + for in order to consider a target as JMX connectable. + displayName: Discovery Port Numbers + path: targetDiscoveryOptions.discoveryPortNumbers + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:fieldDependency:targetDiscoveryOptions.disableBuiltInPortNumbers:true + - description: List of TLS certificates to trust when connecting to targets. + displayName: Trusted TLS Certificates + path: trustedCertSecrets + - description: Name of secret in the local namespace. + displayName: Secret Name + path: trustedCertSecrets[0].secretName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + statusDescriptors: + - description: Address of the deployed Cryostat web application. + displayName: Application URL + path: applicationUrl + x-descriptors: + - urn:alm:descriptor:org.w3:link + - description: Name of the Secret containing the generated Grafana credentials. + displayName: Grafana Secret + path: grafanaSecret + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + - description: List of namespaces that Cryostat has been configured and authorized + to access and profile. + displayName: Target Namespaces + path: targetNamespaces + - description: Conditions of the components managed by the Cryostat Operator. + displayName: Cryostat Conditions + path: conditions + x-descriptors: + - urn:alm:descriptor:io.kubernetes.conditions + version: v1beta1 + - description: Cryostat allows you to install Cryostat for a single namespace. + It contains configuration options for controlling the Deployment of the Cryostat + application and its related components. A ClusterCryostat or Cryostat instance + must be created to instruct the operator to deploy the Cryostat application. + displayName: Cryostat + kind: Cryostat + name: cryostats.operator.cryostat.io + resources: + - kind: ConsoleLink + name: "" + version: v1 + - kind: Deployment + name: "" + version: v1 + - kind: Ingress + name: "" + version: v1 + - kind: PersistentVolumeClaim + name: "" + version: v1 + - kind: Route + name: "" + version: v1 + - kind: Secret + name: "" + version: v1 + - kind: Service + name: "" + version: v1 + specDescriptors: + - description: 'List of namespaces whose workloads Cryostat should be permitted + to access and profile. Defaults to this Cryostat''s namespace. Warning: + All Cryostat users will be able to create and manage recordings for workloads + in the listed namespaces. More details: https://github.com/cryostatio/cryostat-operator/blob/v2.4.0/docs/multi-namespace.md#data-isolation' + displayName: Target Namespaces + path: targetNamespaces + - description: Use cert-manager to secure in-cluster communication between Cryostat + components. Requires cert-manager to be installed. + displayName: Enable cert-manager Integration + path: enableCertManager + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Deploy a pared-down Cryostat instance with no Grafana Dashboard + or JFR Data Source. + displayName: Minimal Deployment + path: minimal + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Override default authorization properties for Cryostat on OpenShift. + displayName: Authorization Properties + path: authProperties + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - description: 'Name of the ClusterRole to use when Cryostat requests a role-scoped + OAuth token. This ClusterRole should contain permissions for all Kubernetes + objects listed in custom permission mapping. More details: https://docs.openshift.com/container-platform/4.11/authentication/tokens-scoping.html#scoping-tokens-role-scope_configuring-internal-oauth' + displayName: ClusterRole Name + path: authProperties.clusterRoleName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:ClusterRole + - description: Name of config map in the local namespace. + displayName: ConfigMap Name + path: authProperties.configMapName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:ConfigMap + - description: Filename within config map containing the resource mapping. + displayName: Filename + path: authProperties.filename + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:text + - description: List of Flight Recorder Event Templates to preconfigure in Cryostat. + displayName: Event Templates + path: eventTemplates + - description: Name of config map in the local namespace. + displayName: Config Map Name + path: eventTemplates[0].configMapName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:ConfigMap + - description: Options to customize the JMX target connections cache for the + Cryostat application. + displayName: JMX Connections Cache Options + path: jmxCacheOptions + - description: The maximum number of JMX connections to cache. Use `-1` for + an unlimited cache size (TTL expiration only). Defaults to `-1`. + displayName: Target Cache Size + path: jmxCacheOptions.targetCacheSize + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: The time to live (in seconds) for cached JMX connections. Defaults + to `10`. + displayName: Target Cache TTL + path: jmxCacheOptions.targetCacheTTL + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: Options to configure the Cryostat application's credentials database. + displayName: Credentials Database Options + path: jmxCredentialsDatabaseOptions + - description: Name of the secret containing the password to encrypt credentials + database. + displayName: Database Secret Name + path: jmxCredentialsDatabaseOptions.databaseSecretName + x-descriptors: + - urn:alm:descriptor:io.kubernetes:Secret + - description: The maximum number of WebSocket client connections allowed (minimum + 1, default unlimited). + displayName: Max WebSocket Connections + path: maxWsConnections + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: Options to control how the operator exposes the application outside + of the cluster, such as using an Ingress or Route. + displayName: Network Options + path: networkOptions + - description: "Specifications for how to expose the Cryostat command service, + which serves the WebSocket command channel. \n Deprecated: CommandConfig + is no longer used." + displayName: Command Config + path: networkOptions.commandConfig + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:hidden + - description: Annotations to add to the Ingress or Route during its creation. + displayName: Annotations + path: networkOptions.commandConfig.annotations + - description: Configuration for an Ingress object. Currently subpaths are not + supported, so unique hosts must be specified (if a single external IP is + being used) to differentiate between ingresses/services. + displayName: Ingress Spec + path: networkOptions.commandConfig.ingressSpec + - description: Labels to add to the Ingress or Route during its creation. The + label with key "app" is reserved for use by the operator. + displayName: Labels + path: networkOptions.commandConfig.labels + - description: Specifications for how to expose the Cryostat service, which + serves the Cryostat application. + displayName: Core Config + path: networkOptions.coreConfig + - description: Annotations to add to the Ingress or Route during its creation. + displayName: Annotations + path: networkOptions.coreConfig.annotations + - description: Configuration for an Ingress object. Currently subpaths are not + supported, so unique hosts must be specified (if a single external IP is + being used) to differentiate between ingresses/services. + displayName: Ingress Spec + path: networkOptions.coreConfig.ingressSpec + - description: Labels to add to the Ingress or Route during its creation. The + label with key "app" is reserved for use by the operator. + displayName: Labels + path: networkOptions.coreConfig.labels + - description: Specifications for how to expose Cryostat's Grafana service, + which serves the Grafana dashboard. + displayName: Grafana Config + path: networkOptions.grafanaConfig + - description: Annotations to add to the Ingress or Route during its creation. + displayName: Annotations + path: networkOptions.grafanaConfig.annotations + - description: Configuration for an Ingress object. Currently subpaths are not + supported, so unique hosts must be specified (if a single external IP is + being used) to differentiate between ingresses/services. + displayName: Ingress Spec + path: networkOptions.grafanaConfig.ingressSpec + - description: Labels to add to the Ingress or Route during its creation. The + label with key "app" is reserved for use by the operator. + displayName: Labels + path: networkOptions.grafanaConfig.labels + - description: Options to configure the Cryostat deployments and pods metadata + displayName: Operand metadata + path: operandMetadata + - description: Options to configure the Cryostat deployments metadata + displayName: Deployments metadata + path: operandMetadata.deploymentMetadata + - description: Options to configure the Cryostat pods metadata + displayName: Pods metadata + path: operandMetadata.podMetadata + - description: Options to configure Cryostat Automated Report Analysis. + displayName: Report Options + path: reportOptions + - description: The number of report sidecar replica containers to deploy. Each + replica can service one report generation request at a time. + displayName: Replicas + path: reportOptions.replicas + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podCount + - description: The resources allocated to each sidecar replica. A replica with + more resources can handle larger input recordings and will process them + faster. + displayName: Resources + path: reportOptions.resources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + - description: Options to configure scheduling for the reports deployment + displayName: Scheduling Options + path: reportOptions.schedulingOptions + - description: Affinity rules for scheduling Cryostat pods. + displayName: Affinity + path: reportOptions.schedulingOptions.affinity + - description: 'Node affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#NodeAffinity' + displayName: Node Affinity + path: reportOptions.schedulingOptions.affinity.nodeAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:nodeAffinity + - description: 'Pod affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAffinity' + displayName: Pod Affinity + path: reportOptions.schedulingOptions.affinity.podAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podAffinity + - description: 'Pod anti-affinity scheduling rules for a Cryostat pod. See: + https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAntiAffinity' + displayName: Pod Anti Affinity + path: reportOptions.schedulingOptions.affinity.podAntiAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podAntiAffinity + - description: 'Label selector used to schedule a Cryostat pod to a node. See: + https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + displayName: Node Selector + path: reportOptions.schedulingOptions.nodeSelector + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:selector:core:v1:Node + - description: 'Tolerations to allow scheduling of Cryostat pods to tainted + nodes. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/' + displayName: Tolerations + path: reportOptions.schedulingOptions.tolerations + - description: Options to configure the Security Contexts for the Cryostat report + generator. + displayName: Security Options + path: reportOptions.securityOptions + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - description: Security Context to apply to the Cryostat report generator pod. + displayName: Pod Security Context + path: reportOptions.securityOptions.podSecurityContext + - description: Security Context to apply to the Cryostat report generator container. + displayName: Reports Security Context + path: reportOptions.securityOptions.reportsSecurityContext + - description: When zero report sidecar replicas are requested, SubProcessMaxHeapSize + configures the maximum heap size of the basic subprocess report generator + in MiB. The default heap size is `200` (MiB). + displayName: Sub Process Max Heap Size + path: reportOptions.subProcessMaxHeapSize + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:number + - description: Resource requirements for the Cryostat deployment. + displayName: Resources + path: resources + - description: Resource requirements for the Cryostat application. If specifying + a memory limit, at least 768MiB is recommended. + displayName: Core Resources + path: resources.coreResources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + - description: Resource requirements for the JFR Data Source container. + displayName: Data Source Resources + path: resources.dataSourceResources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + - description: Resource requirements for the Grafana container. + displayName: Grafana Resources + path: resources.grafanaResources + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:resourceRequirements + - description: Options to configure scheduling for the Cryostat deployment + displayName: Scheduling Options + path: schedulingOptions + - description: Affinity rules for scheduling Cryostat pods. + displayName: Affinity + path: schedulingOptions.affinity + - description: 'Node affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#NodeAffinity' + displayName: Node Affinity + path: schedulingOptions.affinity.nodeAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:nodeAffinity + - description: 'Pod affinity scheduling rules for a Cryostat pod. See: https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAffinity' + displayName: Pod Affinity + path: schedulingOptions.affinity.podAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podAffinity + - description: 'Pod anti-affinity scheduling rules for a Cryostat pod. See: + https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#PodAntiAffinity' + displayName: Pod Anti Affinity + path: schedulingOptions.affinity.podAntiAffinity + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:podAntiAffinity + - description: 'Label selector used to schedule a Cryostat pod to a node. See: + https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + displayName: Node Selector + path: schedulingOptions.nodeSelector + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:selector:core:v1:Node + - description: 'Tolerations to allow scheduling of Cryostat pods to tainted + nodes. See: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/' + displayName: Tolerations + path: schedulingOptions.tolerations + - description: Options to configure the Security Contexts for the Cryostat application. + displayName: Security Options + path: securityOptions + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:advanced + - description: Security Context to apply to the Cryostat application container. + displayName: Core Security Context + path: securityOptions.coreSecurityContext + - description: Security Context to apply to the JFR Data Source container. + displayName: Data Source Security Context + path: securityOptions.dataSourceSecurityContext + - description: Security Context to apply to the Grafana container. + displayName: Grafana Security Context + path: securityOptions.grafanaSecurityContext + - description: Security Context to apply to the Cryostat pod. + displayName: Pod Security Context + path: securityOptions.podSecurityContext + - description: Options to customize the services created for the Cryostat application + and Grafana dashboard. + displayName: Service Options + path: serviceOptions + - description: Options to customize the storage for Flight Recordings and Templates. + displayName: Storage Options + path: storageOptions + - description: Configuration for an EmptyDir to be created by the operator instead + of a PVC. + displayName: Empty Dir + path: storageOptions.emptyDir + - description: When enabled, Cryostat will use EmptyDir volumes instead of a + Persistent Volume Claim. Any PVC configurations will be ignored. + displayName: Enabled + path: storageOptions.emptyDir.enabled + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Unless specified, the emptyDir volume will be mounted on the + same storage medium backing the node. Setting this field to "Memory" will + mount the emptyDir on a tmpfs (RAM-backed filesystem). + displayName: Medium + path: storageOptions.emptyDir.medium + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:fieldDependency:storageOptions.emptyDir.enabled:true + - description: The maximum memory limit for the emptyDir. Default is unbounded. + displayName: Size Limit + path: storageOptions.emptyDir.sizeLimit + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:fieldDependency:storageOptions.emptyDir.enabled:true + - description: Configuration for the Persistent Volume Claim to be created by + the operator. + displayName: PVC + path: storageOptions.pvc + - description: Spec for a Persistent Volume Claim, whose options will override + the defaults used by the operator. Unless overriden, the PVC will be created + with the default Storage Class and 500MiB of storage. Once the operator + has created the PVC, changes to this field have no effect. + displayName: Spec + path: storageOptions.pvc.spec + - description: Options to configure the Cryostat application's target discovery + mechanisms. + displayName: Target Discovery Options + path: targetDiscoveryOptions + - description: When true, the Cryostat application will disable the built-in + discovery mechanisms. Defaults to false displayName: Disable Built-in Discovery path: targetDiscoveryOptions.builtInDiscoveryDisabled x-descriptors: - urn:alm:descriptor:com.tectonic.ui:booleanSwitch - - description: When true, the Cryostat application will use the default port - name jfr-jmx to look for JMX connectable targets. - displayName: Disable Built-in Port Names - path: targetDiscoveryOptions.disableBuiltInPortNames - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:booleanSwitch - - description: When true, the Cryostat application will use the default port - number 9091 to look for JMX connectable targets. - displayName: Disable Built-in Port Numbers - path: targetDiscoveryOptions.disableBuiltInPortNumbers - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:booleanSwitch - - description: List of port names that the Cryostat application should look - for in order to consider a target as JMX connectable. - displayName: Discovery Port Names - path: targetDiscoveryOptions.discoveryPortNames - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:fieldDependency:targetDiscoveryOptions.disableBuiltInPortNames:true - - description: List of port numbers that the Cryostat application should look - for in order to consider a target as JMX connectable. - displayName: Discovery Port Numbers - path: targetDiscoveryOptions.discoveryPortNumbers - x-descriptors: - - urn:alm:descriptor:com.tectonic.ui:fieldDependency:targetDiscoveryOptions.disableBuiltInPortNumbers:true - description: List of TLS certificates to trust when connecting to targets. displayName: Trusted TLS Certificates path: trustedCertSecrets @@ -451,7 +1230,7 @@ spec: path: conditions x-descriptors: - urn:alm:descriptor:io.kubernetes.conditions - version: v1beta1 + version: v1beta2 - description: Cryostat allows you to install Cryostat for a single namespace. It contains configuration options for controlling the Deployment of the Cryostat application and its related components. A ClusterCryostat or Cryostat instance diff --git a/config/manifests/targetNamespaces_patch.yaml b/config/manifests/targetNamespaces_patch.yaml index b669249d4..640710b6a 100644 --- a/config/manifests/targetNamespaces_patch.yaml +++ b/config/manifests/targetNamespaces_patch.yaml @@ -15,3 +15,35 @@ path: targetNamespaces[0] x-descriptors: - "urn:alm:descriptor:io.kubernetes:Namespace" +- op: add + path: /spec/customresourcedefinitions/owned/1/specDescriptors/- + value: + description: "A namespace whose workloads Cryostat should be able to connect and record" + displayName: "Target Namespace" + path: targetNamespaces[0] + x-descriptors: + - "urn:alm:descriptor:io.kubernetes:Namespace" +- op: add + path: /spec/customresourcedefinitions/owned/1/statusDescriptors/- + value: + description: "A namespace whose workloads Cryostat should be able to connect and record" + displayName: "Target Namespace" + path: targetNamespaces[0] + x-descriptors: + - "urn:alm:descriptor:io.kubernetes:Namespace" +- op: add + path: /spec/customresourcedefinitions/owned/2/specDescriptors/- + value: + description: "A namespace whose workloads Cryostat should be able to connect and record" + displayName: "Target Namespace" + path: targetNamespaces[0] + x-descriptors: + - "urn:alm:descriptor:io.kubernetes:Namespace" +- op: add + path: /spec/customresourcedefinitions/owned/2/statusDescriptors/- + value: + description: "A namespace whose workloads Cryostat should be able to connect and record" + displayName: "Target Namespace" + path: targetNamespaces[0] + x-descriptors: + - "urn:alm:descriptor:io.kubernetes:Namespace" diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 534e4c3c2..0ca288fce 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -76,6 +76,12 @@ rules: - selfsubjectaccessreviews verbs: - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create - apiGroups: - cert-manager.io resources: diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index 3e9e735a7..08a69bad7 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -2,4 +2,6 @@ resources: - operator_v1beta1_cryostat.yaml - operator_v1beta1_clustercryostat.yaml +- operator_v1beta2_cryostat.yaml +- operator_v1beta2_clustercryostat.yaml # +kubebuilder:scaffold:manifestskustomizesamples diff --git a/config/samples/operator_v1beta2_clustercryostat.yaml b/config/samples/operator_v1beta2_clustercryostat.yaml new file mode 100644 index 000000000..b4b656843 --- /dev/null +++ b/config/samples/operator_v1beta2_clustercryostat.yaml @@ -0,0 +1,16 @@ +apiVersion: operator.cryostat.io/v1beta2 +kind: ClusterCryostat +metadata: + name: clustercryostat-sample +spec: + minimal: false + enableCertManager: true + trustedCertSecrets: [] + eventTemplates: [] + storageOptions: + pvc: + labels: {} + annotations: {} + spec: {} + reportOptions: + replicas: 0 diff --git a/config/samples/operator_v1beta2_cryostat.yaml b/config/samples/operator_v1beta2_cryostat.yaml new file mode 100644 index 000000000..69cc3b956 --- /dev/null +++ b/config/samples/operator_v1beta2_cryostat.yaml @@ -0,0 +1,16 @@ +apiVersion: operator.cryostat.io/v1beta2 +kind: Cryostat +metadata: + name: cryostat-sample +spec: + minimal: false + enableCertManager: true + trustedCertSecrets: [] + eventTemplates: [] + storageOptions: + pvc: + labels: {} + annotations: {} + spec: {} + reportOptions: + replicas: 0 diff --git a/config/webhook/kustomization.yaml b/config/webhook/kustomization.yaml new file mode 100644 index 000000000..9cf26134e --- /dev/null +++ b/config/webhook/kustomization.yaml @@ -0,0 +1,6 @@ +resources: +- manifests.yaml +- service.yaml + +configurations: +- kustomizeconfig.yaml diff --git a/config/webhook/kustomizeconfig.yaml b/config/webhook/kustomizeconfig.yaml new file mode 100644 index 000000000..25e21e3c9 --- /dev/null +++ b/config/webhook/kustomizeconfig.yaml @@ -0,0 +1,25 @@ +# the following config is for teaching kustomize where to look at when substituting vars. +# It requires kustomize v2.1.0 or newer to work properly. +nameReference: +- kind: Service + version: v1 + fieldSpecs: + - kind: MutatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/name + - kind: ValidatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/name + +namespace: +- kind: MutatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/namespace + create: true +- kind: ValidatingWebhookConfiguration + group: admissionregistration.k8s.io + path: webhooks/clientConfig/service/namespace + create: true + +varReference: +- path: metadata/annotations diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml new file mode 100644 index 000000000..39f016e00 --- /dev/null +++ b/config/webhook/manifests.yaml @@ -0,0 +1,54 @@ +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + creationTimestamp: null + name: mutating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-operator-cryostat-io-v1beta2-cryostat + failurePolicy: Fail + name: mcryostat.kb.io + rules: + - apiGroups: + - operator.cryostat.io + apiVersions: + - v1beta2 + operations: + - CREATE + - UPDATE + resources: + - cryostats + sideEffects: None +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingWebhookConfiguration +metadata: + creationTimestamp: null + name: validating-webhook-configuration +webhooks: +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-operator-cryostat-io-v1beta2-cryostat + failurePolicy: Fail + name: vcryostat.kb.io + rules: + - apiGroups: + - operator.cryostat.io + apiVersions: + - v1beta2 + operations: + - CREATE + - UPDATE + resources: + - cryostats + sideEffects: None diff --git a/config/webhook/service.yaml b/config/webhook/service.yaml new file mode 100644 index 000000000..451723750 --- /dev/null +++ b/config/webhook/service.yaml @@ -0,0 +1,20 @@ + +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/name: service + app.kubernetes.io/instance: webhook-service + app.kubernetes.io/component: webhook + app.kubernetes.io/created-by: cryostat-operator + app.kubernetes.io/part-of: cryostat-operator + app.kubernetes.io/managed-by: kustomize + name: webhook-service + namespace: system +spec: + ports: + - port: 443 + protocol: TCP + targetPort: 9443 + selector: + control-plane: controller-manager diff --git a/internal/controllers/certmanager.go b/internal/controllers/certmanager.go index ae9fa875c..45b305b7a 100644 --- a/internal/controllers/certmanager.go +++ b/internal/controllers/certmanager.go @@ -56,14 +56,14 @@ func (r *Reconciler) setupTLS(ctx context.Context, cr *model.CryostatInstance) ( } // Create CA certificate for Cryostat using the self-signed issuer - caCert := resources.NewCryostatCACert(cr) + caCert := resources.NewCryostatCACert(r.gvk, cr) err = r.createOrUpdateCertificate(ctx, caCert, cr.Object) if err != nil { return nil, err } // Create CA issuer using the CA cert just created - err = r.createOrUpdateIssuer(ctx, resources.NewCryostatCAIssuer(cr), cr.Object) + err = r.createOrUpdateIssuer(ctx, resources.NewCryostatCAIssuer(r.gvk, cr), cr.Object) if err != nil { return nil, err } @@ -136,13 +136,7 @@ func (r *Reconciler) setupTLS(ctx context.Context, cr *model.CryostatInstance) ( }, Type: corev1.SecretTypeOpaque, } - err = r.createOrUpdateSecret(ctx, namespaceSecret, cr.Object, func() error { - if namespaceSecret.Data == nil { - namespaceSecret.Data = map[string][]byte{} - } - namespaceSecret.Data[corev1.TLSCertKey] = secret.Data[corev1.TLSCertKey] - return nil - }) + err = r.createOrUpdateCertSecret(ctx, namespaceSecret, secret.Data[corev1.TLSCertKey]) if err != nil { return nil, err } @@ -174,7 +168,7 @@ func (r *Reconciler) setupTLS(ctx context.Context, cr *model.CryostatInstance) ( } func (r *Reconciler) finalizeTLS(ctx context.Context, cr *model.CryostatInstance) error { - caCert := resources.NewCryostatCACert(cr) + caCert := resources.NewCryostatCACert(r.gvk, cr) for _, ns := range cr.TargetNamespaces { if ns != cr.InstallNamespace { namespaceSecret := &corev1.Secret{ @@ -307,6 +301,21 @@ func (r *Reconciler) createOrUpdateKeystoreSecret(ctx context.Context, secret *c return nil } +func (r *Reconciler) createOrUpdateCertSecret(ctx context.Context, secret *corev1.Secret, cert []byte) error { + op, err := controllerutil.CreateOrUpdate(ctx, r.Client, secret, func() error { + if secret.Data == nil { + secret.Data = map[string][]byte{} + } + secret.Data[corev1.TLSCertKey] = cert + return nil + }) + if err != nil { + return err + } + r.Log.Info(fmt.Sprintf("Secret %s", op), "name", secret.Name, "namespace", secret.Namespace) + return nil +} + func (r *Reconciler) deleteCert(ctx context.Context, cert *certv1.Certificate) error { err := r.Client.Delete(ctx, cert) if err != nil && !kerrors.IsNotFound(err) { diff --git a/internal/controllers/clustercryostat_controller.go b/internal/controllers/clustercryostat_controller.go index a79da08ee..a33b23a62 100644 --- a/internal/controllers/clustercryostat_controller.go +++ b/internal/controllers/clustercryostat_controller.go @@ -19,7 +19,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" - operatorv1beta1 "github.com/cryostatio/cryostat-operator/api/v1beta1" + operatorv1beta2 "github.com/cryostatio/cryostat-operator/api/v1beta2" "github.com/cryostatio/cryostat-operator/internal/controllers/model" kerrors "k8s.io/apimachinery/pkg/api/errors" @@ -39,7 +39,7 @@ type ClusterCryostatReconciler struct { } func NewClusterCryostatReconciler(config *ReconcilerConfig) (*ClusterCryostatReconciler, error) { - delegate, err := newReconciler(config, &operatorv1beta1.ClusterCryostat{}, false) + delegate, err := newReconciler(config, &operatorv1beta2.ClusterCryostat{}, false) if err != nil { return nil, err } @@ -76,7 +76,7 @@ func (r *ClusterCryostatReconciler) Reconcile(ctx context.Context, request ctrl. reqLogger.Info("Reconciling ClusterCryostat") // Fetch the Cryostat instance - cr := &operatorv1beta1.ClusterCryostat{} + cr := &operatorv1beta2.ClusterCryostat{} err := r.Client.Get(ctx, request.NamespacedName, cr) if err != nil { if kerrors.IsNotFound(err) { diff --git a/internal/controllers/clustercryostat_controller_test.go b/internal/controllers/clustercryostat_controller_test.go index a5227600a..249d55e87 100644 --- a/internal/controllers/clustercryostat_controller_test.go +++ b/internal/controllers/clustercryostat_controller_test.go @@ -15,14 +15,8 @@ package controllers_test import ( - "context" - "github.com/cryostatio/cryostat-operator/internal/controllers" . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/types" ) var _ = Describe("ClusterCryostatController", func() { @@ -32,108 +26,8 @@ var _ = Describe("ClusterCryostatController", func() { } c.commonTests() - - Context("reconciling a multi-namespace request", func() { - var t *cryostatTestInput - targetNamespaces := []string{"multi-test-one", "multi-test-two"} - - BeforeEach(func() { - t = c.commonBeforeEach() - t.TargetNamespaces = targetNamespaces - t.objs = append(t.objs, t.NewCryostat().Object) - // Create Namespaces - saveNS := t.Namespace - for _, ns := range targetNamespaces { - t.Namespace = ns - t.objs = append(t.objs, t.NewNamespace()) - } - t.Namespace = saveNS - }) - - JustBeforeEach(func() { - c.commonJustBeforeEach(t) - t.reconcileCryostatFully() - }) - - JustAfterEach(func() { - c.commonJustAfterEach(t) - }) - - It("should create the expected main deployment", func() { - t.expectMainDeployment() - }) - - It("should create CA Cert secret in each namespace", func() { - t.expectCertificates() - }) - - It("should create RBAC in each namespace", func() { - t.expectRBAC() - }) - - It("should update the target namespaces in Status", func() { - t.expectTargetNamespaces() - }) - - Context("with removed target namespaces", func() { - BeforeEach(func() { - t = c.commonBeforeEach() - // Begin with RBAC set up for two namespaces, - // and remove the second namespace from the spec - t.TargetNamespaces = targetNamespaces[:1] - cr := t.NewCryostat() - *cr.TargetNamespaceStatus = targetNamespaces - t.objs = append(t.objs, cr.Object, - t.NewRoleBinding(targetNamespaces[0]), - t.NewRoleBinding(targetNamespaces[1]), - t.NewCACertSecret(targetNamespaces[0]), - t.NewCACertSecret(targetNamespaces[1])) - }) - It("should create the expected main deployment", func() { - t.expectMainDeployment() - }) - It("leave RBAC for the first namespace", func() { - t.expectRBAC() - }) - It("should remove RBAC from the second namespace", func() { - binding := t.NewRoleBinding(targetNamespaces[1]) - err := t.Client.Get(context.Background(), types.NamespacedName{Name: binding.Name, Namespace: binding.Namespace}, binding) - Expect(err).ToNot(BeNil()) - Expect(errors.IsNotFound(err)).To(BeTrue()) - }) - It("leave CA Cert secret for the first namespace", func() { - t.expectCertificates() - }) - It("should remove CA Cert secret from the second namespace", func() { - caCert := t.NewCACert() - secret := &corev1.Secret{} - err := t.Client.Get(context.Background(), types.NamespacedName{Name: caCert.Name, Namespace: targetNamespaces[1]}, secret) - Expect(err).ToNot(BeNil()) - Expect(errors.IsNotFound(err)).To(BeTrue()) - }) - It("should update the target namespaces in Status", func() { - t.expectTargetNamespaces() - }) - }) - - Context("with no target namespaces", func() { - BeforeEach(func() { - t = c.commonBeforeEach() - t.TargetNamespaces = nil - t.objs = append(t.objs, t.NewCryostat().Object) - }) - It("should update the target namespaces in Status", func() { - t.expectTargetNamespaces() - }) - }) - }) }) -func (t *cryostatTestInput) expectTargetNamespaces() { - cr := t.getCryostatInstance() - Expect(*cr.TargetNamespaceStatus).To(ConsistOf(t.TargetNamespaces)) -} - func newClusterCryostatController(config *controllers.ReconcilerConfig) (controllers.CommonReconciler, error) { return controllers.NewClusterCryostatReconciler(config) } diff --git a/internal/controllers/common/common_utils.go b/internal/controllers/common/common_utils.go index 454d349f3..6258a4bfd 100644 --- a/internal/controllers/common/common_utils.go +++ b/internal/controllers/common/common_utils.go @@ -66,10 +66,21 @@ func (o *DefaultOSUtils) GenPasswd(length int) string { // ClusterUniqueName returns a name for cluster-scoped objects that is // uniquely identified by a namespace and name. func ClusterUniqueName(gvk *schema.GroupVersionKind, name string, namespace string) string { + return ClusterUniqueNameWithPrefix(gvk, "", name, namespace) +} + +// ClusterUniqueName returns a name for cluster-scoped objects that is +// uniquely identified by a namespace and name. Appends the prefix to the +// provided Kind. +func ClusterUniqueNameWithPrefix(gvk *schema.GroupVersionKind, prefix string, name string, namespace string) string { + prefixWithKind := strings.ToLower(gvk.Kind) + if len(prefix) > 0 { + prefixWithKind += "-" + prefix + } // Use the SHA256 checksum of the namespaced name as a suffix nn := types.NamespacedName{Namespace: namespace, Name: name} suffix := fmt.Sprintf("%x", sha256.Sum256([]byte(nn.String()))) - return strings.ToLower(gvk.Kind) + "-" + suffix + return prefixWithKind + "-" + suffix } // MergeLabelsAndAnnotations copies labels and annotations from a source diff --git a/internal/controllers/common/resource_definitions/certificates.go b/internal/controllers/common/resource_definitions/certificates.go index 3d3dd0769..33b8ae183 100644 --- a/internal/controllers/common/resource_definitions/certificates.go +++ b/internal/controllers/common/resource_definitions/certificates.go @@ -19,9 +19,11 @@ import ( certv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" certMeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" + "github.com/cryostatio/cryostat-operator/internal/controllers/common" "github.com/cryostatio/cryostat-operator/internal/controllers/constants" "github.com/cryostatio/cryostat-operator/internal/controllers/model" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" ) func NewSelfSignedIssuer(cr *model.CryostatInstance) *certv1.Issuer { @@ -38,7 +40,7 @@ func NewSelfSignedIssuer(cr *model.CryostatInstance) *certv1.Issuer { } } -func NewCryostatCAIssuer(cr *model.CryostatInstance) *certv1.Issuer { +func NewCryostatCAIssuer(gvk *schema.GroupVersionKind, cr *model.CryostatInstance) *certv1.Issuer { return &certv1.Issuer{ ObjectMeta: metav1.ObjectMeta{ Name: cr.Name + "-ca", @@ -47,14 +49,14 @@ func NewCryostatCAIssuer(cr *model.CryostatInstance) *certv1.Issuer { Spec: certv1.IssuerSpec{ IssuerConfig: certv1.IssuerConfig{ CA: &certv1.CAIssuer{ - SecretName: cr.Name + "-ca", + SecretName: NewCryostatCACert(gvk, cr).Spec.SecretName, }, }, }, } } -func NewCryostatCACert(cr *model.CryostatInstance) *certv1.Certificate { +func NewCryostatCACert(gvk *schema.GroupVersionKind, cr *model.CryostatInstance) *certv1.Certificate { return &certv1.Certificate{ ObjectMeta: metav1.ObjectMeta{ Name: cr.Name + "-ca", @@ -62,7 +64,7 @@ func NewCryostatCACert(cr *model.CryostatInstance) *certv1.Certificate { }, Spec: certv1.CertificateSpec{ CommonName: fmt.Sprintf("ca.%s.cert-manager", cr.Name), - SecretName: cr.Name + "-ca", + SecretName: common.ClusterUniqueNameWithPrefix(gvk, "ca", cr.Name, cr.InstallNamespace), IssuerRef: certMeta.ObjectReference{ Name: cr.Name + "-self-signed", }, diff --git a/internal/controllers/cryostat_controller.go b/internal/controllers/cryostat_controller.go index 554f16e2d..97125870b 100644 --- a/internal/controllers/cryostat_controller.go +++ b/internal/controllers/cryostat_controller.go @@ -19,7 +19,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" - operatorv1beta1 "github.com/cryostatio/cryostat-operator/api/v1beta1" + operatorv1beta2 "github.com/cryostatio/cryostat-operator/api/v1beta2" "github.com/cryostatio/cryostat-operator/internal/controllers/model" kerrors "k8s.io/apimachinery/pkg/api/errors" @@ -36,7 +36,7 @@ type CryostatReconciler struct { } func NewCryostatReconciler(config *ReconcilerConfig) (*CryostatReconciler, error) { - delegate, err := newReconciler(config, &operatorv1beta1.Cryostat{}, true) + delegate, err := newReconciler(config, &operatorv1beta2.Cryostat{}, true) if err != nil { return nil, err } @@ -57,7 +57,7 @@ func (r *CryostatReconciler) Reconcile(ctx context.Context, request ctrl.Request reqLogger.Info("Reconciling Cryostat") // Fetch the Cryostat instance - cr := &operatorv1beta1.Cryostat{} + cr := &operatorv1beta2.Cryostat{} err := r.Client.Get(ctx, request.NamespacedName, cr) if err != nil { if kerrors.IsNotFound(err) { diff --git a/internal/controllers/ingresses.go b/internal/controllers/ingresses.go index cadb91562..33cde225a 100644 --- a/internal/controllers/ingresses.go +++ b/internal/controllers/ingresses.go @@ -19,7 +19,7 @@ import ( "fmt" "net/url" - operatorv1beta1 "github.com/cryostatio/cryostat-operator/api/v1beta1" + operatorv1beta2 "github.com/cryostatio/cryostat-operator/api/v1beta2" common "github.com/cryostatio/cryostat-operator/internal/controllers/common" "github.com/cryostatio/cryostat-operator/internal/controllers/common/resource_definitions" "github.com/cryostatio/cryostat-operator/internal/controllers/model" @@ -77,7 +77,7 @@ func (r *Reconciler) reconcileGrafanaIngress(ctx context.Context, cr *model.Cryo } func (r *Reconciler) reconcileIngress(ctx context.Context, ingress *netv1.Ingress, cr *model.CryostatInstance, - config *operatorv1beta1.NetworkConfiguration) (*url.URL, error) { + config *operatorv1beta2.NetworkConfiguration) (*url.URL, error) { ingress, err := r.createOrUpdateIngress(ctx, ingress, cr.Object, config) if err != nil { return nil, err @@ -99,7 +99,7 @@ func (r *Reconciler) reconcileIngress(ctx context.Context, ingress *netv1.Ingres } func (r *Reconciler) createOrUpdateIngress(ctx context.Context, ingress *netv1.Ingress, owner metav1.Object, - config *operatorv1beta1.NetworkConfiguration) (*netv1.Ingress, error) { + config *operatorv1beta2.NetworkConfiguration) (*netv1.Ingress, error) { op, err := controllerutil.CreateOrUpdate(ctx, r.Client, ingress, func() error { // Set labels and annotations from CR common.MergeLabelsAndAnnotations(&ingress.ObjectMeta, config.Labels, config.Annotations) @@ -119,31 +119,31 @@ func (r *Reconciler) createOrUpdateIngress(ctx context.Context, ingress *netv1.I return ingress, nil } -func configureCoreIngress(cr *model.CryostatInstance) *operatorv1beta1.NetworkConfiguration { - var config *operatorv1beta1.NetworkConfiguration +func configureCoreIngress(cr *model.CryostatInstance) *operatorv1beta2.NetworkConfiguration { + var config *operatorv1beta2.NetworkConfiguration if cr.Spec.NetworkOptions == nil || cr.Spec.NetworkOptions.CoreConfig == nil { - config = &operatorv1beta1.NetworkConfiguration{} + config = &operatorv1beta2.NetworkConfiguration{} } else { config = cr.Spec.NetworkOptions.CoreConfig } - configureRoute(config, cr.Name, "cryostat") + configureIngress(config, cr.Name, "cryostat") return config } -func configureGrafanaIngress(cr *model.CryostatInstance) *operatorv1beta1.NetworkConfiguration { - var config *operatorv1beta1.NetworkConfiguration +func configureGrafanaIngress(cr *model.CryostatInstance) *operatorv1beta2.NetworkConfiguration { + var config *operatorv1beta2.NetworkConfiguration if cr.Spec.NetworkOptions == nil || cr.Spec.NetworkOptions.GrafanaConfig == nil { - config = &operatorv1beta1.NetworkConfiguration{} + config = &operatorv1beta2.NetworkConfiguration{} } else { config = cr.Spec.NetworkOptions.GrafanaConfig } - configureRoute(config, cr.Name, "cryostat") + configureIngress(config, cr.Name, "cryostat") return config } -func configureIngress(config *operatorv1beta1.NetworkConfiguration, appLabel string, componentLabel string) { +func configureIngress(config *operatorv1beta2.NetworkConfiguration, appLabel string, componentLabel string) { if config.Labels == nil { config.Labels = map[string]string{} } diff --git a/internal/controllers/model/instance.go b/internal/controllers/model/instance.go index 32dce7a62..04bcf50cf 100644 --- a/internal/controllers/model/instance.go +++ b/internal/controllers/model/instance.go @@ -15,7 +15,7 @@ package model import ( - operatorv1beta1 "github.com/cryostatio/cryostat-operator/api/v1beta1" + operatorv1beta2 "github.com/cryostatio/cryostat-operator/api/v1beta2" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -35,21 +35,20 @@ type CryostatInstance struct { // For ClusterCryostat, this is a reference to status.TargetNamespaces. TargetNamespaceStatus *[]string // Reference to the common Spec properties to both CRD types. - Spec *operatorv1beta1.CryostatSpec + Spec *operatorv1beta2.CryostatSpec // Reference to the common Status properties to both CRD types. - Status *operatorv1beta1.CryostatStatus + Status *operatorv1beta2.CryostatStatus // The actual CR instance as a generic Kubernetes object. Object client.Object } // FromCryostat creates a CryostatInstance from a Cryostat CR -func FromCryostat(cr *operatorv1beta1.Cryostat) *CryostatInstance { - targetNS := []string{cr.Namespace} +func FromCryostat(cr *operatorv1beta2.Cryostat) *CryostatInstance { return &CryostatInstance{ Name: cr.Name, InstallNamespace: cr.Namespace, - TargetNamespaces: targetNS, - TargetNamespaceStatus: &targetNS, + TargetNamespaces: cr.Spec.TargetNamespaces, + TargetNamespaceStatus: &cr.Status.TargetNamespaces, Spec: &cr.Spec, Status: &cr.Status, @@ -59,7 +58,8 @@ func FromCryostat(cr *operatorv1beta1.Cryostat) *CryostatInstance { } // FromClusterCryostat creates a CryostatInstance from a ClusterCryostat CR -func FromClusterCryostat(cr *operatorv1beta1.ClusterCryostat) *CryostatInstance { +func FromClusterCryostat(cr *operatorv1beta2.ClusterCryostat) *CryostatInstance { + // TODO Remove this CRD return &CryostatInstance{ Name: cr.Name, InstallNamespace: cr.Spec.InstallNamespace, diff --git a/internal/controllers/pvc.go b/internal/controllers/pvc.go index 33ee2538b..96c3cb1b9 100644 --- a/internal/controllers/pvc.go +++ b/internal/controllers/pvc.go @@ -18,7 +18,7 @@ import ( "context" "fmt" - operatorv1beta1 "github.com/cryostatio/cryostat-operator/api/v1beta1" + operatorv1beta2 "github.com/cryostatio/cryostat-operator/api/v1beta2" "github.com/cryostatio/cryostat-operator/internal/controllers/common" "github.com/cryostatio/cryostat-operator/internal/controllers/model" corev1 "k8s.io/api/core/v1" @@ -62,7 +62,7 @@ func (r *Reconciler) reconcilePVC(ctx context.Context, cr *model.CryostatInstanc } func (r *Reconciler) createOrUpdatePVC(ctx context.Context, pvc *corev1.PersistentVolumeClaim, - owner metav1.Object, config *operatorv1beta1.PersistentVolumeClaimConfig) error { + owner metav1.Object, config *operatorv1beta2.PersistentVolumeClaimConfig) error { op, err := controllerutil.CreateOrUpdate(ctx, r.Client, pvc, func() error { // Merge labels and annotations to prevent overriding any set by Kubernetes common.MergeLabelsAndAnnotations(&pvc.ObjectMeta, config.Labels, config.Annotations) @@ -94,11 +94,11 @@ func (r *Reconciler) createOrUpdatePVC(ctx context.Context, pvc *corev1.Persiste return nil } -func configurePVC(cr *model.CryostatInstance) *operatorv1beta1.PersistentVolumeClaimConfig { +func configurePVC(cr *model.CryostatInstance) *operatorv1beta2.PersistentVolumeClaimConfig { // Check for PVC config within CR - var config *operatorv1beta1.PersistentVolumeClaimConfig + var config *operatorv1beta2.PersistentVolumeClaimConfig if cr.Spec.StorageOptions == nil || cr.Spec.StorageOptions.PVC == nil { - config = &operatorv1beta1.PersistentVolumeClaimConfig{} + config = &operatorv1beta2.PersistentVolumeClaimConfig{} } else { config = cr.Spec.StorageOptions.PVC.DeepCopy() } diff --git a/internal/controllers/rbac.go b/internal/controllers/rbac.go index 92ab4eab6..cd4cb4a6b 100644 --- a/internal/controllers/rbac.go +++ b/internal/controllers/rbac.go @@ -53,7 +53,11 @@ func (r *Reconciler) reconcileRBAC(ctx context.Context, cr *model.CryostatInstan } func (r *Reconciler) finalizeRBAC(ctx context.Context, cr *model.CryostatInstance) error { - return r.deleteClusterRoleBinding(ctx, r.newClusterRoleBinding(cr)) + err := r.deleteClusterRoleBinding(ctx, r.newClusterRoleBinding(cr)) + if err != nil { + return err + } + return r.finalizeRoleBindings(ctx, cr) } func newServiceAccount(cr *model.CryostatInstance) *corev1.ServiceAccount { @@ -106,10 +110,10 @@ func (r *Reconciler) reconcileRole(ctx context.Context, cr *model.CryostatInstan return r.cleanUpRole(ctx, cr, newRole(cr)) } -func newRoleBinding(cr *model.CryostatInstance, namespace string) *rbacv1.RoleBinding { +func (r *Reconciler) newRoleBinding(cr *model.CryostatInstance, namespace string) *rbacv1.RoleBinding { return &rbacv1.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ - Name: cr.Name, + Name: common.ClusterUniqueName(r.gvk, cr.Name, cr.InstallNamespace), Namespace: namespace, }, } @@ -127,7 +131,7 @@ func (r *Reconciler) reconcileRoleBinding(ctx context.Context, cr *model.Cryosta // Create a RoleBinding in each target namespace for _, ns := range cr.TargetNamespaces { - binding := newRoleBinding(cr, ns) + binding := r.newRoleBinding(cr, ns) roleRef := &rbacv1.RoleRef{ APIGroup: "rbac.authorization.k8s.io", Kind: "ClusterRole", @@ -140,7 +144,7 @@ func (r *Reconciler) reconcileRoleBinding(ctx context.Context, cr *model.Cryosta } // Delete any RoleBindings in target namespaces that are no longer requested for _, ns := range toDelete(cr) { - binding := newRoleBinding(cr, ns) + binding := r.newRoleBinding(cr, ns) err := r.deleteRoleBinding(ctx, binding) if err != nil { return err @@ -150,6 +154,17 @@ func (r *Reconciler) reconcileRoleBinding(ctx context.Context, cr *model.Cryosta return nil } +func (r *Reconciler) finalizeRoleBindings(ctx context.Context, cr *model.CryostatInstance) error { + for _, ns := range cr.TargetNamespaces { + binding := r.newRoleBinding(cr, ns) + err := r.deleteRoleBinding(ctx, binding) + if err != nil { + return err + } + } + return nil +} + func (r *Reconciler) newClusterRoleBinding(cr *model.CryostatInstance) *rbacv1.ClusterRoleBinding { return &rbacv1.ClusterRoleBinding{ ObjectMeta: metav1.ObjectMeta{ @@ -237,11 +252,6 @@ func (r *Reconciler) createOrUpdateRoleBinding(ctx context.Context, binding *rba return err } binding.RoleRef = *roleRef - - // Set the Cryostat CR as controller - if err := controllerutil.SetControllerReference(owner, binding, r.Scheme); err != nil { - return err - } return nil }) if err != nil { diff --git a/internal/controllers/reconciler_test.go b/internal/controllers/reconciler_test.go index 4241d0ae4..ec636d386 100644 --- a/internal/controllers/reconciler_test.go +++ b/internal/controllers/reconciler_test.go @@ -45,7 +45,7 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/reconcile" - operatorv1beta1 "github.com/cryostatio/cryostat-operator/api/v1beta1" + operatorv1beta2 "github.com/cryostatio/cryostat-operator/api/v1beta2" "github.com/cryostatio/cryostat-operator/internal/controllers" "github.com/cryostatio/cryostat-operator/internal/controllers/model" "github.com/cryostatio/cryostat-operator/internal/test" @@ -170,7 +170,7 @@ func expectSuccessful(t **cryostatTestInput) { (*t).expectStatusGrafanaSecretName((*t).NewGrafanaSecret().Name) }) It("should set TLSSetupComplete condition", func() { - (*t).checkConditionPresent(operatorv1beta1.ConditionTypeTLSSetupComplete, metav1.ConditionTrue, + (*t).checkConditionPresent(operatorv1beta2.ConditionTypeTLSSetupComplete, metav1.ConditionTrue, "AllCertificatesReady") }) Context("deployment is progressing", func() { @@ -178,22 +178,22 @@ func expectSuccessful(t **cryostatTestInput) { (*t).makeDeploymentProgress((*t).Name) }) It("should update conditions", func() { - (*t).checkConditionPresent(operatorv1beta1.ConditionTypeMainDeploymentAvailable, metav1.ConditionFalse, + (*t).checkConditionPresent(operatorv1beta2.ConditionTypeMainDeploymentAvailable, metav1.ConditionFalse, "TestAvailable") - (*t).checkConditionPresent(operatorv1beta1.ConditionTypeMainDeploymentProgressing, metav1.ConditionTrue, + (*t).checkConditionPresent(operatorv1beta2.ConditionTypeMainDeploymentProgressing, metav1.ConditionTrue, "TestProgressing") - (*t).checkConditionAbsent(operatorv1beta1.ConditionTypeMainDeploymentReplicaFailure) + (*t).checkConditionAbsent(operatorv1beta2.ConditionTypeMainDeploymentReplicaFailure) }) Context("then becomes available", func() { JustBeforeEach(func() { (*t).makeDeploymentAvailable((*t).Name) }) It("should update conditions", func() { - (*t).checkConditionPresent(operatorv1beta1.ConditionTypeMainDeploymentAvailable, metav1.ConditionTrue, + (*t).checkConditionPresent(operatorv1beta2.ConditionTypeMainDeploymentAvailable, metav1.ConditionTrue, "TestAvailable") - (*t).checkConditionPresent(operatorv1beta1.ConditionTypeMainDeploymentProgressing, metav1.ConditionTrue, + (*t).checkConditionPresent(operatorv1beta2.ConditionTypeMainDeploymentProgressing, metav1.ConditionTrue, "TestProgressing") - (*t).checkConditionAbsent(operatorv1beta1.ConditionTypeMainDeploymentReplicaFailure) + (*t).checkConditionAbsent(operatorv1beta2.ConditionTypeMainDeploymentReplicaFailure) }) }) Context("then fails to roll out", func() { @@ -201,11 +201,11 @@ func expectSuccessful(t **cryostatTestInput) { (*t).makeDeploymentFail((*t).Name) }) It("should update conditions", func() { - (*t).checkConditionPresent(operatorv1beta1.ConditionTypeMainDeploymentAvailable, metav1.ConditionFalse, + (*t).checkConditionPresent(operatorv1beta2.ConditionTypeMainDeploymentAvailable, metav1.ConditionFalse, "TestAvailable") - (*t).checkConditionPresent(operatorv1beta1.ConditionTypeMainDeploymentProgressing, metav1.ConditionFalse, + (*t).checkConditionPresent(operatorv1beta2.ConditionTypeMainDeploymentProgressing, metav1.ConditionFalse, "TestProgressing") - (*t).checkConditionPresent(operatorv1beta1.ConditionTypeMainDeploymentReplicaFailure, metav1.ConditionTrue, + (*t).checkConditionPresent(operatorv1beta2.ConditionTypeMainDeploymentReplicaFailure, metav1.ConditionTrue, "TestReplicaFailure") }) }) @@ -471,18 +471,16 @@ func (c *controllerTest) commonTests() { t.reconcileCryostatFully() }) It("should update the Role Binding", func() { + expected := t.NewRoleBinding(t.Namespace) binding := &rbacv1.RoleBinding{} - err := t.Client.Get(context.Background(), types.NamespacedName{Name: t.Name, Namespace: t.Namespace}, binding) + err := t.Client.Get(context.Background(), types.NamespacedName{Name: expected.Name, Namespace: expected.Namespace}, binding) Expect(err).ToNot(HaveOccurred()) - Expect(metav1.IsControlledBy(binding, cr.Object)).To(BeTrue()) - // Labels are unaffected Expect(binding.Labels).To(Equal(oldBinding.Labels)) Expect(binding.Annotations).To(Equal(oldBinding.Annotations)) // Subjects and RoleRef should be fully replaced - expected := t.NewRoleBinding(t.Namespace) Expect(binding.Subjects).To(Equal(expected.Subjects)) Expect(binding.RoleRef).To(Equal(expected.RoleRef)) }) @@ -752,22 +750,22 @@ func (c *controllerTest) commonTests() { t.makeDeploymentProgress(t.Name + "-reports") }) It("should update conditions", func() { - t.checkConditionPresent(operatorv1beta1.ConditionTypeReportsDeploymentAvailable, metav1.ConditionFalse, + t.checkConditionPresent(operatorv1beta2.ConditionTypeReportsDeploymentAvailable, metav1.ConditionFalse, "TestAvailable") - t.checkConditionPresent(operatorv1beta1.ConditionTypeReportsDeploymentProgressing, metav1.ConditionTrue, + t.checkConditionPresent(operatorv1beta2.ConditionTypeReportsDeploymentProgressing, metav1.ConditionTrue, "TestProgressing") - t.checkConditionAbsent(operatorv1beta1.ConditionTypeReportsDeploymentReplicaFailure) + t.checkConditionAbsent(operatorv1beta2.ConditionTypeReportsDeploymentReplicaFailure) }) Context("then becomes available", func() { JustBeforeEach(func() { t.makeDeploymentAvailable(t.Name + "-reports") }) It("should update conditions", func() { - t.checkConditionPresent(operatorv1beta1.ConditionTypeReportsDeploymentAvailable, metav1.ConditionTrue, + t.checkConditionPresent(operatorv1beta2.ConditionTypeReportsDeploymentAvailable, metav1.ConditionTrue, "TestAvailable") - t.checkConditionPresent(operatorv1beta1.ConditionTypeReportsDeploymentProgressing, metav1.ConditionTrue, + t.checkConditionPresent(operatorv1beta2.ConditionTypeReportsDeploymentProgressing, metav1.ConditionTrue, "TestProgressing") - t.checkConditionAbsent(operatorv1beta1.ConditionTypeReportsDeploymentReplicaFailure) + t.checkConditionAbsent(operatorv1beta2.ConditionTypeReportsDeploymentReplicaFailure) }) }) Context("then fails to roll out", func() { @@ -775,11 +773,11 @@ func (c *controllerTest) commonTests() { t.makeDeploymentFail(t.Name + "-reports") }) It("should update conditions", func() { - t.checkConditionPresent(operatorv1beta1.ConditionTypeReportsDeploymentAvailable, metav1.ConditionFalse, + t.checkConditionPresent(operatorv1beta2.ConditionTypeReportsDeploymentAvailable, metav1.ConditionFalse, "TestAvailable") - t.checkConditionPresent(operatorv1beta1.ConditionTypeReportsDeploymentProgressing, metav1.ConditionFalse, + t.checkConditionPresent(operatorv1beta2.ConditionTypeReportsDeploymentProgressing, metav1.ConditionFalse, "TestProgressing") - t.checkConditionPresent(operatorv1beta1.ConditionTypeReportsDeploymentReplicaFailure, metav1.ConditionTrue, + t.checkConditionPresent(operatorv1beta2.ConditionTypeReportsDeploymentReplicaFailure, metav1.ConditionTrue, "TestReplicaFailure") }) }) @@ -795,7 +793,7 @@ func (c *controllerTest) commonTests() { cryostat := t.getCryostatInstance() t.ReportReplicas = 1 - cryostat.Spec.ReportOptions = &operatorv1beta1.ReportConfiguration{ + cryostat.Spec.ReportOptions = &operatorv1beta2.ReportConfiguration{ Replicas: t.ReportReplicas, } t.updateCryostatInstance(cryostat) @@ -875,9 +873,9 @@ func (c *controllerTest) commonTests() { t.expectNoReportsDeployment() }) It("should remove conditions", func() { - t.checkConditionAbsent(operatorv1beta1.ConditionTypeReportsDeploymentAvailable) - t.checkConditionAbsent(operatorv1beta1.ConditionTypeReportsDeploymentProgressing) - t.checkConditionAbsent(operatorv1beta1.ConditionTypeReportsDeploymentReplicaFailure) + t.checkConditionAbsent(operatorv1beta2.ConditionTypeReportsDeploymentAvailable) + t.checkConditionAbsent(operatorv1beta2.ConditionTypeReportsDeploymentProgressing) + t.checkConditionAbsent(operatorv1beta2.ConditionTypeReportsDeploymentReplicaFailure) }) }) Context("Cryostat CR has list of certificate secrets", func() { @@ -1396,7 +1394,7 @@ func (c *controllerTest) commonTests() { }) It("should set TLSSetupComplete condition", func() { t.reconcileCryostatFully() - t.checkConditionPresent(operatorv1beta1.ConditionTypeTLSSetupComplete, metav1.ConditionTrue, + t.checkConditionPresent(operatorv1beta2.ConditionTypeTLSSetupComplete, metav1.ConditionTrue, "AllCertificatesReady") }) }) @@ -1425,7 +1423,7 @@ func (c *controllerTest) commonTests() { }) It("should set TLSSetupComplete Condition", func() { t.reconcileCryostatFully() - t.checkConditionPresent(operatorv1beta1.ConditionTypeTLSSetupComplete, metav1.ConditionTrue, + t.checkConditionPresent(operatorv1beta2.ConditionTypeTLSSetupComplete, metav1.ConditionTrue, "CertManagerDisabled") }) }) @@ -1452,7 +1450,7 @@ func (c *controllerTest) commonTests() { t.expectRoutes() }) It("should set TLSSetupComplete Condition", func() { - t.checkConditionPresent(operatorv1beta1.ConditionTypeTLSSetupComplete, metav1.ConditionTrue, + t.checkConditionPresent(operatorv1beta2.ConditionTypeTLSSetupComplete, metav1.ConditionTrue, "CertManagerDisabled") }) }) @@ -1483,7 +1481,7 @@ func (c *controllerTest) commonTests() { t.expectRoutes() }) It("should set TLSSetupComplete condition", func() { - t.checkConditionPresent(operatorv1beta1.ConditionTypeTLSSetupComplete, metav1.ConditionTrue, + t.checkConditionPresent(operatorv1beta2.ConditionTypeTLSSetupComplete, metav1.ConditionTrue, "AllCertificatesReady") }) }) @@ -1507,7 +1505,7 @@ func (c *controllerTest) commonTests() { Expect(eventMsg).To(ContainSubstring("CertManagerUnavailable")) }) It("should set TLSSetupComplete Condition", func() { - t.checkConditionPresent(operatorv1beta1.ConditionTypeTLSSetupComplete, metav1.ConditionFalse, + t.checkConditionPresent(operatorv1beta2.ConditionTypeTLSSetupComplete, metav1.ConditionFalse, "CertManagerUnavailable") }) }) @@ -1525,7 +1523,7 @@ func (c *controllerTest) commonTests() { Expect(recorder.Events).ToNot(Receive()) }) It("should set TLSSetupComplete Condition", func() { - t.checkConditionPresent(operatorv1beta1.ConditionTypeTLSSetupComplete, metav1.ConditionTrue, + t.checkConditionPresent(operatorv1beta2.ConditionTypeTLSSetupComplete, metav1.ConditionTrue, "CertManagerDisabled") }) }) @@ -1811,8 +1809,6 @@ func (c *controllerTest) commonTests() { // Reconcile conflicting namespaced Cryostat fully otherInput.reconcileCryostatFully() - // Try reconciling ClusterCryostat - reconcileErr = t.reconcileCryostatFullyWithError() }) JustAfterEach(func() { @@ -1828,6 +1824,11 @@ func (c *controllerTest) commonTests() { otherInput.objs = t.objs }) + JustBeforeEach(func() { + // Try reconciling ClusterCryostat + reconcileErr = t.reconcileCryostatFullyWithError() + }) + It("should fail to reconcile", func() { t.expectAlreadyOwnedError(reconcileErr, "ConfigMap", t.NewLockConfigMap(), otherInput) }) @@ -1881,16 +1882,107 @@ func (c *controllerTest) commonTests() { otherInput.objs = t.objs }) - It("should fail to reconcile", func() { - t.expectAlreadyOwnedError(reconcileErr, "RoleBinding", t.NewRoleBinding(nsInput.Namespace), otherInput) + JustBeforeEach(func() { + // Try reconciling ClusterCryostat + t.reconcileCryostatFully() }) - It("should emit a CryostatNameConflict event", func() { - t.expectNameConflictEvent() + // Existing Cryostat installation should be unaffected + Context("existing installation", func() { + expectSuccessful(&otherInput) }) - // Existing Cryostat installation should be unaffected - expectSuccessful(&otherInput) + // New installation should also be unaffected + Context("new installation", func() { + expectSuccessful(&otherInput) + }) + }) + }) + + Context("reconciling a multi-namespace request", func() { + targetNamespaces := []string{"multi-test-one", "multi-test-two"} + + BeforeEach(func() { + // Create Namespaces + for _, ns := range targetNamespaces { + t.objs = append(t.objs, t.NewOtherNamespace(ns)) + } + }) + + JustBeforeEach(func() { + t.reconcileCryostatFully() + }) + + Context("with unchanged target namespaces", func() { + BeforeEach(func() { + t.TargetNamespaces = targetNamespaces + t.objs = append(t.objs, t.NewCryostat().Object) + }) + + It("should create the expected main deployment", func() { + t.expectMainDeployment() + }) + + It("should create CA Cert secret in each namespace", func() { + t.expectCertificates() + }) + + It("should create RBAC in each namespace", func() { + t.expectRBAC() + }) + + It("should update the target namespaces in Status", func() { + t.expectTargetNamespaces() + }) + }) + + Context("with removed target namespaces", func() { + BeforeEach(func() { + // Begin with RBAC set up for two namespaces, + // and remove the second namespace from the spec + t.TargetNamespaces = targetNamespaces[:1] + cr := t.NewCryostat() + *cr.TargetNamespaceStatus = targetNamespaces + t.objs = append(t.objs, cr.Object, + t.NewRoleBinding(targetNamespaces[0]), + t.NewRoleBinding(targetNamespaces[1]), + t.NewCACertSecret(targetNamespaces[0]), + t.NewCACertSecret(targetNamespaces[1])) + }) + It("should create the expected main deployment", func() { + t.expectMainDeployment() + }) + It("leave RBAC for the first namespace", func() { + t.expectRBAC() + }) + It("should remove RBAC from the second namespace", func() { + binding := t.NewRoleBinding(targetNamespaces[1]) + err := t.Client.Get(context.Background(), types.NamespacedName{Name: binding.Name, Namespace: binding.Namespace}, binding) + Expect(err).ToNot(BeNil()) + Expect(kerrors.IsNotFound(err)).To(BeTrue()) + }) + It("leave CA Cert secret for the first namespace", func() { + t.expectCertificates() + }) + It("should remove CA Cert secret from the second namespace", func() { + secret := t.NewCACertSecret(targetNamespaces[1]) + err := t.Client.Get(context.Background(), types.NamespacedName{Name: secret.Name, Namespace: secret.Namespace}, secret) + Expect(err).ToNot(BeNil()) + Expect(kerrors.IsNotFound(err)).To(BeTrue()) + }) + It("should update the target namespaces in Status", func() { + t.expectTargetNamespaces() + }) + }) + + Context("with no target namespaces", func() { + BeforeEach(func() { + t.TargetNamespaces = nil + t.objs = append(t.objs, t.NewCryostat().Object) + }) + It("should update the target namespaces in Status", func() { + t.expectTargetNamespaces() + }) }) }) }) @@ -2168,18 +2260,16 @@ func (c *controllerTest) commonTests() { It("should update the Role Binding", func() { t.reconcileCryostatFully() + expected := t.NewRoleBinding(t.Namespace) binding := &rbacv1.RoleBinding{} - err := t.Client.Get(context.Background(), types.NamespacedName{Name: t.Name, Namespace: t.Namespace}, binding) + err := t.Client.Get(context.Background(), types.NamespacedName{Name: expected.Name, Namespace: expected.Namespace}, binding) Expect(err).ToNot(HaveOccurred()) - Expect(metav1.IsControlledBy(binding, cr.Object)).To(BeTrue()) - // Labels are unaffected Expect(binding.Labels).To(Equal(oldBinding.Labels)) Expect(binding.Annotations).To(Equal(oldBinding.Annotations)) // Subjects and RoleRef should be fully replaced - expected := t.NewRoleBinding(t.Namespace) Expect(binding.Subjects).To(Equal(expected.Subjects)) Expect(binding.RoleRef).To(Equal(expected.RoleRef)) }) @@ -2246,7 +2336,7 @@ func (t *cryostatTestInput) checkRoute(expected *openshiftv1.Route) *openshiftv1 return route } -func (t *cryostatTestInput) checkConditionPresent(condType operatorv1beta1.CryostatConditionType, status metav1.ConditionStatus, reason string) { +func (t *cryostatTestInput) checkConditionPresent(condType operatorv1beta2.CryostatConditionType, status metav1.ConditionStatus, reason string) { cr := t.getCryostatInstance() condition := meta.FindStatusCondition(cr.Status.Conditions, string(condType)) @@ -2255,7 +2345,7 @@ func (t *cryostatTestInput) checkConditionPresent(condType operatorv1beta1.Cryos Expect(condition.Reason).To(Equal(reason)) } -func (t *cryostatTestInput) checkConditionAbsent(condType operatorv1beta1.CryostatConditionType) { +func (t *cryostatTestInput) checkConditionAbsent(condType operatorv1beta2.CryostatConditionType) { cr := t.getCryostatInstance() condition := meta.FindStatusCondition(cr.Status.Conditions, string(condType)) @@ -2296,12 +2386,16 @@ func (t *cryostatTestInput) reconcileDeletedCryostat() { } func (t *cryostatTestInput) checkMetadata(object metav1.Object, expected metav1.Object) { + t.checkMetadataNoOwner(object, expected) + Expect(object.GetOwnerReferences()).To(HaveLen(1)) + Expect(metav1.IsControlledBy(object, t.getCryostatInstance().Object)) +} + +func (t *cryostatTestInput) checkMetadataNoOwner(object metav1.Object, expected metav1.Object) { Expect(object.GetName()).To(Equal(expected.GetName())) Expect(object.GetNamespace()).To(Equal(expected.GetNamespace())) Expect(object.GetLabels()).To(Equal(expected.GetLabels())) Expect(object.GetAnnotations()).To(Equal(expected.GetAnnotations())) - Expect(object.GetOwnerReferences()).To(HaveLen(1)) - Expect(metav1.IsControlledBy(object, t.getCryostatInstance().Object)) } func (t *cryostatTestInput) expectNoCryostat() { @@ -2315,7 +2409,7 @@ func (t *cryostatTestInput) expectWaitingForCertificate() { Expect(result).To(Equal(reconcile.Result{RequeueAfter: 5 * time.Second})) // Check TLSSetupComplete condition - t.checkConditionPresent(operatorv1beta1.ConditionTypeTLSSetupComplete, metav1.ConditionFalse, + t.checkConditionPresent(operatorv1beta2.ConditionTypeTLSSetupComplete, metav1.ConditionFalse, "WaitingForCertificate") } @@ -2359,13 +2453,14 @@ func (t *cryostatTestInput) expectCertificates() { Expect(t.TargetNamespaces).ToNot(BeEmpty()) for _, ns := range t.TargetNamespaces { if ns != t.Namespace { - namespaceSecret := t.NewCACertSecret(ns) + expectedSecret := t.NewCACertSecret(ns) secret := &corev1.Secret{} - err := t.Client.Get(context.Background(), types.NamespacedName{Name: namespaceSecret.Name, Namespace: ns}, secret) + err := t.Client.Get(context.Background(), types.NamespacedName{Name: expectedSecret.Name, Namespace: ns}, secret) Expect(err).ToNot(HaveOccurred()) - t.checkMetadata(secret, namespaceSecret) - Expect(secret.Data).To(Equal(namespaceSecret.Data)) - Expect(secret.Type).To(Equal(namespaceSecret.Type)) + t.checkMetadataNoOwner(secret, expectedSecret) + Expect(secret.GetOwnerReferences()).To(BeEmpty()) + Expect(secret.Data).To(Equal(expectedSecret.Data)) + Expect(secret.Type).To(Equal(expectedSecret.Type)) } } } @@ -2383,11 +2478,12 @@ func (t *cryostatTestInput) expectRBAC() { // Check for Role and RoleBinding in each target namespace Expect(t.TargetNamespaces).ToNot(BeEmpty()) // Sanity check for tests for _, ns := range t.TargetNamespaces { + expectedBinding := t.NewRoleBinding(ns) binding := &rbacv1.RoleBinding{} - err = t.Client.Get(context.Background(), types.NamespacedName{Name: t.Name, Namespace: ns}, binding) + err = t.Client.Get(context.Background(), types.NamespacedName{Name: expectedBinding.Name, Namespace: expectedBinding.Namespace}, binding) Expect(err).ToNot(HaveOccurred()) - expectedBinding := t.NewRoleBinding(ns) - t.checkMetadata(binding, expectedBinding) + t.checkMetadataNoOwner(binding, expectedBinding) + Expect(binding.GetOwnerReferences()).To(BeEmpty()) Expect(binding.Subjects).To(Equal(expectedBinding.Subjects)) Expect(binding.RoleRef).To(Equal(expectedBinding.RoleRef)) } @@ -3024,14 +3120,14 @@ func (t *cryostatTestInput) getCryostatInstance() *model.CryostatInstance { func (t *cryostatTestInput) lookupCryostatInstance() (*model.CryostatInstance, error) { if t.ClusterScoped { - cr := &operatorv1beta1.ClusterCryostat{} + cr := &operatorv1beta2.ClusterCryostat{} err := t.Client.Get(context.Background(), types.NamespacedName{Name: t.Name}, cr) if err != nil { return nil, err } return t.ConvertClusterToModel(cr), nil } else { - cr := &operatorv1beta1.Cryostat{} + cr := &operatorv1beta2.Cryostat{} err := t.Client.Get(context.Background(), types.NamespacedName{Name: t.Name, Namespace: t.Namespace}, cr) if err != nil { return nil, err @@ -3098,6 +3194,11 @@ func (t *cryostatTestInput) expectResourcesUnaffected() { } } +func (t *cryostatTestInput) expectTargetNamespaces() { + cr := t.getCryostatInstance() + Expect(*cr.TargetNamespaceStatus).To(ConsistOf(t.TargetNamespaces)) +} + func getControllerFunc(clusterScoped bool) func(*controllers.ReconcilerConfig) (controllers.CommonReconciler, error) { if clusterScoped { return newClusterCryostatController diff --git a/internal/controllers/routes.go b/internal/controllers/routes.go index 97564639b..6f2a6145d 100644 --- a/internal/controllers/routes.go +++ b/internal/controllers/routes.go @@ -20,7 +20,7 @@ import ( "fmt" "net/url" - operatorv1beta1 "github.com/cryostatio/cryostat-operator/api/v1beta1" + operatorv1beta2 "github.com/cryostatio/cryostat-operator/api/v1beta2" common "github.com/cryostatio/cryostat-operator/internal/controllers/common" "github.com/cryostatio/cryostat-operator/internal/controllers/common/resource_definitions" "github.com/cryostatio/cryostat-operator/internal/controllers/constants" @@ -79,7 +79,7 @@ func (r *Reconciler) reconcileGrafanaRoute(ctx context.Context, svc *corev1.Serv var ErrIngressNotReady = goerrors.New("ingress configuration not yet available") func (r *Reconciler) reconcileRoute(ctx context.Context, route *routev1.Route, svc *corev1.Service, - cr *model.CryostatInstance, tls *resource_definitions.TLSConfig, config *operatorv1beta1.NetworkConfiguration) (*url.URL, error) { + cr *model.CryostatInstance, tls *resource_definitions.TLSConfig, config *operatorv1beta2.NetworkConfiguration) (*url.URL, error) { port, err := getHTTPPort(svc) if err != nil { return nil, err @@ -101,7 +101,7 @@ func (r *Reconciler) reconcileRoute(ctx context.Context, route *routev1.Route, s } func (r *Reconciler) createOrUpdateRoute(ctx context.Context, route *routev1.Route, owner metav1.Object, - svc *corev1.Service, exposePort *corev1.ServicePort, tlsConfig *resource_definitions.TLSConfig, config *operatorv1beta1.NetworkConfiguration) (*routev1.Route, error) { + svc *corev1.Service, exposePort *corev1.ServicePort, tlsConfig *resource_definitions.TLSConfig, config *operatorv1beta2.NetworkConfiguration) (*routev1.Route, error) { // Use edge termination by default var routeTLS *routev1.TLSConfig if tlsConfig == nil { @@ -165,10 +165,10 @@ func getHTTPPort(svc *corev1.Service) (*corev1.ServicePort, error) { return nil, fmt.Errorf("no \"%s\"port in %s service in %s namespace", constants.HttpPortName, svc.Name, svc.Namespace) } -func configureCoreRoute(cr *model.CryostatInstance) *operatorv1beta1.NetworkConfiguration { - var config *operatorv1beta1.NetworkConfiguration +func configureCoreRoute(cr *model.CryostatInstance) *operatorv1beta2.NetworkConfiguration { + var config *operatorv1beta2.NetworkConfiguration if cr.Spec.NetworkOptions == nil || cr.Spec.NetworkOptions.CoreConfig == nil { - config = &operatorv1beta1.NetworkConfiguration{} + config = &operatorv1beta2.NetworkConfiguration{} } else { config = cr.Spec.NetworkOptions.CoreConfig } @@ -177,10 +177,10 @@ func configureCoreRoute(cr *model.CryostatInstance) *operatorv1beta1.NetworkConf return config } -func configureGrafanaRoute(cr *model.CryostatInstance) *operatorv1beta1.NetworkConfiguration { - var config *operatorv1beta1.NetworkConfiguration +func configureGrafanaRoute(cr *model.CryostatInstance) *operatorv1beta2.NetworkConfiguration { + var config *operatorv1beta2.NetworkConfiguration if cr.Spec.NetworkOptions == nil || cr.Spec.NetworkOptions.GrafanaConfig == nil { - config = &operatorv1beta1.NetworkConfiguration{} + config = &operatorv1beta2.NetworkConfiguration{} } else { config = cr.Spec.NetworkOptions.GrafanaConfig } @@ -189,7 +189,7 @@ func configureGrafanaRoute(cr *model.CryostatInstance) *operatorv1beta1.NetworkC return config } -func configureRoute(config *operatorv1beta1.NetworkConfiguration, appLabel string, componentLabel string) { +func configureRoute(config *operatorv1beta2.NetworkConfiguration, appLabel string, componentLabel string) { if config.Labels == nil { config.Labels = map[string]string{} } diff --git a/internal/controllers/services.go b/internal/controllers/services.go index 2332ee0cc..6718c2d2f 100644 --- a/internal/controllers/services.go +++ b/internal/controllers/services.go @@ -20,7 +20,7 @@ import ( "net/url" "strconv" - operatorv1beta1 "github.com/cryostatio/cryostat-operator/api/v1beta1" + operatorv1beta2 "github.com/cryostatio/cryostat-operator/api/v1beta2" common "github.com/cryostatio/cryostat-operator/internal/controllers/common" "github.com/cryostatio/cryostat-operator/internal/controllers/common/resource_definitions" "github.com/cryostatio/cryostat-operator/internal/controllers/constants" @@ -159,11 +159,11 @@ func (r *Reconciler) reconcileReportsService(ctx context.Context, cr *model.Cryo return nil } -func configureCoreService(cr *model.CryostatInstance) *operatorv1beta1.CoreServiceConfig { +func configureCoreService(cr *model.CryostatInstance) *operatorv1beta2.CoreServiceConfig { // Check CR for config - var config *operatorv1beta1.CoreServiceConfig + var config *operatorv1beta2.CoreServiceConfig if cr.Spec.ServiceOptions == nil || cr.Spec.ServiceOptions.CoreConfig == nil { - config = &operatorv1beta1.CoreServiceConfig{} + config = &operatorv1beta2.CoreServiceConfig{} } else { config = cr.Spec.ServiceOptions.CoreConfig.DeepCopy() } @@ -184,11 +184,11 @@ func configureCoreService(cr *model.CryostatInstance) *operatorv1beta1.CoreServi return config } -func configureGrafanaService(cr *model.CryostatInstance) *operatorv1beta1.GrafanaServiceConfig { +func configureGrafanaService(cr *model.CryostatInstance) *operatorv1beta2.GrafanaServiceConfig { // Check CR for config - var config *operatorv1beta1.GrafanaServiceConfig + var config *operatorv1beta2.GrafanaServiceConfig if cr.Spec.ServiceOptions == nil || cr.Spec.ServiceOptions.GrafanaConfig == nil { - config = &operatorv1beta1.GrafanaServiceConfig{} + config = &operatorv1beta2.GrafanaServiceConfig{} } else { config = cr.Spec.ServiceOptions.GrafanaConfig.DeepCopy() } @@ -205,11 +205,11 @@ func configureGrafanaService(cr *model.CryostatInstance) *operatorv1beta1.Grafan return config } -func configureReportsService(cr *model.CryostatInstance) *operatorv1beta1.ReportsServiceConfig { +func configureReportsService(cr *model.CryostatInstance) *operatorv1beta2.ReportsServiceConfig { // Check CR for config - var config *operatorv1beta1.ReportsServiceConfig + var config *operatorv1beta2.ReportsServiceConfig if cr.Spec.ServiceOptions == nil || cr.Spec.ServiceOptions.ReportsConfig == nil { - config = &operatorv1beta1.ReportsServiceConfig{} + config = &operatorv1beta2.ReportsServiceConfig{} } else { config = cr.Spec.ServiceOptions.ReportsConfig.DeepCopy() } @@ -226,7 +226,7 @@ func configureReportsService(cr *model.CryostatInstance) *operatorv1beta1.Report return config } -func configureService(config *operatorv1beta1.ServiceConfig, appLabel string, componentLabel string) { +func configureService(config *operatorv1beta2.ServiceConfig, appLabel string, componentLabel string) { if config.ServiceType == nil { svcType := corev1.ServiceTypeClusterIP config.ServiceType = &svcType @@ -244,7 +244,7 @@ func configureService(config *operatorv1beta1.ServiceConfig, appLabel string, co } func (r *Reconciler) createOrUpdateService(ctx context.Context, svc *corev1.Service, owner metav1.Object, - config *operatorv1beta1.ServiceConfig, delegate controllerutil.MutateFn) error { + config *operatorv1beta2.ServiceConfig, delegate controllerutil.MutateFn) error { op, err := controllerutil.CreateOrUpdate(ctx, r.Client, svc, func() error { // Update labels and annotations common.MergeLabelsAndAnnotations(&svc.ObjectMeta, config.Labels, config.Annotations) diff --git a/internal/main.go b/internal/main.go index 229200b95..b5d4c2fd4 100644 --- a/internal/main.go +++ b/internal/main.go @@ -15,6 +15,7 @@ package main import ( + "crypto/tls" "flag" "fmt" "net/url" @@ -35,11 +36,14 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" + "sigs.k8s.io/controller-runtime/pkg/webhook" operatorv1beta1 "github.com/cryostatio/cryostat-operator/api/v1beta1" + operatorv1beta2 "github.com/cryostatio/cryostat-operator/api/v1beta2" "github.com/cryostatio/cryostat-operator/internal/controllers" "github.com/cryostatio/cryostat-operator/internal/controllers/common" "github.com/cryostatio/cryostat-operator/internal/controllers/insights" + "github.com/cryostatio/cryostat-operator/internal/webhooks" // +kubebuilder:scaffold:imports ) @@ -59,6 +63,7 @@ func init() { utilruntime.Must(consolev1.AddToScheme(scheme)) utilruntime.Must(configv1.AddToScheme(scheme)) + utilruntime.Must(operatorv1beta2.AddToScheme(scheme)) // +kubebuilder:scaffold:scheme } @@ -66,11 +71,13 @@ func main() { var metricsAddr string var enableLeaderElection bool var probeAddr string + var enableHTTP2 bool flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") flag.BoolVar(&enableLeaderElection, "leader-elect", false, "Enable leader election for controller manager. "+ "Enabling this will ensure there is only one active controller manager.") + flag.BoolVar(&enableHTTP2, "enable-http2", false, "If HTTP/2 should be enabled for the metrics and webhook servers.") opts := zap.Options{ Development: true, } @@ -79,6 +86,17 @@ func main() { ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) + // Customize the webhook server to disable HTTP/2 by default + disableHTTP2 := func(c *tls.Config) { + if enableHTTP2 { + return + } + c.NextProtos = []string{"http/1.1"} + } + webhookServer := &webhook.Server{ + TLSOpts: []func(config *tls.Config){disableHTTP2}, + } + // FIXME Disable metrics until this issue is resolved: // https://github.com/operator-framework/operator-sdk/issues/4684 metricsAddr = "0" @@ -89,6 +107,7 @@ func main() { HealthProbeBindAddress: probeAddr, LeaderElection: enableLeaderElection, LeaderElectionID: "d696d7ab.redhat.com", + WebhookServer: webhookServer, }) if err != nil { setupLog.Error(err, "unable to start manager") @@ -155,6 +174,10 @@ func main() { setupLog.Error(err, "unable to add controller to manager", "controller", "Cryostat") os.Exit(1) } + if err = webhooks.SetupWebhookWithManager(mgr, &operatorv1beta2.Cryostat{}); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "Cryostat") + os.Exit(1) + } // +kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { diff --git a/internal/test/conversion.go b/internal/test/conversion.go new file mode 100644 index 000000000..b1167a327 --- /dev/null +++ b/internal/test/conversion.go @@ -0,0 +1,638 @@ +// Copyright The Cryostat Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package test + +import ( + operatorv1beta1 "github.com/cryostatio/cryostat-operator/api/v1beta1" + corev1 "k8s.io/api/core/v1" + netv1 "k8s.io/api/networking/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// v1beta1 versions of Cryostat CRs used for testing the conversion webhook + +func (r *TestResources) NewCryostatV1Beta1() *operatorv1beta1.Cryostat { + return &operatorv1beta1.Cryostat{ + ObjectMeta: metav1.ObjectMeta{ + Name: r.Name, + Namespace: r.Namespace, + }, + Spec: r.newCryostatSpecV1Beta1(), + } +} + +func (r *TestResources) newCryostatSpecV1Beta1() operatorv1beta1.CryostatSpec { + certManager := true + var reportOptions *operatorv1beta1.ReportConfiguration + if r.ReportReplicas > 0 { + reportOptions = &operatorv1beta1.ReportConfiguration{ + Replicas: r.ReportReplicas, + } + } + return operatorv1beta1.CryostatSpec{ + Minimal: r.Minimal, + EnableCertManager: &certManager, + ReportOptions: reportOptions, + } +} + +func (r *TestResources) NewCryostatWithSecretsV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + key := "test.crt" + cr.Spec.TrustedCertSecrets = []operatorv1beta1.CertificateSecret{ + { + SecretName: "testCert1", + CertificateKey: &key, + }, + { + SecretName: "testCert2", + }, + } + return cr +} + +func (r *TestResources) NewCryostatWithTemplatesV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.EventTemplates = []operatorv1beta1.TemplateConfigMap{ + { + ConfigMapName: "templateCM1", + Filename: "template.jfc", + }, + { + ConfigMapName: "templateCM2", + Filename: "other-template.jfc", + }, + } + return cr +} + +func (r *TestResources) NewCryostatWithIngressV1Beta1() *operatorv1beta1.Cryostat { + return r.addIngressToCryostatV1Beta1(r.NewCryostatV1Beta1()) +} + +func (r *TestResources) NewCryostatWithIngressCertManagerDisabledV1Beta1() *operatorv1beta1.Cryostat { + return r.addIngressToCryostatV1Beta1(r.NewCryostatCertManagerDisabledV1Beta1()) +} + +func (r *TestResources) addIngressToCryostatV1Beta1(cr *operatorv1beta1.Cryostat) *operatorv1beta1.Cryostat { + networkConfig := r.newNetworkConfigurationListV1Beta1() + cr.Spec.NetworkOptions = &networkConfig + return cr +} + +func (r *TestResources) NewCryostatWithPVCSpecV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.StorageOptions = &operatorv1beta1.StorageConfiguration{ + PVC: &operatorv1beta1.PersistentVolumeClaimConfig{ + Annotations: map[string]string{ + "my/custom": "annotation", + }, + Labels: map[string]string{ + "my": "label", + "app": "somethingelse", + }, + Spec: newPVCSpec("cool-storage", "10Gi", corev1.ReadWriteMany), + }, + } + return cr +} + +func (r *TestResources) NewCryostatWithPVCSpecSomeDefaultV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.StorageOptions = &operatorv1beta1.StorageConfiguration{ + PVC: &operatorv1beta1.PersistentVolumeClaimConfig{ + Spec: newPVCSpec("", "1Gi"), + }, + } + return cr +} + +func (r *TestResources) NewCryostatWithPVCLabelsOnlyV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.StorageOptions = &operatorv1beta1.StorageConfiguration{ + PVC: &operatorv1beta1.PersistentVolumeClaimConfig{ + Labels: map[string]string{ + "my": "label", + }, + }, + } + return cr +} + +func (r *TestResources) NewCryostatWithDefaultEmptyDirV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.StorageOptions = &operatorv1beta1.StorageConfiguration{ + EmptyDir: &operatorv1beta1.EmptyDirConfig{ + Enabled: true, + }, + } + return cr +} + +func (r *TestResources) NewCryostatWithEmptyDirSpecV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.StorageOptions = &operatorv1beta1.StorageConfiguration{ + EmptyDir: &operatorv1beta1.EmptyDirConfig{ + Enabled: true, + Medium: "Memory", + SizeLimit: "200Mi", + }, + } + return cr +} + +func (r *TestResources) NewCryostatWithCoreSvcV1Beta1() *operatorv1beta1.Cryostat { + svcType := corev1.ServiceTypeNodePort + httpPort := int32(8080) + jmxPort := int32(9095) + cr := r.NewCryostatV1Beta1() + cr.Spec.ServiceOptions = &operatorv1beta1.ServiceConfigList{ + CoreConfig: &operatorv1beta1.CoreServiceConfig{ + HTTPPort: &httpPort, + JMXPort: &jmxPort, + ServiceConfig: operatorv1beta1.ServiceConfig{ + ServiceType: &svcType, + Annotations: map[string]string{ + "my/custom": "annotation", + }, + Labels: map[string]string{ + "my": "label", + "app": "somethingelse", + }, + }, + }, + } + return cr +} + +func (r *TestResources) NewCryostatWithGrafanaSvcV1Beta1() *operatorv1beta1.Cryostat { + svcType := corev1.ServiceTypeNodePort + httpPort := int32(8080) + cr := r.NewCryostatV1Beta1() + cr.Spec.ServiceOptions = &operatorv1beta1.ServiceConfigList{ + GrafanaConfig: &operatorv1beta1.GrafanaServiceConfig{ + HTTPPort: &httpPort, + ServiceConfig: operatorv1beta1.ServiceConfig{ + ServiceType: &svcType, + Annotations: map[string]string{ + "my/custom": "annotation", + }, + Labels: map[string]string{ + "my": "label", + "app": "somethingelse", + }, + }, + }, + } + return cr +} + +func (r *TestResources) NewCryostatWithReportsSvcV1Beta1() *operatorv1beta1.Cryostat { + svcType := corev1.ServiceTypeNodePort + httpPort := int32(13161) + cr := r.NewCryostatV1Beta1() + cr.Spec.ServiceOptions = &operatorv1beta1.ServiceConfigList{ + ReportsConfig: &operatorv1beta1.ReportsServiceConfig{ + HTTPPort: &httpPort, + ServiceConfig: operatorv1beta1.ServiceConfig{ + ServiceType: &svcType, + Annotations: map[string]string{ + "my/custom": "annotation", + }, + Labels: map[string]string{ + "my": "label", + "app": "somethingelse", + }, + }, + }, + } + return cr +} + +func (r *TestResources) NewCryostatWithCoreNetworkOptionsV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.NetworkOptions = &operatorv1beta1.NetworkConfigurationList{ + CoreConfig: &operatorv1beta1.NetworkConfiguration{ + Annotations: map[string]string{"custom": "annotation"}, + Labels: map[string]string{ + "custom": "label", + "app": "test-app", + "component": "test-comp", + }, + }, + } + return cr +} + +func (r *TestResources) NewCryostatWithGrafanaNetworkOptionsV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.NetworkOptions = &operatorv1beta1.NetworkConfigurationList{ + GrafanaConfig: &operatorv1beta1.NetworkConfiguration{ + Annotations: map[string]string{"grafana": "annotation"}, + Labels: map[string]string{ + "grafana": "label", + "component": "test-comp", + "app": "test-app", + }, + }, + } + return cr +} + +func (r *TestResources) NewCryostatWithReportsResourcesV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.ReportOptions = &operatorv1beta1.ReportConfiguration{ + Replicas: 1, + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("1600m"), + corev1.ResourceMemory: resource.MustParse("1Gi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("800m"), + corev1.ResourceMemory: resource.MustParse("512Mi"), + }, + }, + } + return cr +} + +func (r *TestResources) NewCryostatWithReportLowResourceLimitV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.ReportOptions = &operatorv1beta1.ReportConfiguration{ + Replicas: 1, + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("20m"), + corev1.ResourceMemory: resource.MustParse("32Mi"), + }, + }, + } + return cr +} + +func populateCryostatWithSchedulingV1Beta1() *operatorv1beta1.SchedulingConfiguration { + return &operatorv1beta1.SchedulingConfiguration{ + NodeSelector: map[string]string{"node": "good"}, + Affinity: &operatorv1beta1.Affinity{ + NodeAffinity: &corev1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ + NodeSelectorTerms: []corev1.NodeSelectorTerm{ + { + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Key: "node", + Operator: corev1.NodeSelectorOpIn, + Values: []string{ + "good", + "better", + }, + }, + }, + }, + }, + }, + }, + PodAffinity: &corev1.PodAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: []corev1.PodAffinityTerm{ + { + LabelSelector: metav1.AddLabelToSelector(&metav1.LabelSelector{}, + "pod", "good"), + TopologyKey: "topology.kubernetes.io/zone", + }, + }, + }, + PodAntiAffinity: &corev1.PodAntiAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: []corev1.PodAffinityTerm{ + {LabelSelector: metav1.AddLabelToSelector(&metav1.LabelSelector{}, + "pod", "bad"), + TopologyKey: "topology.kubernetes.io/zone", + }, + }, + }, + }, + Tolerations: []corev1.Toleration{ + { + Key: "node", + Operator: corev1.TolerationOpEqual, + Value: "ok", + Effect: corev1.TaintEffectNoExecute, + }, + }, + } + +} + +func (r *TestResources) NewCryostatWithSchedulingV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.SchedulingOptions = populateCryostatWithSchedulingV1Beta1() + return cr +} + +func (r *TestResources) NewCryostatWithReportsSchedulingV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.ReportOptions = &operatorv1beta1.ReportConfiguration{ + Replicas: 1, + SchedulingOptions: populateCryostatWithSchedulingV1Beta1(), + } + + return cr +} + +func (r *TestResources) NewCryostatCertManagerDisabledV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + certManager := false + cr.Spec.EnableCertManager = &certManager + return cr +} + +func (r *TestResources) NewCryostatCertManagerUndefinedV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.EnableCertManager = nil + return cr +} + +func (r *TestResources) NewCryostatWithResourcesV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.Resources = &operatorv1beta1.ResourceConfigList{ + CoreResources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("500m"), + corev1.ResourceMemory: resource.MustParse("256Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("250m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + }, + GrafanaResources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("550m"), + corev1.ResourceMemory: resource.MustParse("512Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("128m"), + corev1.ResourceMemory: resource.MustParse("256Mi"), + }, + }, + DataSourceResources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("600m"), + corev1.ResourceMemory: resource.MustParse("128Mi"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("300m"), + corev1.ResourceMemory: resource.MustParse("64Mi"), + }, + }, + } + return cr +} + +func (r *TestResources) NewCryostatWithLowResourceLimitV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.Resources = &operatorv1beta1.ResourceConfigList{ + CoreResources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("10m"), + corev1.ResourceMemory: resource.MustParse("32Mi"), + }, + }, + GrafanaResources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("10m"), + corev1.ResourceMemory: resource.MustParse("32Mi"), + }, + }, + DataSourceResources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("10m"), + corev1.ResourceMemory: resource.MustParse("32Mi"), + }, + }, + } + return cr +} + +func (r *TestResources) NewCryostatWithAuthPropertiesV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.AuthProperties = &operatorv1beta1.AuthorizationProperties{ + ConfigMapName: "authConfigMapName", + Filename: "auth.properties", + ClusterRoleName: "custom-auth-cluster-role", + } + return cr +} + +func (r *TestResources) NewCryostatWithBuiltInDiscoveryDisabledV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.TargetDiscoveryOptions = &operatorv1beta1.TargetDiscoveryOptions{ + BuiltInDiscoveryDisabled: true, + } + return cr +} + +func (r *TestResources) NewCryostatWithJmxCacheOptionsSpecV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.JmxCacheOptions = &operatorv1beta1.JmxCacheOptions{ + TargetCacheSize: 10, + TargetCacheTTL: 20, + } + return cr +} + +func (r *TestResources) NewCryostatWithWsConnectionsSpecV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.MaxWsConnections = 10 + return cr +} + +func (r *TestResources) NewCryostatWithReportSubprocessHeapSpecV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + if cr.Spec.ReportOptions == nil { + cr.Spec.ReportOptions = &operatorv1beta1.ReportConfiguration{} + } + cr.Spec.ReportOptions.SubProcessMaxHeapSize = 500 + return cr +} + +func (r *TestResources) NewCryostatWithSecurityOptionsV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + privEscalation := true + nonRoot := false + runAsUser := int64(0) + fsGroup := int64(20000) + cr.Spec.SecurityOptions = &operatorv1beta1.SecurityOptions{ + PodSecurityContext: &corev1.PodSecurityContext{ + RunAsNonRoot: &nonRoot, + FSGroup: &fsGroup, + SeccompProfile: &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + }, + }, + CoreSecurityContext: &corev1.SecurityContext{ + AllowPrivilegeEscalation: &privEscalation, + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{}, + }, + RunAsUser: &runAsUser, + }, + GrafanaSecurityContext: &corev1.SecurityContext{ + AllowPrivilegeEscalation: &privEscalation, + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{}, + }, + RunAsUser: &runAsUser, + }, + DataSourceSecurityContext: &corev1.SecurityContext{ + AllowPrivilegeEscalation: &privEscalation, + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{}, + }, + RunAsUser: &runAsUser, + }, + } + return cr +} + +func (r *TestResources) NewCryostatWithReportSecurityOptionsV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + nonRoot := true + privEscalation := false + runAsUser := int64(1002) + if cr.Spec.ReportOptions == nil { + cr.Spec.ReportOptions = &operatorv1beta1.ReportConfiguration{} + } + cr.Spec.ReportOptions.SecurityOptions = &operatorv1beta1.ReportsSecurityOptions{ + PodSecurityContext: &corev1.PodSecurityContext{ + RunAsNonRoot: &nonRoot, + SeccompProfile: &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + }, + }, + ReportsSecurityContext: &corev1.SecurityContext{ + AllowPrivilegeEscalation: &privEscalation, + RunAsUser: &runAsUser, + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + }, + }, + } + return cr +} + +func (r *TestResources) NewCryostatWithDatabaseSecretProvidedV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.JmxCredentialsDatabaseOptions = &operatorv1beta1.JmxCredentialsDatabaseOptions{ + DatabaseSecretName: &providedDatabaseSecretName, + } + return cr +} + +func (r *TestResources) NewCryostatWithAdditionalMetadataV1Beta1() *operatorv1beta1.Cryostat { + cr := r.NewCryostatV1Beta1() + cr.Spec.OperandMetadata = &operatorv1beta1.OperandMetadata{ + DeploymentMetadata: &operatorv1beta1.ResourceMetadata{ + Labels: map[string]string{ + "myDeploymentExtraLabel": "myDeploymentLabel", + "mySecondDeploymentExtraLabel": "mySecondDeploymentLabel", + // below, labels that should be discarded as overriden by the default + "app": "myApp", + "component": "myComponent", + "kind": "myKind", + "app.kubernetes.io/name": "myName", + }, + Annotations: map[string]string{ + "myDeploymentExtraAnnotation": "myDeploymentAnnotation", + "mySecondDeploymentExtraAnnotation": "mySecondDeploymentAnnotation", + // below, annotation that should be discarded as overriden by the default + "app.openshift.io/connects-to": "connectToMe", + }, + }, + PodMetadata: &operatorv1beta1.ResourceMetadata{ + Labels: map[string]string{ + "myPodExtraLabel": "myPodLabel", + "myPodSecondExtraLabel": "myPodSecondLabel", + // below, labels that should be discarded as overriden by the default + "app": "myApp", + "component": "myComponent", + "kind": "myKind", + }, + Annotations: map[string]string{ + "myPodExtraAnnotation": "myPodAnnotation", + "mySecondPodExtraAnnotation": "mySecondPodAnnotation", + }, + }, + } + return cr +} + +func (r *TestResources) newNetworkConfigurationListV1Beta1() operatorv1beta1.NetworkConfigurationList { + coreSVC := r.NewCryostatService() + coreIng := r.newNetworkConfigurationV1Beta1(coreSVC.Name, coreSVC.Spec.Ports[0].Port) + coreIng.Annotations["custom"] = "annotation" + coreIng.Labels["custom"] = "label" + + grafanaSVC := r.NewGrafanaService() + grafanaIng := r.newNetworkConfigurationV1Beta1(grafanaSVC.Name, grafanaSVC.Spec.Ports[0].Port) + grafanaIng.Annotations["grafana"] = "annotation" + grafanaIng.Labels["grafana"] = "label" + + return operatorv1beta1.NetworkConfigurationList{ + CoreConfig: &coreIng, + GrafanaConfig: &grafanaIng, + } +} + +func (r *TestResources) newNetworkConfigurationV1Beta1(svcName string, svcPort int32) operatorv1beta1.NetworkConfiguration { + pathtype := netv1.PathTypePrefix + host := svcName + ".example.com" + + var ingressTLS []netv1.IngressTLS + if r.ExternalTLS { + ingressTLS = []netv1.IngressTLS{{}} + } + return operatorv1beta1.NetworkConfiguration{ + Annotations: map[string]string{"nginx.ingress.kubernetes.io/backend-protocol": "HTTPS"}, + Labels: map[string]string{"my": "label"}, + IngressSpec: &netv1.IngressSpec{ + Rules: []netv1.IngressRule{ + { + Host: host, + IngressRuleValue: netv1.IngressRuleValue{ + HTTP: &netv1.HTTPIngressRuleValue{ + Paths: []netv1.HTTPIngressPath{ + { + Path: "/", + PathType: &pathtype, + Backend: netv1.IngressBackend{ + Service: &netv1.IngressServiceBackend{ + Name: svcName, + Port: netv1.ServiceBackendPort{ + Number: svcPort, + }, + }, + }, + }, + }, + }, + }, + }, + }, + TLS: ingressTLS, + }, + } +} diff --git a/internal/test/resources.go b/internal/test/resources.go index d72f7b305..b2883741d 100644 --- a/internal/test/resources.go +++ b/internal/test/resources.go @@ -21,7 +21,7 @@ import ( certv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" certMeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" - operatorv1beta1 "github.com/cryostatio/cryostat-operator/api/v1beta1" + operatorv1beta2 "github.com/cryostatio/cryostat-operator/api/v1beta2" "github.com/cryostatio/cryostat-operator/internal/controllers/model" "github.com/onsi/gomega" configv1 "github.com/openshift/api/config/v1" @@ -59,7 +59,7 @@ func NewTestScheme() *runtime.Scheme { // Add all APIs used by the operator to the scheme sb := runtime.NewSchemeBuilder( - operatorv1beta1.AddToScheme, + operatorv1beta2.AddToScheme, certv1.AddToScheme, routev1.AddToScheme, consolev1.AddToScheme, @@ -91,21 +91,20 @@ func (r *TestResources) NewCryostat() *model.CryostatInstance { } } -func (r *TestResources) newClusterCryostat() *operatorv1beta1.ClusterCryostat { - return &operatorv1beta1.ClusterCryostat{ +func (r *TestResources) newClusterCryostat() *operatorv1beta2.ClusterCryostat { + return &operatorv1beta2.ClusterCryostat{ ObjectMeta: metav1.ObjectMeta{ Name: r.Name, }, - Spec: operatorv1beta1.ClusterCryostatSpec{ + Spec: operatorv1beta2.ClusterCryostatSpec{ InstallNamespace: r.Namespace, - TargetNamespaces: r.TargetNamespaces, CryostatSpec: r.newCryostatSpec(), }, } } -func (r *TestResources) newCryostat() *operatorv1beta1.Cryostat { - return &operatorv1beta1.Cryostat{ +func (r *TestResources) newCryostat() *operatorv1beta2.Cryostat { + return &operatorv1beta2.Cryostat{ ObjectMeta: metav1.ObjectMeta{ Name: r.Name, Namespace: r.Namespace, @@ -114,35 +113,35 @@ func (r *TestResources) newCryostat() *operatorv1beta1.Cryostat { } } -func (r *TestResources) newCryostatSpec() operatorv1beta1.CryostatSpec { +func (r *TestResources) newCryostatSpec() operatorv1beta2.CryostatSpec { certManager := true - var reportOptions *operatorv1beta1.ReportConfiguration + var reportOptions *operatorv1beta2.ReportConfiguration if r.ReportReplicas > 0 { - reportOptions = &operatorv1beta1.ReportConfiguration{ + reportOptions = &operatorv1beta2.ReportConfiguration{ Replicas: r.ReportReplicas, } } - return operatorv1beta1.CryostatSpec{ + return operatorv1beta2.CryostatSpec{ + TargetNamespaces: r.TargetNamespaces, Minimal: r.Minimal, EnableCertManager: &certManager, ReportOptions: reportOptions, } } -func (r *TestResources) ConvertNamespacedToModel(cr *operatorv1beta1.Cryostat) *model.CryostatInstance { - targetNS := []string{cr.Namespace} +func (r *TestResources) ConvertNamespacedToModel(cr *operatorv1beta2.Cryostat) *model.CryostatInstance { return &model.CryostatInstance{ Name: cr.Name, InstallNamespace: cr.Namespace, - TargetNamespaces: targetNS, - TargetNamespaceStatus: &targetNS, + TargetNamespaces: cr.Spec.TargetNamespaces, + TargetNamespaceStatus: &cr.Status.TargetNamespaces, Spec: &cr.Spec, Status: &cr.Status, Object: cr, } } -func (r *TestResources) ConvertClusterToModel(cr *operatorv1beta1.ClusterCryostat) *model.CryostatInstance { +func (r *TestResources) ConvertClusterToModel(cr *operatorv1beta2.ClusterCryostat) *model.CryostatInstance { return &model.CryostatInstance{ Name: cr.Name, InstallNamespace: cr.Spec.InstallNamespace, @@ -157,7 +156,7 @@ func (r *TestResources) ConvertClusterToModel(cr *operatorv1beta1.ClusterCryosta func (r *TestResources) NewCryostatWithSecrets() *model.CryostatInstance { cr := r.NewCryostat() key := "test.crt" - cr.Spec.TrustedCertSecrets = []operatorv1beta1.CertificateSecret{ + cr.Spec.TrustedCertSecrets = []operatorv1beta2.CertificateSecret{ { SecretName: "testCert1", CertificateKey: &key, @@ -171,7 +170,7 @@ func (r *TestResources) NewCryostatWithSecrets() *model.CryostatInstance { func (r *TestResources) NewCryostatWithTemplates() *model.CryostatInstance { cr := r.NewCryostat() - cr.Spec.EventTemplates = []operatorv1beta1.TemplateConfigMap{ + cr.Spec.EventTemplates = []operatorv1beta2.TemplateConfigMap{ { ConfigMapName: "templateCM1", Filename: "template.jfc", @@ -200,8 +199,8 @@ func (r *TestResources) addIngressToCryostat(cr *model.CryostatInstance) *model. func (r *TestResources) NewCryostatWithPVCSpec() *model.CryostatInstance { cr := r.NewCryostat() - cr.Spec.StorageOptions = &operatorv1beta1.StorageConfiguration{ - PVC: &operatorv1beta1.PersistentVolumeClaimConfig{ + cr.Spec.StorageOptions = &operatorv1beta2.StorageConfiguration{ + PVC: &operatorv1beta2.PersistentVolumeClaimConfig{ Annotations: map[string]string{ "my/custom": "annotation", }, @@ -217,8 +216,8 @@ func (r *TestResources) NewCryostatWithPVCSpec() *model.CryostatInstance { func (r *TestResources) NewCryostatWithPVCSpecSomeDefault() *model.CryostatInstance { cr := r.NewCryostat() - cr.Spec.StorageOptions = &operatorv1beta1.StorageConfiguration{ - PVC: &operatorv1beta1.PersistentVolumeClaimConfig{ + cr.Spec.StorageOptions = &operatorv1beta2.StorageConfiguration{ + PVC: &operatorv1beta2.PersistentVolumeClaimConfig{ Spec: newPVCSpec("", "1Gi"), }, } @@ -227,8 +226,8 @@ func (r *TestResources) NewCryostatWithPVCSpecSomeDefault() *model.CryostatInsta func (r *TestResources) NewCryostatWithPVCLabelsOnly() *model.CryostatInstance { cr := r.NewCryostat() - cr.Spec.StorageOptions = &operatorv1beta1.StorageConfiguration{ - PVC: &operatorv1beta1.PersistentVolumeClaimConfig{ + cr.Spec.StorageOptions = &operatorv1beta2.StorageConfiguration{ + PVC: &operatorv1beta2.PersistentVolumeClaimConfig{ Labels: map[string]string{ "my": "label", }, @@ -239,8 +238,8 @@ func (r *TestResources) NewCryostatWithPVCLabelsOnly() *model.CryostatInstance { func (r *TestResources) NewCryostatWithDefaultEmptyDir() *model.CryostatInstance { cr := r.NewCryostat() - cr.Spec.StorageOptions = &operatorv1beta1.StorageConfiguration{ - EmptyDir: &operatorv1beta1.EmptyDirConfig{ + cr.Spec.StorageOptions = &operatorv1beta2.StorageConfiguration{ + EmptyDir: &operatorv1beta2.EmptyDirConfig{ Enabled: true, }, } @@ -249,8 +248,8 @@ func (r *TestResources) NewCryostatWithDefaultEmptyDir() *model.CryostatInstance func (r *TestResources) NewCryostatWithEmptyDirSpec() *model.CryostatInstance { cr := r.NewCryostat() - cr.Spec.StorageOptions = &operatorv1beta1.StorageConfiguration{ - EmptyDir: &operatorv1beta1.EmptyDirConfig{ + cr.Spec.StorageOptions = &operatorv1beta2.StorageConfiguration{ + EmptyDir: &operatorv1beta2.EmptyDirConfig{ Enabled: true, Medium: "Memory", SizeLimit: "200Mi", @@ -264,11 +263,11 @@ func (r *TestResources) NewCryostatWithCoreSvc() *model.CryostatInstance { httpPort := int32(8080) jmxPort := int32(9095) cr := r.NewCryostat() - cr.Spec.ServiceOptions = &operatorv1beta1.ServiceConfigList{ - CoreConfig: &operatorv1beta1.CoreServiceConfig{ + cr.Spec.ServiceOptions = &operatorv1beta2.ServiceConfigList{ + CoreConfig: &operatorv1beta2.CoreServiceConfig{ HTTPPort: &httpPort, JMXPort: &jmxPort, - ServiceConfig: operatorv1beta1.ServiceConfig{ + ServiceConfig: operatorv1beta2.ServiceConfig{ ServiceType: &svcType, Annotations: map[string]string{ "my/custom": "annotation", @@ -287,10 +286,10 @@ func (r *TestResources) NewCryostatWithGrafanaSvc() *model.CryostatInstance { svcType := corev1.ServiceTypeNodePort httpPort := int32(8080) cr := r.NewCryostat() - cr.Spec.ServiceOptions = &operatorv1beta1.ServiceConfigList{ - GrafanaConfig: &operatorv1beta1.GrafanaServiceConfig{ + cr.Spec.ServiceOptions = &operatorv1beta2.ServiceConfigList{ + GrafanaConfig: &operatorv1beta2.GrafanaServiceConfig{ HTTPPort: &httpPort, - ServiceConfig: operatorv1beta1.ServiceConfig{ + ServiceConfig: operatorv1beta2.ServiceConfig{ ServiceType: &svcType, Annotations: map[string]string{ "my/custom": "annotation", @@ -309,10 +308,10 @@ func (r *TestResources) NewCryostatWithReportsSvc() *model.CryostatInstance { svcType := corev1.ServiceTypeNodePort httpPort := int32(13161) cr := r.NewCryostat() - cr.Spec.ServiceOptions = &operatorv1beta1.ServiceConfigList{ - ReportsConfig: &operatorv1beta1.ReportsServiceConfig{ + cr.Spec.ServiceOptions = &operatorv1beta2.ServiceConfigList{ + ReportsConfig: &operatorv1beta2.ReportsServiceConfig{ HTTPPort: &httpPort, - ServiceConfig: operatorv1beta1.ServiceConfig{ + ServiceConfig: operatorv1beta2.ServiceConfig{ ServiceType: &svcType, Annotations: map[string]string{ "my/custom": "annotation", @@ -329,8 +328,8 @@ func (r *TestResources) NewCryostatWithReportsSvc() *model.CryostatInstance { func (r *TestResources) NewCryostatWithCoreNetworkOptions() *model.CryostatInstance { cr := r.NewCryostat() - cr.Spec.NetworkOptions = &operatorv1beta1.NetworkConfigurationList{ - CoreConfig: &operatorv1beta1.NetworkConfiguration{ + cr.Spec.NetworkOptions = &operatorv1beta2.NetworkConfigurationList{ + CoreConfig: &operatorv1beta2.NetworkConfiguration{ Annotations: map[string]string{"custom": "annotation"}, Labels: map[string]string{ "custom": "label", @@ -344,8 +343,8 @@ func (r *TestResources) NewCryostatWithCoreNetworkOptions() *model.CryostatInsta func (r *TestResources) NewCryostatWithGrafanaNetworkOptions() *model.CryostatInstance { cr := r.NewCryostat() - cr.Spec.NetworkOptions = &operatorv1beta1.NetworkConfigurationList{ - GrafanaConfig: &operatorv1beta1.NetworkConfiguration{ + cr.Spec.NetworkOptions = &operatorv1beta2.NetworkConfigurationList{ + GrafanaConfig: &operatorv1beta2.NetworkConfiguration{ Annotations: map[string]string{"grafana": "annotation"}, Labels: map[string]string{ "grafana": "label", @@ -359,7 +358,7 @@ func (r *TestResources) NewCryostatWithGrafanaNetworkOptions() *model.CryostatIn func (r *TestResources) NewCryostatWithReportsResources() *model.CryostatInstance { cr := r.NewCryostat() - cr.Spec.ReportOptions = &operatorv1beta1.ReportConfiguration{ + cr.Spec.ReportOptions = &operatorv1beta2.ReportConfiguration{ Replicas: 1, Resources: corev1.ResourceRequirements{ Limits: corev1.ResourceList{ @@ -377,7 +376,7 @@ func (r *TestResources) NewCryostatWithReportsResources() *model.CryostatInstanc func (r *TestResources) NewCryostatWithReportLowResourceLimit() *model.CryostatInstance { cr := r.NewCryostat() - cr.Spec.ReportOptions = &operatorv1beta1.ReportConfiguration{ + cr.Spec.ReportOptions = &operatorv1beta2.ReportConfiguration{ Replicas: 1, Resources: corev1.ResourceRequirements{ Limits: corev1.ResourceList{ @@ -389,10 +388,10 @@ func (r *TestResources) NewCryostatWithReportLowResourceLimit() *model.CryostatI return cr } -func populateCryostatWithScheduling() *operatorv1beta1.SchedulingConfiguration { - return &operatorv1beta1.SchedulingConfiguration{ +func populateCryostatWithScheduling() *operatorv1beta2.SchedulingConfiguration { + return &operatorv1beta2.SchedulingConfiguration{ NodeSelector: map[string]string{"node": "good"}, - Affinity: &operatorv1beta1.Affinity{ + Affinity: &operatorv1beta2.Affinity{ NodeAffinity: &corev1.NodeAffinity{ RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ NodeSelectorTerms: []corev1.NodeSelectorTerm{ @@ -449,7 +448,7 @@ func (r *TestResources) NewCryostatWithScheduling() *model.CryostatInstance { func (r *TestResources) NewCryostatWithReportsScheduling() *model.CryostatInstance { cr := r.NewCryostat() - cr.Spec.ReportOptions = &operatorv1beta1.ReportConfiguration{ + cr.Spec.ReportOptions = &operatorv1beta2.ReportConfiguration{ Replicas: 1, SchedulingOptions: populateCryostatWithScheduling(), } @@ -472,7 +471,7 @@ func (r *TestResources) NewCryostatCertManagerUndefined() *model.CryostatInstanc func (r *TestResources) NewCryostatWithResources() *model.CryostatInstance { cr := r.NewCryostat() - cr.Spec.Resources = &operatorv1beta1.ResourceConfigList{ + cr.Spec.Resources = &operatorv1beta2.ResourceConfigList{ CoreResources: corev1.ResourceRequirements{ Limits: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("500m"), @@ -509,7 +508,7 @@ func (r *TestResources) NewCryostatWithResources() *model.CryostatInstance { func (r *TestResources) NewCryostatWithLowResourceLimit() *model.CryostatInstance { cr := r.NewCryostat() - cr.Spec.Resources = &operatorv1beta1.ResourceConfigList{ + cr.Spec.Resources = &operatorv1beta2.ResourceConfigList{ CoreResources: corev1.ResourceRequirements{ Limits: corev1.ResourceList{ corev1.ResourceCPU: resource.MustParse("10m"), @@ -534,7 +533,7 @@ func (r *TestResources) NewCryostatWithLowResourceLimit() *model.CryostatInstanc func (r *TestResources) NewCryostatWithAuthProperties() *model.CryostatInstance { cr := r.NewCryostat() - cr.Spec.AuthProperties = &operatorv1beta1.AuthorizationProperties{ + cr.Spec.AuthProperties = &operatorv1beta2.AuthorizationProperties{ ConfigMapName: "authConfigMapName", Filename: "auth.properties", ClusterRoleName: "custom-auth-cluster-role", @@ -544,7 +543,7 @@ func (r *TestResources) NewCryostatWithAuthProperties() *model.CryostatInstance func (r *TestResources) NewCryostatWithBuiltInDiscoveryDisabled() *model.CryostatInstance { cr := r.NewCryostat() - cr.Spec.TargetDiscoveryOptions = &operatorv1beta1.TargetDiscoveryOptions{ + cr.Spec.TargetDiscoveryOptions = &operatorv1beta2.TargetDiscoveryOptions{ BuiltInDiscoveryDisabled: true, } return cr @@ -583,7 +582,7 @@ func newPVCSpec(storageClass string, storageRequest string, func (r *TestResources) NewCryostatWithJmxCacheOptionsSpec() *model.CryostatInstance { cr := r.NewCryostat() - cr.Spec.JmxCacheOptions = &operatorv1beta1.JmxCacheOptions{ + cr.Spec.JmxCacheOptions = &operatorv1beta2.JmxCacheOptions{ TargetCacheSize: 10, TargetCacheTTL: 20, } @@ -599,7 +598,7 @@ func (r *TestResources) NewCryostatWithWsConnectionsSpec() *model.CryostatInstan func (r *TestResources) NewCryostatWithReportSubprocessHeapSpec() *model.CryostatInstance { cr := r.NewCryostat() if cr.Spec.ReportOptions == nil { - cr.Spec.ReportOptions = &operatorv1beta1.ReportConfiguration{} + cr.Spec.ReportOptions = &operatorv1beta2.ReportConfiguration{} } cr.Spec.ReportOptions.SubProcessMaxHeapSize = 500 return cr @@ -611,7 +610,7 @@ func (r *TestResources) NewCryostatWithSecurityOptions() *model.CryostatInstance nonRoot := false runAsUser := int64(0) fsGroup := int64(20000) - cr.Spec.SecurityOptions = &operatorv1beta1.SecurityOptions{ + cr.Spec.SecurityOptions = &operatorv1beta2.SecurityOptions{ PodSecurityContext: &corev1.PodSecurityContext{ RunAsNonRoot: &nonRoot, FSGroup: &fsGroup, @@ -650,9 +649,9 @@ func (r *TestResources) NewCryostatWithReportSecurityOptions() *model.CryostatIn privEscalation := false runAsUser := int64(1002) if cr.Spec.ReportOptions == nil { - cr.Spec.ReportOptions = &operatorv1beta1.ReportConfiguration{} + cr.Spec.ReportOptions = &operatorv1beta2.ReportConfiguration{} } - cr.Spec.ReportOptions.SecurityOptions = &operatorv1beta1.ReportsSecurityOptions{ + cr.Spec.ReportOptions.SecurityOptions = &operatorv1beta2.ReportsSecurityOptions{ PodSecurityContext: &corev1.PodSecurityContext{ RunAsNonRoot: &nonRoot, SeccompProfile: &corev1.SeccompProfile{ @@ -674,7 +673,7 @@ var providedDatabaseSecretName string = "credentials-database-secret" func (r *TestResources) NewCryostatWithDatabaseSecretProvided() *model.CryostatInstance { cr := r.NewCryostat() - cr.Spec.JmxCredentialsDatabaseOptions = &operatorv1beta1.JmxCredentialsDatabaseOptions{ + cr.Spec.JmxCredentialsDatabaseOptions = &operatorv1beta2.JmxCredentialsDatabaseOptions{ DatabaseSecretName: &providedDatabaseSecretName, } return cr @@ -682,8 +681,8 @@ func (r *TestResources) NewCryostatWithDatabaseSecretProvided() *model.CryostatI func (r *TestResources) NewCryostatWithAdditionalMetadata() *model.CryostatInstance { cr := r.NewCryostat() - cr.Spec.OperandMetadata = &operatorv1beta1.OperandMetadata{ - DeploymentMetadata: &operatorv1beta1.ResourceMetadata{ + cr.Spec.OperandMetadata = &operatorv1beta2.OperandMetadata{ + DeploymentMetadata: &operatorv1beta2.ResourceMetadata{ Labels: map[string]string{ "myDeploymentExtraLabel": "myDeploymentLabel", "mySecondDeploymentExtraLabel": "mySecondDeploymentLabel", @@ -700,7 +699,7 @@ func (r *TestResources) NewCryostatWithAdditionalMetadata() *model.CryostatInsta "app.openshift.io/connects-to": "connectToMe", }, }, - PodMetadata: &operatorv1beta1.ResourceMetadata{ + PodMetadata: &operatorv1beta2.ResourceMetadata{ Labels: map[string]string{ "myPodExtraLabel": "myPodLabel", "myPodSecondExtraLabel": "myPodSecondLabel", @@ -726,7 +725,7 @@ func (r *TestResources) NewCryostatService() *corev1.Service { Namespace: r.Namespace, OwnerReferences: []metav1.OwnerReference{ { - APIVersion: operatorv1beta1.GroupVersion.String(), + APIVersion: operatorv1beta2.GroupVersion.String(), Kind: "Cryostat", Name: r.Name, UID: "", @@ -768,7 +767,7 @@ func (r *TestResources) NewGrafanaService() *corev1.Service { Namespace: r.Namespace, OwnerReferences: []metav1.OwnerReference{ { - APIVersion: operatorv1beta1.GroupVersion.String(), + APIVersion: operatorv1beta2.GroupVersion.String(), Kind: "Cryostat", Name: r.Name, UID: "", @@ -805,7 +804,7 @@ func (r *TestResources) NewReportsService() *corev1.Service { Namespace: r.Namespace, OwnerReferences: []metav1.OwnerReference{ { - APIVersion: operatorv1beta1.GroupVersion.String(), + APIVersion: operatorv1beta2.GroupVersion.String(), Kind: "Cryostat", Name: r.Name + "-reports", UID: "", @@ -901,7 +900,7 @@ func (r *TestResources) NewTestService() *corev1.Service { func (r *TestResources) NewCACertSecret(ns string) *corev1.Secret { return &corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ - Name: r.Name + "-ca", + Name: r.getClusterUniqueNameForCA(), Namespace: ns, }, Type: corev1.SecretTypeOpaque, @@ -1110,7 +1109,7 @@ func (r *TestResources) NewCACert() *certv1.Certificate { }, Spec: certv1.CertificateSpec{ CommonName: fmt.Sprintf("ca.%s.cert-manager", r.Name), - SecretName: r.Name + "-ca", + SecretName: r.getClusterUniqueNameForCA(), IssuerRef: certMeta.ObjectReference{ Name: r.Name + "-self-signed", }, @@ -1142,7 +1141,7 @@ func (r *TestResources) NewCryostatCAIssuer() *certv1.Issuer { Spec: certv1.IssuerSpec{ IssuerConfig: certv1.IssuerConfig{ CA: &certv1.CAIssuer{ - SecretName: r.Name + "-ca", + SecretName: r.getClusterUniqueNameForCA(), }, }, }, @@ -2364,7 +2363,7 @@ func (r *TestResources) OtherGrafanaIngress() *netv1.Ingress { } } -func (r *TestResources) newNetworkConfigurationList() operatorv1beta1.NetworkConfigurationList { +func (r *TestResources) newNetworkConfigurationList() operatorv1beta2.NetworkConfigurationList { coreSVC := r.NewCryostatService() coreIng := r.newNetworkConfiguration(coreSVC.Name, coreSVC.Spec.Ports[0].Port) coreIng.Annotations["custom"] = "annotation" @@ -2375,13 +2374,13 @@ func (r *TestResources) newNetworkConfigurationList() operatorv1beta1.NetworkCon grafanaIng.Annotations["grafana"] = "annotation" grafanaIng.Labels["grafana"] = "label" - return operatorv1beta1.NetworkConfigurationList{ + return operatorv1beta2.NetworkConfigurationList{ CoreConfig: &coreIng, GrafanaConfig: &grafanaIng, } } -func (r *TestResources) newNetworkConfiguration(svcName string, svcPort int32) operatorv1beta1.NetworkConfiguration { +func (r *TestResources) newNetworkConfiguration(svcName string, svcPort int32) operatorv1beta2.NetworkConfiguration { pathtype := netv1.PathTypePrefix host := svcName + ".example.com" @@ -2389,7 +2388,7 @@ func (r *TestResources) newNetworkConfiguration(svcName string, svcPort int32) o if r.ExternalTLS { ingressTLS = []netv1.IngressTLS{{}} } - return operatorv1beta1.NetworkConfiguration{ + return operatorv1beta2.NetworkConfiguration{ Annotations: map[string]string{"nginx.ingress.kubernetes.io/backend-protocol": "HTTPS"}, Labels: map[string]string{"my": "label"}, IngressSpec: &netv1.IngressSpec{ @@ -2551,7 +2550,7 @@ func (r *TestResources) NewAuthClusterRole() *rbacv1.ClusterRole { func (r *TestResources) NewRoleBinding(ns string) *rbacv1.RoleBinding { return &rbacv1.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ - Name: r.Name, + Name: r.getClusterUniqueName(), Namespace: ns, }, Subjects: []rbacv1.Subject{ @@ -2572,7 +2571,7 @@ func (r *TestResources) NewRoleBinding(ns string) *rbacv1.RoleBinding { func (r *TestResources) OtherRoleBinding(ns string) *rbacv1.RoleBinding { return &rbacv1.RoleBinding{ ObjectMeta: metav1.ObjectMeta{ - Name: r.Name, + Name: r.getClusterUniqueName(), Namespace: ns, Labels: map[string]string{ "test": "label", @@ -2693,6 +2692,14 @@ func (r *TestResources) NewNamespace() *corev1.Namespace { } } +func (r *TestResources) NewOtherNamespace(name string) *corev1.Namespace { + return &corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + } +} + func (r *TestResources) NewNamespaceWithSCCSupGroups() *corev1.Namespace { ns := r.NewNamespace() ns.Annotations = map[string]string{ @@ -2908,3 +2915,11 @@ func (r *TestResources) getClusterUniqueName() string { } return prefix + r.clusterUniqueSuffix() } + +func (r *TestResources) getClusterUniqueNameForCA() string { + prefix := "cryostat-ca-" + if r.ClusterScoped { + prefix = "clustercryostat-ca-" + } + return prefix + r.clusterUniqueSuffix() +} diff --git a/internal/webhooks/cryostat_webhook.go b/internal/webhooks/cryostat_webhook.go new file mode 100644 index 000000000..64da3fa40 --- /dev/null +++ b/internal/webhooks/cryostat_webhook.go @@ -0,0 +1,44 @@ +// Copyright The Cryostat Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package webhooks + +import ( + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" +) + +// log is for logging in this package. +var cryostatlog = logf.Log.WithName("cryostat-resource") + +// +kubebuilder:rbac:groups=authorization.k8s.io,resources=subjectaccessreviews,verbs=create + +//+kubebuilder:webhook:path=/mutate-operator-cryostat-io-v1beta2-cryostat,mutating=true,failurePolicy=fail,sideEffects=None,groups=operator.cryostat.io,resources=cryostats,verbs=create;update,versions=v1beta2,name=mcryostat.kb.io,admissionReviewVersions=v1 + +// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +//+kubebuilder:webhook:path=/validate-operator-cryostat-io-v1beta2-cryostat,mutating=false,failurePolicy=fail,sideEffects=None,groups=operator.cryostat.io,resources=cryostats,verbs=create;update,versions=v1beta2,name=vcryostat.kb.io,admissionReviewVersions=v1 + +func SetupWebhookWithManager(mgr ctrl.Manager, apiType runtime.Object) error { + return ctrl.NewWebhookManagedBy(mgr). + For(apiType). + WithValidator(&CryostatValidator{ + Client: mgr.GetClient(), + Log: &cryostatlog, + }). + WithDefaulter(&cryostatDefaulter{ + log: &cryostatlog, + }). + Complete() +} diff --git a/internal/webhooks/defaulter.go b/internal/webhooks/defaulter.go new file mode 100644 index 000000000..f58292625 --- /dev/null +++ b/internal/webhooks/defaulter.go @@ -0,0 +1,46 @@ +// Copyright The Cryostat Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package webhooks + +import ( + "context" + "fmt" + + operatorv1beta2 "github.com/cryostatio/cryostat-operator/api/v1beta2" + "github.com/go-logr/logr" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +type cryostatDefaulter struct { + log *logr.Logger +} + +var _ admission.CustomDefaulter = &cryostatDefaulter{} + +// Default applies default values to a Cryostat +func (r *cryostatDefaulter) Default(ctx context.Context, obj runtime.Object) error { + cr, ok := obj.(*operatorv1beta2.Cryostat) + if !ok { + return fmt.Errorf("expected a Cryostat, but received a %T", obj) + } + r.log.Info("defaulting Cryostat", "name", cr.Name, "namespace", cr.Namespace) + + if cr.Spec.TargetNamespaces == nil { + r.log.Info("defaulting target namespaces", "name", cr.Name, "namespace", cr.Namespace) + cr.Spec.TargetNamespaces = []string{cr.Namespace} + } + return nil +} diff --git a/internal/webhooks/test/resources.go b/internal/webhooks/test/resources.go new file mode 100644 index 000000000..b8839530e --- /dev/null +++ b/internal/webhooks/test/resources.go @@ -0,0 +1,72 @@ +// Copyright The Cryostat Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package test + +import ( + operatorv1beta2 "github.com/cryostatio/cryostat-operator/api/v1beta2" + "github.com/cryostatio/cryostat-operator/internal/test" + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type WebhookTestResources struct { + *test.TestResources +} + +func (r *WebhookTestResources) NewWebhookTestServiceAccount() *corev1.ServiceAccount { + return &corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: r.Name + "-webhook-test", + Namespace: r.Namespace, + }, + } +} + +func (r *WebhookTestResources) NewWebhookTestRole(namespace string) *rbacv1.Role { + return &rbacv1.Role{ + ObjectMeta: metav1.ObjectMeta{ + Name: r.Name + "-webhook-test", + Namespace: namespace, + }, + Rules: []rbacv1.PolicyRule{ + { + APIGroups: []string{operatorv1beta2.GroupVersion.Group}, + Verbs: []string{"*"}, + Resources: []string{"cryostats"}, + }, + }, + } +} + +func (r *WebhookTestResources) NewWebhookTestRoleBinding(namespace string) *rbacv1.RoleBinding { + return &rbacv1.RoleBinding{ + ObjectMeta: metav1.ObjectMeta{ + Name: r.Name + "-webhook-test", + Namespace: namespace, + }, + RoleRef: rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "Role", + Name: r.NewWebhookTestRole(namespace).Name, + }, + Subjects: []rbacv1.Subject{ + { + Kind: "ServiceAccount", + Name: r.NewWebhookTestServiceAccount().Name, + }, + }, + } +} diff --git a/internal/webhooks/validator.go b/internal/webhooks/validator.go new file mode 100644 index 000000000..f1b3dd910 --- /dev/null +++ b/internal/webhooks/validator.go @@ -0,0 +1,128 @@ +// Copyright The Cryostat Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package webhooks + +import ( + "context" + "fmt" + + operatorv1beta2 "github.com/cryostatio/cryostat-operator/api/v1beta2" + "github.com/go-logr/logr" + authnv1 "k8s.io/api/authentication/v1" + authzv1 "k8s.io/api/authorization/v1" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +type CryostatValidator struct { + Client client.Client + Log *logr.Logger +} + +var _ admission.CustomValidator = &CryostatValidator{} + +// ValidateCreate validates a Create operation on a Cryostat +func (r *CryostatValidator) ValidateCreate(ctx context.Context, obj runtime.Object) error { + return r.validate(ctx, obj, "create") +} + +// ValidateCreate validates an Update operation on a Cryostat +func (r *CryostatValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) error { + return r.validate(ctx, newObj, "update") +} + +// ValidateCreate validates a Delete operation on a Cryostat +func (r *CryostatValidator) ValidateDelete(ctx context.Context, obj runtime.Object) error { + // Nothing to validate on deletion + return nil +} + +type ErrNotPermitted struct { + operation string + namespace string +} + +func NewErrNotPermitted(operation string, namespace string) *ErrNotPermitted { + return &ErrNotPermitted{ + operation: operation, + namespace: namespace, + } +} + +func (e *ErrNotPermitted) Error() string { + return fmt.Sprintf("unable to %s Cryostat: user is not permitted to create a Cryostat in namespace %s", e.operation, e.namespace) +} + +var _ error = &ErrNotPermitted{} + +func (r *CryostatValidator) validate(ctx context.Context, obj runtime.Object, op string) error { + cr, ok := obj.(*operatorv1beta2.Cryostat) + if !ok { + return fmt.Errorf("expected a Cryostat, but received a %T", obj) + } + r.Log.Info(fmt.Sprintf("validate %s", op), "name", cr.Name, "namespace", cr.Namespace) + + // Look up the user who made this request + req, err := admission.RequestFromContext(ctx) + if err != nil { + return fmt.Errorf("no admission request found in context: %w", err) + } + userInfo := req.UserInfo + + // Check that for each target namespace, the user has permissions + // to create a Cryostat CR in that namespace + for _, namespace := range cr.Spec.TargetNamespaces { + sar := &authzv1.SubjectAccessReview{ + Spec: authzv1.SubjectAccessReviewSpec{ + User: userInfo.Username, + Groups: userInfo.Groups, + UID: userInfo.UID, + Extra: translateExtra(userInfo.Extra), + ResourceAttributes: &authzv1.ResourceAttributes{ + Namespace: namespace, + Verb: "create", + Group: operatorv1beta2.GroupVersion.Group, + Version: operatorv1beta2.GroupVersion.Version, + Resource: "cryostats", + }, + }, + } + + err := r.Client.Create(ctx, sar) + if err != nil { + return fmt.Errorf("failed to check permissions: %w", err) + } + + if !sar.Status.Allowed { + return NewErrNotPermitted(op, namespace) + } + } + + return nil +} + +func translateExtra(extra map[string]authnv1.ExtraValue) map[string]authzv1.ExtraValue { + var result map[string]authzv1.ExtraValue + if extra == nil { + return result + } + result = make(map[string]authzv1.ExtraValue, len(extra)) + for k, v := range extra { + result[k] = authzv1.ExtraValue(v) + } + + return result +} diff --git a/internal/webhooks/validator_test.go b/internal/webhooks/validator_test.go new file mode 100644 index 000000000..584976ac0 --- /dev/null +++ b/internal/webhooks/validator_test.go @@ -0,0 +1,199 @@ +// Copyright The Cryostat Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package webhooks_test + +import ( + "fmt" + "strconv" + + "github.com/cryostatio/cryostat-operator/internal/controllers/model" + "github.com/cryostatio/cryostat-operator/internal/test" + "github.com/cryostatio/cryostat-operator/internal/webhooks" + webhooktests "github.com/cryostatio/cryostat-operator/internal/webhooks/test" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + corev1 "k8s.io/api/core/v1" + kerrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/rest" + ctrlclient "sigs.k8s.io/controller-runtime/pkg/client" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" +) + +type validatorTestInput struct { + client ctrlclient.Client + validator *webhooks.CryostatValidator + objs []ctrlclient.Object + *webhooktests.WebhookTestResources +} + +var _ = Describe("CryostatValidator", func() { + var t *validatorTestInput + var otherNS string + count := 0 + + namespaceWithSuffix := func(name string) string { + return name + "-" + strconv.Itoa(count) + } + + BeforeEach(func() { + ns := namespaceWithSuffix("test") + otherNS = namespaceWithSuffix("other") + t = &validatorTestInput{ + WebhookTestResources: &webhooktests.WebhookTestResources{ + TestResources: &test.TestResources{ + Name: "cryostat", + Namespace: ns, + TargetNamespaces: []string{ + ns, otherNS, + }, + }, + }, + } + t.objs = []ctrlclient.Object{ + t.NewNamespace(), t.NewOtherNamespace(otherNS), + } + }) + + JustBeforeEach(func() { + logger := zap.New() + logf.SetLogger(logger) + + t.client = k8sClient + t.validator = &webhooks.CryostatValidator{ + Client: k8sClient, + Log: &logger, + } + + for _, obj := range t.objs { + err := t.client.Create(ctx, obj) + Expect(err).ToNot(HaveOccurred()) + } + }) + + JustAfterEach(func() { + for _, obj := range t.objs { + err := ctrlclient.IgnoreNotFound(t.client.Delete(ctx, obj)) + Expect(err).ToNot(HaveOccurred()) + } + }) + + AfterEach(func() { + count++ + }) + + Context("authorized user", func() { + var cr *model.CryostatInstance + + BeforeEach(func() { + cr = t.NewCryostat() + }) + + Context("creates a Cryostat", func() { + It("should allow the request", func() { + err := t.client.Create(ctx, cr.Object) + Expect(err).ToNot(HaveOccurred()) + }) + }) + + Context("updates a Cryostat", func() { + BeforeEach(func() { + t.objs = append(t.objs, cr.Object) + }) + + It("should allow the request", func() { + err := t.client.Update(ctx, cr.Object) + Expect(err).ToNot(HaveOccurred()) + }) + }) + + Context("deletes a Cryostat", func() { + BeforeEach(func() { + t.objs = append(t.objs, cr.Object) + }) + + It("should allow the request", func() { + err := t.client.Delete(ctx, cr.Object) + Expect(err).ToNot(HaveOccurred()) + }) + }) + }) + + Context("unauthorized user", func() { + var cr *model.CryostatInstance + var sa *corev1.ServiceAccount + var saClient ctrlclient.Client + + BeforeEach(func() { + cr = t.NewCryostat() + sa = t.NewWebhookTestServiceAccount() + t.objs = append(t.objs, + sa, + t.NewWebhookTestRole(t.Namespace), + t.NewWebhookTestRoleBinding(t.Namespace), + ) + }) + + JustBeforeEach(func() { + config := rest.CopyConfig(cfg) + config.Impersonate = rest.ImpersonationConfig{ + UserName: fmt.Sprintf("system:serviceaccount:%s:%s", sa.Namespace, sa.Name), + } + client, err := ctrlclient.New(config, ctrlclient.Options{Scheme: k8sScheme}) + Expect(err).ToNot(HaveOccurred()) + saClient = client + }) + + Context("creates a Cryostat", func() { + It("should deny the request", func() { + err := saClient.Create(ctx, cr.Object) + Expect(err).To((HaveOccurred())) + expectErrNotPermitted(err, "create", otherNS) + }) + }) + + Context("updates a Cryostat", func() { + BeforeEach(func() { + t.objs = append(t.objs, cr.Object) + }) + + It("should deny the request", func() { + err := saClient.Update(ctx, cr.Object) + Expect(err).To((HaveOccurred())) + expectErrNotPermitted(err, "update", otherNS) + }) + }) + + Context("deletes a Cryostat", func() { + BeforeEach(func() { + t.objs = append(t.objs, cr.Object) + }) + + It("should allow the request", func() { + err := saClient.Delete(ctx, cr.Object) + Expect(err).ToNot(HaveOccurred()) + }) + }) + }) + +}) + +func expectErrNotPermitted(actual error, op string, namespace string) { + expectedErr := webhooks.NewErrNotPermitted(op, namespace) + Expect(kerrors.IsForbidden(actual)).To(BeTrue(), "expected Forbidden API error") + Expect(kerrors.ReasonForError(actual)).To(Equal(metav1.StatusReason(expectedErr.Error()))) +} diff --git a/internal/webhooks/webhook_suite_test.go b/internal/webhooks/webhook_suite_test.go new file mode 100644 index 000000000..7d7dca37f --- /dev/null +++ b/internal/webhooks/webhook_suite_test.go @@ -0,0 +1,137 @@ +// Copyright The Cryostat Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package webhooks_test + +import ( + "context" + "crypto/tls" + "fmt" + "net" + "path/filepath" + "testing" + "time" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + operatorv1beta2 "github.com/cryostatio/cryostat-operator/api/v1beta2" + "github.com/cryostatio/cryostat-operator/internal/webhooks" + admissionv1beta1 "k8s.io/api/admission/v1beta1" + + //+kubebuilder:scaffold:imports + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. + +var cfg *rest.Config +var k8sClient client.Client +var testEnv *envtest.Environment +var ctx context.Context +var cancel context.CancelFunc +var k8sScheme *runtime.Scheme + +func TestAPIs(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecs(t, "Webhook Suite") +} + +var _ = BeforeSuite(func() { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + ctx, cancel = context.WithCancel(context.TODO()) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + ErrorIfCRDPathMissing: false, + WebhookInstallOptions: envtest.WebhookInstallOptions{ + Paths: []string{filepath.Join("..", "..", "config", "webhook")}, + }, + } + + var err error + // cfg is defined in this file globally. + cfg, err = testEnv.Start() + Expect(err).NotTo(HaveOccurred()) + Expect(cfg).NotTo(BeNil()) + + k8sScheme = runtime.NewScheme() + err = scheme.AddToScheme(k8sScheme) + Expect(err).NotTo(HaveOccurred()) + err = operatorv1beta2.AddToScheme(k8sScheme) + Expect(err).NotTo(HaveOccurred()) + + err = admissionv1beta1.AddToScheme(k8sScheme) + Expect(err).NotTo(HaveOccurred()) + + //+kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: k8sScheme}) + Expect(err).NotTo(HaveOccurred()) + Expect(k8sClient).NotTo(BeNil()) + + // start webhook server using Manager + webhookInstallOptions := &testEnv.WebhookInstallOptions + mgr, err := ctrl.NewManager(cfg, ctrl.Options{ + Scheme: k8sScheme, + Host: webhookInstallOptions.LocalServingHost, + Port: webhookInstallOptions.LocalServingPort, + CertDir: webhookInstallOptions.LocalServingCertDir, + LeaderElection: false, + MetricsBindAddress: "0", + }) + Expect(err).NotTo(HaveOccurred()) + + err = webhooks.SetupWebhookWithManager(mgr, &operatorv1beta2.Cryostat{}) + Expect(err).NotTo(HaveOccurred()) + + //+kubebuilder:scaffold:webhook + + go func() { + defer GinkgoRecover() + err = mgr.Start(ctx) + Expect(err).NotTo(HaveOccurred()) + }() + + // wait for the webhook server to get ready + dialer := &net.Dialer{Timeout: time.Second} + addrPort := fmt.Sprintf("%s:%d", webhookInstallOptions.LocalServingHost, webhookInstallOptions.LocalServingPort) + Eventually(func() error { + conn, err := tls.DialWithDialer(dialer, "tcp", addrPort, &tls.Config{InsecureSkipVerify: true}) + if err != nil { + return err + } + conn.Close() + return nil + }).Should(Succeed()) + +}) + +var _ = AfterSuite(func() { + cancel() + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).NotTo(HaveOccurred()) +})