|
|
@@ -0,0 +1,100 @@
|
|
|
+/*
|
|
|
+Copyright 2026 LocoStack.
|
|
|
+
|
|
|
+Licensed 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 reconciler
|
|
|
+
|
|
|
+import (
|
|
|
+ "context"
|
|
|
+ "fmt"
|
|
|
+
|
|
|
+ "github.com/LocoStack/loco-operator/api/v1alpha1"
|
|
|
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
+ "k8s.io/apimachinery/pkg/runtime"
|
|
|
+ "sigs.k8s.io/controller-runtime/pkg/client"
|
|
|
+ "sigs.k8s.io/controller-runtime/pkg/client/apiutil"
|
|
|
+ logf "sigs.k8s.io/controller-runtime/pkg/log"
|
|
|
+)
|
|
|
+
|
|
|
+func ReconcileGatewayStatus(ctx context.Context, c client.Client, scheme *runtime.Scheme, stack string, obj client.Object) (*metav1.Condition, error) {
|
|
|
+ log := logf.FromContext(ctx)
|
|
|
+
|
|
|
+ if stack == "" {
|
|
|
+ return &metav1.Condition{
|
|
|
+ Type: "GatewayBound",
|
|
|
+ Status: metav1.ConditionFalse,
|
|
|
+ Reason: "NoStackRef",
|
|
|
+ Message: "No stack reference provided",
|
|
|
+ ObservedGeneration: obj.GetGeneration(),
|
|
|
+ }, nil
|
|
|
+ }
|
|
|
+
|
|
|
+ gvk, err := apiutil.GVKForObject(obj, scheme)
|
|
|
+ if err != nil {
|
|
|
+ log.Error(err, "Failed to get GVK for object", "object", obj)
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ gwList := &v1alpha1.ComponentList{}
|
|
|
+ err = c.List(ctx, gwList, client.InNamespace(obj.GetNamespace()), client.MatchingLabels{"locostack.com/component": "Gateway"})
|
|
|
+ if err != nil {
|
|
|
+ log.Error(err, "Failed to list gateway Components", "namespace", obj.GetNamespace(), "stack", stack)
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ gatewayFound := 0
|
|
|
+ gatewayBound := 0
|
|
|
+ for _, gw := range gwList.Items {
|
|
|
+ if gw.Spec.StackRef.Name != stack {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ gatewayFound += 1
|
|
|
+ emStatus, hasKindStatus := gw.Status.Dependencies[gvk.Kind]
|
|
|
+ if !hasKindStatus {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ status, hasStatus := emStatus[obj.GetName()]
|
|
|
+ if !hasStatus {
|
|
|
+ continue
|
|
|
+ }
|
|
|
+ if status == obj.GetGeneration() {
|
|
|
+ gatewayBound += 1
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if gatewayFound == 0 {
|
|
|
+ return &metav1.Condition{
|
|
|
+ Type: "GatewayBound",
|
|
|
+ Status: metav1.ConditionFalse,
|
|
|
+ Reason: "GatewayNotFound",
|
|
|
+ Message: fmt.Sprintf("No gateway Components found that reference this %s in the Stack", gvk.Kind),
|
|
|
+ ObservedGeneration: obj.GetGeneration(),
|
|
|
+ }, nil
|
|
|
+ } else if gatewayBound < gatewayFound {
|
|
|
+ return &metav1.Condition{
|
|
|
+ Type: "GatewayBound",
|
|
|
+ Status: metav1.ConditionFalse,
|
|
|
+ Reason: "GatewayNotBound",
|
|
|
+ Message: fmt.Sprintf("%d out of %d gateway Components reference this %s in their status", gatewayBound, gatewayFound, gvk.Kind),
|
|
|
+ ObservedGeneration: obj.GetGeneration(),
|
|
|
+ }, nil
|
|
|
+ } else {
|
|
|
+ return &metav1.Condition{
|
|
|
+ Type: "GatewayBound",
|
|
|
+ Status: metav1.ConditionTrue,
|
|
|
+ Reason: "GatewayBound",
|
|
|
+ Message: fmt.Sprintf("All %d gateway Components reference this %s in their status", gatewayFound, gvk.Kind),
|
|
|
+ ObservedGeneration: obj.GetGeneration(),
|
|
|
+ }, nil
|
|
|
+ }
|
|
|
+}
|