Skip to content

Commit

Permalink
Merge pull request #4545 from zenoss/bugfix/ZEN-35054.6x
Browse files Browse the repository at this point in the history
Remove implicit wildcards from configcache commands.
  • Loading branch information
jpeacock-zenoss authored Sep 13, 2024
2 parents 02cb53e + 6f7e8cc commit 3ca4225
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 3ca4225

Please sign in to comment.