Skip to content

Commit

Permalink
Remove implicit wildcards from configcache commands.
Browse files Browse the repository at this point in the history
The configcache commands now require the user to specify `*` to get
wildcard selection behavior.

ZEN-35054
  • Loading branch information
jpeacock-zenoss committed Sep 13, 2024
1 parent 02cb53e commit 6f7e8cc
Show file tree
Hide file tree
Showing 10 changed files with 1,002 additions and 116 deletions.
45 changes: 23 additions & 22 deletions Products/ZenCollector/configcache/cli/expire.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,18 +81,20 @@ def run(self):
file=sys.stderr,
)
return
else:
self._devices = self._devices[0].replace("*", "")
if not self._confirm_inputs():
print("exit")
return
initialize_environment(configs=self.configs, useZope=False)
client = getRedisClient(url=getRedisUrl())
store = createObject("deviceconfigcache-store", client)
query = DeviceQuery(service=self._service, monitor=self._monitor)
self._expire(store, self._get(store, haswildcard))

def _get(self, store, haswildcard):
query = self._make_query(haswildcard)
results = store.query_statuses(query)
method = self._no_devices if not self._devices else self._with_devices
keys = method(results, wildcard=haswildcard)
return tuple(self._get_keys_from_results(results, haswildcard))

def _expire(self, store, keys):
now = time.time()
store.set_expired(*((key, now) for key in keys))
count = len(keys)
Expand All @@ -101,25 +103,24 @@ def run(self):
% (count, "" if count == 1 else "s")
)

def _no_devices(self, results, wildcard=False):
return tuple(status.key for status in results)

def _with_devices(self, results, wildcard=False):
if wildcard:
predicate = self._check_wildcard
else:
predicate = self._check_list

return tuple(
status.key for status in results if predicate(status.key.device)
def _make_query(self, haswildcard):
if haswildcard:
return DeviceQuery(
service=self._service,
monitor=self._monitor,
device=self._devices[0],
)
return DeviceQuery(service=self._service, monitor=self._monitor)

def _get_keys_from_results(self, results, haswildcard):
if not self._devices or haswildcard:
return (status.key for status in results)
return (
status.key
for status in results
if status.key.device in self._devices
)

def _check_wildcard(self, device):
return self._devices in device

def _check_list(self, device):
return device in self._devices

def _confirm_inputs(self):
if self._devices:
return True
Expand Down
45 changes: 20 additions & 25 deletions Products/ZenCollector/configcache/cli/list.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,8 @@ def add_arguments(parser, subparsers):
listp.set_defaults(factory=ListDevice)

def __init__(self, args):
self._monitor = "*{}*".format(args.collector).replace("***", "*")
self._service = "*{}*".format(args.service).replace("***", "*")
self._monitor = args.collector
self._service = args.service
self._showuid = args.show_uid
self._devices = getattr(args, "device", [])
state_names = getattr(args, "states", ())
Expand All @@ -81,17 +81,22 @@ def run(self):
)
return
initialize_environment(configs=self.configs, useZope=False)
self._display(*self._collate(*self._get(haswildcard)))

def _get(self, haswildcard):
client = getRedisClient(url=getRedisUrl())
store = createObject("deviceconfigcache-store", client)
query = self._make_query(haswildcard)
data = tuple(self._filter(store.query_statuses(query)))
uid_map = self._get_uidmap(store, data)
statuses = tuple(self._filter(store.query_statuses(query)))
uid_map = self._get_uidmap(store, statuses)
return (statuses, uid_map)

def _collate(self, statuses, uid_map):
rows = []
maxd, maxs, maxt, maxa, maxm = 1, 1, 1, 1, 1
now = time.time()
for status in sorted(
data, key=lambda x: (x.key.device, x.key.service)
statuses, key=lambda x: (x.key.device, x.key.service)
):
devid = (
status.key.device
Expand All @@ -117,30 +122,16 @@ def run(self):
status.key.service,
)
)
hdr_tmplt = "{0:{6}} {1:{7}} {2:^{8}} {3:^{9}} {4:{10}} {5}"
row_tmplt = "{0:{6}} {1:{7}} {2:{8}} {3:>{9}} {4:{10}} {5}"
headings = (
"DEVICE",
"STATUS",
"LAST CHANGE",
"AGE",
"COLLECTOR",
"SERVICE",
)
widths = (maxd, maxs, maxt, maxa, maxm)
return rows, (maxd, maxs, maxt, maxa, maxm)

def _display(self, rows, widths):
if rows:
print(hdr_tmplt.format(*chain(headings, widths)))
print(_header_template.format(*chain(_headings, widths)))
for row in rows:
print(row_tmplt.format(*chain(row, widths)))
print(_row_template.format(*chain(row, widths)))

def _make_query(self, haswildcard):
if haswildcard:
return DeviceQuery(
service=self._service,
monitor=self._monitor,
device=self._devices[0],
)
if len(self._devices) == 1:
if haswildcard or len(self._devices) == 1:
return DeviceQuery(
service=self._service,
monitor=self._monitor,
Expand All @@ -167,6 +158,10 @@ def _get_uidmap(self, store, data):
return {}


_header_template = "{0:{6}} {1:{7}} {2:^{8}} {3:^{9}} {4:{10}} {5}"
_row_template = "{0:{6}} {1:{7}} {2:{8}} {3:>{9}} {4:{10}} {5}"
_headings = ("DEVICE", "STATUS", "LAST CHANGE", "AGE", "COLLECTOR", "SERVICE")

_name_state_lookup = {
"current": ConfigStatus.Current,
"retired": ConfigStatus.Retired,
Expand Down
47 changes: 23 additions & 24 deletions Products/ZenCollector/configcache/cli/remove.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@


class RemoveOidMap(object):

description = "Remove oidmap configuration from the cache"
configs = (("store.zcml", __name__),)

Expand Down Expand Up @@ -53,7 +52,6 @@ def run(self):


class RemoveDevice(object):

description = "Delete device configurations from the cache"
configs = (("store.zcml", __name__),)

Expand Down Expand Up @@ -82,44 +80,45 @@ def run(self):
file=sys.stderr,
)
return
else:
self._devices = self._devices[0].replace("*", "")
if not self._confirm_inputs():
print("exit")
return
initialize_environment(configs=self.configs, useZope=False)
client = getRedisClient(url=getRedisUrl())
store = createObject("deviceconfigcache-store", client)
query = DeviceQuery(service=self._service, monitor=self._monitor)
self._remove(self._get(store, haswildcard))

def _get(self, store, haswildcard):
query = self._make_query(haswildcard)
results = store.query_statuses(query)
method = self._no_devices if not self._devices else self._with_devices
keys = method(results, wildcard=haswildcard)
return tuple(self._get_keys_from_results(results, haswildcard))

def _remove(self, store, keys):
store.remove(*keys)
count = len(keys)
print(
"deleted %d device configuration%s"
% (count, "" if count == 1 else "s")
)

def _no_devices(self, results, wildcard=False):
return tuple(status.key for status in results)

def _with_devices(self, results, wildcard=False):
if wildcard:
predicate = self._check_wildcard
else:
predicate = self._check_list

return tuple(
status.key for status in results if predicate(status.key.device)
def _make_query(self, haswildcard):
if haswildcard:
return DeviceQuery(
service=self._service,
monitor=self._monitor,
device=self._devices[0],
)
return DeviceQuery(service=self._service, monitor=self._monitor)

def _get_keys_from_results(self, results, haswildcard):
if not self._devices or haswildcard:
return (status.key for status in results)
return (
status.key
for status in results
if status.key.device in self._devices
)

def _check_wildcard(self, device):
return self._devices in device

def _check_list(self, device):
return device in self._devices

def _confirm_inputs(self):
if self._devices:
return True
Expand Down
6 changes: 3 additions & 3 deletions Products/ZenCollector/configcache/cli/show.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,9 @@ def run(self):
store = createObject("deviceconfigcache-store", client)
results, err = _query_cache(
store,
service="*{}*".format(self._service),
monitor="*{}*".format(self._monitor),
device="*{}*".format(self._device),
service=self._service,
monitor=self._monitor,
device=self._device,
)
if results:
for cls in set(unjellyableRegistry.values()):
Expand Down
93 changes: 51 additions & 42 deletions Products/ZenCollector/configcache/cli/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,45 +121,20 @@ def add_arguments(parser, subparsers):
subp.set_defaults(factory=StatsDevice)

def __init__(self, args):
stats = []
for statId in getattr(args, "statistic", StatsDevice._statistics):
if statId == "count":
stats.append(CountStat)
elif statId == "avg_age":
stats.append(AverageAgeStat)
elif statId == "median_age":
stats.append(MedianAgeStat)
elif statId == "min_age":
stats.append(MinAgeStat)
elif statId == "max_age":
stats.append(MaxAgeStat)
self._groups = []
for groupId in getattr(args, "group", StatsDevice._groups):
if groupId == "collector":
self._groups.append(MonitorGroup(stats))
elif groupId == "device":
try:
# DeviceGroup doesn't want CountStat
posn = stats.index(CountStat)
except ValueError:
# Not found, so don't worry about it
dg_stats = stats
pass
else:
# Found, replace it with UniqueCountStat
dg_stats = list(stats)
dg_stats[posn] = UniqueCountStat
self._groups.append(DeviceGroup(dg_stats))
if groupId == "service":
self._groups.append(ServiceGroup(stats))
elif groupId == "status":
self._groups.append(StatusGroup(stats))
stats = [
_name_stat_map.get(statId)
for statId in getattr(args, "statistic", StatsDevice._statistics)
]
self._groups = [
_make_statgroup(groupId, stats)
for groupId in getattr(args, "group", StatsDevice._groups)
]
if args.format == "tables":
self._format = TablesOutput()
elif args.format == "json":
self._format = JSONOutput()
self._monitor = "*{}*".format(args.collector).replace("***", "*")
self._service = "*{}*".format(args.service).replace("***", "*")
self._monitor = args.collector
self._service = args.service
self._devices = getattr(args, "device", [])

def run(self):
Expand All @@ -174,19 +149,19 @@ def run(self):
client = getRedisClient(url=getRedisUrl())
store = createObject("deviceconfigcache-store", client)

if len(self._devices) == 1:
if haswildcard:
query = DeviceQuery(self._service, self._monitor, self._devices[0])
else:
query = DeviceQuery(self._service, self._monitor)
include = _get_device_predicate(self._devices)
included = _get_device_predicate(self._devices, haswildcard)
for key, ts in store.query_updated(query):
if not include(key.device):
if not included(key.device):
continue
for group in self._groups:
group.handle_key(key)
group.handle_timestamp(key, ts)
for status in store.query_statuses(query):
if not include(status.key.device):
if not included(status.key.device):
continue
for group in self._groups:
group.handle_status(status)
Expand All @@ -196,7 +171,41 @@ def run(self):
)


def _get_device_predicate(devices):
if len(devices) < 2:
return lambda _: True
def _make_statgroup(groupId, stats):
if groupId == "collector":
return MonitorGroup(stats)

if groupId == "device":
try:
# DeviceGroup doesn't want CountStat
posn = stats.index(CountStat)
except ValueError:
# Not found, so don't worry about it
dg_stats = stats
pass
else:
# Found, replace it with UniqueCountStat
dg_stats = list(stats)
dg_stats[posn] = UniqueCountStat
return DeviceGroup(dg_stats)

if groupId == "service":
return ServiceGroup(stats)

if groupId == "status":
return StatusGroup(stats)


_name_stat_map = {
"count": CountStat,
"avg_age": AverageAgeStat,
"median_age": MedianAgeStat,
"min_age": MinAgeStat,
"max_age": MaxAgeStat,
}


def _get_device_predicate(devices, haswildcard):
if haswildcard:
return lambda x: True
return lambda x: next((True for d in devices if x == d), False)
Empty file.
Loading

0 comments on commit 6f7e8cc

Please sign in to comment.