Skip to content

Commit 0a7a756

Browse files
authored
Add command to delete the specified rule namespace (#8) (#8)
Signed-off-by: songjiayang <[email protected]>
1 parent f22f3db commit 0a7a756

File tree

5 files changed

+98
-6
lines changed

5 files changed

+98
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ Order should be `CHANGE`, `FEATURE`, `ENHANCEMENT`, and `BUGFIX`
1212
* [CHANGE] Match prometheus/prometheus with version used by cortex v1.11.1 #5
1313
* [CHANGE] Remove loki support #7
1414
* [FEATURE] Support Arm64 on Darwin for all binaries (benchtool etc). #215
15+
* [FEATURE] Add `cortextool rules delete-namespace` command to delete the specified rule namespace. #8
1516
* [BUGFIX] Fix `cortextool rules` legends displaying wrong symbols for updates and deletions. #226
1617

1718
## v0.10.7

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,12 @@ This command will delete the specified rule group from the specified namespace.
7878

7979
cortextool rules delete example_namespace example_rule_group
8080

81+
##### Rule Namespace Delete
82+
83+
This command will delete the specified rule namespace.
84+
85+
cortextool rules delete-namespace example_namespace
86+
8187
##### Rules Load
8288

8389
This command will load each rule group in the specified files and load them into Cortex. If a rule already exists in Cortex it will be overwritten, if a diff is found.

pkg/client/rules.go

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func (r *CortexClient) CreateRuleGroup(ctx context.Context, namespace string, rg
3333
return nil
3434
}
3535

36-
// DeleteRuleGroup creates a new rule group
36+
// DeleteRuleGroup deletes a rule group
3737
func (r *CortexClient) DeleteRuleGroup(ctx context.Context, namespace, groupName string) error {
3838
escapedNamespace := url.PathEscape(namespace)
3939
escapedGroupName := url.PathEscape(groupName)
@@ -49,6 +49,21 @@ func (r *CortexClient) DeleteRuleGroup(ctx context.Context, namespace, groupName
4949
return nil
5050
}
5151

52+
// DeleteRuleNamespace deletes a rule namespace
53+
func (r *CortexClient) DeleteRuleNamespace(ctx context.Context, namespace string) error {
54+
escapedNamespace := url.PathEscape(namespace)
55+
path := r.apiPath + "/" + escapedNamespace
56+
57+
res, err := r.doRequest(path, "DELETE", nil)
58+
if err != nil {
59+
return err
60+
}
61+
62+
res.Body.Close()
63+
64+
return nil
65+
}
66+
5267
// GetRuleGroup retrieves a rule group
5368
func (r *CortexClient) GetRuleGroup(ctx context.Context, namespace, groupName string) (*rwrulefmt.RuleGroup, error) {
5469
escapedNamespace := url.PathEscape(namespace)

pkg/client/rules_test.go

Lines changed: 60 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,18 @@ package client
22

33
import (
44
"context"
5-
"fmt"
65
"net/http"
76
"net/http/httptest"
87
"testing"
98

109
"github.com/stretchr/testify/require"
1110
)
1211

13-
func TestCortexClient_X(t *testing.T) {
12+
func TestCortexClient_DeleteRuleGroup(t *testing.T) {
1413
requestCh := make(chan *http.Request, 1)
1514

1615
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
1716
requestCh <- r
18-
fmt.Fprintln(w, "hello")
1917
}))
2018
defer ts.Close()
2119

@@ -57,7 +55,7 @@ func TestCortexClient_X(t *testing.T) {
5755
expURLPath: "/api/v1/rules/My%2FNamespace/%2Ffirst-char-slash",
5856
},
5957
{
60-
test: "special-characters-slash-first",
58+
test: "special-characters-slash-last",
6159
namespace: "My/Namespace",
6260
name: "last-char-slash/",
6361
expURLPath: "/api/v1/rules/My%2FNamespace/last-char-slash%2F",
@@ -69,7 +67,65 @@ func TestCortexClient_X(t *testing.T) {
6967

7068
req := <-requestCh
7169
require.Equal(t, tc.expURLPath, req.URL.EscapedPath())
70+
require.Equal(t, http.MethodDelete, req.Method)
71+
})
72+
}
73+
74+
}
75+
76+
func TestCortexClient_DeleteRuleNamespace(t *testing.T) {
77+
requestCh := make(chan *http.Request, 1)
78+
79+
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
80+
requestCh <- r
81+
}))
82+
defer ts.Close()
7283

84+
client, err := New(Config{
85+
Address: ts.URL,
86+
ID: "my-id",
87+
Key: "my-key",
88+
})
89+
require.NoError(t, err)
90+
91+
for _, tc := range []struct {
92+
test string
93+
namespace string
94+
expURLPath string
95+
}{
96+
{
97+
test: "regular-characters",
98+
namespace: "my-namespace",
99+
expURLPath: "/api/v1/rules/my-namespace",
100+
},
101+
{
102+
test: "special-characters-spaces",
103+
namespace: "My: Namespace",
104+
expURLPath: "/api/v1/rules/My:%20Namespace",
105+
},
106+
{
107+
test: "special-characters-slashes",
108+
namespace: "My/Namespace",
109+
expURLPath: "/api/v1/rules/My%2FNamespace",
110+
},
111+
{
112+
test: "special-characters-slash-first",
113+
namespace: "/My/Namespace",
114+
expURLPath: "/api/v1/rules/%2FMy%2FNamespace",
115+
},
116+
{
117+
test: "special-characters-slash-last",
118+
namespace: "My/Namespace/",
119+
expURLPath: "/api/v1/rules/My%2FNamespace%2F",
120+
},
121+
} {
122+
t.Run(tc.test, func(t *testing.T) {
123+
ctx := context.Background()
124+
require.NoError(t, client.DeleteRuleNamespace(ctx, tc.namespace))
125+
126+
req := <-requestCh
127+
require.Equal(t, tc.expURLPath, req.URL.EscapedPath())
128+
require.Equal(t, http.MethodDelete, req.Method)
73129
})
74130
}
75131

pkg/commands/rules.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ func (r *RuleCommand) Register(app *kingpin.Application) {
103103
deleteRuleGroupCmd := rulesCmd.
104104
Command("delete", "Delete a rulegroup from the ruler.").
105105
Action(r.deleteRuleGroup)
106+
deleteRuleNamespaceCmd := rulesCmd.
107+
Command("delete-namespace", "Delete a namespace from the ruler.").
108+
Action(r.deleteRuleNamespace)
106109
loadRulesCmd := rulesCmd.
107110
Command("load", "load a set of rules to a designated cortex endpoint").
108111
Action(r.loadRules)
@@ -123,7 +126,7 @@ func (r *RuleCommand) Register(app *kingpin.Application) {
123126
Action(r.checkRecordingRuleNames)
124127

125128
// Require Cortex cluster address and tentant ID on all these commands
126-
for _, c := range []*kingpin.CmdClause{listCmd, printRulesCmd, getRuleGroupCmd, deleteRuleGroupCmd, loadRulesCmd, diffRulesCmd, syncRulesCmd} {
129+
for _, c := range []*kingpin.CmdClause{listCmd, printRulesCmd, getRuleGroupCmd, deleteRuleGroupCmd, deleteRuleNamespaceCmd, loadRulesCmd, diffRulesCmd, syncRulesCmd} {
127130
c.Flag("address", "Address of the cortex cluster, alternatively set CORTEX_ADDRESS.").
128131
Envar("CORTEX_ADDRESS").
129132
Required().
@@ -168,6 +171,9 @@ func (r *RuleCommand) Register(app *kingpin.Application) {
168171
deleteRuleGroupCmd.Arg("namespace", "Namespace of the rulegroup to delete.").Required().StringVar(&r.Namespace)
169172
deleteRuleGroupCmd.Arg("group", "Name of the rulegroup ot delete.").Required().StringVar(&r.RuleGroup)
170173

174+
// Delete Rule Namespace Command
175+
deleteRuleNamespaceCmd.Arg("namespace", "Namespace of the rule to delete.").Required().StringVar(&r.Namespace)
176+
171177
// Load Rules Command
172178
loadRulesCmd.Arg("rule-files", "The rule files to check.").Required().ExistingFilesVar(&r.RuleFilesList)
173179

@@ -367,6 +373,14 @@ func (r *RuleCommand) deleteRuleGroup(k *kingpin.ParseContext) error {
367373
return nil
368374
}
369375

376+
func (r *RuleCommand) deleteRuleNamespace(k *kingpin.ParseContext) error {
377+
err := r.cli.DeleteRuleNamespace(context.Background(), r.Namespace)
378+
if err != nil && err != client.ErrResourceNotFound {
379+
log.Fatalf("unable to delete namespace from cortex, %v", err)
380+
}
381+
return nil
382+
}
383+
370384
func (r *RuleCommand) loadRules(k *kingpin.ParseContext) error {
371385
nss, err := rules.ParseFiles(r.RuleFilesList)
372386
if err != nil {

0 commit comments

Comments
 (0)