Add CRD, Controller for SkyWalking Event Exporter (#113)
* Add CRD and Controller for EventExporter and EventExporterConfig
* Add auto-generated config files for EventExporter and EventExporterConfig
* Merge EventExporterConfig into EventExporter
* Remove EventExporterConfig in PROJECT
* Remove unused type in eventexporter_types.go
* Pass linting
* Refactor event exporter CRD and controller
* Remove unused dependency
* Update EventExporterController rabc and configMap
* Add a simple test case to eventexporter e2e test
* Add eventexporter e2e test to GitHub workflows
* Remove unused UI component in event exporter e2e test
* Update event exporter controller: delete old configMap after creating the new one, generate fixed-length name for configMaps
diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml
index e647d9a..1ef554e 100644
--- a/.github/workflows/go.yml
+++ b/.github/workflows/go.yml
@@ -227,9 +227,24 @@
uses: apache/skywalking-infra-e2e@996ed8902e941e2883fcf0ac5b3090364942d205
with:
e2e-file: test/e2e/oap-ui-agent-oapserverconfig-oapserverdynamicconfig/e2e.yaml
+ oapserver-eventexporter-e2e-tests:
+ name: e2e tests(oap+eventexporter)
+ runs-on: ubuntu-latest
+ steps:
+ - name: Install Go
+ uses: actions/setup-go@v3
+ with:
+ go-version: '1.22'
+ id: go
+ - name: Check out code into the Go module directory
+ uses: actions/checkout@v3
+ - name: Run E2E Test
+ uses: apache/skywalking-infra-e2e@996ed8902e941e2883fcf0ac5b3090364942d205
+ with:
+ e2e-file: test/e2e/oap-eventexporter/e2e.yaml
checks:
name: build
runs-on: ubuntu-20.04
- needs: [check, build, unit-tests, e2e-tests, swagent-e2e-tests, swagent-configmap-e2e-tests, internel-storage-e2e-tests, external-storage-e2e-tests, adapter-hpa-e2e-tests, e2e-tests-with-satellite, adapter-satellite-hpa-e2e-tests, oapserver-configuration-e2e-tests]
+ needs: [check, build, unit-tests, e2e-tests, swagent-e2e-tests, swagent-configmap-e2e-tests, internel-storage-e2e-tests, external-storage-e2e-tests, adapter-hpa-e2e-tests, e2e-tests-with-satellite, adapter-satellite-hpa-e2e-tests, oapserver-configuration-e2e-tests, oapserver-eventexporter-e2e-tests]
steps:
- run: echo 'success'
diff --git a/operator/PROJECT b/operator/PROJECT
index 73b6a37..e603a61 100644
--- a/operator/PROJECT
+++ b/operator/PROJECT
@@ -131,4 +131,17 @@
kind: BanyanDB
path: github.com/apache/skywalking-swck/operator/apis/operator/v1alpha1
version: v1alpha1
+- api:
+ crdVersion: v1
+ namespaced: true
+ controller: true
+ domain: skywalking.apache.org
+ group: operator
+ kind: EventExporter
+ path: github.com/apache/skywalking-swck/operator/apis/operator/v1alpha1
+ version: v1alpha1
+ webhooks:
+ defaulting: true
+ validation: true
+ webhookVersion: v1
version: "3"
diff --git a/operator/apis/operator/v1alpha1/eventexporter_types.go b/operator/apis/operator/v1alpha1/eventexporter_types.go
new file mode 100644
index 0000000..f548fd7
--- /dev/null
+++ b/operator/apis/operator/v1alpha1/eventexporter_types.go
@@ -0,0 +1,79 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you 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
+
+import (
+ appsv1 "k8s.io/api/apps/v1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// EventExporterSpec defines the desired state of EventExporter
+type EventExporterSpec struct {
+ // Version of EventExporter.
+ // +kubebuilder:validation:Required
+ Version string `json:"version,omitempty"`
+ // Image is the event exporter Docker image to deploy.
+ Image string `json:"image,omitempty"`
+ // Replicas is the number of event exporter pods
+ // +kubebuilder:validation:Required
+ Replicas int32 `json:"replicas,omitempty"`
+ // Config of filters and exporters
+ // +kubebuilder:validation:Optional
+ Config string `json:"config,omitempty"`
+}
+
+// EventExporterStatus defines the observed state of EventExporter
+type EventExporterStatus struct {
+ // Total number of available pods targeted by this deployment.
+ // +kubebuilder:validation:Optional
+ AvailableReplicas int32 `json:"availableReplicas,omitempty"`
+ // Represents the latest available observations of the underlying deployment's current state.
+ // +kubebuilder:validation:Optional
+ Conditions []appsv1.DeploymentCondition `json:"conditions,omitempty"`
+ // Name of the configMap.
+ // +kubebuilder:validation:Optional
+ ConfigMapName string `json:"configMapName,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+// +kubebuilder:subresource:status
+// +kubebuilder:printcolumn:name="Version",type="string",priority=1,JSONPath=".spec.version",description="The version"
+// +kubebuilder:printcolumn:name="Image",type="string",priority=1,JSONPath=".spec.image"
+// +kubebuilder:printcolumn:name="Instances",type="string",JSONPath=".spec.instances",description="The number of expected instances"
+
+// EventExporter is the Schema for the eventexporters API
+type EventExporter struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ Spec EventExporterSpec `json:"spec,omitempty"`
+ Status EventExporterStatus `json:"status,omitempty"`
+}
+
+//+kubebuilder:object:root=true
+
+// EventExporterList contains a list of EventExporter
+type EventExporterList struct {
+ metav1.TypeMeta `json:",inline"`
+ metav1.ListMeta `json:"metadata,omitempty"`
+ Items []EventExporter `json:"items"`
+}
+
+func init() {
+ SchemeBuilder.Register(&EventExporter{}, &EventExporterList{})
+}
diff --git a/operator/apis/operator/v1alpha1/eventexporter_webhook.go b/operator/apis/operator/v1alpha1/eventexporter_webhook.go
new file mode 100644
index 0000000..eac2e55
--- /dev/null
+++ b/operator/apis/operator/v1alpha1/eventexporter_webhook.go
@@ -0,0 +1,95 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you 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
+
+import (
+ "fmt"
+
+ "k8s.io/apimachinery/pkg/runtime"
+ ctrl "sigs.k8s.io/controller-runtime"
+ logf "sigs.k8s.io/controller-runtime/pkg/log"
+ "sigs.k8s.io/controller-runtime/pkg/webhook"
+ "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
+)
+
+const latestVersion = "latest"
+const image = "apache/skywalking-kubernetes-event-exporter"
+
+// log is for logging in this package.
+var eventexporterlog = logf.Log.WithName("eventexporter-resource")
+
+func (r *EventExporter) SetupWebhookWithManager(mgr ctrl.Manager) error {
+ return ctrl.NewWebhookManagedBy(mgr).
+ For(r).
+ Complete()
+}
+
+// nolint: lll
+//+kubebuilder:webhook:path=/mutate-operator-skywalking-apache-org-v1alpha1-eventexporter,mutating=true,failurePolicy=fail,sideEffects=None,groups=operator.skywalking.apache.org,resources=eventexporters,verbs=create;update,versions=v1alpha1,name=meventexporter.kb.io,admissionReviewVersions=v1
+
+var _ webhook.Defaulter = &EventExporter{}
+
+// Default implements webhook.Defaulter so a webhook will be registered for the type
+func (r *EventExporter) Default() {
+ eventexporterlog.Info("default", "name", r.Name)
+
+ if r.Spec.Version == "" {
+ r.Spec.Version = latestVersion
+ }
+
+ if r.Spec.Image == "" {
+ r.Spec.Image = fmt.Sprintf("%s:%s", image, r.Spec.Version)
+ }
+
+ if r.Spec.Replicas == 0 {
+ r.Spec.Replicas = 1
+ }
+}
+
+// nolint: lll
+// +kubebuilder:webhook:admissionReviewVersions=v1,sideEffects=None,path=/mutate-operator-skywalking-apache-org-v1alpha1-eventexporter,mutating=true,failurePolicy=fail,groups=operator.skywalking.apache.org,resources=eventexporters,verbs=create;update,versions=v1alpha1,name=meventexporter.kb.io
+
+var _ webhook.Validator = &EventExporter{}
+
+// ValidateCreate implements webhook.Validator so a webhook will be registered for the type
+func (r *EventExporter) ValidateCreate() (admission.Warnings, error) {
+ eventexporterlog.Info("validate create", "name", r.Name)
+
+ return nil, r.validate()
+}
+
+// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
+func (r *EventExporter) ValidateUpdate(_ runtime.Object) (admission.Warnings, error) {
+ eventexporterlog.Info("validate update", "name", r.Name)
+
+ return nil, r.validate()
+}
+
+// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
+func (r *EventExporter) ValidateDelete() (admission.Warnings, error) {
+ eventexporterlog.Info("validate delete", "name", r.Name)
+
+ return nil, nil
+}
+
+func (r *EventExporter) validate() error {
+ if r.Spec.Image == "" {
+ return fmt.Errorf("image is absent")
+ }
+ return nil
+}
diff --git a/operator/apis/operator/v1alpha1/zz_generated.deepcopy.go b/operator/apis/operator/v1alpha1/zz_generated.deepcopy.go
index 627c68a..340ef8b 100644
--- a/operator/apis/operator/v1alpha1/zz_generated.deepcopy.go
+++ b/operator/apis/operator/v1alpha1/zz_generated.deepcopy.go
@@ -1,5 +1,4 @@
//go:build !ignore_autogenerated
-// +build !ignore_autogenerated
// Licensed to Apache Software Foundation (ASF) under one or more contributor
// license agreements. See the NOTICE file distributed with
@@ -156,6 +155,102 @@
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *EventExporter) DeepCopyInto(out *EventExporter) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+ out.Spec = in.Spec
+ in.Status.DeepCopyInto(&out.Status)
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EventExporter.
+func (in *EventExporter) DeepCopy() *EventExporter {
+ if in == nil {
+ return nil
+ }
+ out := new(EventExporter)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *EventExporter) 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 *EventExporterList) DeepCopyInto(out *EventExporterList) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ListMeta.DeepCopyInto(&out.ListMeta)
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]EventExporter, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EventExporterList.
+func (in *EventExporterList) DeepCopy() *EventExporterList {
+ if in == nil {
+ return nil
+ }
+ out := new(EventExporterList)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *EventExporterList) 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 *EventExporterSpec) DeepCopyInto(out *EventExporterSpec) {
+ *out = *in
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EventExporterSpec.
+func (in *EventExporterSpec) DeepCopy() *EventExporterSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(EventExporterSpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *EventExporterStatus) DeepCopyInto(out *EventExporterStatus) {
+ *out = *in
+ if in.Conditions != nil {
+ in, out := &in.Conditions, &out.Conditions
+ *out = make([]v1.DeploymentCondition, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EventExporterStatus.
+func (in *EventExporterStatus) DeepCopy() *EventExporterStatus {
+ if in == nil {
+ return nil
+ }
+ out := new(EventExporterStatus)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Fetcher) DeepCopyInto(out *Fetcher) {
*out = *in
out.TypeMeta = in.TypeMeta
diff --git a/operator/config/crd/bases/operator.skywalking.apache.org_eventexporters.yaml b/operator/config/crd/bases/operator.skywalking.apache.org_eventexporters.yaml
new file mode 100644
index 0000000..568bb11
--- /dev/null
+++ b/operator/config/crd/bases/operator.skywalking.apache.org_eventexporters.yaml
@@ -0,0 +1,136 @@
+# Licensed to Apache Software Foundation (ASF) under one or more contributor
+# license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright
+# ownership. Apache Software Foundation (ASF) licenses this file to you 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.
+
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ controller-gen.kubebuilder.io/version: v0.14.0
+ name: eventexporters.operator.skywalking.apache.org
+spec:
+ group: operator.skywalking.apache.org
+ names:
+ kind: EventExporter
+ listKind: EventExporterList
+ plural: eventexporters
+ singular: eventexporter
+ scope: Namespaced
+ versions:
+ - additionalPrinterColumns:
+ - description: The version
+ jsonPath: .spec.version
+ name: Version
+ priority: 1
+ type: string
+ - jsonPath: .spec.image
+ name: Image
+ priority: 1
+ type: string
+ - description: The number of expected instances
+ jsonPath: .spec.instances
+ name: Instances
+ type: string
+ name: v1alpha1
+ schema:
+ openAPIV3Schema:
+ description: EventExporter is the Schema for the eventexporters API
+ 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: EventExporterSpec defines the desired state of EventExporter
+ properties:
+ config:
+ description: Config of filters and exporters
+ type: string
+ image:
+ description: Image is the event exporter Docker image to deploy.
+ type: string
+ replicas:
+ description: Replicas is the number of event exporter pods
+ format: int32
+ type: integer
+ version:
+ description: Version of EventExporter.
+ type: string
+ type: object
+ status:
+ description: EventExporterStatus defines the observed state of EventExporter
+ properties:
+ availableReplicas:
+ description: Total number of available pods targeted by this deployment.
+ format: int32
+ type: integer
+ conditions:
+ description: Represents the latest available observations of the underlying
+ deployment's current state.
+ items:
+ description: DeploymentCondition describes the state of a deployment
+ at a certain point.
+ properties:
+ lastTransitionTime:
+ description: Last time the condition transitioned from one status
+ to another.
+ format: date-time
+ type: string
+ lastUpdateTime:
+ description: The last time this condition was updated.
+ format: date-time
+ type: string
+ message:
+ description: A human readable message indicating details about
+ the transition.
+ type: string
+ reason:
+ description: The reason for the condition's last transition.
+ type: string
+ status:
+ description: Status of the condition, one of True, False, Unknown.
+ type: string
+ type:
+ description: Type of deployment condition.
+ type: string
+ required:
+ - status
+ - type
+ type: object
+ type: array
+ configMapName:
+ description: Name of the configMap.
+ type: string
+ type: object
+ type: object
+ served: true
+ storage: true
+ subresources:
+ status: {}
diff --git a/operator/config/crd/kustomization.yaml b/operator/config/crd/kustomization.yaml
index 468804a..109b8ec 100644
--- a/operator/config/crd/kustomization.yaml
+++ b/operator/config/crd/kustomization.yaml
@@ -29,6 +29,7 @@
- bases/operator.skywalking.apache.org_oapserverconfigs.yaml
- bases/operator.skywalking.apache.org_oapserverdynamicconfigs.yaml
- bases/operator.skywalking.apache.org_banyandbs.yaml
+- bases/operator.skywalking.apache.org_eventexporters.yaml
#+kubebuilder:scaffold:crdkustomizeresource
patchesStrategicMerge:
@@ -44,6 +45,7 @@
#- patches/webhook_in_oapserverdynamicconfigs.yaml
#- patches/webhook_in_swagents.yaml
#- patches/webhook_in_banyandbs.yaml
+#- patches/webhook_in_eventexporters.yaml
#+kubebuilder:scaffold:crdkustomizewebhookpatch
# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
@@ -58,6 +60,7 @@
#- patches/cainjection_in_oapserverdynamicconfigs.yaml
#- patches/cainjection_in_swagents.yaml
#- patches/cainjection_in_banyandbs.yaml
+#- patches/cainjection_in_eventexporters.yaml
#+kubebuilder:scaffold:crdkustomizecainjectionpatch
# the following config is for teaching kustomize how to do kustomization for CRDs.
diff --git a/operator/config/crd/patches/cainjection_in_operator_eventexporters.yaml b/operator/config/crd/patches/cainjection_in_operator_eventexporters.yaml
new file mode 100644
index 0000000..0519865
--- /dev/null
+++ b/operator/config/crd/patches/cainjection_in_operator_eventexporters.yaml
@@ -0,0 +1,24 @@
+# Licensed to Apache Software Foundation (ASF) under one or more contributor
+# license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright
+# ownership. Apache Software Foundation (ASF) licenses this file to you 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.
+
+# The following patch adds a directive for certmanager to inject CA into the CRD
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ annotations:
+ cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
+ name: eventexporters.operator.skywalking.apache.org
diff --git a/operator/config/crd/patches/webhook_in_operator_eventexporters.yaml b/operator/config/crd/patches/webhook_in_operator_eventexporters.yaml
new file mode 100644
index 0000000..9751a89
--- /dev/null
+++ b/operator/config/crd/patches/webhook_in_operator_eventexporters.yaml
@@ -0,0 +1,33 @@
+# Licensed to Apache Software Foundation (ASF) under one or more contributor
+# license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright
+# ownership. Apache Software Foundation (ASF) licenses this file to you 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.
+
+# The following patch enables a conversion webhook for the CRD
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+ name: eventexporters.operator.skywalking.apache.org
+spec:
+ conversion:
+ strategy: Webhook
+ webhook:
+ clientConfig:
+ service:
+ namespace: system
+ name: webhook-service
+ path: /convert
+ conversionReviewVersions:
+ - v1
diff --git a/operator/config/rbac/operator_eventexporter_editor_role.yaml b/operator/config/rbac/operator_eventexporter_editor_role.yaml
new file mode 100644
index 0000000..e0f27b7
--- /dev/null
+++ b/operator/config/rbac/operator_eventexporter_editor_role.yaml
@@ -0,0 +1,48 @@
+# Licensed to Apache Software Foundation (ASF) under one or more contributor
+# license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright
+# ownership. Apache Software Foundation (ASF) licenses this file to you 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.
+
+# permissions for end users to edit eventexporters.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ labels:
+ app.kubernetes.io/name: clusterrole
+ app.kubernetes.io/instance: eventexporter-editor-role
+ app.kubernetes.io/component: rbac
+ app.kubernetes.io/created-by: skywalking-swck
+ app.kubernetes.io/part-of: skywalking-swck
+ app.kubernetes.io/managed-by: kustomize
+ name: eventexporter-editor-role
+rules:
+- apiGroups:
+ - operator.skywalking.apache.org
+ resources:
+ - eventexporters
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - patch
+ - update
+ - watch
+- apiGroups:
+ - operator.skywalking.apache.org
+ resources:
+ - eventexporters/status
+ verbs:
+ - get
diff --git a/operator/config/rbac/operator_eventexporter_viewer_role.yaml b/operator/config/rbac/operator_eventexporter_viewer_role.yaml
new file mode 100644
index 0000000..e5202e1
--- /dev/null
+++ b/operator/config/rbac/operator_eventexporter_viewer_role.yaml
@@ -0,0 +1,44 @@
+# Licensed to Apache Software Foundation (ASF) under one or more contributor
+# license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright
+# ownership. Apache Software Foundation (ASF) licenses this file to you 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.
+
+# permissions for end users to view eventexporters.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+ labels:
+ app.kubernetes.io/name: clusterrole
+ app.kubernetes.io/instance: eventexporter-viewer-role
+ app.kubernetes.io/component: rbac
+ app.kubernetes.io/created-by: skywalking-swck
+ app.kubernetes.io/part-of: skywalking-swck
+ app.kubernetes.io/managed-by: kustomize
+ name: eventexporter-viewer-role
+rules:
+- apiGroups:
+ - operator.skywalking.apache.org
+ resources:
+ - eventexporters
+ verbs:
+ - get
+ - list
+ - watch
+- apiGroups:
+ - operator.skywalking.apache.org
+ resources:
+ - eventexporters/status
+ verbs:
+ - get
diff --git a/operator/config/rbac/role.yaml b/operator/config/rbac/role.yaml
index 9e941d3..01d4d38 100644
--- a/operator/config/rbac/role.yaml
+++ b/operator/config/rbac/role.yaml
@@ -19,7 +19,6 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
- creationTimestamp: null
name: manager-role
rules:
- apiGroups:
@@ -182,6 +181,32 @@
- apiGroups:
- operator.skywalking.apache.org
resources:
+ - eventexporters
+ verbs:
+ - create
+ - delete
+ - get
+ - list
+ - patch
+ - update
+ - watch
+- apiGroups:
+ - operator.skywalking.apache.org
+ resources:
+ - eventexporters/finalizers
+ verbs:
+ - update
+- apiGroups:
+ - operator.skywalking.apache.org
+ resources:
+ - eventexporters/status
+ verbs:
+ - get
+ - patch
+ - update
+- apiGroups:
+ - operator.skywalking.apache.org
+ resources:
- fetchers
verbs:
- create
diff --git a/operator/config/samples/eventexporter.yaml b/operator/config/samples/eventexporter.yaml
new file mode 100644
index 0000000..edab9d0
--- /dev/null
+++ b/operator/config/samples/eventexporter.yaml
@@ -0,0 +1,58 @@
+# Licensed to Apache Software Foundation (ASF) under one or more contributor
+# license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright
+# ownership. Apache Software Foundation (ASF) licenses this file to you 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.
+
+apiVersion: operator.skywalking.apache.org/v1alpha1
+kind: EventExporter
+metadata:
+ name: eventexporter-sample
+spec:
+ replicas: 1
+ config: |
+ filters:
+ - reason: ""
+ message: ""
+ minCount: 1
+ type: ""
+ action: ""
+ kind: "Pod|Service"
+ namespace: "^default$"
+ name: ""
+ service: "[^\\s]{1,}"
+ exporters:
+ - skywalking
+ exporters:
+ skywalking:
+ template:
+ source:
+ service: "{{ .Service.Name }}"
+ serviceInstance: "{{ .Pod.Name }}"
+ endpoint: ""
+ message: "{{ .Event.Message }}"
+ address: "default-oap:11800"
+
+---
+apiVersion: operator.skywalking.apache.org/v1alpha1
+kind: OAPServer
+metadata:
+ name: default
+spec:
+ version: 9.5.0
+ instances: 1
+ image: apache/skywalking-oap-server:9.5.0
+ service:
+ template:
+ type: ClusterIP
\ No newline at end of file
diff --git a/operator/config/webhook/manifests.yaml b/operator/config/webhook/manifests.yaml
index 5c1811c..24970d7 100644
--- a/operator/config/webhook/manifests.yaml
+++ b/operator/config/webhook/manifests.yaml
@@ -19,7 +19,6 @@
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
- creationTimestamp: null
name: mutating-webhook-configuration
webhooks:
- admissionReviewVersions:
@@ -48,6 +47,46 @@
service:
name: webhook-service
namespace: system
+ path: /mutate-operator-skywalking-apache-org-v1alpha1-eventexporter
+ failurePolicy: Fail
+ name: meventexporter.kb.io
+ rules:
+ - apiGroups:
+ - operator.skywalking.apache.org
+ apiVersions:
+ - v1alpha1
+ operations:
+ - CREATE
+ - UPDATE
+ resources:
+ - eventexporters
+ sideEffects: None
+- admissionReviewVersions:
+ - v1
+ clientConfig:
+ service:
+ name: webhook-service
+ namespace: system
+ path: /mutate-operator-skywalking-apache-org-v1alpha1-eventexporter
+ failurePolicy: Fail
+ name: meventexporter.kb.io
+ rules:
+ - apiGroups:
+ - operator.skywalking.apache.org
+ apiVersions:
+ - v1alpha1
+ operations:
+ - CREATE
+ - UPDATE
+ resources:
+ - eventexporters
+ sideEffects: None
+- admissionReviewVersions:
+ - v1
+ clientConfig:
+ service:
+ name: webhook-service
+ namespace: system
path: /mutate-operator-skywalking-apache-org-v1alpha1-fetcher
failurePolicy: Fail
name: mfetcher.kb.io
@@ -242,12 +281,10 @@
resources:
- pods
sideEffects: None
-
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
- creationTimestamp: null
name: validating-webhook-configuration
webhooks:
- admissionReviewVersions:
diff --git a/operator/controllers/operator/eventexporter_controller.go b/operator/controllers/operator/eventexporter_controller.go
new file mode 100644
index 0000000..ba94285
--- /dev/null
+++ b/operator/controllers/operator/eventexporter_controller.go
@@ -0,0 +1,218 @@
+// Licensed to Apache Software Foundation (ASF) under one or more contributor
+// license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright
+// ownership. Apache Software Foundation (ASF) licenses this file to you 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 operator
+
+import (
+ "context"
+ "fmt"
+ "text/template"
+
+ "github.com/go-logr/logr"
+ l "github.com/sirupsen/logrus"
+ apps "k8s.io/api/apps/v1"
+ core "k8s.io/api/core/v1"
+ apiequal "k8s.io/apimachinery/pkg/api/equality"
+ apierrors "k8s.io/apimachinery/pkg/api/errors"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "k8s.io/apimachinery/pkg/runtime"
+ "k8s.io/client-go/tools/record"
+ "k8s.io/client-go/util/retry"
+ ctrl "sigs.k8s.io/controller-runtime"
+ "sigs.k8s.io/controller-runtime/pkg/client"
+ runtimelog "sigs.k8s.io/controller-runtime/pkg/log"
+
+ operatorv1alpha1 "github.com/apache/skywalking-swck/operator/apis/operator/v1alpha1"
+ "github.com/apache/skywalking-swck/operator/pkg/kubernetes"
+)
+
+var useImmutableConfigMap = true
+
+// EventExporterReconciler reconciles a EventExporter object
+type EventExporterReconciler struct {
+ client.Client
+ Scheme *runtime.Scheme
+ FileRepo kubernetes.Repo
+ Recorder record.EventRecorder
+}
+
+// +kubebuilder:rbac:groups=operator.skywalking.apache.org,resources=eventexporters,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups=operator.skywalking.apache.org,resources=eventexporters/status,verbs=get;update;patch
+// +kubebuilder:rbac:groups=operator.skywalking.apache.org,resources=eventexporters/finalizers,verbs=update
+// +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update;patch;delete
+// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch
+
+func (r *EventExporterReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
+ log := runtimelog.FromContext(ctx)
+ log.Info(fmt.Sprintf("===============eventexporter reconcile started (ns: %s, name: %s)===============", req.Namespace, req.Name))
+
+ eventExporter := operatorv1alpha1.EventExporter{}
+ if err := r.Client.Get(ctx, req.NamespacedName, &eventExporter); err != nil {
+ return ctrl.Result{}, client.IgnoreNotFound(err)
+ }
+
+ newConfigMapName := configMapName(&eventExporter)
+ if _, err := r.overlayData(ctx, log, &eventExporter, newConfigMapName); err != nil {
+ log.Error(err, "failed to delete eventexporter's configMap")
+ return ctrl.Result{}, err
+ }
+
+ ff, err := r.FileRepo.GetFilesRecursive("templates")
+ if err != nil {
+ log.Error(err, "failed to load resource templates")
+ return ctrl.Result{}, err
+ }
+
+ app := kubernetes.Application{
+ Client: r.Client,
+ FileRepo: r.FileRepo,
+ CR: &eventExporter,
+ GVK: operatorv1alpha1.GroupVersion.WithKind("EventExporter"),
+ Recorder: r.Recorder,
+ TmplFunc: template.FuncMap{
+ "configMapName": func() string { return newConfigMapName },
+ },
+ }
+
+ if err := app.ApplyAll(ctx, ff, log); err != nil {
+ return ctrl.Result{}, err
+ }
+
+ if err := r.checkState(ctx, log, &eventExporter); err != nil {
+ l.Error(err, "failed to check sub resources state")
+ return ctrl.Result{}, err
+ }
+
+ return ctrl.Result{RequeueAfter: schedDuration}, nil
+
+}
+
+func (r *EventExporterReconciler) overlayData(ctx context.Context, log logr.Logger,
+ eventExporter *operatorv1alpha1.EventExporter, newConfigMapName string) (changed bool, err error) {
+
+ oldConfigMapName := eventExporter.Status.ConfigMapName
+ if oldConfigMapName == newConfigMapName {
+ log.Info("eventexporter configuration keeps the same as before")
+ return false, nil
+ }
+
+ newConfigMap := core.ConfigMap{
+ ObjectMeta: metav1.ObjectMeta{
+ Namespace: eventExporter.Namespace,
+ Name: newConfigMapName,
+ OwnerReferences: []metav1.OwnerReference{
+ {
+ APIVersion: eventExporter.APIVersion,
+ Kind: eventExporter.Kind,
+ Name: eventExporter.Name,
+ UID: eventExporter.UID,
+ },
+ },
+ Labels: map[string]string{
+ "app": "eventexporter",
+ "operator.skywalking.apache.org/eventexporter-name": eventExporter.Name,
+ "operator.skywalking.apache.org/application": "eventexporter",
+ "operator.skywalking.apache.org/component": "configmap",
+ },
+ },
+ Immutable: &useImmutableConfigMap,
+ Data: map[string]string{"config.yaml": eventExporter.Spec.Config},
+ }
+
+ if err = r.Client.Create(ctx, &newConfigMap); err != nil {
+ log.Error(err, "failed to create eventexporter's configmap")
+ return true, err
+ }
+
+ oldConfigMap := core.ConfigMap{}
+ err = r.Client.Get(ctx, client.ObjectKey{Namespace: eventExporter.Namespace, Name: oldConfigMapName}, &oldConfigMap)
+ if err != nil && !apierrors.IsNotFound(err) {
+ log.Error(err, "failed to get the eventexporter's configmap")
+ return true, err
+ }
+
+ if !apierrors.IsNotFound(err) {
+ if err = r.Client.Delete(ctx, &oldConfigMap); err != nil {
+ log.Error(err, "failed to delete eventexporter's configmap")
+ return true, err
+ }
+ }
+
+ return true, nil
+}
+
+func (r *EventExporterReconciler) checkState(ctx context.Context, log logr.Logger, eventExporter *operatorv1alpha1.EventExporter) error {
+ overlay := operatorv1alpha1.EventExporterStatus{}
+ deployment := apps.Deployment{}
+ errCol := new(kubernetes.ErrorCollector)
+
+ if err := r.Client.Get(ctx, client.ObjectKey{Namespace: eventExporter.Namespace,
+ Name: eventExporter.Name + "-eventexporter"}, &deployment); err != nil && !apierrors.IsNotFound(err) {
+ errCol.Collect(fmt.Errorf("failed to get deployment: %w", err))
+ } else {
+ overlay.Conditions = deployment.Status.Conditions
+ overlay.AvailableReplicas = deployment.Status.AvailableReplicas
+ overlay.ConfigMapName = configMapName(eventExporter)
+ }
+
+ if apiequal.Semantic.DeepDerivative(overlay, eventExporter.Status) {
+ log.Info("Status keeps the same as before")
+ return errCol.Error()
+ }
+
+ if err := r.updateStatus(ctx, eventExporter, overlay, errCol); err != nil {
+ errCol.Collect(fmt.Errorf("failed to update status of EventExporter: %w", err))
+ }
+
+ log.Info("updated Status sub resource")
+
+ return errCol.Error()
+}
+
+func (r *EventExporterReconciler) updateStatus(ctx context.Context, eventExporter *operatorv1alpha1.EventExporter,
+ overlay operatorv1alpha1.EventExporterStatus, errCol *kubernetes.ErrorCollector) error {
+ // avoid resource conflict
+ return retry.RetryOnConflict(retry.DefaultBackoff, func() error {
+ if err := r.Client.Get(ctx, client.ObjectKey{Name: eventExporter.Name, Namespace: eventExporter.Namespace}, eventExporter); err != nil {
+ errCol.Collect(fmt.Errorf("failed to get EventExporter: %w", err))
+ }
+
+ eventExporter.Status = overlay
+ eventExporter.Kind = "EventExporter"
+ if err := kubernetes.ApplyOverlay(eventExporter, &operatorv1alpha1.EventExporter{Status: overlay}); err != nil {
+ errCol.Collect(fmt.Errorf("failed to apply overlay: %w", err))
+ }
+
+ if err := r.Status().Update(ctx, eventExporter); err != nil {
+ errCol.Collect(fmt.Errorf("failed to update status of EventExporter: %w", err))
+ }
+ return errCol.Error()
+ })
+}
+
+func configMapName(eventExporter *operatorv1alpha1.EventExporter) string {
+ md5 := MD5Hash(eventExporter.Name + eventExporter.Spec.Config)
+ return fmt.Sprintf("eventexporter-cm-%s", md5)
+}
+
+// SetupWithManager sets up the controller with the Manager.
+func (r *EventExporterReconciler) SetupWithManager(mgr ctrl.Manager) error {
+ return ctrl.NewControllerManagedBy(mgr).
+ For(&operatorv1alpha1.EventExporter{}).
+ Complete(r)
+}
diff --git a/operator/main.go b/operator/main.go
index 7ee7408..c048484 100644
--- a/operator/main.go
+++ b/operator/main.go
@@ -170,6 +170,15 @@
setupLog.Error(err, "unable to create controller", "controller", "BanyanDB")
os.Exit(1)
}
+ if err = (&operatorcontrollers.EventExporterReconciler{
+ Client: mgr.GetClient(),
+ Scheme: mgr.GetScheme(),
+ FileRepo: manifests.NewRepo("eventexporter"),
+ Recorder: mgr.GetEventRecorderFor("eventexporter-controller"),
+ }).SetupWithManager(mgr); err != nil {
+ setupLog.Error(err, "unable to create controller", "controller", "EventExporter")
+ os.Exit(1)
+ }
//+kubebuilder:scaffold:builder
if os.Getenv("ENABLE_WEBHOOKS") != "false" {
if err = (&operatorv1alpha1.OAPServer{}).SetupWebhookWithManager(mgr); err != nil {
@@ -212,6 +221,10 @@
setupLog.Error(err, "unable to create webhook", "webhook", "BanyanDB")
os.Exit(1)
}
+ if err = (&operatorv1alpha1.EventExporter{}).SetupWebhookWithManager(mgr); err != nil {
+ setupLog.Error(err, "unable to create webhook", "webhook", "EventExporter")
+ os.Exit(1)
+ }
// register a webhook to enable the java agent injector
setupLog.Info("registering /mutate-v1-pod webhook")
mgr.GetWebhookServer().Register("/mutate-v1-pod",
diff --git a/operator/pkg/operator/manifests/eventexporter/templates/cluster_role.yaml b/operator/pkg/operator/manifests/eventexporter/templates/cluster_role.yaml
new file mode 100644
index 0000000..1566e6b
--- /dev/null
+++ b/operator/pkg/operator/manifests/eventexporter/templates/cluster_role.yaml
@@ -0,0 +1,31 @@
+# Licensed to Apache Software Foundation (ASF) under one or more contributor
+# license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright
+# ownership. Apache Software Foundation (ASF) licenses this file to you 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.
+
+kind: ClusterRole
+apiVersion: rbac.authorization.k8s.io/v1
+metadata:
+ name: swck:eventexporter
+ labels:
+ operator.skywalking.apache.org/application: eventexporter
+ operator.skywalking.apache.org/component: rbac
+rules:
+ - apiGroups: [""]
+ resources: ["pods", "endpoints", "configmaps", "events", "services"]
+ verbs: ["get", "watch", "list"]
+ - apiGroups: ["extensions"]
+ resources: ["deployments", "replicasets"]
+ verbs: ["get", "watch", "list"]
diff --git a/operator/pkg/operator/manifests/eventexporter/templates/cluster_role_binding.yaml b/operator/pkg/operator/manifests/eventexporter/templates/cluster_role_binding.yaml
new file mode 100644
index 0000000..e174eb0
--- /dev/null
+++ b/operator/pkg/operator/manifests/eventexporter/templates/cluster_role_binding.yaml
@@ -0,0 +1,32 @@
+# Licensed to Apache Software Foundation (ASF) under one or more contributor
+# license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright
+# ownership. Apache Software Foundation (ASF) licenses this file to you 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.
+
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: swck:eventexporter
+ labels:
+ operator.skywalking.apache.org/application: eventexporter
+ operator.skywalking.apache.org/component: rbac
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: swck:eventexporter
+subjects:
+ - kind: ServiceAccount
+ name: {{ .Name }}-eventexporter
+ namespace: {{ .Namespace }}
diff --git a/operator/pkg/operator/manifests/eventexporter/templates/deployment.yaml b/operator/pkg/operator/manifests/eventexporter/templates/deployment.yaml
new file mode 100644
index 0000000..3d3629e
--- /dev/null
+++ b/operator/pkg/operator/manifests/eventexporter/templates/deployment.yaml
@@ -0,0 +1,65 @@
+# Licensed to Apache Software Foundation (ASF) under one or more contributor
+# license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright
+# ownership. Apache Software Foundation (ASF) licenses this file to you 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.
+
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: {{ .Name }}-eventexporter
+ namespace: {{ .Namespace }}
+ labels:
+ app: eventexporter
+ operator.skywalking.apache.org/eventexporter-name: {{ .Name }}
+ operator.skywalking.apache.org/application: eventexporter
+ operator.skywalking.apache.org/component: deployment
+spec:
+ replicas: {{ .Spec.Replicas }}
+ selector:
+ matchLabels:
+ operator.skywalking.apache.org/eventexporter-name: {{ .Name }}
+ template:
+ metadata:
+ labels:
+ operator.skywalking.apache.org/eventexporter-name: {{ .Name }}
+ operator.skywalking.apache.org/application: eventexporter
+ operator.skywalking.apache.org/component: pod
+ spec:
+ serviceAccountName: {{ .Name }}-eventexporter
+ affinity:
+ podAntiAffinity:
+ preferredDuringSchedulingIgnoredDuringExecution:
+ - weight: 1
+ podAffinityTerm:
+ topologyKey: kubernetes.io/hostname
+ labelSelector:
+ matchLabels:
+ app: eventexporter
+ operator.skywalking.apache.org/eventexporter-name: {{ .Name }}
+ containers:
+ - name: eventexporter
+ image: {{ .Spec.Image }}
+ imagePullPolicy: IfNotPresent
+ args:
+ - start
+ - -v=debug
+ - -c=/data/config.yaml
+ volumeMounts:
+ - mountPath: /data
+ name: config
+ volumes:
+ - name: config
+ configMap:
+ name: {{ configMapName }}
diff --git a/operator/pkg/operator/manifests/eventexporter/templates/service_account.yaml b/operator/pkg/operator/manifests/eventexporter/templates/service_account.yaml
new file mode 100644
index 0000000..1cf5baa
--- /dev/null
+++ b/operator/pkg/operator/manifests/eventexporter/templates/service_account.yaml
@@ -0,0 +1,26 @@
+# Licensed to Apache Software Foundation (ASF) under one or more contributor
+# license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright
+# ownership. Apache Software Foundation (ASF) licenses this file to you 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.
+
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: {{ .Name }}-eventexporter
+ namespace: {{ .Namespace }}
+ labels:
+ operator.skywalking.apache.org/fetcher-name: {{ .Name }}
+ operator.skywalking.apache.org/application: eventexporter
+ operator.skywalking.apache.org/component: rbac
diff --git a/operator/pkg/operator/manifests/repo.go b/operator/pkg/operator/manifests/repo.go
index 769697f..420cdf5 100644
--- a/operator/pkg/operator/manifests/repo.go
+++ b/operator/pkg/operator/manifests/repo.go
@@ -28,7 +28,7 @@
var _ kubernetes.Repo = &AssetsRepo{}
-//go:embed fetcher injector oapserver satellite storage ui banyandb
+//go:embed fetcher injector oapserver satellite storage ui banyandb eventexporter
var manifests embed.FS
// AssetsRepo provides templates through assets
diff --git a/test/e2e/oap-eventexporter/e2e.yaml b/test/e2e/oap-eventexporter/e2e.yaml
new file mode 100644
index 0000000..9116bd9
--- /dev/null
+++ b/test/e2e/oap-eventexporter/e2e.yaml
@@ -0,0 +1,83 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+setup:
+ env: kind
+ file: ../kind.yaml
+ steps:
+ - name: prepare e2e.yaml
+ command: bash hack/prepare-e2e.sh
+ - name: install cert-manager
+ command: |
+ # kind k8s cluster is in $TMPDIR
+ export KUBECONFIG=$TMPDIR/e2e-k8s.config
+ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.8.0/cert-manager.yaml
+ wait:
+ - namespace: cert-manager
+ resource: pod
+ for: condition=Ready
+ - name: install operator
+ command: |
+ export OPERATOR_IMG=controller
+ make -C operator docker-build
+ kind load docker-image controller
+ make -C operator install
+ make -C operator deploy
+ wait:
+ - namespace: skywalking-swck-system
+ resource: pod
+ for: condition=Ready
+ - name: setup oapserver and eventexporter
+ command: |
+ kubectl create namespace skywalking-system
+ kubectl apply -f test/e2e/skywalking-components-with-eventexporter.yaml
+ wait:
+ - namespace: skywalking-system
+ resource: OAPServer/skywalking-system
+ for: condition=Available
+ - namespace: skywalking-system
+ resource: EventExporter/skywalking-system
+ for: condition=Available
+ - name: setup java agent demo
+ command: |
+ kubectl label namespace skywalking-system swck-injection=enabled
+ sed 's/oap-service/skywalking-system-oap.skywalking-system/' test/e2e/demo.yaml | kubectl create -f -
+ wait:
+ - namespace: skywalking-system
+ resource: deployment/demo
+ for: condition=Available
+
+ kind:
+ expose-ports:
+ - namespace: skywalking-system
+ resource: service/skywalking-system-oap
+ port: 12800
+ timeout: 20m
+
+cleanup:
+ # always never success failure
+ on: always
+
+verify:
+ # verify with retry strategy
+ retry:
+ # max retry count
+ count: 10
+ # the interval between two attempts, e.g. 10s, 1m.
+ interval: 10s
+ cases:
+ # test eventexporter
+ - query: 'swctl --display yaml --base-url=http://${service_skywalking_system_oap_host}:${service_skywalking_system_oap_12800}/graphql event ls | yq e ''.events | map({"service": .source.service, "name": .name})'''
+ expected: ../verify/eventexporter-event.yaml
\ No newline at end of file
diff --git a/test/e2e/skywalking-components-with-eventexporter.yaml b/test/e2e/skywalking-components-with-eventexporter.yaml
new file mode 100644
index 0000000..484c059
--- /dev/null
+++ b/test/e2e/skywalking-components-with-eventexporter.yaml
@@ -0,0 +1,62 @@
+# Licensed to Apache Software Foundation (ASF) under one or more contributor
+# license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright
+# ownership. Apache Software Foundation (ASF) licenses this file to you 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.
+
+apiVersion: operator.skywalking.apache.org/v1alpha1
+kind: OAPServer
+metadata:
+ name: skywalking-system
+ namespace: skywalking-system
+spec:
+ version: 9.5.0
+ instances: 1
+ image: apache/skywalking-oap-server:9.5.0
+ service:
+ template:
+ type: ClusterIP
+
+---
+apiVersion: operator.skywalking.apache.org/v1alpha1
+kind: EventExporter
+metadata:
+ name: skywalking-system
+ namespace: skywalking-system
+spec:
+ replicas: 1
+ config: |
+ filters:
+ - reason: ""
+ message: ""
+ minCount: 1
+ type: ""
+ action: ""
+ kind: "Pod|Service"
+ namespace: "^skywalking-system$"
+ name: ""
+ service: "[^\\s]{1,}"
+ exporters:
+ - skywalking
+ exporters:
+ skywalking:
+ template:
+ source:
+ service: "{{ .Service.Name }}"
+ serviceInstance: "{{ .Pod.Name }}"
+ endpoint: ""
+ message: "{{ .Event.Message }}"
+ address: "skywalking-system-oap.skywalking-system:11800"
+
+
\ No newline at end of file
diff --git a/test/e2e/verify/eventexporter-event.yaml b/test/e2e/verify/eventexporter-event.yaml
new file mode 100644
index 0000000..015f1c8
--- /dev/null
+++ b/test/e2e/verify/eventexporter-event.yaml
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+
+{{- contains . }}
+- service: demo
+ name: Pulled
+- service: demo
+ name: Started
+- service: demo
+ name: Created
+{{- end}}
\ No newline at end of file