Skip to content
Closed
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
16 changes: 3 additions & 13 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,10 @@ import (
"github.com/kyma-project/lifecycle-manager/internal/service/skrclient"
skrclientcache "github.com/kyma-project/lifecycle-manager/internal/service/skrclient/cache"
"github.com/kyma-project/lifecycle-manager/internal/setup"
"github.com/kyma-project/lifecycle-manager/internal/templatelookup"
"github.com/kyma-project/lifecycle-manager/pkg/log"
"github.com/kyma-project/lifecycle-manager/pkg/matcher"
"github.com/kyma-project/lifecycle-manager/pkg/queue"
"github.com/kyma-project/lifecycle-manager/pkg/templatelookup"
"github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup"
"github.com/kyma-project/lifecycle-manager/pkg/watcher"

_ "k8s.io/client-go/plugin/pkg/client/auth"
Expand Down Expand Up @@ -383,17 +382,9 @@ func setupKymaReconciler(mgr ctrl.Manager, descriptorProvider *provider.CachedDe
options.CacheSyncTimeout = flagVar.CacheSyncTimeout
options.MaxConcurrentReconciles = flagVar.MaxConcurrentKymaReconciles

moduleTemplateInfoLookupStrategies := moduletemplateinfolookup.NewModuleTemplateInfoLookupStrategies(
[]moduletemplateinfolookup.ModuleTemplateInfoLookupStrategy{
moduletemplateinfolookup.NewByVersionStrategy(mgr.GetClient()),
moduletemplateinfolookup.NewByChannelStrategy(mgr.GetClient()),
moduletemplateinfolookup.NewWithMaintenanceWindowDecorator(maintenanceWindow,
moduletemplateinfolookup.NewByModuleReleaseMetaStrategy(mgr.GetClient())),
},
)

kcpClient := mgr.GetClient()
moduleStatusGen := generator.NewModuleStatusGenerator(fromerror.GenerateModuleStatusFromError)

modulesStatusHandler := modules.NewStatusHandler(moduleStatusGen, kcpClient, kymaMetrics.RemoveModuleStateMetrics)

if err := (&kyma.Reconciler{
Expand All @@ -415,8 +406,7 @@ func setupKymaReconciler(mgr ctrl.Manager, descriptorProvider *provider.CachedDe
Metrics: kymaMetrics,
RemoteCatalog: remote.NewRemoteCatalogFromKyma(kcpClient, skrContextFactory,
flagVar.RemoteSyncNamespace),
TemplateLookup: templatelookup.NewTemplateLookup(kcpClient, descriptorProvider,
moduleTemplateInfoLookupStrategies),
TemplateLookup: templatelookup.NewTemplateLookup(kcpClient, descriptorProvider, maintenanceWindow),
}).SetupWithManager(
mgr, options, kyma.SetupOptions{
ListenerAddr: flagVar.KymaListenerAddr,
Expand Down
2 changes: 1 addition & 1 deletion internal/controller/kyma/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ import (
"github.com/kyma-project/lifecycle-manager/internal/pkg/metrics"
"github.com/kyma-project/lifecycle-manager/internal/remote"
"github.com/kyma-project/lifecycle-manager/internal/service/accessmanager"
"github.com/kyma-project/lifecycle-manager/internal/templatelookup"
"github.com/kyma-project/lifecycle-manager/pkg/log"
modulecommon "github.com/kyma-project/lifecycle-manager/pkg/module/common"
"github.com/kyma-project/lifecycle-manager/pkg/module/sync"
"github.com/kyma-project/lifecycle-manager/pkg/queue"
"github.com/kyma-project/lifecycle-manager/pkg/status"
"github.com/kyma-project/lifecycle-manager/pkg/templatelookup"
"github.com/kyma-project/lifecycle-manager/pkg/util"
"github.com/kyma-project/lifecycle-manager/pkg/watcher"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@ import (
"github.com/kyma-project/lifecycle-manager/internal/descriptor/provider"
"github.com/kyma-project/lifecycle-manager/internal/manifest/parser"
"github.com/kyma-project/lifecycle-manager/internal/pkg/metrics"
"github.com/kyma-project/lifecycle-manager/internal/templatelookup"
"github.com/kyma-project/lifecycle-manager/pkg/log"
modulecommon "github.com/kyma-project/lifecycle-manager/pkg/module/common"
"github.com/kyma-project/lifecycle-manager/pkg/module/sync"
"github.com/kyma-project/lifecycle-manager/pkg/queue"
"github.com/kyma-project/lifecycle-manager/pkg/templatelookup"
"github.com/kyma-project/lifecycle-manager/pkg/util"
)

Expand Down
2 changes: 1 addition & 1 deletion internal/manifest/parser/template_to_module.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ import (
"github.com/kyma-project/lifecycle-manager/internal/descriptor/provider"
"github.com/kyma-project/lifecycle-manager/internal/descriptor/types"
"github.com/kyma-project/lifecycle-manager/internal/manifest/img"
"github.com/kyma-project/lifecycle-manager/internal/templatelookup"
modulecommon "github.com/kyma-project/lifecycle-manager/pkg/module/common"
"github.com/kyma-project/lifecycle-manager/pkg/templatelookup"
)

var ErrConvertingToOCIAccessSpec = errors.New("failed converting resource.AccessSpec to *ociartifact.AccessSpec")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@ import (

"github.com/kyma-project/lifecycle-manager/api/shared"
"github.com/kyma-project/lifecycle-manager/api/v1beta2"
"github.com/kyma-project/lifecycle-manager/pkg/templatelookup"
"github.com/kyma-project/lifecycle-manager/pkg/templatelookup/common"
"github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup"
"github.com/kyma-project/lifecycle-manager/internal/templatelookup"
"github.com/kyma-project/lifecycle-manager/internal/templatelookup/common"
)

var errFunctionCalledWitNilError = errors.New("can not generate a modulestatus without error")
Expand Down Expand Up @@ -54,11 +53,11 @@ func GenerateModuleStatusFromError(err error, moduleName, desiredChannel, fqdn s
}

func errorIsWaitingForMaintenanceWindow(err error) bool {
return errors.Is(err, moduletemplateinfolookup.ErrWaitingForNextMaintenanceWindow)
return errors.Is(err, templatelookup.ErrWaitingForNextMaintenanceWindow)
}

func errorIsMaintenanceWindowUnknown(err error) bool {
return errors.Is(err, moduletemplateinfolookup.ErrFailedToDetermineIfMaintenanceWindowIsActive)
return errors.Is(err, templatelookup.ErrFailedToDetermineIfMaintenanceWindowIsActive)
}

func errorIsForbiddenTemplateUpdate(err error) bool {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@ import (
"github.com/kyma-project/lifecycle-manager/api/shared"
"github.com/kyma-project/lifecycle-manager/api/v1beta2"
"github.com/kyma-project/lifecycle-manager/internal/service/kyma/status/modules/generator/fromerror"
"github.com/kyma-project/lifecycle-manager/pkg/templatelookup"
"github.com/kyma-project/lifecycle-manager/pkg/templatelookup/common"
"github.com/kyma-project/lifecycle-manager/pkg/templatelookup/moduletemplateinfolookup"
"github.com/kyma-project/lifecycle-manager/internal/templatelookup"
"github.com/kyma-project/lifecycle-manager/internal/templatelookup/common"
)

func TestGenerateModuleStatusFromError_WhenCalledWithAnyOtherError_ReturnsDefaultNewStatusWithStateError(t *testing.T) {
Expand Down Expand Up @@ -50,7 +49,7 @@ func TestGenerateModuleStatusFromError_WhenCalledWithMaintenanceWindowActiveErro
someChannel := "some-channel"
someFQDN := "some-fqdn"
status := createStatus()
templateError := moduletemplateinfolookup.ErrWaitingForNextMaintenanceWindow
templateError := templatelookup.ErrWaitingForNextMaintenanceWindow

result, err := fromerror.GenerateModuleStatusFromError(templateError, someModuleName, someChannel, someFQDN, status)

Expand All @@ -75,7 +74,7 @@ func TestGenerateModuleStatusFromError_WhenCalledWithMaintenanceWindowUnknownErr
someChannel := "some-channel"
someFQDN := "some-fqdn"
status := createStatus()
templateError := moduletemplateinfolookup.ErrFailedToDetermineIfMaintenanceWindowIsActive
templateError := templatelookup.ErrFailedToDetermineIfMaintenanceWindowIsActive

result, err := fromerror.GenerateModuleStatusFromError(templateError, someModuleName, someChannel, someFQDN, status)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import (
"github.com/kyma-project/lifecycle-manager/api/shared"
"github.com/kyma-project/lifecycle-manager/api/v1beta2"
"github.com/kyma-project/lifecycle-manager/internal/service/kyma/status/modules/generator"
"github.com/kyma-project/lifecycle-manager/internal/templatelookup"
modulecommon "github.com/kyma-project/lifecycle-manager/pkg/module/common"
"github.com/kyma-project/lifecycle-manager/pkg/templatelookup"
"github.com/kyma-project/lifecycle-manager/pkg/testutils/builder"
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client/fake"

"github.com/kyma-project/lifecycle-manager/api/v1beta2"
"github.com/kyma-project/lifecycle-manager/pkg/templatelookup"
"github.com/kyma-project/lifecycle-manager/internal/templatelookup"
"github.com/kyma-project/lifecycle-manager/pkg/testutils/builder"
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
apimetav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/kyma-project/lifecycle-manager/api/v1beta2"
"github.com/kyma-project/lifecycle-manager/pkg/templatelookup"
"github.com/kyma-project/lifecycle-manager/internal/templatelookup"
)

func Test_FetchModuleInfo_When_EmptySpecAndStatus(t *testing.T) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/stretchr/testify/require"

"github.com/kyma-project/lifecycle-manager/api/v1beta2"
"github.com/kyma-project/lifecycle-manager/pkg/templatelookup"
"github.com/kyma-project/lifecycle-manager/internal/templatelookup"
)

func Test_GetChannelVersionForModule_WhenEmptyChannels(t *testing.T) {
Expand Down
160 changes: 142 additions & 18 deletions pkg/templatelookup/regular.go → internal/templatelookup/regular.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,49 +11,124 @@ import (

"github.com/kyma-project/lifecycle-manager/api/v1beta2"
"github.com/kyma-project/lifecycle-manager/internal/descriptor/provider"
"github.com/kyma-project/lifecycle-manager/pkg/templatelookup/common"
"github.com/kyma-project/lifecycle-manager/internal/templatelookup/common"
)

var (
ErrTemplateNotAllowed = errors.New("module template not allowed")
ErrTemplateUpdateNotAllowed = errors.New("module template update not allowed")
ErrTemplateNotAllowed = errors.New("module template not allowed")
ErrTemplateUpdateNotAllowed = errors.New("module template update not allowed")
ErrWaitingForNextMaintenanceWindow = errors.New(
"waiting for next maintenance window to update module version",
)
ErrFailedToDetermineIfMaintenanceWindowIsActive = errors.New("failed to determine if maintenance window is active")
ErrModuleReleaseMetaNotFound = errors.New("ModuleReleaseMeta not found for module")
)

type MaintenanceWindow interface {
IsRequired(moduleTemplate *v1beta2.ModuleTemplate, kyma *v1beta2.Kyma) bool
IsActive(kyma *v1beta2.Kyma) (bool, error)
}

type ModuleTemplateInfo struct {
*v1beta2.ModuleTemplate

Err error
DesiredChannel string
}

type ModuleTemplateInfoLookupStrategy interface {
Lookup(ctx context.Context,
moduleInfo *ModuleInfo,
kyma *v1beta2.Kyma,
moduleReleaseMeta *v1beta2.ModuleReleaseMeta,
) ModuleTemplateInfo
}

type TemplateLookup struct {
client.Reader

descriptorProvider *provider.CachedDescriptorProvider
moduleTemplateInfoLookupStrategy ModuleTemplateInfoLookupStrategy
descriptorProvider *provider.CachedDescriptorProvider
maintenanceWindow MaintenanceWindow
}

func NewTemplateLookup(reader client.Reader,
descriptorProvider *provider.CachedDescriptorProvider,
moduleTemplateInfoLookupStrategy ModuleTemplateInfoLookupStrategy,
maintenanceWindow MaintenanceWindow,
) *TemplateLookup {
return &TemplateLookup{
Reader: reader,
descriptorProvider: descriptorProvider,
moduleTemplateInfoLookupStrategy: moduleTemplateInfoLookupStrategy,
Reader: reader,
descriptorProvider: descriptorProvider,
maintenanceWindow: maintenanceWindow,
}
}

type ModuleTemplatesByModuleName map[string]*ModuleTemplateInfo

// LookupModuleTemplate looks up the module template via the module release meta.
// In production, moduleReleaseMeta is guaranteed to exist for valid modules.
func LookupModuleTemplate(ctx context.Context,
clnt client.Reader,
moduleInfo *ModuleInfo,
kyma *v1beta2.Kyma,
moduleReleaseMeta *v1beta2.ModuleReleaseMeta,
) ModuleTemplateInfo {
moduleTemplateInfo := ModuleTemplateInfo{}
moduleTemplateInfo.DesiredChannel = getDesiredChannel(moduleInfo.Channel, kyma.Spec.Channel)

var desiredModuleVersion string
var err error
if moduleReleaseMeta.Spec.Mandatory != nil {
desiredModuleVersion, err = GetMandatoryVersionForModule(moduleReleaseMeta)
} else {
desiredModuleVersion, err = GetChannelVersionForModule(moduleReleaseMeta,
moduleTemplateInfo.DesiredChannel)
}
if err != nil {
moduleTemplateInfo.Err = err
return moduleTemplateInfo
}

template, err := getTemplateByVersion(ctx,
clnt,
moduleInfo.Name,
desiredModuleVersion,
kyma.Namespace)
if err != nil {
moduleTemplateInfo.Err = err
return moduleTemplateInfo
}

moduleTemplateInfo.ModuleTemplate = template
return moduleTemplateInfo
}

// getDesiredChannel determines the desired channel based on module-specific channel or global channel.
func getDesiredChannel(moduleChannel, globalChannel string) string {
var desiredChannel string

switch {
case moduleChannel != "":
desiredChannel = moduleChannel
case globalChannel != "":
desiredChannel = globalChannel
default:
desiredChannel = v1beta2.DefaultChannel
}

return desiredChannel
}

func getTemplateByVersion(ctx context.Context,
clnt client.Reader,
moduleName,
moduleVersion,
namespace string,
) (*v1beta2.ModuleTemplate, error) {
moduleTemplate := &v1beta2.ModuleTemplate{}

moduleTemplateName := fmt.Sprintf("%s-%s", moduleName, moduleVersion)
if err := clnt.Get(ctx, client.ObjectKey{
Name: moduleTemplateName,
Namespace: namespace,
}, moduleTemplate); err != nil {
return nil, fmt.Errorf("failed to get module template: %w", err)
}

return moduleTemplate, nil
}

func (t *TemplateLookup) GetRegularTemplates(ctx context.Context, kyma *v1beta2.Kyma) ModuleTemplatesByModuleName {
templates := make(ModuleTemplatesByModuleName)
for _, moduleInfo := range FetchModuleInfo(kyma) {
Expand All @@ -72,7 +147,15 @@ func (t *TemplateLookup) GetRegularTemplates(ctx context.Context, kyma *v1beta2.
continue
}

templateInfo := t.moduleTemplateInfoLookupStrategy.Lookup(ctx,
// If ModuleReleaseMeta doesn't exist, we can't proceed with template lookup
if moduleReleaseMeta == nil {
templates[moduleInfo.Name] = &ModuleTemplateInfo{
Err: fmt.Errorf("%w: %s", ErrModuleReleaseMetaNotFound, moduleInfo.Name),
}
continue
}

templateInfo := t.lookupModuleTemplateWithMaintenanceWindow(ctx,
&moduleInfo,
kyma,
moduleReleaseMeta)
Expand Down Expand Up @@ -104,6 +187,42 @@ func (t *TemplateLookup) GetRegularTemplates(ctx context.Context, kyma *v1beta2.
return templates
}

// lookupModuleTemplateWithMaintenanceWindow performs the core lookup and applies maintenance window logic.
func (t *TemplateLookup) lookupModuleTemplateWithMaintenanceWindow(ctx context.Context,
moduleInfo *ModuleInfo,
kyma *v1beta2.Kyma,
moduleReleaseMeta *v1beta2.ModuleReleaseMeta,
) ModuleTemplateInfo {
// First perform the standard lookup
moduleTemplateInfo := LookupModuleTemplate(ctx, t.Reader, moduleInfo, kyma, moduleReleaseMeta)

// If lookup failed or no maintenance window configured, return as-is
if moduleTemplateInfo.ModuleTemplate == nil || moduleTemplateInfo.Err != nil || t.maintenanceWindow == nil {
return moduleTemplateInfo
}

// Check if maintenance window is required for this module template
if !t.maintenanceWindow.IsRequired(moduleTemplateInfo.ModuleTemplate, kyma) {
return moduleTemplateInfo
}

// Check if maintenance window is currently active
active, err := t.maintenanceWindow.IsActive(kyma)
if err != nil {
moduleTemplateInfo.Err = fmt.Errorf("%w: %w", ErrFailedToDetermineIfMaintenanceWindowIsActive, err)
moduleTemplateInfo.ModuleTemplate = nil
return moduleTemplateInfo
}

if !active {
moduleTemplateInfo.Err = ErrWaitingForNextMaintenanceWindow
moduleTemplateInfo.ModuleTemplate = nil
return moduleTemplateInfo
}

return moduleTemplateInfo
}

func ValidateTemplateMode(template ModuleTemplateInfo,
kyma *v1beta2.Kyma,
) ModuleTemplateInfo {
Expand Down Expand Up @@ -196,3 +315,8 @@ func filterVersion(version *semver.Version) *semver.Version {
version.Major(), version.Minor(), version.Patch()))
return filteredVersion
}

// TemplateNameMatch checks if a module template matches the given name.
func TemplateNameMatch(template *v1beta2.ModuleTemplate, name string) bool {
return template.Spec.ModuleName == name
}
Loading
Loading