From a5300feaedec8e15fed4ee954df6fea419b7c5e6 Mon Sep 17 00:00:00 2001 From: Hy3n4 Date: Thu, 26 Oct 2023 14:05:40 +0200 Subject: [PATCH] feat(slo): sli inline support and type fixes - add suuport for inline SLI definition - fixed SLOSpec.Indicator type Signed-off-by: Hy3n4 --- apis/openslo/v1/slo_types.go | 4 +- apis/openslo/v1/zz_generated.deepcopy.go | 4 +- config/crd/bases/openslo.com_slos.yaml | 138 +++++++++++------- internal/controller/openslo/sli_controller.go | 9 +- internal/controller/openslo/slo_controller.go | 59 ++++---- 5 files changed, 126 insertions(+), 88 deletions(-) diff --git a/apis/openslo/v1/slo_types.go b/apis/openslo/v1/slo_types.go index b0849a6..c2737bd 100644 --- a/apis/openslo/v1/slo_types.go +++ b/apis/openslo/v1/slo_types.go @@ -54,7 +54,7 @@ type TimeWindowSpec struct { type SLOSpec struct { Description Description `json:"description,omitempty"` Service string `json:"service,omitempty"` - Indicator *SLISpec `json:"indicator,omitempty"` + Indicator *Indicator `json:"indicator,omitempty"` IndicatorRef *string `json:"indicatorRef,omitempty"` // +kubebuilder:validation:MaxItems=1 TimeWindow []TimeWindowSpec `json:"timeWindow,omitempty"` @@ -78,6 +78,8 @@ type SLOStatus struct { //+kubebuilder:object:root=true //+kubebuilder:subresource:status //+kubebuilder:printcolumn:name="Status",type=string,JSONPath=.status.ready,description="The reason for the current status of the SLO resource" +//+kubebuilder:printcolumn:name="Window",type=string,JSONPath=.spec.timeWindow[0].duration,description="The time window for the SLO resource" +//+kubebuilder:printcolumn:name="Age",type=date,JSONPath=.metadata.creationTimestamp,description="The time when the SLO resource was created" // SLO is the Schema for the slos API type SLO struct { diff --git a/apis/openslo/v1/zz_generated.deepcopy.go b/apis/openslo/v1/zz_generated.deepcopy.go index 82565cf..8c3f95a 100644 --- a/apis/openslo/v1/zz_generated.deepcopy.go +++ b/apis/openslo/v1/zz_generated.deepcopy.go @@ -780,8 +780,8 @@ func (in *SLOSpec) DeepCopyInto(out *SLOSpec) { *out = *in if in.Indicator != nil { in, out := &in.Indicator, &out.Indicator - *out = new(SLISpec) - **out = **in + *out = new(Indicator) + (*in).DeepCopyInto(*out) } if in.IndicatorRef != nil { in, out := &in.IndicatorRef, &out.IndicatorRef diff --git a/config/crd/bases/openslo.com_slos.yaml b/config/crd/bases/openslo.com_slos.yaml index 8fd556e..94ca4f5 100644 --- a/config/crd/bases/openslo.com_slos.yaml +++ b/config/crd/bases/openslo.com_slos.yaml @@ -19,6 +19,14 @@ spec: jsonPath: .status.ready name: Status type: string + - description: The time window for the SLO resource + jsonPath: .spec.timeWindow[0].duration + name: Window + type: string + - description: The time when the SLO resource was created + jsonPath: .metadata.creationTimestamp + name: Age + type: date name: v1 schema: openAPIV3Schema: @@ -201,57 +209,93 @@ spec: maxLength: 1050 type: string indicator: - description: SLISpec defines the desired state of SLI properties: - description: - maxLength: 1050 - type: string - ratioMetric: + metadata: properties: - bad: + annotations: + additionalProperties: + type: string + type: object + displayName: + type: string + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + description: SLISpec defines the desired state of SLI + properties: + description: + maxLength: 1050 + type: string + ratioMetric: properties: - metricSource: + bad: properties: - metricSourceRef: - type: string - spec: - type: string - type: - type: string + metricSource: + properties: + metricSourceRef: + type: string + spec: + type: string + type: + type: string + type: object type: object - type: object - counter: - type: boolean - good: - properties: - metricSource: + counter: + type: boolean + good: properties: - metricSourceRef: - type: string - spec: - type: string - type: - type: string + metricSource: + properties: + metricSourceRef: + type: string + spec: + type: string + type: + type: string + type: object type: object - type: object - raw: - properties: - metricSource: + raw: properties: - metricSourceRef: - type: string - spec: - type: string - type: - type: string + metricSource: + properties: + metricSourceRef: + type: string + spec: + type: string + type: + type: string + type: object + type: object + rawType: + enum: + - success + - failure + type: string + total: + properties: + metricSource: + properties: + metricSourceRef: + type: string + spec: + type: string + type: + type: string + type: object type: object type: object - rawType: - enum: - - success - - failure - type: string - total: + thresholdMetric: properties: metricSource: properties: @@ -264,18 +308,6 @@ spec: type: object type: object type: object - thresholdMetric: - properties: - metricSource: - properties: - metricSourceRef: - type: string - spec: - type: string - type: - type: string - type: object - type: object type: object indicatorRef: type: string diff --git a/internal/controller/openslo/sli_controller.go b/internal/controller/openslo/sli_controller.go index 2920675..c3ea31a 100644 --- a/internal/controller/openslo/sli_controller.go +++ b/internal/controller/openslo/sli_controller.go @@ -37,16 +37,15 @@ type SLIReconciler struct { func (r *SLIReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := log.FromContext(ctx) - var sli openslov1.SLI - - err := r.Get(ctx, req.NamespacedName, &sli) + sli := &openslov1.SLI{} + err := r.Get(ctx, req.NamespacedName, sli) if err != nil { if apierrors.IsNotFound(err) { - log.Info("SLI deleted") + log.Info("SLI resource not found. Object must have been deleted.") return ctrl.Result{}, nil } - log.Error(err, errGetDS) + log.Error(err, errGetSLI) return ctrl.Result{}, nil } diff --git a/internal/controller/openslo/slo_controller.go b/internal/controller/openslo/slo_controller.go index 3a65916..28413c8 100644 --- a/internal/controller/openslo/slo_controller.go +++ b/internal/controller/openslo/slo_controller.go @@ -62,48 +62,53 @@ func (r *SLOReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R // Get SLI from SLO's ref if slo.Spec.IndicatorRef != nil { err = r.Get(ctx, client.ObjectKey{Name: *slo.Spec.IndicatorRef, Namespace: slo.Namespace}, sli) - } else if slo.Spec.Indicator != nil { - //TODO: Create SLI from SLO's indicator spec - } + if err != nil { + apierrors.IsNotFound(err) + { + log.Error(err, errGetSLI) + err = utils.UpdateStatus( + ctx, + slo, + r.Client, + "Ready", + metav1.ConditionFalse, + "SLIObjectNotFound", + "SLI Object not found", + ) + if err != nil { + log.Error(err, "Failed to update SLO status") + return ctrl.Result{}, err + } + return ctrl.Result{}, err + } + } - if err != nil { - apierrors.IsNotFound(err) - { - log.Error(err, errGetSLI) + // Set SLI instance as the owner and controller. + if err := ctrl.SetControllerReference(slo, sli, r.Scheme); err != nil { err = utils.UpdateStatus( ctx, slo, r.Client, "Ready", metav1.ConditionFalse, - "SLIObjectNotFound", - "SLI Object not found", + "FailedToSetSLIOwner", + "Failed to set SLI owner reference", ) if err != nil { log.Error(err, "Failed to update SLO status") return ctrl.Result{}, err } + log.Error(err, "Failed to set owner reference for SLI") return ctrl.Result{}, err } - } - - // Set SLI instance as the owner and controller. - if err := ctrl.SetControllerReference(slo, sli, r.Scheme); err != nil { - err = utils.UpdateStatus( - ctx, - slo, - r.Client, - "Ready", - metav1.ConditionFalse, - "FailedToSetSLIOwner", - "Failed to set SLI owner reference", - ) - if err != nil { - log.Error(err, "Failed to update SLO status") - return ctrl.Result{}, err + } else if slo.Spec.Indicator != nil { + log.Info("SLO has an inline SLI") + sli.Name = slo.Spec.Indicator.Metadata.Name + sli.Spec.Description = slo.Spec.Indicator.Spec.Description + if slo.Spec.Indicator.Spec.RatioMetric != (openslov1.RatioMetricSpec{}) { + sli.Spec.RatioMetric = slo.Spec.Indicator.Spec.RatioMetric } - log.Error(err, "Failed to set owner reference for SLI") - return ctrl.Result{}, err + log.Info("SLI created", "SLI Name", sli.Name, "SLI Namespace", sli.Namespace, "SLI RatioMetric", sli.Spec.RatioMetric) } // Check if this PrometheusRule already exists