Skip to content

Commit d5663c7

Browse files
committed
add disabled parameter and support for tags
1 parent 9207a88 commit d5663c7

File tree

5 files changed

+90
-15
lines changed

5 files changed

+90
-15
lines changed

cli/README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,12 @@ Manages **Scheduled Repair** in AxonOps.
144144
* `--optimisestreams` Optimize Streams during repair (require Cassandra 4.1+).
145145
* `--datacenters` Comma-separated list of datacenters to include in the repair. If not set, all datacenters will be
146146
included.
147-
* `--tags` Tags to associate with the scheduled repair job.
147+
* `--tags` Tags to associate with the scheduled repair job. Tags are used to identify repair jobs in AxonOps.
148+
This parameter accepts a string value.
148149
* `--paxosonly` Run paxos repair only. Default is false.
149150
* `--skippaxos` Skip paxos repair. Default is false.
151+
* `--delete` Delete Scheduled Repair. This option needs to be paired with a tags value to identify which scheduled
152+
repair job to disable.
150153

151154
#### Examples:
152155

@@ -261,4 +264,10 @@ Run a scheduled repair skipping paxos repair with a cron expression:
261264

262265
```shell
263266
$ pipenv run python axonops.py scheduledrepair --scheduleexpr '0 0 * * 0' --paxosonly
267+
```
268+
269+
Delete a scheduled repair job with specific tags:
270+
271+
```shell
272+
$ pipenv run python axonops.py scheduledrepair --delete --tags 'Weekly repair'
264273
```

cli/axonopscli/application.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -119,26 +119,30 @@ def run(self, argv: Sequence):
119119
scheduledrepair_parser.add_argument('--datacenters', type=str, required=False,
120120
help='Comma-separated list of datacenters to repair, if not specified all datacenters are included')
121121
scheduledrepair_parser.add_argument('--tags', type=str, required=False,
122-
help='Tag for the repair job')
122+
help='Tag for the repair job', default="")
123+
scheduledrepair_parser.add_argument('--delete', action='store_true',
124+
help='Delete the scheduled repair instead of enabling it')
123125

124126
paxos_group = scheduledrepair_parser.add_mutually_exclusive_group()
125127
paxos_group.add_argument('--paxosonly', action='store_true', default=False,
126-
help='Run only Paxos repairs')
128+
help='Run only Paxos repairs')
127129
paxos_group.add_argument('--skippaxos', action='store_true', default=False,
128-
help='Skip Paxos repairs')
130+
help='Skip Paxos repairs')
129131

130132
parsed_result: argparse.Namespace = parser.parse_args(args=argv)
131133

132134
# ensure --tables is only used together with --keyspace
133135
if getattr(parsed_result, "tables", None) and not getattr(parsed_result, "keyspace", None):
134136
parser.error("--tables requires --keyspace")
135137

138+
# ensure --disabled is only used together with tags
139+
if getattr(parsed_result, "delete", None) and not getattr(parsed_result, "tags", None):
140+
parser.error("--delete requires --tags")
141+
136142
# ensure --excludedtables is only used together with --keyspace
137143
if getattr(parsed_result, "excludedtables", None) and not getattr(parsed_result, "keyspace", None):
138144
parser.error("--excludedtables requires --keyspace")
139145

140-
141-
142146
# if func() is not present it means that no command was inserted
143147
if hasattr(parsed_result, 'func'):
144148
self.run_mandatory_args_check(parsed_result)
@@ -203,6 +207,8 @@ def run_scheduled_repair(self, args: argparse.Namespace):
203207

204208
scheduled_repair = ScheduledRepair(axonops, args)
205209

210+
scheduled_repair.remove_old_repairs_from_axonops()
211+
206212
scheduled_repair.set_options()
207213

208214
scheduled_repair.set_repair()

cli/axonopscli/axonops.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,9 @@
11
import json
22
import urllib.parse
33
from typing import List
4-
54
import requests
65

7-
8-
class HTTPCodeError(Exception):
9-
pass
6+
from .utils import HTTPCodeError
107

118

129
class AxonOps:

cli/axonopscli/components/scheduled_repair.py

Lines changed: 64 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,49 @@
1+
from axonopscli.axonops import HTTPCodeError
2+
3+
14
class ScheduledRepair:
25
""" Class to manage the Scheduled Repair in AxonOps """
36
schedule_repair_add_url = "/api/v1/addrepair"
7+
repair_url = "/api/v1/repair"
8+
cassandrascheduledrepair_url = "/api/v1/cassandrascheduledrepair"
49

510
def __init__(self, axonops, args):
611
self.axonops = axonops
712
self.args = args
813
self.repair_data = None
9-
self.full_url = f"{self.schedule_repair_add_url}/{args.org}/cassandra/{args.cluster}"
14+
self.full_add_repair_url = f"{self.schedule_repair_add_url}/{args.org}/cassandra/{args.cluster}"
15+
self.full_repair_url = f"{self.repair_url}/{args.org}/cassandra/{args.cluster}"
16+
self.full_cassandrascheduledrepair_url = f"{self.cassandrascheduledrepair_url}/{args.org}/cassandra/{args.cluster}"
17+
18+
def remove_old_repairs_from_axonops(self):
19+
""" Check if the scheduled repair already exists in AxonOps, if so, remove it. """
20+
if self.args.v:
21+
print("Checking if scheduled repair already exists")
22+
23+
if self.args.tags != "":
24+
if self.args.v:
25+
print("Getting scheduled repair with tag:", self.args.tags)
26+
response = self.axonops.do_request(
27+
url=self.full_repair_url,
28+
method='GET',
29+
)
30+
if not response:
31+
if self.args.v:
32+
print("No response received when checking for existing scheduled repair")
33+
return
34+
elif 'ScheduledRepairs' in response and response['ScheduledRepairs']:
35+
for repair in response['ScheduledRepairs']:
36+
if self.args.v:
37+
print(f"Checking scheduled repair: {repair['ID']}")
38+
self.remove_repair(repair['ID'])
39+
if 'Params' in repair:
40+
print(repair['Params'])
41+
42+
else:
43+
print("Repair tag not found, this will be threaded as a new scheduled repair")
44+
else:
45+
if self.args.v:
46+
print("No tag provided, this will be threaded as a new scheduled repair")
1047

1148
def set_options(self):
1249
"""Apply optional CLI parameters into the payload before sending it."""
@@ -59,13 +96,36 @@ def set_options(self):
5996
self.repair_data['paxos'] = "Paxos Only"
6097

6198
def set_repair(self):
62-
full_url = f"{self.axonops.dash_url()}{self.schedule_repair_add_url}"
6399
print("Setting the scheduled repair")
64100
if self.args.v:
65-
print("POST", self.full_url, self.repair_data)
101+
print("POST", self.full_add_repair_url, self.repair_data)
102+
103+
if self.args.delete:
104+
if self.args.v:
105+
print("This scheduled repair is delete, not sending to AxonOps")
106+
return
66107

67108
self.axonops.do_request(
68-
url=self.full_url,
109+
url=self.full_add_repair_url,
69110
method='POST',
70111
json_data=self.repair_data,
71112
)
113+
114+
def remove_repair(self, repair_id: str) -> bool:
115+
""" Remove a scheduled repair from AxonOps by its ID. """
116+
if self.args.v:
117+
print(f"Removing scheduled repair with ID: {repair_id}")
118+
119+
try:
120+
response = self.axonops.do_request(
121+
url=f"{self.full_cassandrascheduledrepair_url}?id={repair_id}",
122+
method='DELETE',
123+
)
124+
except HTTPCodeError:
125+
print(f"Failed to remove scheduled repair with ID: {repair_id}")
126+
raise
127+
else:
128+
if self.args.v:
129+
print(f"Response received when removing scheduled repair with ID: {repair_id}: {response}")
130+
131+
return True

cli/axonopscli/utils.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
class HTTPCodeError(Exception):
2+
pass
3+
4+
15
def remove_not_alphanumeric(s: str) -> str:
26
"""Remove non-alphanumeric characters from a string."""
37
return ''.join(c for c in s if c.isalnum())
4-

0 commit comments

Comments
 (0)