Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .golangci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ linters:
alias: declarativetest
- pkg: github.com/kyma-project/lifecycle-manager/tests/integration/controller/manifest
alias: manifesttest
- pkg: github.com/kyma-project/runtime-watcher/listener/pkg/event
- pkg: github.com/kyma-project/runtime-watcher/listener/pkg/v2/event
alias: watcherevent
- pkg: github.com/kyma-project/runtime-watcher/listener/pkg/metrics
alias: watchermetrics
Expand Down
14 changes: 1 addition & 13 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,6 @@ test: unittest manifests test-crd generate fmt vet envtest ## Run tests.
unittest: ## Run the unit test suite.
$(GO) test `go list ./... | grep -v /tests/` -coverprofile cover.out -coverpkg=./...

.PHONY: dry-run
dry-run: kustomize manifests
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
mkdir -p dry-run
$(KUSTOMIZE) build config/default > dry-run/manifests.yaml


.PHONY: dry-run-control-plane
dry-run-control-plane: kustomize manifests
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
Expand Down Expand Up @@ -124,11 +117,6 @@ install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~
uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
$(KUSTOMIZE) build config/crd | kubectl delete --ignore-not-found=$(ignore-not-found) -f -

.PHONY: deploy
deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
$(KUSTOMIZE) build config/default | kubectl apply -f -

.PHONY: local-deploy-with-watcher
local-deploy-with-watcher: generate kustomize ## Deploy the controller locally with the watcher component using cert-manager for certificate management.
cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG}
Expand All @@ -141,7 +129,7 @@ local-deploy-with-watcher-gcm: generate kustomize ## Deploy the controller local

.PHONY: undeploy
undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
$(KUSTOMIZE) build config/default | kubectl delete --ignore-not-found=$(ignore-not-found) -f -
$(KUSTOMIZE) build config/control-plane | kubectl delete --ignore-not-found=$(ignore-not-found) -f -

## Location to install dependencies to
LOCALBIN ?= $(shell pwd)/bin
Expand Down
2 changes: 1 addition & 1 deletion config/watcher/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ patches:
value: --skr-watcher-path=/skr-webhook
- op: add
path: /spec/template/spec/containers/0/args/-
value: --skr-watcher-image-tag=1.2.0
value: --skr-watcher-image-tag=2.0.0
- op: add
path: /spec/template/spec/containers/0/args/-
value: --skr-watcher-image-registry=europe-docker.pkg.dev/kyma-project/prod
Expand Down
10 changes: 5 additions & 5 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ require (
github.com/jellydator/ttlcache/v3 v3.4.0
github.com/kyma-project/lifecycle-manager/api v0.0.0-00010101000000-000000000000
github.com/kyma-project/lifecycle-manager/maintenancewindows v0.0.0-20250113095044-41115399d588
github.com/kyma-project/runtime-watcher/listener v0.0.0-20240502124257-9d96561ef070
github.com/kyma-project/runtime-watcher/listener v0.0.0-20250825111833-2cf3f8cc5232
github.com/onsi/ginkgo/v2 v2.23.4
github.com/onsi/gomega v1.38.0
github.com/prometheus/client_golang v1.23.0
github.com/stretchr/testify v1.10.0
github.com/stretchr/testify v1.11.0
go.uber.org/zap v1.27.0
golang.org/x/sync v0.16.0
golang.org/x/time v0.12.0
Expand All @@ -42,11 +42,11 @@ require (
github.com/go-co-op/gocron v1.37.0
github.com/kyma-project/template-operator/api v0.0.0-20240404131948-52c84f14e73c
github.com/prometheus/client_model v0.6.2
k8s.io/api v0.33.3
k8s.io/api v0.33.4
k8s.io/apiextensions-apiserver v0.33.3
k8s.io/apimachinery v0.33.3
k8s.io/apimachinery v0.33.4
k8s.io/cli-runtime v0.33.3
k8s.io/client-go v0.33.3
k8s.io/client-go v0.33.4
k8s.io/kubectl v0.33.3
)

Expand Down
18 changes: 16 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -606,8 +606,12 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/kyma-project/runtime-watcher/listener v0.0.0-20240502124257-9d96561ef070 h1:AFegQ/P12b1jTZ90ydCQd7h/pVaj1XZkcYXwLHZYSPk=
github.com/kyma-project/runtime-watcher/listener v0.0.0-20240502124257-9d96561ef070/go.mod h1:MbLimL7PbR8lDadZ0Po9irrpAf1S2v6YymFFST/HYFA=
github.com/kyma-project/runtime-watcher/listener v0.0.0-20250822075504-353a2aaa9894 h1:9coOPviV16M+EZKrOfhsMrmScX+bH93C4UAlkl8EL6k=
github.com/kyma-project/runtime-watcher/listener v0.0.0-20250822075504-353a2aaa9894/go.mod h1:dmTTjYNhk6o/Frb2xRzk7R2nZxn1Rw1dEblM/auQMHs=
github.com/kyma-project/runtime-watcher/listener v0.0.0-20250825111833-2cf3f8cc5232 h1:4jPg3Ey0ie5ipYCR72VuxsCR3139uywIIYIfjZs+zQs=
github.com/kyma-project/runtime-watcher/listener v0.0.0-20250825111833-2cf3f8cc5232/go.mod h1:KdQvykzVhghVhwLZJbrXUoV1YplGVnxe2wgAfMDWoXM=
github.com/kyma-project/runtime-watcher/listener v1.1.18 h1:vJJJnhagHyhnxnoZhVvOAxU8SH6Ex3X6TXc9J79hbDg=
github.com/kyma-project/runtime-watcher/listener v1.1.18/go.mod h1:c9h0QMzzlc7DSP09OI0c+vwV8iR0jdp623a9E9+FivY=
github.com/kyma-project/template-operator/api v0.0.0-20240404131948-52c84f14e73c h1:alsRB1f5TaNNOCg8f1DEI/74lk5lpq6bbNmi8PZpFxI=
github.com/kyma-project/template-operator/api v0.0.0-20240404131948-52c84f14e73c/go.mod h1:WpDVtbu62bjMTNY2kWThlw6iffWRrG3zERdRwZHnwv8=
github.com/letsencrypt/boulder v0.0.0-20241010192615-6692160cedfa h1:/kPrcWfMENmWJh9AceGWaTJ0QBS3OyCDENx2vI71T8k=
Expand Down Expand Up @@ -636,6 +640,8 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/medmes/runtime-watcher/listener v0.0.0-20250810204720-3bfb15765847 h1:U6iMAEONChS8sSjzb4EmpSC+RPAozfu1mmqFMFVbKLk=
github.com/medmes/runtime-watcher/listener v0.0.0-20250810204720-3bfb15765847/go.mod h1:gqXEeFh/TLX8yc16yWdn0DDqriRzI+yHrQS8xyqAenQ=
github.com/miekg/dns v1.1.66 h1:FeZXOS3VCVsKnEAd+wBkjMC3D2K+ww66Cq3VnCINuJE=
github.com/miekg/dns v1.1.66/go.mod h1:jGFzBsSNbJw6z1HYut1RKBKHA9PBdxeHrZG8J+gC2WE=
github.com/miekg/pkcs11 v1.0.3-0.20190429190417-a667d056470f/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
Expand Down Expand Up @@ -855,6 +861,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8=
github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs=
Expand Down Expand Up @@ -1216,14 +1224,20 @@ istio.io/client-go v1.26.3 h1:ryF4+Nyz5wDO4mVCzXcm2W+fqbnekY88Z36hTcv5fnw=
istio.io/client-go v1.26.3/go.mod h1:u2p5L7UvjNswrrlHZ+QMlUOjERK2sXputywzyNhtTMg=
k8s.io/api v0.33.3 h1:SRd5t//hhkI1buzxb288fy2xvjubstenEKL9K51KBI8=
k8s.io/api v0.33.3/go.mod h1:01Y/iLUjNBM3TAvypct7DIj0M0NIZc+PzAHCIo0CYGE=
k8s.io/api v0.33.4 h1:oTzrFVNPXBjMu0IlpA2eDDIU49jsuEorGHB4cvKupkk=
k8s.io/api v0.33.4/go.mod h1:VHQZ4cuxQ9sCUMESJV5+Fe8bGnqAARZ08tSTdHWfeAc=
k8s.io/apiextensions-apiserver v0.33.3 h1:qmOcAHN6DjfD0v9kxL5udB27SRP6SG/MTopmge3MwEs=
k8s.io/apiextensions-apiserver v0.33.3/go.mod h1:oROuctgo27mUsyp9+Obahos6CWcMISSAPzQ77CAQGz8=
k8s.io/apimachinery v0.33.3 h1:4ZSrmNa0c/ZpZJhAgRdcsFcZOw1PQU1bALVQ0B3I5LA=
k8s.io/apimachinery v0.33.3/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
k8s.io/apimachinery v0.33.4 h1:SOf/JW33TP0eppJMkIgQ+L6atlDiP/090oaX0y9pd9s=
k8s.io/apimachinery v0.33.4/go.mod h1:BHW0YOu7n22fFv/JkYOEfkUYNRN0fj0BlvMFWA7b+SM=
k8s.io/cli-runtime v0.33.3 h1:Dgy4vPjNIu8LMJBSvs8W0LcdV0PX/8aGG1DA1W8lklA=
k8s.io/cli-runtime v0.33.3/go.mod h1:yklhLklD4vLS8HNGgC9wGiuHWze4g7x6XQZ+8edsKEo=
k8s.io/client-go v0.33.3 h1:M5AfDnKfYmVJif92ngN532gFqakcGi6RvaOF16efrpA=
k8s.io/client-go v0.33.3/go.mod h1:luqKBQggEf3shbxHY4uVENAxrDISLOarxpTKMiUuujg=
k8s.io/client-go v0.33.4 h1:TNH+CSu8EmXfitntjUPwaKVPN0AYMbc9F1bBS8/ABpw=
k8s.io/client-go v0.33.4/go.mod h1:LsA0+hBG2DPwovjd931L/AoaezMPX9CmBgyVyBZmbCY=
k8s.io/component-base v0.33.3 h1:mlAuyJqyPlKZM7FyaoM/LcunZaaY353RXiOd2+B5tGA=
k8s.io/component-base v0.33.3/go.mod h1:ktBVsBzkI3imDuxYXmVxZ2zxJnYTZ4HAsVj9iF09qp4=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
Expand Down
21 changes: 21 additions & 0 deletions internal/common/interfaces.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package common

import (
"context"

"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/source"
)

// EventService defines the interface for event services consumed by controllers.
// Moved to common package to avoid circular dependencies between service and controller packages.
type EventService interface {
// Start begins the event service lifecycle
Start(ctx context.Context) error

// Stop shuts down the event service
Stop() error

// CreateEventSource creates a controller-runtime compatible event source
CreateEventSource(eventHandler handler.EventHandler) source.Source
}
9 changes: 9 additions & 0 deletions internal/controller/interfaces.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package controller

import (
"github.com/kyma-project/lifecycle-manager/internal/common"
)

// EventService re-exports the common EventService interface for backward compatibility.
// This allows controllers to use controller.EventService while avoiding circular dependencies.
type EventService = common.EventService
62 changes: 23 additions & 39 deletions internal/controller/kyma/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,20 @@ import (
"context"
"errors"
"fmt"
"net/http"

watcherevent "github.com/kyma-project/runtime-watcher/listener/pkg/event"
"github.com/kyma-project/runtime-watcher/listener/pkg/types"
apicorev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/client-go/util/workqueue"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/builder"
"sigs.k8s.io/controller-runtime/pkg/client"
ctrlruntime "sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/event"
"sigs.k8s.io/controller-runtime/pkg/handler"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/source"

"github.com/kyma-project/lifecycle-manager/api/shared"
"github.com/kyma-project/lifecycle-manager/api/v1beta2"
"github.com/kyma-project/lifecycle-manager/internal/service/skrevent"
"github.com/kyma-project/lifecycle-manager/internal/watch"
"github.com/kyma-project/lifecycle-manager/pkg/security"
)

type SetupOptions struct {
Expand All @@ -34,29 +28,24 @@ type SetupOptions struct {

const controllerName = "kyma"

var (
errConvertingWatched = errors.New("error converting watched to object key")
errParsingWatched = errors.New("error getting watched object from unstructured event")
errConvertingWatcherEvent = errors.New("error converting watched object to unstructured event")
)
var errConvertingWatcherEvent = errors.New("error converting watched object to unstructured event")

func (r *Reconciler) SetupWithManager(mgr ctrl.Manager, opts ctrlruntime.Options, settings SetupOptions) error {
var verifyFunc watcherevent.Verify
if settings.EnableDomainNameVerification {
verifyFunc = security.NewRequestVerifier(mgr.GetClient()).Verify
} else {
verifyFunc = func(r *http.Request, watcherEvtObject *types.WatchEvent) error {
return nil
}
}
runnableListener := watcherevent.NewSKREventListener(
runtimeEventService, err := skrevent.NewSKREventService(
mgr,
settings.ListenerAddr,
shared.OperatorName,
verifyFunc,
"kyma", // Component name for Kyma controller events
settings.EnableDomainNameVerification,
)
if err := mgr.Add(runnableListener); err != nil {
return fmt.Errorf("KymaReconciler %w", err)
if err != nil {
return fmt.Errorf("failed to create runtime event service: %w", err)
}

// Note: Service is automatically started by the manager (implements manager.Runnable)

// Create event source for this controller using the service's channel
runtimeEventSource := runtimeEventService.CreateEventSource(r.runtimeEventHandler())

if err := ctrl.NewControllerManagedBy(mgr).For(&v1beta2.Kyma{}).
Named(controllerName).
WithOptions(opts).
Expand All @@ -68,44 +57,39 @@ func (r *Reconciler) SetupWithManager(mgr ctrl.Manager, opts ctrlruntime.Options
Watches(&v1beta2.Manifest{},
handler.EnqueueRequestForOwner(mgr.GetScheme(), mgr.GetRESTMapper(), &v1beta2.Kyma{},
handler.OnlyControllerOwner()), builder.WithPredicates(predicate.ResourceVersionChangedPredicate{})).
WatchesRawSource(source.Channel(runnableListener.ReceivedEvents, r.skrEventHandler())).
WatchesRawSource(runtimeEventSource).
Complete(r); err != nil {
return fmt.Errorf("failed to setup manager for kyma controller: %w", err)
}

return nil
}

func (r *Reconciler) skrEventHandler() *handler.Funcs {
func (r *Reconciler) runtimeEventHandler() *handler.Funcs {
return &handler.Funcs{
GenericFunc: func(ctx context.Context, evnt event.GenericEvent,
queue workqueue.TypedRateLimitingInterface[ctrl.Request],
) {
logger := ctrl.Log.WithName("listener")
logger := ctrl.Log.WithName("kyma-listener")
unstructWatcherEvt, conversionOk := evnt.Object.(*unstructured.Unstructured)
if !conversionOk {
logger.Error(errConvertingWatcherEvent, fmt.Sprintf("event: %v", evnt.Object))
return
}

// get owner object from unstructured event, owner = KymaCR object reference in KCP
unstructuredOwner, ok := unstructWatcherEvt.Object["owner"]
if !ok {
logger.Error(errParsingWatched, fmt.Sprintf("unstructured event: %v", unstructWatcherEvt))
return
}

ownerObjectKey, conversionOk := unstructuredOwner.(client.ObjectKey)
if !conversionOk {
logger.Error(errConvertingWatched, fmt.Sprintf("unstructured Owner object: %v", unstructuredOwner))
// This is where ExtractOwnerKey is essential - it tells us WHICH Kyma to reconcile
ownerObjectKey, err := skrevent.ExtractOwnerKey(unstructWatcherEvt)
if err != nil {
logger.Error(err, "failed to extract owner key from runtime watcher event")
return
}

logger.Info(
fmt.Sprintf("event received from SKR, adding %s to queue",
fmt.Sprintf("kyma event received from runtime-watcher, adding %s to queue",
ownerObjectKey),
)

// The extracted owner key becomes the reconciliation target
queue.Add(ctrl.Request{
NamespacedName: ownerObjectKey,
})
Expand Down
Loading
Loading