• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

opendefensecloud / solution-arsenal / 24241142292

10 Apr 2026 11:40AM UTC coverage: 72.944%. First build
24241142292

Pull #395

github

web-flow
Merge e34c62818 into ef59b87e2
Pull Request #395: feat: split of additional resources from Target and refactor rendering

514 of 657 new or added lines in 9 files covered. (78.23%)

1987 of 2724 relevant lines covered (72.94%)

23.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

78.85
/pkg/controller/release_controller.go
1
// Copyright 2026 BWI GmbH and Solution Arsenal contributors
2
// SPDX-License-Identifier: Apache-2.0
3

4
package controller
5

6
import (
7
        "context"
8

9
        apierrors "k8s.io/apimachinery/pkg/api/errors"
10
        apimeta "k8s.io/apimachinery/pkg/api/meta"
11
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
12
        "k8s.io/apimachinery/pkg/runtime"
13
        "k8s.io/apimachinery/pkg/types"
14
        "k8s.io/client-go/tools/events"
15
        ctrl "sigs.k8s.io/controller-runtime"
16
        "sigs.k8s.io/controller-runtime/pkg/client"
17

18
        solarv1alpha1 "go.opendefense.cloud/solar/api/solar/v1alpha1"
19
)
20

21
const (
22
        ConditionTypeComponentVersionResolved = "ComponentVersionResolved"
23
)
24

25
// ReleaseReconciler reconciles a Release object.
26
// It validates that the referenced ComponentVersion exists and sets status conditions.
27
// Rendering is handled by the Target controller.
28
type ReleaseReconciler struct {
29
        client.Client
30
        Scheme   *runtime.Scheme
31
        Recorder events.EventRecorder
32
        // WatchNamespace restricts reconciliation to this namespace.
33
        // Should be empty in production (watches all namespaces).
34
        // Intended for use in integration tests only.
35
        // See: https://book.kubebuilder.io/reference/envtest#testing-considerations
36
        WatchNamespace string
37
}
38

39
//+kubebuilder:rbac:groups=solar.opendefense.cloud,resources=releases,verbs=get;list;watch;create;update;patch;delete
40
//+kubebuilder:rbac:groups=solar.opendefense.cloud,resources=releases/status,verbs=get;update;patch
41
//+kubebuilder:rbac:groups=solar.opendefense.cloud,resources=componentversions,verbs=get;list;watch
42
//+kubebuilder:rbac:groups=core,resources=events,verbs=create;patch
43
//+kubebuilder:rbac:groups=events.k8s.io,resources=events,verbs=create;patch
44

45
// Reconcile validates the Release by resolving its ComponentVersion reference.
46
func (r *ReleaseReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
10✔
47
        log := ctrl.LoggerFrom(ctx)
10✔
48
        ctrlResult := ctrl.Result{}
10✔
49

10✔
50
        log.V(1).Info("Release is being reconciled", "req", req)
10✔
51

10✔
52
        if r.WatchNamespace != "" && req.Namespace != r.WatchNamespace {
10✔
53
                return ctrlResult, nil
×
54
        }
×
55

56
        // Fetch the Release instance
57
        res := &solarv1alpha1.Release{}
10✔
58
        if err := r.Get(ctx, req.NamespacedName, res); err != nil {
10✔
59
                if apierrors.IsNotFound(err) {
×
60
                        return ctrlResult, nil
×
61
                }
×
62

63
                return ctrlResult, errLogAndWrap(log, err, "failed to get object")
×
64
        }
65

66
        // Resolve ComponentVersion
67
        cvRef := types.NamespacedName{
10✔
68
                Name:      res.Spec.ComponentVersionRef.Name,
10✔
69
                Namespace: res.Namespace,
10✔
70
        }
10✔
71
        cv := &solarv1alpha1.ComponentVersion{}
10✔
72
        if err := r.Get(ctx, cvRef, cv); err != nil {
12✔
73
                if apierrors.IsNotFound(err) {
4✔
74
                        changed := apimeta.SetStatusCondition(&res.Status.Conditions, metav1.Condition{
2✔
75
                                Type:               ConditionTypeComponentVersionResolved,
2✔
76
                                Status:             metav1.ConditionFalse,
2✔
77
                                ObservedGeneration: res.Generation,
2✔
78
                                Reason:             "NotFound",
2✔
79
                                Message:            "ComponentVersion not found: " + res.Spec.ComponentVersionRef.Name,
2✔
80
                        })
2✔
81
                        if changed {
3✔
82
                                if err := r.Status().Update(ctx, res); err != nil {
1✔
NEW
83
                                        return ctrlResult, errLogAndWrap(log, err, "failed to update status")
×
NEW
84
                                }
×
85
                        }
86

87
                        return ctrlResult, nil
2✔
88
                }
89

NEW
90
                return ctrlResult, errLogAndWrap(log, err, "failed to get ComponentVersion")
×
91
        }
92

93
        // ComponentVersion found — set resolved condition
94
        changed := apimeta.SetStatusCondition(&res.Status.Conditions, metav1.Condition{
8✔
95
                Type:               ConditionTypeComponentVersionResolved,
8✔
96
                Status:             metav1.ConditionTrue,
8✔
97
                ObservedGeneration: res.Generation,
8✔
98
                Reason:             "Resolved",
8✔
99
                Message:            "ComponentVersion resolved: " + cv.Name,
8✔
100
        })
8✔
101
        if changed {
12✔
102
                if err := r.Status().Update(ctx, res); err != nil {
4✔
103
                        return ctrlResult, errLogAndWrap(log, err, "failed to update status")
×
104
                }
×
105
        }
106

107
        return ctrlResult, nil
8✔
108
}
109

110
// SetupWithManager sets up the controller with the Manager.
111
func (r *ReleaseReconciler) SetupWithManager(mgr ctrl.Manager) error {
1✔
112
        return ctrl.NewControllerManagedBy(mgr).
1✔
113
                For(&solarv1alpha1.Release{}).
1✔
114
                Complete(r)
1✔
115
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc