diff --git a/Makefile b/Makefile
index 4732c8998..b7d419c6a 100644
--- a/Makefile
+++ b/Makefile
@@ -43,7 +43,7 @@ check-jq:
jq --version > /dev/null
.PHONY: docs
-docs: $(CRDOC)
+docs: $(CRDOC) generate-crds
mkdir -p docs
$(CRDOC) --resources deploy/crds/common --output docs/api.md
diff --git a/bundle/manifests/observability-operator.clusterserviceversion.yaml b/bundle/manifests/observability-operator.clusterserviceversion.yaml
index 1a4a4ae16..f721444dc 100644
--- a/bundle/manifests/observability-operator.clusterserviceversion.yaml
+++ b/bundle/manifests/observability-operator.clusterserviceversion.yaml
@@ -41,8 +41,8 @@ metadata:
capabilities: Basic Install
categories: Monitoring
certified: "false"
- containerImage: observability-operator:1.0.0
- createdAt: "2025-03-03T08:38:22Z"
+ containerImage: grover.home:5000/alanconway/observability-operator:3.3.3
+ createdAt: "2025-04-10T17:19:16Z"
description: A Go based Kubernetes operator to setup and manage highly available
Monitoring Stack using Prometheus, Alertmanager and Thanos Querier.
operatorframework.io/cluster-monitoring: "true"
@@ -58,7 +58,7 @@ metadata:
]
operators.operatorframework.io/project_layout: unknown
repository: https://github.com/rhobs/observability-operator
- name: observability-operator.v1.0.0
+ name: observability-operator.v3.3.3
namespace: placeholder
spec:
apiservicedefinitions: {}
@@ -511,23 +511,33 @@ spec:
- apiGroups:
- observability.openshift.io
resources:
- - uiplugins
+ - signalmanagers
verbs:
- - create
- - delete
- get
- list
- - patch
- - update
- watch
- apiGroups:
- observability.openshift.io
resources:
+ - signalmanagers/finalizers
+ - signalmanagers/status
- uiplugins/finalizers
- uiplugins/status
verbs:
- get
- update
+ - apiGroups:
+ - observability.openshift.io
+ resources:
+ - uiplugins
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - patch
+ - update
+ - watch
- apiGroups:
- operator.openshift.io
resources:
@@ -917,7 +927,7 @@ spec:
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- image: observability-operator:1.0.0
+ image: grover.home:5000/alanconway/observability-operator:3.3.3
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -1045,7 +1055,7 @@ spec:
maturity: alpha
provider:
name: Red Hat
- version: 1.0.0
+ version: 3.3.3
webhookdefinitions:
- admissionReviewVersions:
- v1
diff --git a/cmd/operator/main.go b/cmd/operator/main.go
index d61d8d0b3..aa4884a0f 100644
--- a/cmd/operator/main.go
+++ b/cmd/operator/main.go
@@ -40,13 +40,13 @@ var defaultImages = map[string]string{
"alertmanager": "",
"thanos": obopo.DefaultThanosImage,
"ui-dashboards": "quay.io/openshift-observability-ui/console-dashboards-plugin:v0.4.0",
- "ui-troubleshooting-panel": "quay.io/openshift-observability-ui/troubleshooting-panel-console-plugin:v0.4.0",
+ "ui-troubleshooting-panel": "grover.home:5000/alanconway/troubleshooting-panel-console-plugin:latest",
"ui-distributed-tracing-pf4": "quay.io/openshift-observability-ui/distributed-tracing-console-plugin:v0.3.0",
"ui-distributed-tracing": "quay.io/openshift-observability-ui/distributed-tracing-console-plugin:v0.4.0",
"ui-logging-pf4": "quay.io/openshift-observability-ui/logging-view-plugin:v6.0.0",
"ui-logging": "quay.io/openshift-observability-ui/logging-view-plugin:v6.1.0",
"ui-monitoring": "quay.io/openshift-observability-ui/monitoring-console-plugin:release-coo-1.1",
- "korrel8r": "quay.io/korrel8r/korrel8r:0.7.4",
+ "korrel8r": "grover.home:5000/alanconway/korrel8r:latest",
"health-analyzer": "quay.io/openshiftanalytics/cluster-health-analyzer:v0.4.0",
"perses": "quay.io/persesdev/perses:v0.50.1",
}
@@ -95,7 +95,7 @@ func main() {
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
flag.StringVar(&healthProbeAddr, "health-probe-bind-address", ":8081", "The address the health probe endpoint binds to.")
flag.Var(images, "images", fmt.Sprintf("Full images refs to use for containers managed by the operator. E.g thanos=quay.io/thanos/thanos:v0.33.0. Images used are %v", imagesUsed()))
- flag.BoolVar(&openShiftEnabled, "openshift.enabled", false, "Enable OpenShift specific features such as Console Plugins.")
+ flag.BoolVar(&openShiftEnabled, "openshift.enabled", true, "Enable OpenShift specific features such as Console Plugins.")
opts := zap.Options{
Development: true,
diff --git a/deploy/crds/common/observability.openshift.io_configs.yaml b/deploy/crds/common/observability.openshift.io_configs.yaml
new file mode 100644
index 000000000..64c5e62d0
--- /dev/null
+++ b/deploy/crds/common/observability.openshift.io_configs.yaml
@@ -0,0 +1,94 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.16.2
+ name: configs.observability.openshift.io
+spec:
+ group: observability.openshift.io
+ names:
+ kind: Config
+ listKind: ConfigList
+ plural: configs
+ singular: config
+ scope: Cluster
+ versions:
+ - name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: |-
+ Config defines an observability configuration that can deploy operators and resources for
+ observability signal collectors and stores.
+ 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: ConfigSpec specifies what to install.
+ properties:
+ defaultInstall:
+ description: |-
+ DefaultInstall is the default install type for signals that are not listed or
+ are listed without an `install` field.
+ For example, `{ defaultinstall: Default }` with no `signals` field installs all signal
+ types with default settings.
+ type: string
+ installDefinitions:
+ items:
+ description: InstallDefinitionSpec defines a new installation type.
+ properties:
+ configMap:
+ description: |-
+ ConfigMap contains deployment bundles for the install type, with key=signal type.
+ FIXME: which way around? install < signal or signal < install
+ type: string
+ install:
+ description: Name of the installation type.
+ type: string
+ type: object
+ type: array
+ signals:
+ description: Signals specifies what to install for each signal type.
+ items:
+ properties:
+ installType:
+ description: Install type for this signal. Optional, if absent
+ use ..defaultInstall
+ type: string
+ namespace:
+ description: |-
+ Namespace to install to. Optional, each signal type has a default namespace.
+ A signal can be listed multiple times with different `namespace` values,
+ to install in multiple namespaces.
+ type: string
+ signal:
+ description: Name of this signal type.
+ type: string
+ required:
+ - signal
+ type: object
+ type: array
+ type: object
+ status:
+ description: FIXME Status
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/deploy/crds/common/observability.openshift.io_signalmanagers.yaml b/deploy/crds/common/observability.openshift.io_signalmanagers.yaml
new file mode 100644
index 000000000..b3b05e023
--- /dev/null
+++ b/deploy/crds/common/observability.openshift.io_signalmanagers.yaml
@@ -0,0 +1,135 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.16.2
+ name: signalmanagers.observability.openshift.io
+spec:
+ group: observability.openshift.io
+ names:
+ kind: SignalManager
+ listKind: SignalManagerList
+ plural: signalmanagers
+ singular: signalmanager
+ scope: Cluster
+ versions:
+ - name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: "SignalManager is a custom resource to enable observability in
+ the cluster.\n\nEach type of observability signal (logs, metrics, network
+ events, ...) requires operators to be\ninstalled and resources created to
+ configure collection, processing, and storage of signal data.\n\nThe SignalManager
+ automatically installs the operators, custom resource definitions, and\nresources
+ to enable all the desired observability signals in a cluster with default\nconfigurations.\n\nThis
+ means you can get observability up and running quickly and easily,\nbut
+ still customize the details if and when you need to.\n\n## Pattern\n\nA
+ \"Pattern\" is a named set of configurations for each of the observability
+ signals.\nChoosing a pattern automatically installs required operators (if
+ needed) _and_ creates\nworking resources so you have complete, working,
+ observability stacks.\n\nThe following patterns are always available, others
+ may be made available.\n\n - Default:\n Installs operators and resources
+ suitable for the most common use cases.\n The operator owns and manages
+ the resources, and keeps them in the default state.\n - Custom:\n Installs
+ operators, but does not create any live resources.\n The user can create
+ customized resources, they will not be modified by this operator.\n - Disabled:
+ Do not install any operators, resource definitions, or resources.\n\nCustom
+ patterns can be defined in `spec.patterns`.\n\n## Examples\n\nEnable all
+ observability components with default settings.\n\n\tkind: SignalManager\n\tspec:\n\t
+ \ pattern: Default\n\nDisable all observability components except for logging.\n\n\tkind:
+ SignalManager\n\tspec:\n\t pattern: Disabled\n\t signals:\n\t name:
+ Log\n\t pattern: Default\n\nEnable most components with defaults, install
+ the logging operators,\nbut use custom logging resources (created separately)\n\n\tkind:
+ SignalManager\n\tspec:\n\t pattern: Default\n\t signals:\n\t name:
+ log\n\t pattern: Custom\n\n## Lifecycle and ownership\n\nOwnership of
+ resources depends on the pattern:\n\n - None: No operators installed, no
+ resources created or reconciled.\n - Custom: Operators installed but no
+ resources created. User is free to create resources\n they are not owned
+ or reconciled by this operator.\n - Default, or any other defined configuration:\n
+ \ This operator creates, owns, and reconciles resources to keep them consistent
+ with the chosen\n pattern.\n\nFIXME: Operator may reconcile only part
+ of the resource and allow user to tweak other parts.\nNeeds consideration.
+ COO already uses server-side-apply to do this in some cases.\n\nFIXME: Patterns
+ may need to be \"parameterized\" e.g. with sizing data.\nHow to include
+ such parameters without duplicating existing CRs?\n\nFIXME: Define behavior
+ on spec changes: deleting, re-creating, updating resources.\nChange to Custom
+ should leave resources in place so user can eddit.\nWhat to do on change
+ _from_ Custom?"
+ 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: Lists signals and the pattern to deploy them.
+ properties:
+ pattern:
+ description: The default pattern for signals that are not listed or
+ have no `pattern` field.
+ type: string
+ patterns:
+ description: Patterns is a list of custom pattern definitions.
+ items:
+ description: |-
+ PatternSpec defines a custom pattern.
+
+ on the cluster. Simplest format is a flat YAML file, but we may need more structure
+ to store kustomize scripts, multi-stage deployments, health checks, metadata etc....
+ Possible storage formats: ConfigMap, PersistentVolume, container image...
+
+ Patterns should also be usable directly, without depending on this API.
+ Preferably using only kubectl and kustomize.
+ properties:
+ pattern:
+ description: Name of the pattern.
+ type: string
+ required:
+ - pattern
+ type: object
+ type: array
+ signals:
+ description: Signals is a list of signal types with the desired pattern.
+ items:
+ properties:
+ name:
+ description: Signal name
+ type: string
+ namespace:
+ description: |-
+ Namespace to install to.
+
+ Optional, each signal type has a default namespace.
+ type: string
+ pattern:
+ description: Pattern for this signal. Optional, if absent use
+ the 'Default' pattern.
+ type: string
+ required:
+ - name
+ type: object
+ type: array
+ required:
+ - pattern
+ type: object
+ status:
+ description: Status of the signal manager.
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/deploy/olm/kustomization.yaml b/deploy/olm/kustomization.yaml
index ba0c104fb..994541ea6 100644
--- a/deploy/olm/kustomization.yaml
+++ b/deploy/olm/kustomization.yaml
@@ -12,8 +12,8 @@ resources:
images:
- name: observability-operator
- newName: observability-operator
- newTag: 1.0.0
+ newName: grover.home:5000/alanconway/observability-operator
+ newTag: 3.3.3
patches:
- patch: |-
diff --git a/deploy/operator/observability-operator-cluster-role.yaml b/deploy/operator/observability-operator-cluster-role.yaml
index 6b0b82ca1..ef9d305d4 100644
--- a/deploy/operator/observability-operator-cluster-role.yaml
+++ b/deploy/operator/observability-operator-cluster-role.yaml
@@ -226,23 +226,33 @@ rules:
- apiGroups:
- observability.openshift.io
resources:
- - uiplugins
+ - signalmanagers
verbs:
- - create
- - delete
- get
- list
- - patch
- - update
- watch
- apiGroups:
- observability.openshift.io
resources:
+ - signalmanagers/finalizers
+ - signalmanagers/status
- uiplugins/finalizers
- uiplugins/status
verbs:
- get
- update
+- apiGroups:
+ - observability.openshift.io
+ resources:
+ - uiplugins
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - patch
+ - update
+ - watch
- apiGroups:
- operator.openshift.io
resources:
diff --git a/deploy/package-operator/operator/kustomization.yaml b/deploy/package-operator/operator/kustomization.yaml
index cebb4fc32..68c43937e 100644
--- a/deploy/package-operator/operator/kustomization.yaml
+++ b/deploy/package-operator/operator/kustomization.yaml
@@ -3,8 +3,8 @@ kind: Kustomization
namespace: observability-operator
images:
- name: observability-operator
- newName: observability-operator
- newTag: 1.0.0
+ newName: grover.home:5000/alanconway/observability-operator
+ newTag: 3.3.3
commonAnnotations:
package-operator.run/phase: operator
resources:
diff --git a/docs/api.md b/docs/api.md
index 37e47a052..35836e01c 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -3984,11 +3984,438 @@ Reference to the TLS private key for the web server.
Resource Types:
+- [Config](#config)
+
+- [SignalManager](#signalmanager)
+
- [UIPlugin](#uiplugin)
+## Config
+[↩ Parent](#observabilityopenshiftiov1alpha1 )
+
+
+
+
+
+
+Config defines an observability configuration that can deploy operators and resources for
+observability signal collectors and stores.
+
+
+
+
+ Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ apiVersion |
+ string |
+ observability.openshift.io/v1alpha1 |
+ true |
+
+
+ kind |
+ string |
+ Config |
+ true |
+
+
+ metadata |
+ object |
+ Refer to the Kubernetes API documentation for the fields of the `metadata` field. |
+ true |
+
+ spec |
+ object |
+
+ ConfigSpec specifies what to install.
+ |
+ false |
+
+ status |
+ object |
+
+ FIXME Status
+ |
+ false |
+
+
+
+
+### Config.spec
+[↩ Parent](#config)
+
+
+
+ConfigSpec specifies what to install.
+
+
+
+
+ Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ defaultInstall |
+ string |
+
+ DefaultInstall is the default install type for signals that are not listed or
+are listed without an `install` field.
+For example, `{ defaultinstall: Default }` with no `signals` field installs all signal
+types with default settings.
+ |
+ false |
+
+ installDefinitions |
+ []object |
+
+
+ |
+ false |
+
+ signals |
+ []object |
+
+ Signals specifies what to install for each signal type.
+ |
+ false |
+
+
+
+
+### Config.spec.installDefinitions[index]
+[↩ Parent](#configspec)
+
+
+
+InstallDefinitionSpec defines a new installation type.
+
+
+
+
+ Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ configMap |
+ string |
+
+ ConfigMap contains deployment bundles for the install type, with key=signal type.
+FIXME: which way around? install < signal or signal < install
+ |
+ false |
+
+ install |
+ string |
+
+ Name of the installation type.
+ |
+ false |
+
+
+
+
+### Config.spec.signals[index]
+[↩ Parent](#configspec)
+
+
+
+
+
+
+
+
+ Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ signal |
+ string |
+
+ Name of this signal type.
+ |
+ true |
+
+ installType |
+ string |
+
+ Install type for this signal. Optional, if absent use ..defaultInstall
+ |
+ false |
+
+ namespace |
+ string |
+
+ Namespace to install to. Optional, each signal type has a default namespace.
+A signal can be listed multiple times with different `namespace` values,
+to install in multiple namespaces.
+ |
+ false |
+
+
+
+## SignalManager
+[↩ Parent](#observabilityopenshiftiov1alpha1 )
+
+
+
+
+
+
+SignalManager is a custom resource to enable observability in the cluster.
+
+Each type of observability signal (logs, metrics, network events, ...) requires operators to be
+installed and resources created to configure collection, processing, and storage of signal data.
+
+The SignalManager automatically installs the operators, custom resource definitions, and
+resources to enable all the desired observability signals in a cluster with default
+configurations.
+
+This means you can get observability up and running quickly and easily,
+but still customize the details if and when you need to.
+
+## Pattern
+
+A "Pattern" is a named set of configurations for each of the observability signals.
+Choosing a pattern automatically installs required operators (if needed) _and_ creates
+working resources so you have complete, working, observability stacks.
+
+The following patterns are always available, others may be made available.
+
+ - Default:
+ Installs operators and resources suitable for the most common use cases.
+ The operator owns and manages the resources, and keeps them in the default state.
+ - Custom:
+ Installs operators, but does not create any live resources.
+ The user can create customized resources, they will not be modified by this operator.
+ - Disabled: Do not install any operators, resource definitions, or resources.
+
+Custom patterns can be defined in `spec.patterns`.
+
+## Examples
+
+Enable all observability components with default settings.
+
+ kind: SignalManager
+ spec:
+ pattern: Default
+
+Disable all observability components except for logging.
+
+ kind: SignalManager
+ spec:
+ pattern: Disabled
+ signals:
+ name: Log
+ pattern: Default
+
+Enable most components with defaults, install the logging operators,
+but use custom logging resources (created separately)
+
+ kind: SignalManager
+ spec:
+ pattern: Default
+ signals:
+ name: log
+ pattern: Custom
+
+## Lifecycle and ownership
+
+Ownership of resources depends on the pattern:
+
+ - None: No operators installed, no resources created or reconciled.
+ - Custom: Operators installed but no resources created. User is free to create resources
+ they are not owned or reconciled by this operator.
+ - Default, or any other defined configuration:
+ This operator creates, owns, and reconciles resources to keep them consistent with the chosen
+ pattern.
+
+FIXME: Operator may reconcile only part of the resource and allow user to tweak other parts.
+Needs consideration. COO already uses server-side-apply to do this in some cases.
+
+FIXME: Patterns may need to be "parameterized" e.g. with sizing data.
+How to include such parameters without duplicating existing CRs?
+
+FIXME: Define behavior on spec changes: deleting, re-creating, updating resources.
+Change to Custom should leave resources in place so user can eddit.
+What to do on change _from_ Custom?
+
+
+
+
+ Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ apiVersion |
+ string |
+ observability.openshift.io/v1alpha1 |
+ true |
+
+
+ kind |
+ string |
+ SignalManager |
+ true |
+
+
+ metadata |
+ object |
+ Refer to the Kubernetes API documentation for the fields of the `metadata` field. |
+ true |
+
+ spec |
+ object |
+
+ Lists signals and the pattern to deploy them.
+ |
+ false |
+
+ status |
+ object |
+
+ Status of the signal manager.
+ |
+ false |
+
+
+
+
+### SignalManager.spec
+[↩ Parent](#signalmanager)
+
+
+
+Lists signals and the pattern to deploy them.
+
+
+
+
+ Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ pattern |
+ string |
+
+ The default pattern for signals that are not listed or have no `pattern` field.
+ |
+ true |
+
+ patterns |
+ []object |
+
+ Patterns is a list of custom pattern definitions.
+ |
+ false |
+
+ signals |
+ []object |
+
+ Signals is a list of signal types with the desired pattern.
+ |
+ false |
+
+
+
+
+### SignalManager.spec.patterns[index]
+[↩ Parent](#signalmanagerspec)
+
+
+
+PatternSpec defines a custom pattern.
+
+on the cluster. Simplest format is a flat YAML file, but we may need more structure
+to store kustomize scripts, multi-stage deployments, health checks, metadata etc....
+Possible storage formats: ConfigMap, PersistentVolume, container image...
+
+Patterns should also be usable directly, without depending on this API.
+Preferably using only kubectl and kustomize.
+
+
+
+
+ Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ pattern |
+ string |
+
+ Name of the pattern.
+ |
+ true |
+
+
+
+
+### SignalManager.spec.signals[index]
+[↩ Parent](#signalmanagerspec)
+
+
+
+
+
+
+
+
+ Name |
+ Type |
+ Description |
+ Required |
+
+
+
+ name |
+ string |
+
+ Signal name
+ |
+ true |
+
+ namespace |
+ string |
+
+ Namespace to install to.
+
+Optional, each signal type has a default namespace.
+ |
+ false |
+
+ pattern |
+ string |
+
+ Pattern for this signal. Optional, if absent use the 'Default' pattern.
+ |
+ false |
+
+
+
## UIPlugin
[↩ Parent](#observabilityopenshiftiov1alpha1 )
diff --git a/pkg/apis/signal_manager/v1alpha1/#zz_generated.deepcopy.go# b/pkg/apis/signal_manager/v1alpha1/#zz_generated.deepcopy.go#
new file mode 100644
index 000000000..7ea43fb61
--- /dev/null
+++ b/pkg/apis/signal_manager/v1alpha1/#zz_generated.deepcopy.go#
@@ -0,0 +1,146 @@
+//go:build !ignore_autogenerated
+
+/*
+Copyright 2021.
+
+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 v1alpha1
+
+import (
+ 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 *StrategySpec) DeepCopyInto(out *StrategySpec) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InstallDefinitionSpec.
+func (in *StrategySpec) DeepCopy() *StrategySpec {
+ if in == nil {
+ return nil
+ }
+ out := new(StrategySpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SignalManager) DeepCopyInto(out *SignalManager) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+ in.Spec.DeepCopyInto(&out.Spec)
+ out.Status = in.Status
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SignalManager.
+func (in *SignalManager) DeepCopy() *SignalManager {
+ if in == nil {
+ return nil
+ }
+ out := new(SignalManager)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SignalManagerList) DeepCopyInto(out *SignalManagerList) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ListMeta.DeepCopyInto(&out.ListMeta)
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]SignalManager, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SignalManagerList.
+func (in *SignalManagerList) DeepCopy() *SignalManagerList {
+ if in == nil {
+ return nil
+ }
+ out := new(SignalManagerList)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *SignalManagerList) 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 *SignalManagerSpec) DeepCopyInto(out *SignalManagerSpec) {
+ *out = *in
+ if in.Signals != nil {
+ in, out := &in.Signals, &out.Signals
+ *out = make([]SignalSpec, len(*in))
+ copy(*out, *in)
+ }
+ if in.InstallDefinitions != nil {
+ in, out := &in.InstallDefinitions, &out.InstallDefinitions
+ *out = make([]StrategySpec, len(*in))
+ copy(*out, *in)
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SignalManagerSpec.
+func (in *SignalManagerSpec) DeepCopy() *SignalManagerSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(SignalManagerSpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SignalManagerStatus) DeepCopyInto(out *SignalManagerStatus) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SignalManagerStatus.
+func (in *SignalManagerStatus) DeepCopy() *SignalManagerStatus {
+ if in == nil {
+ return nil
+ }
+ out := new(SignalManagerStatus)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SignalSpec) DeepCopyInto(out *SignalSpec) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SignalSpec.
+func (in *SignalSpec) DeepCopy() *SignalSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(SignalSpec)
+ in.DeepCopyInto(out)
+ return out
+}
diff --git a/pkg/apis/signal_manager/v1alpha1/register.go b/pkg/apis/signal_manager/v1alpha1/register.go
new file mode 100644
index 000000000..116f9d39c
--- /dev/null
+++ b/pkg/apis/signal_manager/v1alpha1/register.go
@@ -0,0 +1,40 @@
+/*
+Copyright 2021.
+
+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 v1alpha1 contains API Schema definitions for the config APIs.
+// +kubebuilder:object:generate=true
+// +groupName=observability.openshift.io
+package v1alpha1
+
+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: "observability.openshift.io", Version: "v1alpha1"}
+
+ // 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
+)
+
+func init() {
+ SchemeBuilder.Register(&SignalManager{}, &SignalManagerList{})
+}
diff --git a/pkg/apis/signal_manager/v1alpha1/types.go b/pkg/apis/signal_manager/v1alpha1/types.go
new file mode 100644
index 000000000..f58347e09
--- /dev/null
+++ b/pkg/apis/signal_manager/v1alpha1/types.go
@@ -0,0 +1,185 @@
+// +groupName=observability.openshift.io
+// +kubebuilder:rbac:groups=observability.openshift.io,resources=signalmanagers,verbs=list;get;watch
+// +kubebuilder:rbac:groups=observability.openshift.io,resources=signalmanagers/status;signalmanagers/finalizers,verbs=get;update
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+package v1alpha1
+
+import (
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// FIXME review naming: SignalManager, Pattern
+// FIXME: review cluster scope, validation
+
+// SignalManager is a custom resource to enable observability in the cluster.
+//
+// Each type of observability signal (logs, metrics, network events, ...) requires operators to be
+// installed and resources created to configure collection, processing, and storage of signal data.
+//
+// The SignalManager automatically installs the operators, custom resource definitions, and
+// resources to enable all the desired observability signals in a cluster with default
+// configurations.
+//
+// This means you can get observability up and running quickly and easily,
+// but still customize the details if and when you need to.
+//
+// ## Pattern
+//
+// A "Pattern" is a named set of configurations for each of the observability signals.
+// Choosing a pattern automatically installs required operators (if needed) _and_ creates
+// working resources so you have complete, working, observability stacks.
+//
+// The following patterns are always available, others may be made available.
+//
+// - Default:
+// Installs operators and resources suitable for the most common use cases.
+// The operator owns and manages the resources, and keeps them in the default state.
+// - Custom:
+// Installs operators, but does not create any live resources.
+// The user can create customized resources, they will not be modified by this operator.
+// - Disabled: Do not install any operators, resource definitions, or resources.
+//
+// Custom patterns can be defined in `spec.patterns`.
+//
+// ## Examples
+//
+// Enable all observability components with default settings.
+//
+// kind: SignalManager
+// spec:
+// pattern: Default
+//
+// Disable all observability components except for logging.
+//
+// kind: SignalManager
+// spec:
+// pattern: Disabled
+// signals:
+// name: Log
+// pattern: Default
+//
+// Enable most components with defaults, install the logging operators,
+// but use custom logging resources (created separately)
+//
+// kind: SignalManager
+// spec:
+// pattern: Default
+// signals:
+// name: log
+// pattern: Custom
+//
+// ## Lifecycle and ownership
+//
+// Ownership of resources depends on the pattern:
+//
+// - None: No operators installed, no resources created or reconciled.
+// - Custom: Operators installed but no resources created. User is free to create resources
+// they are not owned or reconciled by this operator.
+// - Default, or any other defined configuration:
+// This operator creates, owns, and reconciles resources to keep them consistent with the chosen
+// pattern.
+//
+// FIXME: Operator may reconcile only part of the resource and allow user to tweak other parts.
+// Needs consideration. COO already uses server-side-apply to do this in some cases.
+//
+// FIXME: Patterns may need to be "parameterized" e.g. with sizing data.
+// How to include such parameters without duplicating existing CRs?
+//
+// FIXME: Define behavior on spec changes: deleting, re-creating, updating resources.
+// Change to Custom should leave resources in place so user can eddit.
+// What to do on change _from_ Custom?
+//
+// +k8s:openapi-gen=true
+// +kubebuilder:resource:scope=Cluster
+// +kubebuilder:subresource:status
+type SignalManager struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ // Lists signals and the pattern to deploy them.
+ Spec SignalManagerSpec `json:"spec,omitempty"`
+
+ // Status of the signal manager.
+ Status SignalManagerStatus `json:"status,omitempty"`
+}
+
+// +kubebuilder:resource
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+type SignalManagerList struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ListMeta `json:"metadata,omitempty"`
+ Items []SignalManager `json:"items"`
+}
+
+type SignalManagerSpec struct {
+
+ // The default pattern for signals that are not listed or have no `pattern` field.
+ Pattern Pattern `json:"pattern"`
+
+ // Signals is a list of signal types with the desired pattern.
+ Signals []SignalSpec `json:"signals,omitempty"`
+
+ // Patterns is a list of custom pattern definitions.
+ Patterns []PatternSpec `json:"patterns,omitempty"`
+}
+
+type SignalSpec struct {
+ // Signal name
+ Name Signal `json:"name"`
+
+ // Pattern for this signal. Optional, if absent use the 'Default' pattern.
+ Pattern Pattern `json:"pattern,omitempty"`
+
+ // Namespace to install to.
+ //
+ // Optional, each signal type has a default namespace.
+ Namespace string `json:"namespace,omitempty"`
+}
+
+// Signal is the name of a signal type.
+// TODO complete the list
+type Signal string
+
+const (
+ SignalLog Signal = "Log"
+ SignalTrace = "Trace"
+ SignalMetric = "Metric"
+ SignalNetflow = "Netflow"
+)
+
+// Pattern is the name of a deployment pattern. The following patterns are always available:
+// - Default: Install operators and custom resources to enable the signal with a default configuration
+// intended to be suitable for most single-cluster use cases.
+// The operator owns and manages the resources, and keeps them in the default state.
+// - Custom: Install operators and custom resource definitions, but do not create any resources.
+// The user can create customized resources, they will not be managed or modified by this operator.
+// - Disabled: Do not install operators, resource definitions, or resources.
+//
+// Custom patterns can also be defined in spec.patterns.
+// The operator owns and manages the resources, and keeps them in the state specified by the pattern.
+type Pattern string
+
+const (
+ PatternDefault = "Default"
+ PatternCustom = "Custom"
+ PatternDisabled Pattern = "Disabled"
+)
+
+// PatternSpec defines a custom pattern.
+//
+// TODO a pattern is a bundle of YAML resources. Need to define how they are stored
+// on the cluster. Simplest format is a flat YAML file, but we may need more structure
+// to store kustomize scripts, multi-stage deployments, health checks, metadata etc....
+// Possible storage formats: ConfigMap, PersistentVolume, container image...
+//
+// Patterns should also be usable directly, without depending on this API.
+// Preferably using only kubectl and kustomize.
+type PatternSpec struct {
+ // Name of the pattern.
+ Name Pattern `json:"pattern"`
+}
+
+// SignalManagerStatus TODO
+// - Conditions to track status of each pattern - pull condition info from signal operators?
+type SignalManagerStatus struct{}
diff --git a/pkg/apis/signal_manager/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/signal_manager/v1alpha1/zz_generated.deepcopy.go
new file mode 100644
index 000000000..193467846
--- /dev/null
+++ b/pkg/apis/signal_manager/v1alpha1/zz_generated.deepcopy.go
@@ -0,0 +1,146 @@
+//go:build !ignore_autogenerated
+
+/*
+Copyright 2021.
+
+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 v1alpha1
+
+import (
+ 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 *SignalManager) DeepCopyInto(out *SignalManager) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+ in.Spec.DeepCopyInto(&out.Spec)
+ out.Status = in.Status
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SignalManager.
+func (in *SignalManager) DeepCopy() *SignalManager {
+ if in == nil {
+ return nil
+ }
+ out := new(SignalManager)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SignalManagerList) DeepCopyInto(out *SignalManagerList) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ListMeta.DeepCopyInto(&out.ListMeta)
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]SignalManager, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SignalManagerList.
+func (in *SignalManagerList) DeepCopy() *SignalManagerList {
+ if in == nil {
+ return nil
+ }
+ out := new(SignalManagerList)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *SignalManagerList) 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 *SignalManagerSpec) DeepCopyInto(out *SignalManagerSpec) {
+ *out = *in
+ if in.Signals != nil {
+ in, out := &in.Signals, &out.Signals
+ *out = make([]SignalSpec, len(*in))
+ copy(*out, *in)
+ }
+ if in.Strategies != nil {
+ in, out := &in.Strategies, &out.Strategies
+ *out = make([]StrategySpec, len(*in))
+ copy(*out, *in)
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SignalManagerSpec.
+func (in *SignalManagerSpec) DeepCopy() *SignalManagerSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(SignalManagerSpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SignalManagerStatus) DeepCopyInto(out *SignalManagerStatus) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SignalManagerStatus.
+func (in *SignalManagerStatus) DeepCopy() *SignalManagerStatus {
+ if in == nil {
+ return nil
+ }
+ out := new(SignalManagerStatus)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *SignalSpec) DeepCopyInto(out *SignalSpec) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SignalSpec.
+func (in *SignalSpec) DeepCopy() *SignalSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(SignalSpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *StrategySpec) DeepCopyInto(out *StrategySpec) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StrategySpec.
+func (in *StrategySpec) DeepCopy() *StrategySpec {
+ if in == nil {
+ return nil
+ }
+ out := new(StrategySpec)
+ in.DeepCopyInto(out)
+ return out
+}