Skip to content

Commit f4d117b

Browse files
authored
Fix rules lint/prepare/check failing with "cortex address is required" (#61)
1 parent daf157d commit f4d117b

2 files changed

Lines changed: 46 additions & 3 deletions

File tree

pkg/commands/rules.go

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -248,10 +248,10 @@ func (r *RuleCommand) setup(_ *kingpin.ParseContext) error {
248248
)
249249

250250
// Apply config file defaults
251-
if err := ApplyConfigDefaults(&r.ClientConfig); err != nil {
252-
return err
253-
}
251+
return ApplyConfigDefaults(&r.ClientConfig)
252+
}
254253

254+
func (r *RuleCommand) setupClient() error {
255255
// Validate required fields (they may come from config file)
256256
if r.ClientConfig.Address == "" {
257257
return fmt.Errorf("cortex address is required (use --address flag, CORTEX_ADDRESS env var, or config file)")
@@ -345,6 +345,9 @@ func (r *RuleCommand) setupFiles() error {
345345
}
346346

347347
func (r *RuleCommand) listRules(_ *kingpin.ParseContext) error {
348+
if err := r.setupClient(); err != nil {
349+
return err
350+
}
348351
rules, err := r.cli.ListRules(context.Background(), "")
349352
if err != nil {
350353
if errors.Is(err, client.ErrResourceNotFound) {
@@ -359,6 +362,9 @@ func (r *RuleCommand) listRules(_ *kingpin.ParseContext) error {
359362
}
360363

361364
func (r *RuleCommand) printRules(_ *kingpin.ParseContext) error {
365+
if err := r.setupClient(); err != nil {
366+
return err
367+
}
362368
rules, err := r.cli.ListRules(context.Background(), "")
363369
if err != nil {
364370
if errors.Is(err, client.ErrResourceNotFound) {
@@ -373,6 +379,9 @@ func (r *RuleCommand) printRules(_ *kingpin.ParseContext) error {
373379
}
374380

375381
func (r *RuleCommand) getRuleGroup(_ *kingpin.ParseContext) error {
382+
if err := r.setupClient(); err != nil {
383+
return err
384+
}
376385
group, err := r.cli.GetRuleGroup(context.Background(), r.Namespace, r.RuleGroup)
377386
if err != nil {
378387
if errors.Is(err, client.ErrResourceNotFound) {
@@ -387,6 +396,9 @@ func (r *RuleCommand) getRuleGroup(_ *kingpin.ParseContext) error {
387396
}
388397

389398
func (r *RuleCommand) deleteRuleGroup(_ *kingpin.ParseContext) error {
399+
if err := r.setupClient(); err != nil {
400+
return err
401+
}
390402
err := r.cli.DeleteRuleGroup(context.Background(), r.Namespace, r.RuleGroup)
391403
if err != nil && !errors.Is(err, client.ErrResourceNotFound) {
392404
log.Fatalf("unable to delete rule group from cortex, %v", err)
@@ -395,6 +407,9 @@ func (r *RuleCommand) deleteRuleGroup(_ *kingpin.ParseContext) error {
395407
}
396408

397409
func (r *RuleCommand) deleteRuleNamespace(_ *kingpin.ParseContext) error {
410+
if err := r.setupClient(); err != nil {
411+
return err
412+
}
398413
err := r.cli.DeleteRuleNamespace(context.Background(), r.Namespace)
399414
if err != nil && !errors.Is(err, client.ErrResourceNotFound) {
400415
log.Fatalf("unable to delete namespace from cortex, %v", err)
@@ -403,6 +418,9 @@ func (r *RuleCommand) deleteRuleNamespace(_ *kingpin.ParseContext) error {
403418
}
404419

405420
func (r *RuleCommand) loadRules(_ *kingpin.ParseContext) error {
421+
if err := r.setupClient(); err != nil {
422+
return err
423+
}
406424
nss, err := rules.ParseFiles(r.RuleFilesList, r.getValidationScheme())
407425
if err != nil {
408426
return errors.Wrap(err, "load operation unsuccessful, unable to parse rules files")
@@ -460,6 +478,9 @@ func (r *RuleCommand) shouldCheckNamespace(namespace string) bool {
460478
}
461479

462480
func (r *RuleCommand) diffRules(_ *kingpin.ParseContext) error {
481+
if err := r.setupClient(); err != nil {
482+
return err
483+
}
463484
err := r.setupFiles()
464485
if err != nil {
465486
return errors.Wrap(err, "diff operation unsuccessful, unable to load rules files")
@@ -523,6 +544,9 @@ func (r *RuleCommand) diffRules(_ *kingpin.ParseContext) error {
523544
}
524545

525546
func (r *RuleCommand) syncRules(_ *kingpin.ParseContext) error {
547+
if err := r.setupClient(); err != nil {
548+
return err
549+
}
526550
err := r.setupFiles()
527551
if err != nil {
528552
return errors.Wrap(err, "sync operation unsuccessful, unable to load rules files")

pkg/commands/rules_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55

66
"github.com/prometheus/prometheus/model/rulefmt"
77
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
89

910
"github.com/cortexproject/cortex-tools/pkg/rules/rwrulefmt"
1011
)
@@ -61,3 +62,21 @@ func TestCheckDuplicates(t *testing.T) {
6162
})
6263
}
6364
}
65+
66+
// TestSetupClientRequiresAddress verifies that setupClient returns an error when
67+
// no address is configured, while setup (the PreAction) does not.
68+
// This ensures local-only commands (lint, prepare, check) work without a Cortex address.
69+
func TestSetupClientRequiresAddress(t *testing.T) {
70+
r := &RuleCommand{}
71+
72+
// setupClient should fail when no address is set.
73+
err := r.setupClient()
74+
require.Error(t, err)
75+
assert.Contains(t, err.Error(), "cortex address is required")
76+
77+
// setupClient should fail when address is set but tenant ID is missing.
78+
r.ClientConfig.Address = "http://cortex:9009"
79+
err = r.setupClient()
80+
require.Error(t, err)
81+
assert.Contains(t, err.Error(), "tenant ID is required")
82+
}

0 commit comments

Comments
 (0)