Skip to content

Commit e8df483

Browse files
creates CRD for OpAMPBridge resource (open-telemetry#1559)
* creates CRD for OpAMPBridge resource * minor changes * fixes kustomization.yaml issues * adds age field to status * fixes lint issues * fixes lint issues * fixes lint issues Signed-off-by: Avadhut Pisal <[email protected]> * fixes lint issues * fix ci issues * updates bundle * fixes webhook test issue * updates bundle * updates bundle * adds enum for opamp-bridge capabilities * fix opamp server endpoint in e2e test case * fix e2e test case * fix e2e test case * validate maximum replica count * add delete verb to webhook * code refactoring to move reconciliation implementation in separate package * resolves merge conflicts * using common reconciliation implementation for opampbridge * add test cases * resolves goimports lint issues * add validations for capabilities * removes validation on specific set of capabilities * change capabilities data type to map * defaulting required capabilities * add local e2e image entry for opampbridge in hack * add OPERATOROPAMPBRIDGE_IMG to prepare-e2e * fix review comments * fix e2e hack * add e2e test-suit to github action --------- Signed-off-by: Avadhut Pisal <[email protected]>
1 parent 1ae2fe6 commit e8df483

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+14733
-70
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
2+
change_type: 'enhancement'
3+
4+
# The name of the component, or a single word describing the area of concern, (e.g. operator, target allocator, github action)
5+
component: operator-opamp-bridge
6+
7+
# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
8+
note: "Creates the CRD for the OpAMPBridge resource"
9+
10+
# One or more tracking issues related to the change
11+
issues: [1368]
12+
13+
# (Optional) One or more lines of additional information to render under the primary note.
14+
# These lines will be padded with 2 spaces and then inserted directly into the document.
15+
# Use pipe (|) for multiline entries.
16+
subtext:

.github/workflows/e2e.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ jobs:
3131
- e2e-autoscale
3232
- e2e-multi-instrumentation
3333
- e2e-pdb
34+
- e2e-opampbridge
3435

3536
steps:
3637
- name: Set up Go

Makefile

+6-1
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,14 @@ e2e-log-operator:
218218
e2e-multi-instrumentation:
219219
$(KUTTL) test --config kuttl-test-multi-instr.yaml
220220

221+
# OpAMPBridge CR end-to-tests
222+
.PHONY: e2e-opampbridge
223+
e2e-opampbridge:
224+
$(KUTTL) test --config kuttl-test-opampbridge.yaml
225+
221226
.PHONY: prepare-e2e
222227
prepare-e2e: kuttl set-image-controller container container-target-allocator container-operator-opamp-bridge start-kind cert-manager install-metrics-server load-image-all deploy
223-
TARGETALLOCATOR_IMG=$(TARGETALLOCATOR_IMG) OPERATOR_IMG=$(IMG) SED_BIN="$(SED)" ./hack/modify-test-images.sh
228+
TARGETALLOCATOR_IMG=$(TARGETALLOCATOR_IMG) OPERATOROPAMPBRIDGE_IMG=$(OPERATOROPAMPBRIDGE_IMG) OPERATOR_IMG=$(IMG) SED_BIN="$(SED)" ./hack/modify-test-images.sh
224229

225230
.PHONY: enable-prometheus-feature-flag
226231
enable-prometheus-feature-flag:

PROJECT

+12
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,16 @@ resources:
3030
webhooks:
3131
defaulting: true
3232
webhookVersion: v1
33+
- api:
34+
crdVersion: v1
35+
namespaced: true
36+
controller: true
37+
domain: opentelemetry.io
38+
kind: OpAMPBridge
39+
path: github.com/open-telemetry/opentelemetry-operator/apis/v1alpha1
40+
version: v1alpha1
41+
webhooks:
42+
defaulting: true
43+
validation: true
44+
webhookVersion: v1
3345
version: "3"
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package v1alpha1
16+
17+
type (
18+
// OpAMPBridgeCapability represents capability supported by OpAMP Bridge.
19+
// +kubebuilder:validation:Enum=AcceptsRemoteConfig;ReportsEffectiveConfig;ReportsOwnTraces;ReportsOwnMetrics;ReportsOwnLogs;AcceptsOpAMPConnectionSettings;AcceptsOtherConnectionSettings;AcceptsRestartCommand;ReportsHealth;ReportsRemoteConfig
20+
OpAMPBridgeCapability string
21+
)
22+
23+
const (
24+
OpAMPBridgeCapabilityReportsStatus OpAMPBridgeCapability = "ReportsStatus"
25+
OpAMPBridgeCapabilityAcceptsRemoteConfig OpAMPBridgeCapability = "AcceptsRemoteConfig"
26+
OpAMPBridgeCapabilityReportsEffectiveConfig OpAMPBridgeCapability = "ReportsEffectiveConfig"
27+
OpAMPBridgeCapabilityReportsOwnTraces OpAMPBridgeCapability = "ReportsOwnTraces"
28+
OpAMPBridgeCapabilityReportsOwnMetrics OpAMPBridgeCapability = "ReportsOwnMetrics"
29+
OpAMPBridgeCapabilityReportsOwnLogs OpAMPBridgeCapability = "ReportsOwnLogs"
30+
OpAMPBridgeCapabilityAcceptsOpAMPConnectionSettings OpAMPBridgeCapability = "AcceptsOpAMPConnectionSettings"
31+
OpAMPBridgeCapabilityAcceptsOtherConnectionSettings OpAMPBridgeCapability = "AcceptsOtherConnectionSettings"
32+
OpAMPBridgeCapabilityAcceptsRestartCommand OpAMPBridgeCapability = "AcceptsRestartCommand"
33+
OpAMPBridgeCapabilityReportsHealth OpAMPBridgeCapability = "ReportsHealth"
34+
OpAMPBridgeCapabilityReportsRemoteConfig OpAMPBridgeCapability = "ReportsRemoteConfig"
35+
)

apis/v1alpha1/opampbridge_types.go

+141
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package v1alpha1
16+
17+
import (
18+
v1 "k8s.io/api/core/v1"
19+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
20+
)
21+
22+
// OpAMPBridgeSpec defines the desired state of OpAMPBridge.
23+
type OpAMPBridgeSpec struct {
24+
// OpAMP backend Server endpoint
25+
// +required
26+
Endpoint string `json:"endpoint"`
27+
// Capabilities supported by the OpAMP Bridge
28+
// +required
29+
Capabilities map[OpAMPBridgeCapability]bool `json:"capabilities"`
30+
// ComponentsAllowed is a list of allowed OpenTelemetry components for each pipeline type (receiver, processor, etc.)
31+
// +optional
32+
ComponentsAllowed map[string][]string `json:"componentsAllowed,omitempty"`
33+
// Resources to set on the OpAMPBridge pods.
34+
// +optional
35+
Resources v1.ResourceRequirements `json:"resources,omitempty"`
36+
// NodeSelector to schedule OpAMPBridge pods.
37+
// +optional
38+
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
39+
// Replicas is the number of pod instances for the OpAMPBridge.
40+
// +optional
41+
// +kubebuilder:validation:Maximum=1
42+
Replicas *int32 `json:"replicas,omitempty"`
43+
// SecurityContext will be set as the container security context.
44+
// +optional
45+
SecurityContext *v1.SecurityContext `json:"securityContext,omitempty"`
46+
// PodSecurityContext will be set as the pod security context.
47+
// +optional
48+
PodSecurityContext *v1.PodSecurityContext `json:"podSecurityContext,omitempty"`
49+
// PodAnnotations is the set of annotations that will be attached to
50+
// OpAMPBridge pods.
51+
// +optional
52+
PodAnnotations map[string]string `json:"podAnnotations,omitempty"`
53+
// ServiceAccount indicates the name of an existing service account to use with this instance. When set,
54+
// the operator will not automatically create a ServiceAccount for the OpAMPBridge.
55+
// +optional
56+
ServiceAccount string `json:"serviceAccount,omitempty"`
57+
// Image indicates the container image to use for the OpAMPBridge.
58+
// +optional
59+
Image string `json:"image,omitempty"`
60+
// UpgradeStrategy represents how the operator will handle upgrades to the CR when a newer version of the operator is deployed
61+
// +optional
62+
UpgradeStrategy UpgradeStrategy `json:"upgradeStrategy"`
63+
// ImagePullPolicy indicates the pull policy to be used for retrieving the container image (Always, Never, IfNotPresent)
64+
// +optional
65+
ImagePullPolicy v1.PullPolicy `json:"imagePullPolicy,omitempty"`
66+
// VolumeMounts represents the mount points to use in the underlying OpAMPBridge deployment(s)
67+
// +optional
68+
// +listType=atomic
69+
VolumeMounts []v1.VolumeMount `json:"volumeMounts,omitempty"`
70+
// Ports allows a set of ports to be exposed by the underlying v1.Service.
71+
// +optional
72+
// +listType=atomic
73+
Ports []v1.ServicePort `json:"ports,omitempty"`
74+
// ENV vars to set on the OpAMPBridge Pods.
75+
// +optional
76+
Env []v1.EnvVar `json:"env,omitempty"`
77+
// List of sources to populate environment variables on the OpAMPBridge Pods.
78+
// +optional
79+
EnvFrom []v1.EnvFromSource `json:"envFrom,omitempty"`
80+
// Toleration to schedule OpAMPBridge pods.
81+
// +optional
82+
Tolerations []v1.Toleration `json:"tolerations,omitempty"`
83+
// Volumes represents which volumes to use in the underlying OpAMPBridge deployment(s).
84+
// +optional
85+
// +listType=atomic
86+
Volumes []v1.Volume `json:"volumes,omitempty"`
87+
// HostNetwork indicates if the pod should run in the host networking namespace.
88+
// +optional
89+
HostNetwork bool `json:"hostNetwork,omitempty"`
90+
// If specified, indicates the pod's priority.
91+
// If not specified, the pod priority will be default or zero if there is no
92+
// default.
93+
// +optional
94+
PriorityClassName string `json:"priorityClassName,omitempty"`
95+
// If specified, indicates the pod's scheduling constraints
96+
// +optional
97+
Affinity *v1.Affinity `json:"affinity,omitempty"`
98+
// TopologySpreadConstraints embedded kubernetes pod configuration option,
99+
// controls how pods are spread across your cluster among failure-domains
100+
// such as regions, zones, nodes, and other user-defined topology domains
101+
// https://kubernetes.io/docs/concepts/workloads/pods/pod-topology-spread-constraints/
102+
// +optional
103+
TopologySpreadConstraints []v1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"`
104+
}
105+
106+
// OpAMPBridgeStatus defines the observed state of OpAMPBridge.
107+
type OpAMPBridgeStatus struct {
108+
// Version of the managed OpAMP Bridge (operand)
109+
// +optional
110+
Version string `json:"version,omitempty"`
111+
}
112+
113+
// +kubebuilder:object:root=true
114+
// +kubebuilder:subresource:status
115+
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
116+
// +kubebuilder:printcolumn:name="Version",type="string",JSONPath=".status.version",description="OpenTelemetry Version"
117+
// +kubebuilder:printcolumn:name="Endpoint",type="string",JSONPath=".spec.endpoint"
118+
// +operator-sdk:csv:customresourcedefinitions:displayName="OpAMP Bridge"
119+
// +operator-sdk:csv:customresourcedefinitions:resources={{Pod,v1},{Deployment,apps/v1},{ConfigMaps,v1},{Service,v1}}
120+
121+
// OpAMPBridge is the Schema for the opampbridges API.
122+
type OpAMPBridge struct {
123+
metav1.TypeMeta `json:",inline"`
124+
metav1.ObjectMeta `json:"metadata,omitempty"`
125+
126+
Spec OpAMPBridgeSpec `json:"spec,omitempty"`
127+
Status OpAMPBridgeStatus `json:"status,omitempty"`
128+
}
129+
130+
//+kubebuilder:object:root=true
131+
132+
// OpAMPBridgeList contains a list of OpAMPBridge.
133+
type OpAMPBridgeList struct {
134+
metav1.TypeMeta `json:",inline"`
135+
metav1.ListMeta `json:"metadata,omitempty"`
136+
Items []OpAMPBridge `json:"items"`
137+
}
138+
139+
func init() {
140+
SchemeBuilder.Register(&OpAMPBridge{}, &OpAMPBridgeList{})
141+
}

apis/v1alpha1/opampbridge_webhook.go

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Copyright The OpenTelemetry Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package v1alpha1
16+
17+
import (
18+
"fmt"
19+
"strings"
20+
21+
"k8s.io/apimachinery/pkg/runtime"
22+
"k8s.io/apimachinery/pkg/util/validation"
23+
ctrl "sigs.k8s.io/controller-runtime"
24+
logf "sigs.k8s.io/controller-runtime/pkg/log"
25+
"sigs.k8s.io/controller-runtime/pkg/webhook"
26+
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
27+
)
28+
29+
// log is for logging in this package.
30+
var opampbridgelog = logf.Log.WithName("opampbridge-resource")
31+
32+
func (r *OpAMPBridge) SetupWebhookWithManager(mgr ctrl.Manager) error {
33+
return ctrl.NewWebhookManagedBy(mgr).
34+
For(r).
35+
Complete()
36+
}
37+
38+
//+kubebuilder:webhook:path=/mutate-opentelemetry-io-v1alpha1-opampbridge,mutating=true,failurePolicy=fail,sideEffects=None,groups=opentelemetry.io,resources=opampbridges,verbs=create;update,versions=v1alpha1,name=mopampbridge.kb.io,admissionReviewVersions=v1
39+
40+
var _ webhook.Defaulter = &OpAMPBridge{}
41+
42+
// Default implements webhook.Defaulter so a webhook will be registered for the type.
43+
func (r *OpAMPBridge) Default() {
44+
opampbridgelog.Info("default", "name", r.Name)
45+
if len(r.Spec.UpgradeStrategy) == 0 {
46+
r.Spec.UpgradeStrategy = UpgradeStrategyAutomatic
47+
}
48+
49+
if r.Labels == nil {
50+
r.Labels = map[string]string{}
51+
}
52+
if r.Labels["app.kubernetes.io/managed-by"] == "" {
53+
r.Labels["app.kubernetes.io/managed-by"] = "opentelemetry-operator"
54+
}
55+
56+
one := int32(1)
57+
if r.Spec.Replicas == nil {
58+
r.Spec.Replicas = &one
59+
}
60+
61+
// ReportsStatus Capability must be set
62+
if r.Spec.Capabilities == nil {
63+
r.Spec.Capabilities = make(map[OpAMPBridgeCapability]bool)
64+
}
65+
enabled, found := r.Spec.Capabilities[OpAMPBridgeCapabilityReportsStatus]
66+
if !enabled || !found {
67+
r.Spec.Capabilities[OpAMPBridgeCapabilityReportsStatus] = true
68+
}
69+
}
70+
71+
//+kubebuilder:webhook:path=/validate-opentelemetry-io-v1alpha1-opampbridge,mutating=false,failurePolicy=fail,sideEffects=None,groups=opentelemetry.io,resources=opampbridges,verbs=create;update;delete,versions=v1alpha1,name=vopampbridge.kb.io,admissionReviewVersions=v1
72+
73+
var _ webhook.Validator = &OpAMPBridge{}
74+
75+
// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
76+
func (r *OpAMPBridge) ValidateCreate() (admission.Warnings, error) {
77+
opampbridgelog.Info("validate create", "name", r.Name)
78+
return nil, r.validateCRDSpec()
79+
}
80+
81+
// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
82+
func (r *OpAMPBridge) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
83+
opampbridgelog.Info("validate update", "name", r.Name)
84+
return nil, r.validateCRDSpec()
85+
}
86+
87+
// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
88+
func (r *OpAMPBridge) ValidateDelete() (admission.Warnings, error) {
89+
opampbridgelog.Info("validate delete", "name", r.Name)
90+
return nil, nil
91+
}
92+
93+
func (r *OpAMPBridge) validateCRDSpec() error {
94+
95+
// check required fields
96+
97+
if len(strings.TrimSpace(r.Spec.Endpoint)) == 0 {
98+
return fmt.Errorf("the OpAMP server endpoint is not specified")
99+
}
100+
101+
if len(r.Spec.Capabilities) == 0 {
102+
return fmt.Errorf("the capabilities supported by OpAMP Bridge are not specified")
103+
}
104+
105+
// validate port config
106+
for _, p := range r.Spec.Ports {
107+
nameErrs := validation.IsValidPortName(p.Name)
108+
numErrs := validation.IsValidPortNum(int(p.Port))
109+
if len(nameErrs) > 0 || len(numErrs) > 0 {
110+
return fmt.Errorf("the OpAMPBridge Spec Ports configuration is incorrect, port name '%s' errors: %s, num '%d' errors: %s",
111+
p.Name, nameErrs, p.Port, numErrs)
112+
}
113+
}
114+
115+
// check for maximum replica count
116+
if r.Spec.Replicas != nil && *r.Spec.Replicas > 1 {
117+
return fmt.Errorf("replica count must not be greater than 1")
118+
}
119+
return nil
120+
}

0 commit comments

Comments
 (0)