Skip to content

Commit 4f27ff3

Browse files
authored
Merge pull request #4 from thobiast/dev
Dev
2 parents fccb1a1 + 23baeb2 commit 4f27ff3

2 files changed

Lines changed: 160 additions & 120 deletions

File tree

src/openstack_lb_info/loadbalancer_info.py

Lines changed: 148 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,56 @@ def __init__(self, openstack_api, lb, details, formatter):
4040
self.lb_tree = None
4141
self.openstack_api = openstack_api
4242

43+
def _add_all_attr_to_tree(self, obj, tree):
44+
"""
45+
Add all attributes of an object to a tree.
46+
47+
This function iterates through all the attributes of a given Python object and
48+
adds them to a Rich tree. Each attribute is displayed in the
49+
format "attribute_name: value".
50+
51+
Args:
52+
obj (object): The object whose attributes are to be added.
53+
tree: The tree to which the attributes will be added.
54+
"""
55+
obj_dict = obj.to_dict()
56+
for attr in sorted(obj_dict):
57+
value = obj_dict[attr]
58+
content = f"{attr}: {value}"
59+
self.formatter.add_to_tree(tree, content, highlight=True)
60+
61+
# pylint: disable=too-many-arguments
62+
def _retrieve_and_add_to_tree(self, label, resource_id, retrieve_method, tree, format_fn):
63+
"""
64+
Generic helper to retrieve a resource, add its formatted information to a tree.
65+
66+
This method displays a status message while retrieving a resource via the provided API call.
67+
If the resource is found, its formatted information is added to the specified tree node. In
68+
detailed mode, all resource attributes are appended to the tree node as well.
69+
70+
Args:
71+
label (str): The resource label (e.g., "Listener, "Health Monitor", ...).
72+
resource_id (str): The ID of the resource to retrieve.
73+
retrieve_method (Callable): The API method used to retrieve the resource.
74+
tree: The tree node to which the resource's info will be added.
75+
format_fn (Callable): A function that takes the resource and returns a formatted string.
76+
77+
Returns:
78+
The retrieved resource object if found; otherwise, returns None.
79+
"""
80+
with self.formatter.status(f"Getting {label} details id [b]{resource_id}[/b]"):
81+
resource = retrieve_method(resource_id)
82+
83+
if resource:
84+
resource_tree = self.formatter.add_to_tree(tree, format_fn(resource))
85+
if self.details:
86+
self._add_all_attr_to_tree(resource, resource_tree)
87+
return resource
88+
89+
self.formatter.add_to_tree(tree, f"[b green]{label}:[/] None")
90+
91+
return None
92+
4393
def create_lb_tree(self):
4494
"""
4595
Create a tree representing Load Balancer information.
@@ -55,71 +105,43 @@ def create_lb_tree(self):
55105
f"tags:[magenta]{self.lb.tags}[/]"
56106
)
57107
if self.details:
58-
self.add_all_attr_to_tree(self.lb, self.lb_tree)
108+
self._add_all_attr_to_tree(self.lb, self.lb_tree)
59109

60110
return self.lb_tree
61111

62-
def add_health_monitor_info(self, pool_tree, health_monitor_id):
63-
"""
64-
Add information about a Health Monitor to a Pool tree.
65-
66-
Args:
67-
pool_tree: The tree representing the Pool.
68-
health_monitor_id (str): The ID of the Health Monitor.
69-
70-
Returns:
71-
None
72-
"""
73-
with self.formatter.status(f"Getting health monitor details id [b]{health_monitor_id}[/b]"):
74-
health_monitor = self.openstack_api.retrieve_health_monitor(health_monitor_id)
75-
76-
if health_monitor:
77-
health_monitor_tree = self.formatter.add_to_tree(
78-
pool_tree,
79-
f"[b green]Health Monitor:[/] [b white]{health_monitor.id}[/] "
80-
f"type:[magenta]{health_monitor.type}[/magenta] "
81-
f"http_method:[magenta]{health_monitor.http_method}[/magenta] "
82-
f"http_codes:[magenta]{health_monitor.expected_codes}[/magenta] "
83-
f"url_path:[magenta]{health_monitor.url_path}[/magenta] "
84-
f"prov_status:{self.formatter.format_status(health_monitor.provisioning_status)} "
85-
f"oper_status:{self.formatter.format_status(health_monitor.operating_status)}",
86-
)
87-
88-
if self.details:
89-
self.add_all_attr_to_tree(health_monitor, health_monitor_tree)
90-
else:
91-
self.formatter.add_to_tree(pool_tree, "[b green]Health Monitor:[/] None")
92-
93-
def add_pool_members(self, pool_tree, pool_id, pool_members):
112+
def add_listener_info(self, listener_id):
94113
"""
95-
Add information about Members of a Pool to the Pool tree.
114+
Add information about a Listener to the Load Balancer tree.
96115
97116
Args:
98-
pool_tree: The tree representing the Pool.
99-
pool_id (str): The ID of the Pool for which to retrieve Member information.
100-
pool_members (list): A list of dictionaries containing Member information,
101-
where each dictionary includes the Member's ID and additional details.
117+
listener_id (str): The ID of the Listener for which to retrieve and display
118+
information.
102119
103120
Returns:
104121
None
105122
"""
106-
for member in pool_members:
107-
with self.formatter.status(f"Getting member details id [b]{member['id']}[/b]"):
108-
os_m = self.openstack_api.retrieve_member(member["id"], pool_id)
109123

110-
member_tree = self.formatter.add_to_tree(
111-
pool_tree,
112-
f"[b green]Member:[/] [b white]{os_m.id}[/] "
113-
f"IP:[magenta]{os_m.address}[/magenta] "
114-
f"port:[magenta]{os_m.protocol_port}[/magenta] "
115-
f"weight:[magenta]{os_m.weight}[/magenta] "
116-
f"backup:[magenta]{os_m.backup}[/magenta] "
117-
f"prov_status:{self.formatter.format_status(os_m.provisioning_status)} "
118-
f"oper_status:{self.formatter.format_status(os_m.operating_status)}",
124+
def format_listener(listener):
125+
return (
126+
f"[b green]Listener:[/] [b white]{listener.id}[/] "
127+
f"([blue b]{listener.name}[/]) "
128+
f"port:[cyan]{listener.protocol}/{listener.protocol_port}[/] "
129+
f"prov_status:{self.formatter.format_status(listener.provisioning_status)} "
130+
f"oper_status:{self.formatter.format_status(listener.operating_status)}"
119131
)
120132

121-
if self.details:
122-
self.add_all_attr_to_tree(os_m, member_tree)
133+
listener = self._retrieve_and_add_to_tree(
134+
"Listener",
135+
listener_id,
136+
self.openstack_api.retrieve_listener,
137+
self.lb_tree,
138+
format_listener,
139+
)
140+
if listener:
141+
if listener.default_pool_id:
142+
self.add_pool_info(self.lb_tree, listener.default_pool_id)
143+
else:
144+
self.formatter.add_to_tree(self.lb_tree, "[b green]Pool:[/] None")
123145

124146
def add_pool_info(self, tree, pool_id):
125147
"""
@@ -132,80 +154,96 @@ def add_pool_info(self, tree, pool_id):
132154
Returns:
133155
None
134156
"""
135-
with self.formatter.status(f"Getting pool details id [b]{pool_id}[/b]"):
136-
pool = self.openstack_api.retrieve_pool(pool_id)
137-
138-
pool_tree = self.formatter.add_to_tree(
139-
tree,
140-
f"[b green]Pool:[/] [b white]{pool.id}[/] "
141-
f"protocol:[magenta]{pool.protocol}[/magenta] "
142-
f"algorithm:[magenta]{pool.lb_algorithm}[/magenta] "
143-
f"prov_status:{self.formatter.format_status(pool.provisioning_status)} "
144-
f"oper_status:{self.formatter.format_status(pool.operating_status)} ",
145-
)
146-
if self.details:
147-
self.add_all_attr_to_tree(pool, pool_tree)
148157

149-
if pool.health_monitor_id:
150-
self.add_health_monitor_info(pool_tree, pool.health_monitor_id)
151-
else:
152-
self.formatter.add_to_tree(pool_tree, "[b green]Health Monitor:[/] None")
158+
def format_pool(pool):
159+
return (
160+
f"[b green]Pool:[/] [b white]{pool.id}[/] "
161+
f"protocol:[magenta]{pool.protocol}[/magenta] "
162+
f"algorithm:[magenta]{pool.lb_algorithm}[/magenta] "
163+
f"prov_status:{self.formatter.format_status(pool.provisioning_status)} "
164+
f"oper_status:{self.formatter.format_status(pool.operating_status)}"
165+
)
153166

154-
if pool.members:
155-
self.add_pool_members(pool_tree, pool.id, pool.members)
156-
else:
157-
self.formatter.add_to_tree(pool_tree, "[b green]Member:[/] None")
167+
pool = self._retrieve_and_add_to_tree(
168+
"Pool", pool_id, self.openstack_api.retrieve_pool, tree, format_pool
169+
)
170+
if pool:
171+
if pool.health_monitor_id:
172+
self.add_health_monitor_info(tree, pool.health_monitor_id)
173+
else:
174+
self.formatter.add_to_tree(tree, "[b green]Health Monitor:[/] None")
158175

159-
def add_listener_info(self, listener_id):
176+
if pool.members:
177+
self.add_pool_members(tree, pool.id, pool.members)
178+
else:
179+
self.formatter.add_to_tree(tree, "[b green]Member:[/] None")
180+
181+
def add_health_monitor_info(self, pool_tree, health_monitor_id):
160182
"""
161-
Add information about a Listener to the Load Balancer tree.
183+
Add information about a Health Monitor to a Pool tree.
162184
163185
Args:
164-
listener_id (str): The ID of the Listener for which to retrieve and display
165-
information.
186+
pool_tree: The tree representing the Pool.
187+
health_monitor_id (str): The ID of the Health Monitor.
166188
167189
Returns:
168190
None
169191
"""
170-
with self.formatter.status(
171-
f"Getting listener details for loadbalancers "
172-
f"[b]{self.lb.id}[/b] listener: [b]{listener_id}[/b]"
173-
):
174-
listener = self.openstack_api.retrieve_listener(listener_id)
175192

176-
listener_tree = self.formatter.add_to_tree(
177-
self.lb_tree,
178-
f"[b green]Listener:[/] [b white]{listener.id}[/] "
179-
f"([blue b]{listener.name}[/]) "
180-
f"port:[cyan]{listener.protocol}/{listener.protocol_port}[/] "
181-
f"prov_status:{self.formatter.format_status(listener.provisioning_status)} "
182-
f"oper_status:{self.formatter.format_status(listener.operating_status)} ",
183-
)
184-
if self.details:
185-
self.add_all_attr_to_tree(listener, listener_tree)
193+
def format_health_monitor(hm):
194+
return (
195+
f"[b green]Health Monitor:[/] [b white]{hm.id}[/] "
196+
f"type:[magenta]{hm.type}[/magenta] "
197+
f"http_method:[magenta]{hm.http_method}[/magenta] "
198+
f"http_codes:[magenta]{hm.expected_codes}[/magenta] "
199+
f"url_path:[magenta]{hm.url_path}[/magenta] "
200+
f"prov_status:{self.formatter.format_status(hm.provisioning_status)} "
201+
f"oper_status:{self.formatter.format_status(hm.operating_status)}"
202+
)
186203

187-
if listener.default_pool_id:
188-
self.add_pool_info(listener_tree, listener.default_pool_id)
189-
else:
190-
self.formatter.add_to_tree(listener_tree, "[b green]Pool:[/] None")
204+
self._retrieve_and_add_to_tree(
205+
"Health Monitor",
206+
health_monitor_id,
207+
self.openstack_api.retrieve_health_monitor,
208+
pool_tree,
209+
format_health_monitor,
210+
)
191211

192-
def add_all_attr_to_tree(self, obj, tree):
212+
def add_pool_members(self, pool_tree, pool_id, pool_members):
193213
"""
194-
Add all attributes of an object to a tree.
195-
196-
This function iterates through all the attributes of a given Python object and
197-
adds them to a Rich tree. Each attribute is displayed in the
198-
format "attribute_name: value".
214+
Add information about Members of a Pool to the Pool tree.
199215
200216
Args:
201-
obj (object): The object whose attributes are to be added.
202-
tree: The tree to which the attributes will be added.
217+
pool_tree: The tree representing the Pool.
218+
pool_id (str): The ID of the Pool for which to retrieve Member information.
219+
pool_members (list): A list of dictionaries containing Member information,
220+
where each dictionary includes the Member's ID and additional details.
221+
222+
Returns:
223+
None
203224
"""
204-
obj_dict = obj.to_dict()
205-
for attr in sorted(obj_dict):
206-
value = obj_dict[attr]
207-
content = f"{attr}: {value}"
208-
self.formatter.add_to_tree(tree, content, highlight=True)
225+
for member in pool_members:
226+
with self.formatter.status(f"Getting member details id [b]{member['id']}[/b]"):
227+
os_m = self.openstack_api.retrieve_member(member["id"], pool_id)
228+
229+
def format_member(m):
230+
return (
231+
f"[b green]Member:[/] [b white]{m.id}[/] "
232+
f"IP:[magenta]{m.address}[/magenta] "
233+
f"port:[magenta]{m.protocol_port}[/magenta] "
234+
f"weight:[magenta]{m.weight}[/magenta] "
235+
f"backup:[magenta]{m.backup}[/magenta] "
236+
f"prov_status:{self.formatter.format_status(m.provisioning_status)} "
237+
f"oper_status:{self.formatter.format_status(m.operating_status)}"
238+
)
239+
240+
def return_member(_, os_m=os_m):
241+
# Simply return the already retrieved member.
242+
return os_m
243+
244+
self._retrieve_and_add_to_tree(
245+
"Member", member["id"], return_member, pool_tree, format_member
246+
)
209247

210248
def display_lb_info(self):
211249
"""
@@ -320,7 +358,7 @@ def add_amphora_to_tree(self, amphora):
320358
f"compute host:([magenta]{server_compute_host}[/])",
321359
)
322360
if self.details:
323-
self.add_all_attr_to_tree(amphora, amphora_tree)
361+
self._add_all_attr_to_tree(amphora, amphora_tree)
324362

325363
def display_amp_info(self):
326364
"""

src/openstack_lb_info/main.py

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -198,18 +198,20 @@ def query_openstack_lbs(openstackapi, args, formatter):
198198
list: A list of OpenStack Load Balancer objects that match the specified
199199
filters, or an empty list if no load balancers match the criteria.
200200
"""
201-
# Define filter criteria
201+
# Define filter criteria. It includes only keys with non-None values.
202202
filter_criteria = {
203-
"tags": args.tags,
204-
"availability_zone": args.availability_zone,
205-
"vip_network_id": args.vip_network_id,
206-
"vip_subnet_id": args.vip_subnet_id,
207-
"flavor_id": args.flavor_id,
208-
"vip_address": args.vip_address,
203+
k: v
204+
for k, v in {
205+
"tags": args.tags,
206+
"availability_zone": args.availability_zone,
207+
"vip_network_id": args.vip_network_id,
208+
"vip_subnet_id": args.vip_subnet_id,
209+
"flavor_id": args.flavor_id,
210+
"vip_address": args.vip_address,
211+
"id": args.id if args.id else None,
212+
}.items()
213+
if v is not None
209214
}
210-
if args.id:
211-
# Add the "id" key to the filter criteria only if specified
212-
filter_criteria["id"] = args.id
213215

214216
with formatter.status("Quering load balancers..."):
215217
filtered_lbs_tmp = openstackapi.retrieve_load_balancers(filter_criteria)

0 commit comments

Comments
 (0)