Ver código fonte

feat(component): add stack reference

Thomas Zhang 3 meses atrás
pai
commit
d384d3ce92

+ 6 - 0
api/v1alpha1/component_types.go

@@ -40,6 +40,12 @@ type ComponentSpec struct {
 	// dependencies lists other components that this component depends on.
 	// +optional
 	Dependencies []corev1.ObjectReference `json:"dependencies,omitempty"`
+
+	// stackRef optionally references the Stack this component belongs to.
+	// Component may integrate with other enabled components in the same stack,
+	// resulting in different deployment manifests.
+	// +optional
+	StackRef *corev1.LocalObjectReference `json:"stackRef,omitempty"`
 }
 
 // ComponentStatus defines the observed state of Component.

+ 5 - 0
api/v1alpha1/zz_generated.deepcopy.go

@@ -105,6 +105,11 @@ func (in *ComponentSpec) DeepCopyInto(out *ComponentSpec) {
 		*out = make([]v1.ObjectReference, len(*in))
 		copy(*out, *in)
 	}
+	if in.StackRef != nil {
+		in, out := &in.StackRef, &out.StackRef
+		*out = new(v1.LocalObjectReference)
+		**out = **in
+	}
 }
 
 // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComponentSpec.

+ 17 - 0
config/crd/bases/locostack.com_components.yaml

@@ -105,6 +105,23 @@ spec:
                   type: object
                   x-kubernetes-map-type: atomic
                 type: array
+              stackRef:
+                description: |-
+                  stackRef optionally references the Stack this component belongs to.
+                  Component may integrate with other enabled components in the same stack,
+                  resulting in different deployment manifests.
+                properties:
+                  name:
+                    default: ""
+                    description: |-
+                      Name of the referent.
+                      This field is effectively required, but due to backwards compatibility is
+                      allowed to be empty. Instances of this type with an empty value here are
+                      almost certainly wrong.
+                      More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
+                    type: string
+                type: object
+                x-kubernetes-map-type: atomic
               template:
                 description: template holds the configuration overrides for the component.
                 properties:

+ 10 - 3
internal/controller/component_controller.go

@@ -80,7 +80,14 @@ func (r *ComponentReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
 		return ctrl.Result{}, nil
 	}
 
-	componentReconciler := r.getComponentReconciler(comp)
+	stack := &v1alpha1.Stack{}
+	if comp.Spec.StackRef == nil || comp.Spec.StackRef.Name == "" {
+		stack = nil
+	} else if err := r.Get(ctx, client.ObjectKey{Namespace: comp.Namespace, Name: comp.Spec.StackRef.Name}, stack); err != nil {
+		stack = nil
+	}
+
+	componentReconciler := r.getComponentReconciler(comp, stack)
 	dependencies, err := componentReconciler.ReconcileComponent(ctx, &tmpl, make(map[string]string))
 	if err != nil {
 		apimeta.SetStatusCondition(&comp.Status.Conditions, metav1.Condition{
@@ -150,8 +157,8 @@ func (r *ComponentReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
 	return ctrl.Result{}, nil
 }
 
-func (r *ComponentReconciler) getComponentReconciler(comp *v1alpha1.Component) reconciler.ComponentReconciler {
-	return reconciler.NewDefaultComponentReconciler(r.Client, r.Scheme, comp)
+func (r *ComponentReconciler) getComponentReconciler(comp *v1alpha1.Component, stack *v1alpha1.Stack) reconciler.ComponentReconciler {
+	return reconciler.NewDefaultComponentReconciler(r.Client, r.Scheme, stack, comp)
 }
 
 // SetupWithManager sets up the controller with the Manager.

+ 2 - 1
internal/reconciler/common.go

@@ -33,9 +33,10 @@ type ComponentReconciler interface {
 	ResourceName(name string) string
 }
 
-func ResourceLabels(component, name, namespace string) map[string]string {
+func ResourceLabels(stack, component, name, namespace string) map[string]string {
 	labels := map[string]string{
 		"app.kubernetes.io/managed-by": "loco-operator",
+		"locostack.com/stack":          stack,
 		"locostack.com/component":      component,
 		"locostack.com/name":           name,
 	}

+ 5 - 3
internal/reconciler/component.go

@@ -41,13 +41,15 @@ import (
 type DefaultComponentReconciler struct {
 	client    client.Client
 	scheme    *runtime.Scheme
+	stack     *v1alpha1.Stack
 	component *v1alpha1.Component
 }
 
-func NewDefaultComponentReconciler(client client.Client, scheme *runtime.Scheme, component *v1alpha1.Component) *DefaultComponentReconciler {
+func NewDefaultComponentReconciler(client client.Client, scheme *runtime.Scheme, stack *v1alpha1.Stack, component *v1alpha1.Component) *DefaultComponentReconciler {
 	reconciler := &DefaultComponentReconciler{
 		client:    client,
 		scheme:    scheme,
+		stack:     stack,
 		component: component,
 	}
 	return reconciler
@@ -94,11 +96,11 @@ func (r *DefaultComponentReconciler) ResourceName(name string) string {
 }
 
 func (r *DefaultComponentReconciler) ResourceLabels() map[string]string {
-	return ResourceLabels(r.component.Spec.Category, r.ResourceName(""), "")
+	return ResourceLabels(r.stack.Name, r.component.Spec.Category, r.ResourceName(""), "")
 }
 
 func (r *DefaultComponentReconciler) ResourceLabelsWithNamespace() map[string]string {
-	return ResourceLabels(r.component.Spec.Category, r.ResourceName(""), r.component.GetNamespace())
+	return ResourceLabels(r.stack.Name, r.component.Spec.Category, r.ResourceName(""), r.component.GetNamespace())
 }
 
 func (r *DefaultComponentReconciler) reconcileService(ctx context.Context, tmpl *v1alpha1.Template) error {