Skip to content

Commit fee4a70

Browse files
committed
Set Sloth lib storage options into the generator struct
Signed-off-by: Xabier Larrakoetxea <me@slok.dev>
1 parent fbdcb45 commit fee4a70

File tree

8 files changed

+90
-113
lines changed

8 files changed

+90
-113
lines changed

cmd/sloth/commands/generate.go

Lines changed: 22 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import (
1717

1818
"github.com/slok/sloth/internal/log"
1919
"github.com/slok/sloth/internal/plugin"
20-
storageio "github.com/slok/sloth/internal/storage/io"
2120
"github.com/slok/sloth/pkg/common/model"
2221
utilsdata "github.com/slok/sloth/pkg/common/utils/data"
2322
slothlib "github.com/slok/sloth/pkg/lib"
@@ -237,10 +236,27 @@ func (g generateCommand) Run(ctx context.Context, config RootConfig) error {
237236
}
238237

239238
for _, genTarget := range genTargets {
240-
err := generateSLOs(ctx, logger, *genService, genTarget, g.disableAlerts, g.disableRecordings)
239+
// Generate SLOs.
240+
genResult, err := genService.GenerateFromRaw(ctx, []byte(genTarget.SLOData))
241241
if err != nil {
242242
return fmt.Errorf("could not generate SLOs: %w", err)
243243
}
244+
245+
// Disable data if required.
246+
for i := range genResult.SLOResults {
247+
if g.disableAlerts {
248+
genResult.SLOResults[i].PrometheusRules.AlertRules = model.PromRuleGroup{}
249+
}
250+
if g.disableRecordings {
251+
genResult.SLOResults[i].PrometheusRules.SLIErrorRecRules = model.PromRuleGroup{}
252+
genResult.SLOResults[i].PrometheusRules.MetadataRecRules = model.PromRuleGroup{}
253+
}
254+
}
255+
256+
err = g.storeSLOs(ctx, logger, genService, *genResult, genTarget.Out)
257+
if err != nil {
258+
return fmt.Errorf("could not store SLOs: %w", err)
259+
}
244260
}
245261

246262
return nil
@@ -251,65 +267,29 @@ type generateTarget struct {
251267
SLOData string
252268
}
253269

254-
func generateSLOs(ctx context.Context, logger log.Logger, genService slothlib.PrometheusSLOGenerator, genTarget generateTarget, disableAlerts, disableRecordings bool) error {
255-
dataB := []byte(genTarget.SLOData)
256-
257-
// Generate SLOs.
258-
genResult, err := genService.GenerateFromRaw(ctx, dataB)
259-
if err != nil {
260-
return fmt.Errorf("could not generate SLOs: %w", err)
261-
}
262-
263-
// Disable data if required.
264-
for i := range genResult.SLOResults {
265-
if disableAlerts {
266-
genResult.SLOResults[i].PrometheusRules.AlertRules = model.PromRuleGroup{}
267-
}
268-
if disableRecordings {
269-
genResult.SLOResults[i].PrometheusRules.SLIErrorRecRules = model.PromRuleGroup{}
270-
genResult.SLOResults[i].PrometheusRules.MetadataRecRules = model.PromRuleGroup{}
271-
}
272-
}
273-
270+
func (g generateCommand) storeSLOs(ctx context.Context, logger log.Logger, generator *slothlib.PrometheusSLOGenerator, genResult model.PromSLOGroupResult, out io.Writer) error {
274271
// Store results.
275272
switch {
276273
// Standard prometheus.
277274
case genResult.OriginalSource.SlothV1 != nil:
278-
repo := storageio.NewStdPrometheusGroupedRulesYAMLRepo(genTarget.Out, logger)
279-
err = repo.StoreSLOs(ctx, *genResult)
280-
if err != nil {
281-
return fmt.Errorf("could not store SLOS: %w", err)
282-
}
283-
284-
return nil
275+
return generator.WriteResultAsPrometheusStd(ctx, genResult, out)
285276

286277
// K8s Sloth CR.
287278
case genResult.OriginalSource.K8sSlothV1 != nil:
288-
repo := storageio.NewIOWriterPrometheusOperatorYAMLRepo(genTarget.Out, logger)
289-
290279
kmeta := model.K8sMeta{
291280
Name: genResult.OriginalSource.K8sSlothV1.Name,
292281
Namespace: genResult.OriginalSource.K8sSlothV1.Namespace,
293282
Labels: genResult.OriginalSource.K8sSlothV1.Labels,
294283
Annotations: genResult.OriginalSource.K8sSlothV1.Annotations,
295284
}
296285

297-
err = repo.StoreSLOs(ctx, kmeta, *genResult)
298-
if err != nil {
299-
return fmt.Errorf("could not store SLOS: %w", err)
300-
}
286+
return generator.WriteResultAsK8sPrometheusOperator(ctx, kmeta, genResult, out)
301287

302288
// OpenSLO.
303289
case genResult.OriginalSource.OpenSLOV1Alpha != nil:
304-
repo := storageio.NewStdPrometheusGroupedRulesYAMLRepo(genTarget.Out, logger)
305-
err = repo.StoreSLOs(ctx, *genResult)
306-
if err != nil {
307-
return fmt.Errorf("could not store SLOS: %w", err)
308-
}
290+
return generator.WriteResultAsPrometheusStd(ctx, genResult, out)
309291

310292
default:
311293
return fmt.Errorf("invalid spec, could not load with any of the supported spec types")
312294
}
313-
314-
return nil
315295
}

cmd/sloth/commands/validate.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,9 @@ func (v validateCommand) Run(ctx context.Context, config RootConfig) error {
138138
SLOData: data,
139139
Out: io.Discard,
140140
}
141-
err := generateSLOs(ctx, logger, *genService, genTarget, false, false)
141+
142+
// Generate SLOs.
143+
_, err := genService.GenerateFromRaw(ctx, []byte(genTarget.SLOData))
142144
if err != nil {
143145
validation.Errs = append(validation.Errs, fmt.Errorf("invalid SLO: %w", err))
144146
}

pkg/lib/bench_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ slos:
6060
b.Fatal(err)
6161
}
6262

63-
err = lib.WriteResultAsPrometheusStd(ctx, *slo, io.Discard)
63+
err = gen.WriteResultAsPrometheusStd(ctx, *slo, io.Discard)
6464
if err != nil {
6565
b.Fatal(err)
6666
}

pkg/lib/gen.go

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package lib
33
import (
44
"context"
55
"fmt"
6+
"io"
67
"io/fs"
78
"time"
89

@@ -11,6 +12,7 @@ import (
1112
"github.com/slok/sloth/internal/alert"
1213
"github.com/slok/sloth/internal/app/generate"
1314
"github.com/slok/sloth/internal/info"
15+
storagefs "github.com/slok/sloth/internal/storage/fs"
1416
storageio "github.com/slok/sloth/internal/storage/io"
1517
"github.com/slok/sloth/pkg/common/model"
1618
utilsdata "github.com/slok/sloth/pkg/common/utils/data"
@@ -78,16 +80,14 @@ func (c *PrometheusSLOGeneratorConfig) defaults() error {
7880

7981
// PrometheusSLOGenerator is a Prometheus SLO rules generator from the Sloth supported SLO definitions.
8082
type PrometheusSLOGenerator struct {
81-
// Generator.
82-
genSvc generate.Service
83-
84-
// Spec loaders.
83+
genSvc generate.Service
8584
promYAMLLoader storageio.SlothPrometheusYAMLSpecLoader
8685
kubeYAMLLoader storageio.K8sSlothPrometheusYAMLSpecLoader
8786
openSLOYAMLLoader storageio.OpenSLOYAMLSpecLoader
88-
89-
extraLabels map[string]string
90-
agent CallerAgent
87+
pluginsRepo *storagefs.FilePluginRepo
88+
extraLabels map[string]string
89+
agent CallerAgent
90+
logger log.Logger
9191
}
9292

9393
func NewPrometheusSLOGenerator(config PrometheusSLOGeneratorConfig) (*PrometheusSLOGenerator, error) {
@@ -132,7 +132,7 @@ func NewPrometheusSLOGenerator(config PrometheusSLOGeneratorConfig) (*Prometheus
132132
DefaultPlugins: defSLOPlugins,
133133
SLOPluginGetter: pluginRepo,
134134
ExtraPlugins: config.CMDSLOPlugins,
135-
Logger: log.Noop,
135+
Logger: config.Logger,
136136
})
137137
if err != nil {
138138
return nil, fmt.Errorf("could not create application service: %w", err)
@@ -143,8 +143,10 @@ func NewPrometheusSLOGenerator(config PrometheusSLOGeneratorConfig) (*Prometheus
143143
promYAMLLoader: storageio.NewSlothPrometheusYAMLSpecLoader(pluginRepo, config.DefaultSLOPeriod),
144144
kubeYAMLLoader: storageio.NewK8sSlothPrometheusYAMLSpecLoader(pluginRepo, config.DefaultSLOPeriod),
145145
openSLOYAMLLoader: storageio.NewOpenSLOYAMLSpecLoader(config.DefaultSLOPeriod),
146+
pluginsRepo: pluginRepo,
146147
extraLabels: config.ExtraLabels,
147148
agent: config.CallerAgent,
149+
logger: config.Logger,
148150
}, nil
149151
}
150152

@@ -297,3 +299,19 @@ func (p PrometheusSLOGenerator) generateFromModel(ctx context.Context, req gener
297299
SLOResults: result,
298300
}, nil
299301
}
302+
303+
// WriteResultAsPrometheusStd writes the SLO results into the writer as a Prometheus standard rules file.
304+
// More information in:
305+
// - https://prometheus.io/docs/prometheus/latest/configuration/recording_rules/#recording-rules.
306+
// - https://prometheus.io/docs/prometheus/latest/configuration/alerting_rules/.
307+
func (p PrometheusSLOGenerator) WriteResultAsPrometheusStd(ctx context.Context, slo model.PromSLOGroupResult, w io.Writer) error {
308+
repo := storageio.NewStdPrometheusGroupedRulesYAMLRepo(w, p.logger)
309+
return repo.StoreSLOs(ctx, slo)
310+
}
311+
312+
// WriteResultAsK8sPrometheusOperator writes the SLO results into the writer as a Prometheus Operator CRD file.
313+
// More information in: https://prometheus-operator.dev/docs/api-reference/api/#monitoring.coreos.com/v1.PrometheusRule.
314+
func (p PrometheusSLOGenerator) WriteResultAsK8sPrometheusOperator(ctx context.Context, k8sMeta model.K8sMeta, slo model.PromSLOGroupResult, w io.Writer) error {
315+
repo := storageio.NewIOWriterPrometheusOperatorYAMLRepo(w, p.logger)
316+
return repo.StoreSLOs(ctx, k8sMeta, slo)
317+
}

pkg/lib/lib_as_cli_use_cases_test.go

Lines changed: 34 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func TestLibAsCLIIntegration(t *testing.T) {
2525
tests := map[string]struct {
2626
config func() lib.PrometheusSLOGeneratorConfig
2727
inFilePath string
28-
resultFormatter func(t *testing.T, result model.PromSLOGroupResult) []byte
28+
resultFormatter func(t *testing.T, gen *lib.PrometheusSLOGenerator, result model.PromSLOGroupResult) []byte
2929
expOutFilePath string
3030
expGenErr bool
3131
}{
@@ -43,9 +43,9 @@ func TestLibAsCLIIntegration(t *testing.T) {
4343
},
4444
inFilePath: "../../test/integration/prometheus/testdata/in-base.yaml",
4545
expOutFilePath: "../../test/integration/prometheus/testdata/out-base.yaml.tpl",
46-
resultFormatter: func(t *testing.T, result model.PromSLOGroupResult) []byte {
46+
resultFormatter: func(t *testing.T, gen *lib.PrometheusSLOGenerator, result model.PromSLOGroupResult) []byte {
4747
var b bytes.Buffer
48-
err := lib.WriteResultAsPrometheusStd(t.Context(), result, &b)
48+
err := gen.WriteResultAsPrometheusStd(t.Context(), result, &b)
4949
require.NoError(t, err)
5050
return b.Bytes()
5151
},
@@ -57,10 +57,10 @@ func TestLibAsCLIIntegration(t *testing.T) {
5757
},
5858
inFilePath: "../../test/integration/prometheus/testdata/in-base-k8s.yaml",
5959
expOutFilePath: "../../test/integration/prometheus/testdata/out-base-k8s.yaml.tpl",
60-
resultFormatter: func(t *testing.T, result model.PromSLOGroupResult) []byte {
60+
resultFormatter: func(t *testing.T, gen *lib.PrometheusSLOGenerator, result model.PromSLOGroupResult) []byte {
6161
var b bytes.Buffer
6262
kmeta := model.K8sMeta{Name: "svc", Namespace: "test-ns"}
63-
err := lib.WriteResultAsK8sPrometheusOperator(t.Context(), kmeta, result, &b)
63+
err := gen.WriteResultAsK8sPrometheusOperator(t.Context(), kmeta, result, &b)
6464
require.NoError(t, err)
6565
return b.Bytes()
6666
},
@@ -72,9 +72,9 @@ func TestLibAsCLIIntegration(t *testing.T) {
7272
},
7373
inFilePath: "../../test/integration/prometheus/testdata/in-openslo.yaml",
7474
expOutFilePath: "../../test/integration/prometheus/testdata/out-openslo.yaml.tpl",
75-
resultFormatter: func(t *testing.T, result model.PromSLOGroupResult) []byte {
75+
resultFormatter: func(t *testing.T, gen *lib.PrometheusSLOGenerator, result model.PromSLOGroupResult) []byte {
7676
var b bytes.Buffer
77-
err := lib.WriteResultAsPrometheusStd(t.Context(), result, &b)
77+
err := gen.WriteResultAsPrometheusStd(t.Context(), result, &b)
7878
require.NoError(t, err)
7979
return b.Bytes()
8080
},
@@ -89,9 +89,9 @@ func TestLibAsCLIIntegration(t *testing.T) {
8989
},
9090
inFilePath: "../../test/integration/prometheus/testdata/in-base.yaml",
9191
expOutFilePath: "../../test/integration/prometheus/testdata/out-base-28d.yaml.tpl",
92-
resultFormatter: func(t *testing.T, result model.PromSLOGroupResult) []byte {
92+
resultFormatter: func(t *testing.T, gen *lib.PrometheusSLOGenerator, result model.PromSLOGroupResult) []byte {
9393
var b bytes.Buffer
94-
err := lib.WriteResultAsPrometheusStd(t.Context(), result, &b)
94+
err := gen.WriteResultAsPrometheusStd(t.Context(), result, &b)
9595
require.NoError(t, err)
9696
return b.Bytes()
9797
},
@@ -107,9 +107,9 @@ func TestLibAsCLIIntegration(t *testing.T) {
107107
},
108108
inFilePath: "../../test/integration/prometheus/testdata/in-base.yaml",
109109
expOutFilePath: "../../test/integration/prometheus/testdata/out-base-custom-windows-7d.yaml.tpl",
110-
resultFormatter: func(t *testing.T, result model.PromSLOGroupResult) []byte {
110+
resultFormatter: func(t *testing.T, gen *lib.PrometheusSLOGenerator, result model.PromSLOGroupResult) []byte {
111111
var b bytes.Buffer
112-
err := lib.WriteResultAsPrometheusStd(t.Context(), result, &b)
112+
err := gen.WriteResultAsPrometheusStd(t.Context(), result, &b)
113113
require.NoError(t, err)
114114
return b.Bytes()
115115
},
@@ -124,9 +124,9 @@ func TestLibAsCLIIntegration(t *testing.T) {
124124
},
125125
inFilePath: "../../test/integration/prometheus/testdata/in-base.yaml",
126126
expOutFilePath: "../../test/integration/prometheus/testdata/out-base-extra-labels.yaml.tpl",
127-
resultFormatter: func(t *testing.T, result model.PromSLOGroupResult) []byte {
127+
resultFormatter: func(t *testing.T, gen *lib.PrometheusSLOGenerator, result model.PromSLOGroupResult) []byte {
128128
var b bytes.Buffer
129-
err := lib.WriteResultAsPrometheusStd(t.Context(), result, &b)
129+
err := gen.WriteResultAsPrometheusStd(t.Context(), result, &b)
130130
require.NoError(t, err)
131131
return b.Bytes()
132132
},
@@ -138,14 +138,14 @@ func TestLibAsCLIIntegration(t *testing.T) {
138138
},
139139
inFilePath: "../../test/integration/prometheus/testdata/in-base.yaml",
140140
expOutFilePath: "../../test/integration/prometheus/testdata/out-base-no-alerts.yaml.tpl",
141-
resultFormatter: func(t *testing.T, result model.PromSLOGroupResult) []byte {
141+
resultFormatter: func(t *testing.T, gen *lib.PrometheusSLOGenerator, result model.PromSLOGroupResult) []byte {
142142

143143
for i := range result.SLOResults {
144144
result.SLOResults[i].PrometheusRules.AlertRules = model.PromRuleGroup{}
145145
}
146146

147147
var b bytes.Buffer
148-
err := lib.WriteResultAsPrometheusStd(t.Context(), result, &b)
148+
err := gen.WriteResultAsPrometheusStd(t.Context(), result, &b)
149149
require.NoError(t, err)
150150
return b.Bytes()
151151
},
@@ -157,15 +157,15 @@ func TestLibAsCLIIntegration(t *testing.T) {
157157
},
158158
inFilePath: "../../test/integration/prometheus/testdata/in-base.yaml",
159159
expOutFilePath: "../../test/integration/prometheus/testdata/out-base-no-recordings.yaml.tpl",
160-
resultFormatter: func(t *testing.T, result model.PromSLOGroupResult) []byte {
160+
resultFormatter: func(t *testing.T, gen *lib.PrometheusSLOGenerator, result model.PromSLOGroupResult) []byte {
161161
// Remove alerts.
162162
for i := range result.SLOResults {
163163
result.SLOResults[i].PrometheusRules.SLIErrorRecRules = model.PromRuleGroup{}
164164
result.SLOResults[i].PrometheusRules.MetadataRecRules = model.PromRuleGroup{}
165165
}
166166

167167
var b bytes.Buffer
168-
err := lib.WriteResultAsPrometheusStd(t.Context(), result, &b)
168+
err := gen.WriteResultAsPrometheusStd(t.Context(), result, &b)
169169
require.NoError(t, err)
170170
return b.Bytes()
171171
},
@@ -180,9 +180,9 @@ func TestLibAsCLIIntegration(t *testing.T) {
180180
},
181181
inFilePath: "../../test/integration/prometheus/testdata/in-sli-plugin.yaml",
182182
expOutFilePath: "../../test/integration/prometheus/testdata/out-sli-plugin.yaml.tpl",
183-
resultFormatter: func(t *testing.T, result model.PromSLOGroupResult) []byte {
183+
resultFormatter: func(t *testing.T, gen *lib.PrometheusSLOGenerator, result model.PromSLOGroupResult) []byte {
184184
var b bytes.Buffer
185-
err := lib.WriteResultAsPrometheusStd(t.Context(), result, &b)
185+
err := gen.WriteResultAsPrometheusStd(t.Context(), result, &b)
186186
require.NoError(t, err)
187187
return b.Bytes()
188188
},
@@ -197,9 +197,9 @@ func TestLibAsCLIIntegration(t *testing.T) {
197197
},
198198
inFilePath: "../../test/integration/prometheus/testdata/in-slo-plugin.yaml",
199199
expOutFilePath: "../../test/integration/prometheus/testdata/out-slo-plugin.yaml.tpl",
200-
resultFormatter: func(t *testing.T, result model.PromSLOGroupResult) []byte {
200+
resultFormatter: func(t *testing.T, gen *lib.PrometheusSLOGenerator, result model.PromSLOGroupResult) []byte {
201201
var b bytes.Buffer
202-
err := lib.WriteResultAsPrometheusStd(t.Context(), result, &b)
202+
err := gen.WriteResultAsPrometheusStd(t.Context(), result, &b)
203203
require.NoError(t, err)
204204
return b.Bytes()
205205
},
@@ -214,10 +214,10 @@ func TestLibAsCLIIntegration(t *testing.T) {
214214
},
215215
inFilePath: "../../test/integration/prometheus/testdata/in-slo-plugin-k8s.yaml",
216216
expOutFilePath: "../../test/integration/prometheus/testdata/out-slo-plugin-k8s.yaml.tpl",
217-
resultFormatter: func(t *testing.T, result model.PromSLOGroupResult) []byte {
217+
resultFormatter: func(t *testing.T, gen *lib.PrometheusSLOGenerator, result model.PromSLOGroupResult) []byte {
218218
var b bytes.Buffer
219219
kmeta := model.K8sMeta{Name: "svc", Namespace: "test-ns"}
220-
err := lib.WriteResultAsK8sPrometheusOperator(t.Context(), kmeta, result, &b)
220+
err := gen.WriteResultAsK8sPrometheusOperator(t.Context(), kmeta, result, &b)
221221
require.NoError(t, err)
222222
return b.Bytes()
223223
},
@@ -227,18 +227,22 @@ func TestLibAsCLIIntegration(t *testing.T) {
227227
config: func() lib.PrometheusSLOGeneratorConfig {
228228
return lib.PrometheusSLOGeneratorConfig{CallerAgent: lib.CallerAgentCLI}
229229
},
230-
inFilePath: "../../test/integration/prometheus/testdata/in-multifile.yaml",
231-
resultFormatter: func(t *testing.T, result model.PromSLOGroupResult) []byte { return nil },
232-
expGenErr: true,
230+
inFilePath: "../../test/integration/prometheus/testdata/in-multifile.yaml",
231+
resultFormatter: func(t *testing.T, gen *lib.PrometheusSLOGenerator, result model.PromSLOGroupResult) []byte {
232+
return nil
233+
},
234+
expGenErr: true,
233235
},
234236

235237
"A multifile Kubernetes case (Not supported).": {
236238
config: func() lib.PrometheusSLOGeneratorConfig {
237239
return lib.PrometheusSLOGeneratorConfig{CallerAgent: lib.CallerAgentCLI}
238240
},
239-
inFilePath: "../../test/integration/prometheus/testdata/in-multifile-k8s.yaml",
240-
resultFormatter: func(t *testing.T, result model.PromSLOGroupResult) []byte { return nil },
241-
expGenErr: true,
241+
inFilePath: "../../test/integration/prometheus/testdata/in-multifile-k8s.yaml",
242+
resultFormatter: func(t *testing.T, gen *lib.PrometheusSLOGenerator, result model.PromSLOGroupResult) []byte {
243+
return nil
244+
},
245+
expGenErr: true,
242246
},
243247
}
244248

@@ -256,10 +260,9 @@ func TestLibAsCLIIntegration(t *testing.T) {
256260
result, err := gen.GenerateFromRaw(t.Context(), expInData)
257261
if test.expGenErr {
258262
assert.Error(err)
259-
return
260263
} else if assert.NoError(err) {
261264
// Check result.
262-
resultOutData := test.resultFormatter(t, *result)
265+
resultOutData := test.resultFormatter(t, gen, *result)
263266
expOutData := getExpData(t, test.expOutFilePath)
264267
assert.Equal(string(expOutData), string(resultOutData))
265268
}

0 commit comments

Comments
 (0)