Skip to content

Commit

Permalink
chore(metrics-operator): refactor fetching resouce namespaces during …
Browse files Browse the repository at this point in the history
…analysis

Signed-off-by: odubajDT <ondrej.dubaj@dynatrace.com>
  • Loading branch information
odubajDT committed Sep 15, 2023
1 parent b2853f9 commit e137aca
Show file tree
Hide file tree
Showing 11 changed files with 170 additions and 20 deletions.
7 changes: 7 additions & 0 deletions metrics-operator/api/v1alpha3/analysis_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,10 @@ type Timeframe struct {
func init() {
SchemeBuilder.Register(&Analysis{}, &AnalysisList{})
}

func (a *Analysis) GetAnalysisDefinitionNamespace() string {
if a.Spec.AnalysisDefinition.Namespace == "" {
return a.Namespace
}
return a.Spec.AnalysisDefinition.Namespace
}
22 changes: 22 additions & 0 deletions metrics-operator/api/v1alpha3/analysis_types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package v1alpha3

import (
"testing"

"github.com/stretchr/testify/require"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func TestAnalysis_GetAnalysisDefinitionNamespace(t *testing.T) {
a := Analysis{
ObjectMeta: v1.ObjectMeta{
Namespace: "ns",
},
}

require.Equal(t, "ns", a.GetAnalysisDefinitionNamespace())

a.Spec.AnalysisDefinition.Namespace = "ns2"

require.Equal(t, "ns2", a.GetAnalysisDefinitionNamespace())
}
7 changes: 7 additions & 0 deletions metrics-operator/api/v1alpha3/analysisdefinition_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,3 +124,10 @@ func init() {
func (o *OperatorValue) GetFloatValue() float64 {
return o.FixedValue.AsApproximateFloat64()
}

func (o *Objective) GetAnalysisValueTemplateNamespace(namespace string) string {
if o.AnalysisValueTemplateRef.Namespace == "" {
return namespace
}
return o.AnalysisValueTemplateRef.Namespace
}
12 changes: 12 additions & 0 deletions metrics-operator/api/v1alpha3/analysisdefinition_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,15 @@ func TestOperatorValue_GetFloatValue(t *testing.T) {

require.Equal(t, 15.0, o.GetFloatValue())
}

func TestObjective_GetAnalysisValueTemplateNamespace(t *testing.T) {
o := Objective{
AnalysisValueTemplateRef: ObjectReference{},
}

require.Equal(t, "default", o.GetAnalysisValueTemplateNamespace("default"))

o.AnalysisValueTemplateRef.Namespace = "ns"

require.Equal(t, "ns", o.GetAnalysisValueTemplateNamespace("default"))
}
7 changes: 7 additions & 0 deletions metrics-operator/api/v1alpha3/analysisvaluetemplate_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,10 @@ type AnalysisValueTemplateList struct {
func init() {
SchemeBuilder.Register(&AnalysisValueTemplate{}, &AnalysisValueTemplateList{})
}

func (a *AnalysisValueTemplate) GetProviderNamespace(namespace string) string {
if a.Spec.Provider.Namespace == "" {
return namespace
}
return a.Spec.Provider.Namespace
}
17 changes: 17 additions & 0 deletions metrics-operator/api/v1alpha3/analysisvaluetemplate_types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package v1alpha3

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestAnalysisValueTemplate_GetProviderNamespace(t *testing.T) {
a := AnalysisValueTemplate{}

require.Equal(t, "default", a.GetProviderNamespace("default"))

a.Spec.Provider.Namespace = "ns"

require.Equal(t, "ns", a.GetProviderNamespace("default"))
}
10 changes: 3 additions & 7 deletions metrics-operator/controllers/analysis/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ type AnalysisReconciler struct {
Scheme *runtime.Scheme
Log logr.Logger
MaxWorkers int //maybe 2 or 4 as def
Namespace string
NewWorkersPoolFactory
common.IAnalysisEvaluator
}
Expand Down Expand Up @@ -74,13 +73,10 @@ func (a *AnalysisReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c

//find AnalysisDefinition to have the collection of Objectives
analysisDef := &metricsapi.AnalysisDefinition{}
if analysis.Spec.AnalysisDefinition.Namespace == "" {
analysis.Spec.AnalysisDefinition.Namespace = a.Namespace
}
err := a.Client.Get(ctx,
types.NamespacedName{
Name: analysis.Spec.AnalysisDefinition.Name,
Namespace: analysis.Spec.AnalysisDefinition.Namespace},
Namespace: analysis.GetAnalysisDefinitionNamespace()},
analysisDef,
)

Expand All @@ -89,7 +85,7 @@ func (a *AnalysisReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
a.Log.Info(
fmt.Sprintf("AnalysisDefinition '%s' in namespace '%s' not found, requeue",
analysis.Spec.AnalysisDefinition.Name,
analysis.Spec.AnalysisDefinition.Namespace),
analysis.GetAnalysisDefinitionNamespace()),
)
return ctrl.Result{Requeue: true, RequeueAfter: 10 * time.Second}, nil
}
Expand All @@ -107,7 +103,7 @@ func (a *AnalysisReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
}

//create multiple workers handling the Objectives
childCtx, wp := a.NewWorkersPoolFactory(ctx, analysis, todo, a.MaxWorkers, a.Client, a.Log, a.Namespace)
childCtx, wp := a.NewWorkersPoolFactory(ctx, analysis, todo, a.MaxWorkers, a.Client, a.Log, analysis.GetAnalysisDefinitionNamespace())

res, err := wp.DispatchAndCollect(childCtx)
if err != nil {
Expand Down
55 changes: 55 additions & 0 deletions metrics-operator/controllers/analysis/controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,54 @@ func TestAnalysisReconciler_Reconcile_BasicControlLoop(t *testing.T) {

analysis, analysisDef, template, _ := getTestCRDs()

analysis2 := metricsapi.Analysis{
ObjectMeta: metav1.ObjectMeta{
Name: "my-analysis",
Namespace: "default",
},
Spec: metricsapi.AnalysisSpec{
Timeframe: metricsapi.Timeframe{
From: metav1.Time{
Time: time.Now(),
},
To: metav1.Time{
Time: time.Now(),
},
},
Args: map[string]string{
"good": "good",
"dot": ".",
},
AnalysisDefinition: metricsapi.ObjectReference{
Name: "my-analysis-def",
Namespace: "default2",
},
},
}

analysisDef2 := metricsapi.AnalysisDefinition{
ObjectMeta: metav1.ObjectMeta{
Name: "my-analysis-def",
Namespace: "default2",
},
Spec: metricsapi.AnalysisDefinitionSpec{
Objectives: []metricsapi.Objective{
{
AnalysisValueTemplateRef: metricsapi.ObjectReference{
Name: "my-template",
Namespace: "default",
},
Weight: 1,
KeyObjective: false,
},
},
TotalScore: metricsapi.TotalScore{
PassPercentage: 0,
WarningPercentage: 0,
},
},
}

tests := []struct {
name string
client client.Client
Expand Down Expand Up @@ -55,6 +103,13 @@ func TestAnalysisReconciler_Reconcile_BasicControlLoop(t *testing.T) {
wantErr: false,
status: &metricsapi.AnalysisStatus{Raw: "{\"objectiveResults\":null,\"totalScore\":0,\"maximumScore\":0,\"pass\":true,\"warning\":false}", Pass: true},
res: metricstypes.AnalysisResult{Pass: true},
}, {
name: "succeeded - analysis in different namespace, status updated",
client: fake2.NewClient(&analysis2, &analysisDef2, &template),
want: controllerruntime.Result{},
wantErr: false,
status: &metricsapi.AnalysisStatus{Raw: "{\"objectiveResults\":null,\"totalScore\":0,\"maximumScore\":0,\"pass\":true,\"warning\":false}", Pass: true},
res: metricstypes.AnalysisResult{Pass: true},
},
}

Expand Down
17 changes: 6 additions & 11 deletions metrics-operator/controllers/analysis/provider_selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,44 +54,39 @@ func (ps ProvidersPool) DispatchToProviders(ctx context.Context, id int) {
default:
ps.log.Info("worker", "id:", id, "started job:", j.AnalysisValueTemplateRef.Name)
templ := &metricsapi.AnalysisValueTemplate{}
if j.AnalysisValueTemplateRef.Namespace == "" {
j.AnalysisValueTemplateRef.Namespace = ps.Namespace
}
err := ps.Client.Get(ctx,
types.NamespacedName{
Name: j.AnalysisValueTemplateRef.Name,
Namespace: j.AnalysisValueTemplateRef.Namespace},
Namespace: j.GetAnalysisValueTemplateNamespace(ps.Namespace)},
templ,
)

if err != nil {
ps.log.Error(err, "Failed to get the correct Provider")
ps.log.Error(err, "Failed to get AnalysisValueTemplate")
ps.results <- metricsapi.ProviderResult{Objective: j.AnalysisValueTemplateRef, ErrMsg: err.Error()}
ps.cancel()
return
}

ns := templ.GetProviderNamespace(ps.Namespace)
providerRef := &metricsapi.KeptnMetricsProvider{}
if templ.Spec.Provider.Namespace == "" {
templ.Spec.Provider.Namespace = ps.Namespace
}
err = ps.Client.Get(ctx,
types.NamespacedName{
Name: templ.Spec.Provider.Name,
Namespace: templ.Spec.Provider.Namespace},
Namespace: ns},
providerRef,
)

if err != nil {
ps.log.Error(err, "Failed to get Provider")
ps.log.Error(err, "Failed to get KeptnMetricsProvider")
ps.results <- metricsapi.ProviderResult{Objective: j.AnalysisValueTemplateRef, ErrMsg: err.Error()}
ps.cancel()
return
}

templatedQuery, err := generateQuery(templ.Spec.Query, ps.Analysis.Spec.Args)
if err != nil {
ps.log.Error(err, "Failed to substitute args in templ")
ps.log.Error(err, "Failed to substitute args in AnalysisValueTemplate")
ps.results <- metricsapi.ProviderResult{Objective: j.AnalysisValueTemplateRef, ErrMsg: err.Error()}
ps.cancel()
return
Expand Down
35 changes: 34 additions & 1 deletion metrics-operator/controllers/analysis/provider_selector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
metricstypes "github.com/keptn/lifecycle-toolkit/metrics-operator/controllers/common/analysis/types"
fake2 "github.com/keptn/lifecycle-toolkit/metrics-operator/controllers/common/fake"
"github.com/stretchr/testify/require"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
)

Expand Down Expand Up @@ -75,7 +76,32 @@ func TestProvidersPool(t *testing.T) {

analysis, analysisDef, template, provider := getTestCRDs()

provider2 := metricsapi.KeptnMetricsProvider{
ObjectMeta: metav1.ObjectMeta{
Name: "my-provider",
Namespace: "default2",
},
Spec: metricsapi.KeptnMetricsProviderSpec{
Type: "prometheus",
TargetServer: "localhost:2000",
},
}

template2 := metricsapi.AnalysisValueTemplate{
ObjectMeta: metav1.ObjectMeta{
Name: "my-template",
Namespace: "default",
},
Spec: metricsapi.AnalysisValueTemplateSpec{
Provider: metricsapi.ObjectReference{
Name: "my-provider",
},
Query: "this is a {{.good}} query{{.dot}}",
},
}

provider.Spec.Type = "mock-provider"
provider2.Spec.Type = "mock-provider"

testCases := []struct {
name string
Expand All @@ -101,6 +127,13 @@ func TestProvidersPool(t *testing.T) {
Query: "this is a good query.",
},
},
{
name: "Success - provider in different namespace",
mockClient: fake2.NewClient(&analysis, &analysisDef, &template2, &provider2),
providerResult: &metricstypes.ProviderRequest{
Query: "this is a good query.",
},
},
}

for _, tc := range testCases {
Expand All @@ -118,7 +151,7 @@ func TestProvidersPool(t *testing.T) {
IObjectivesEvaluator: mockEvaluator,
Client: tc.mockClient,
log: mockLogger,
Namespace: "default",
Namespace: "default2",
Objectives: map[int][]metricsapi.Objective{
1: analysisDef.Spec.Objectives,
},
Expand Down
1 change: 0 additions & 1 deletion metrics-operator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,6 @@ func main() {
Scheme: mgr.GetScheme(),
Log: analysisLogger.V(env.AnalysisControllerLogLevel),
MaxWorkers: 2,
Namespace: env.PodNamespace,
NewWorkersPoolFactory: analysiscontroller.NewWorkersPool,
IAnalysisEvaluator: &analysisEval,
}).SetupWithManager(mgr); err != nil {
Expand Down

0 comments on commit e137aca

Please sign in to comment.