Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Handle Mandatory ModuleTemplates with the new ModuleTemplate naming #2123

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
c29e819
Adjust mandatory lookup code to handle multiple versions
nesmabadr Dec 12, 2024
4263316
Merge branch 'main' into mandatorymodules_multipleversion
nesmabadr Dec 13, 2024
e961bd9
Add unit tests
nesmabadr Dec 13, 2024
536de4d
Merge branch 'main' into mandatorymodules_multipleversion
nesmabadr Dec 13, 2024
4990ee6
Merge branch 'main' into mandatorymodules_multipleversion
nesmabadr Dec 13, 2024
7080032
E2E test
nesmabadr Dec 13, 2024
68ff152
Remove TODO + add more unit tests coverage
nesmabadr Dec 13, 2024
cacb76a
Fix coverage
nesmabadr Dec 15, 2024
10f48a4
Fix linting
nesmabadr Dec 15, 2024
09f10f6
Debug E2E test
nesmabadr Dec 15, 2024
b44bc9d
Fix E2E test
nesmabadr Dec 15, 2024
246c5b1
Fix E2E test
nesmabadr Dec 15, 2024
cd4beb3
debug E2E test
nesmabadr Dec 15, 2024
091c3da
fix E2E test
nesmabadr Dec 16, 2024
9e6da1a
Merge branch 'main' into mandatorymodules_multipleversion
nesmabadr Dec 16, 2024
6a91453
debug E2E test
nesmabadr Dec 16, 2024
ac033e4
debug E2E test
nesmabadr Dec 16, 2024
87a8cf3
debug E2E test
nesmabadr Dec 16, 2024
eb5bb90
Merge branch 'main' into mandatorymodules_multipleversion
nesmabadr Dec 16, 2024
e9cd3d2
Fix E2E test
nesmabadr Dec 16, 2024
38f86a8
Add documentation
nesmabadr Dec 16, 2024
99b606b
Fix E2E test
nesmabadr Dec 16, 2024
bee95a2
Merge branch 'main' into mandatorymodules_multipleversion
nesmabadr Dec 16, 2024
69e0db2
Fix deletion for multiple versioned
nesmabadr Dec 16, 2024
f143650
Fix linting
nesmabadr Dec 16, 2024
a18de2c
Fix deletion to handle multiple versions
nesmabadr Dec 16, 2024
36fad1e
Merge branch 'main' into mandatorymodules_multipleversion
nesmabadr Dec 16, 2024
582ab04
Merge branch 'main' into mandatorymodules_multipleversion
nesmabadr Dec 17, 2024
ffe957b
code review comments
nesmabadr Dec 17, 2024
bd7d58c
Update docs/contributor/02-controllers.md
nesmabadr Dec 18, 2024
eee3a27
Merge branch 'main' into mandatorymodules_multipleversion
nesmabadr Dec 18, 2024
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
3 changes: 2 additions & 1 deletion .github/actions/deploy-lifecycle-manager-e2e/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ runs:
matrix.e2e-test == 'module-status-decoupling-with-deployment' ||
matrix.e2e-test == 'purge-metrics' ||
matrix.e2e-test == 'self-signed-certificate-rotation' ||
matrix.e2e-test == 'mandatory-module-metrics'}}
matrix.e2e-test == 'mandatory-module-metrics' ||
matrix.e2e-test == 'mandatory-module-metrics-with-old-naming-pattern'}}
shell: bash
run: |
kubectl patch svc klm-controller-manager-metrics -p '{"spec": {"type": "LoadBalancer"}}' -n kcp-system
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ runs:
cp ../lifecycle-manager/scripts/tests/deploy_modulereleasemeta.sh .
- name: Create and apply Template Operator ModuleTemplate from the latest release
working-directory: template-operator
if: ${{ matrix.e2e-test != 'mandatory-module' &&
matrix.e2e-test != 'mandatory-module-metrics'
}}
shell: bash
run: |
modulectl create --config-file ./module-config.yaml --registry http://localhost:5111 --insecure
Expand All @@ -28,13 +31,19 @@ runs:
kubectl apply -f template.yaml
- name: Create and apply Template Operator ModuleTemplate with ModuleDeploymentNameInOlderVersion
working-directory: template-operator
if: ${{ matrix.e2e-test != 'mandatory-module' &&
matrix.e2e-test != 'mandatory-module-metrics'
}}
shell: bash
run: |
make build-manifests
yq eval '(. | select(.kind == "Deployment") | .metadata.name) = "${{ env.ModuleDeploymentNameInOlderVersion }}"' -i template-operator.yaml
./deploy_moduletemplate.sh ${{ env.ModuleName }} ${{ env.OlderVersion }}
- name: Create and apply Template Operator ModuleTemplate with ModuleDeploymentNameInNewerVersion
working-directory: template-operator
if: ${{ matrix.e2e-test != 'mandatory-module' &&
matrix.e2e-test != 'mandatory-module-metrics'
}}
shell: bash
run: |
make build-manifests
Expand Down Expand Up @@ -70,14 +79,27 @@ runs:
shell: bash
run: |
./deploy_modulereleasemeta.sh ${{ env.ModuleName }} fast:${{ env.NewerVersion }} regular:${{ env.OlderVersion }}
- name: Create Template Operator Module as Mandatory Module
working-directory: lifecycle-manager

- name: Create and apply Template Operator Module as Mandatory Module
working-directory: template-operator
if: ${{ matrix.e2e-test == 'mandatory-module' ||
matrix.e2e-test == 'mandatory-module-metrics'
}}
shell: bash
run: |
kubectl apply -f tests/e2e/moduletemplate/mandatory_moduletemplate_template_operator_v1.yaml
make build-manifests
yq eval '(. | select(.kind == "Deployment") | .metadata.name) = "${{ env.ModuleDeploymentNameInOlderVersion }}"' -i template-operator.yaml
./deploy_moduletemplate.sh ${{ env.ModuleName }} ${{ env.OlderVersionForMandatoryModule }} true true

- name: Create ModuleTemplate in a new version for Mandatory module
if: ${{ matrix.e2e-test == 'mandatory-module'}}
working-directory: template-operator
shell: bash
run: |
make build-manifests
yq eval '(. | select(.kind == "Deployment") | .metadata.name) = "${{ env.ModuleDeploymentNameInNewerVersion }}"' -i template-operator.yaml
./deploy_moduletemplate.sh ${{ env.ModuleName }} ${{ env.NewerVersionForMandatoryModule }} true true false
nesmabadr marked this conversation as resolved.
Show resolved Hide resolved
cp template.yaml ../lifecycle-manager/tests/e2e/mandatory_template_v2.yaml
- name: Create and apply ModuleReleaseMeta Template Operator with newer version in fast channel and older version in regular channel
working-directory: template-operator
if: ${{ matrix.e2e-test == 'non-blocking-deletion' }}
Expand Down
4 changes: 2 additions & 2 deletions .github/actions/deploy-template-operator/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ runs:
kubectl apply -f tests/e2e/moduletemplate/moduletemplate_template_operator_v2_direct_version.yaml
- name: Create Template Operator Module as Mandatory Module
working-directory: lifecycle-manager
if: ${{ matrix.e2e-test == 'mandatory-module' ||
matrix.e2e-test == 'mandatory-module-metrics'
if: ${{ matrix.e2e-test == 'mandatory-module-with-old-naming-pattern' ||
matrix.e2e-test == 'mandatory-module-metrics-with-old-naming-pattern'
}}
shell: bash
run: |
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/test-e2e-with-modulereleasemeta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ jobs:
ModuleDeploymentNameInOlderVersion: template-operator-v1-controller-manager
NewerVersion: 2.4.2-e2e-test
OlderVersion: 1.1.1-e2e-test
OlderVersionForMandatoryModule: 1.1.0-smoke-test
NewerVersionForMandatoryModule: 2.4.1-smoke-test
VersionForStatefulSetInWarning: 1.0.0-warning-statefulset
VersionForDeploymentInWarning: 1.0.0-warning-deployment
VersionForMisconfiguredDeploymentImage: 1.0.0-misconfigured-deployment
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ jobs:
- ca-certificate-rotation
- istio-gateway-secret-rotation
- self-signed-certificate-rotation
- mandatory-module
- mandatory-module-metrics
- mandatory-module-with-old-naming-pattern
- mandatory-module-metrics-with-old-naming-pattern
- misconfigured-kyma-secret
- rbac-privileges
- ocm-compatible-module-template
Expand Down
2 changes: 1 addition & 1 deletion docs/contributor/02-controllers.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Lifecycle Manager uses two Mandatory Modules Controllers:
* [Mandatory modules installation controller](../../internal/controller/mandatorymodule/installation_controller.go) deals with the reconciliation of mandatory modules
* [Mandatory modules deletion controller](../../internal/controller/mandatorymodule/deletion_controller.go) deals with the deletion of mandatory modules

Since the channel concept does not apply to mandatory modules, the Mandatory Modules Installation Controller fetches all the Mandatory ModuleTemplate CRs without any channel filtering. It then translates the ModuleTemplate CR for the mandatory module to a [Manifest CR](../../api/v1beta2/manifest_types.go) with an OwnerReference to the Kyma CR. Similarly to the [Kyma Controller](../../internal/controller/kyma/controller.go),
Since the channel concept does not apply to mandatory modules, the Mandatory Modules Installation Controller fetches all the Mandatory ModuleTemplate CRs with the 'operator.kyma-project.io/mandatory-module' label. If multiple ModuleTemplates exist for the same mandatory module, the Controller fetches the ModuleTemplate with the highest version. It then translates the ModuleTemplate CR for the mandatory module to a [Manifest CR](../../api/v1beta2/manifest_types.go) with an OwnerReference to the Kyma CR. Similarly to the [Kyma Controller](../../internal/controller/kyma/controller.go),
it propagates changes from the ModuleTemplate CR to the Manifest CR. The mandatory ModuleTemplate CR is not synchronized to the remote cluster and the module status does not appear in the Kyma CR status. If a mandatory module needs to be removed from all clusters, the corresponding ModuleTemplate CR needs to be deleted. The Mandatory Module Deletion Controller picks this event up and marks all associated Manifest CRs for deletion. To ensure that the ModuleTemplate CR is not removed immediately, the controller adds a finalizer to the ModuleTemplate CR. Once all associated Manifest CRs are deleted, the finalizer is removed and the ModuleTemplate CR is deleted.

## Manifest Controller
Expand Down
6 changes: 4 additions & 2 deletions internal/controller/mandatorymodule/deletion_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ func (r *DeletionReconciler) getCorrespondingManifests(ctx context.Context,
if err := r.List(ctx, manifests, &client.ListOptions{
Namespace: template.Namespace,
LabelSelector: k8slabels.SelectorFromSet(k8slabels.Set{shared.IsMandatoryModule: "true"}),
}); err != nil {
}); client.IgnoreNotFound(err) != nil {
return nil, fmt.Errorf("not able to list mandatory module manifests: %w", err)
}

Expand All @@ -136,7 +136,9 @@ func (r *DeletionReconciler) removeManifests(ctx context.Context, manifests []v1
return nil
}

func filterManifestsByAnnotation(manifests []v1beta2.Manifest, annotationKey, annotationValue string) []v1beta2.Manifest {
func filterManifestsByAnnotation(manifests []v1beta2.Manifest,
annotationKey, annotationValue string,
) []v1beta2.Manifest {
filteredManifests := make([]v1beta2.Manifest, 0)
for _, manifest := range manifests {
if manifest.Annotations[annotationKey] == annotationValue {
Expand Down
70 changes: 68 additions & 2 deletions pkg/templatelookup/mandatory.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"

"github.com/Masterminds/semver/v3"
k8slabels "k8s.io/apimachinery/pkg/labels"
"sigs.k8s.io/controller-runtime/pkg/client"

Expand All @@ -22,14 +23,79 @@ func GetMandatory(ctx context.Context, kymaClient client.Reader) (ModuleTemplate
return nil, fmt.Errorf("could not list mandatory ModuleTemplates: %w", err)
}

// maps module name to the module template of the highest version encountered
mandatoryModules := make(map[string]*ModuleTemplateInfo)
nesmabadr marked this conversation as resolved.
Show resolved Hide resolved
for _, moduleTemplate := range mandatoryModuleTemplateList.Items {
if moduleTemplate.DeletionTimestamp.IsZero() {
mandatoryModules[moduleTemplate.Name] = &ModuleTemplateInfo{
ModuleTemplate: &moduleTemplate,
currentModuleTemplate := &moduleTemplate
moduleName := GetModuleName(currentModuleTemplate)
if mandatoryModules[moduleName] != nil {
var err error
currentModuleTemplate, err = GetModuleTemplateWithHigherVersion(currentModuleTemplate,
mandatoryModules[moduleName].ModuleTemplate)
if err != nil {
mandatoryModules[moduleName] = &ModuleTemplateInfo{
ModuleTemplate: nil,
Err: err,
}
continue
}
}
mandatoryModules[moduleName] = &ModuleTemplateInfo{
ModuleTemplate: currentModuleTemplate,
Err: nil,
}
}
}
return mandatoryModules, nil
}

func GetModuleName(moduleTemplate *v1beta2.ModuleTemplate) string {
nesmabadr marked this conversation as resolved.
Show resolved Hide resolved
if moduleTemplate.Spec.ModuleName != "" {
return moduleTemplate.Spec.ModuleName
}

// https://github.com/kyma-project/lifecycle-manager/issues/2135
// Remove this after warden ModuleTemplate is created using modulectl
return moduleTemplate.Labels[shared.ModuleName]
}

func GetModuleSemverVersion(moduleTemplate *v1beta2.ModuleTemplate) (*semver.Version, error) {
if moduleTemplate.Spec.Version != "" {
version, err := semver.NewVersion(moduleTemplate.Spec.Version)
if err != nil {
return nil, fmt.Errorf("could not parse version as a semver: %s: %w",
moduleTemplate.Spec.Version, err)
}
return version, nil
}

// https://github.com/kyma-project/lifecycle-manager/issues/2135
// Remove this after warden ModuleTemplate is created using modulectl
version, err := semver.NewVersion(moduleTemplate.Annotations[shared.ModuleVersionAnnotation])
if err != nil {
return nil, fmt.Errorf("could not parse version as a semver %s: %w",
moduleTemplate.Annotations[shared.ModuleVersionAnnotation], err)
}
nesmabadr marked this conversation as resolved.
Show resolved Hide resolved
return version, nil
}

func GetModuleTemplateWithHigherVersion(firstModuleTemplate, secondModuleTemplate *v1beta2.ModuleTemplate) (*v1beta2.ModuleTemplate,
error,
) {
firstVersion, err := GetModuleSemverVersion(firstModuleTemplate)
if err != nil {
return nil, err
}

secondVersion, err := GetModuleSemverVersion(secondModuleTemplate)
if err != nil {
return nil, err
}

if firstVersion.GreaterThan(secondVersion) {
return firstModuleTemplate, nil
}

return secondModuleTemplate, nil
}
Loading
Loading