Skip to content

Commit 05dfde5

Browse files
committed
chore: fix up utils, secrets, provisioner
1 parent 7ae3858 commit 05dfde5

6 files changed

Lines changed: 73 additions & 37 deletions

File tree

juju/provisioner.py

Lines changed: 15 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -317,33 +317,26 @@ def _run_configure_script(self, script):
317317
:raises: :class:`paramiko.ssh_exception.AuthenticationException`
318318
if the upload fails
319319
"""
320-
_, tmpFile = tempfile.mkstemp()
321-
with open(tmpFile, "w") as f:
322-
f.write(script)
320+
with tempfile.NamedTemporaryFile("w") as tmp_file:
321+
tmp_file.write(script)
322+
tmp_file.flush()
323323

324-
try:
325324
# get ssh client
326325
ssh = self._get_ssh_client(
327326
self.host,
328327
"ubuntu",
329328
self.private_key_path,
330329
)
331330

332-
# copy the local copy of the script to the remote machine
333-
sftp = paramiko.SFTPClient.from_transport(ssh.get_transport())
334-
sftp.put(
335-
tmpFile,
336-
tmpFile,
337-
)
338-
339-
# run the provisioning script
340-
stdout, stderr = self._run_command(
341-
ssh,
342-
f"sudo /bin/bash {tmpFile}",
343-
)
344-
345-
except paramiko.ssh_exception.AuthenticationException as e:
346-
raise e
347-
finally:
348-
os.remove(tmpFile)
349-
ssh.close()
331+
try:
332+
# copy the local copy of the script to the remote machine
333+
sftp = paramiko.SFTPClient.from_transport(ssh.get_transport())
334+
sftp.put(tmp_file.name, tmp_file.name)
335+
336+
# run the provisioning script
337+
_stdout, _stderr = self._run_command(
338+
ssh,
339+
f"sudo /bin/bash {tmp_file.name}",
340+
)
341+
finally:
342+
ssh.close()

juju/secrets.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Copyright 2023 Canonical Ltd.
22
# Licensed under the Apache V2, see LICENCE file for details.
33

4-
"""This module contains utility logic for secrets such as reading secret data from yaml and creating data bag for secrets."""
4+
"""A utility module for secrets such as reading secret data from yaml and creating data bag for secrets."""
55

66
import base64
77
import json

juju/status.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
# Licensed under the Apache V2, see LICENCE file for details.
33

44
import logging
5+
import warnings
56

67
from .client import client
78

@@ -53,6 +54,11 @@ async def formatted_status(model, target=None, raw=False, filters=None):
5354
:param str filters: Optional list of applications, units, or machines
5455
to include, which can use wildcards ('*').
5556
"""
57+
warnings.warn(
58+
"juju.status.formatted_status is deprecated, the implementation is likely broken",
59+
DeprecationWarning,
60+
stacklevel=1,
61+
)
5662
client_facade = client.ClientFacade.from_connection(model.connection())
5763
result_status = await client_facade.FullStatus(patterns=filters)
5864

@@ -138,10 +144,10 @@ def _print_status_units(result_status):
138144

139145
limits = "{:<15} {:<15} {:<20} {:<10} {:<15} {:<10} {:<30}"
140146
summary = ""
141-
for app_name, app in apps.items():
147+
for app in apps.values():
142148
units = app.units
143149
if units is None or len(units) == 0:
144-
next
150+
continue
145151

146152
for name, unit in units.items():
147153
addr = unit.public_address

juju/unit.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,10 @@ async def get_public_address(self):
121121
return addr
122122

123123
app_facade = client.ApplicationFacade.from_connection(self.connection)
124-
defResult = await app_facade.UnitsInfo(entities=[client.Entity(self.tag)])
125-
if defResult is not None and len(defResult.results) > 1:
124+
def_result = await app_facade.UnitsInfo(entities=[client.Entity(self.tag)])
125+
if def_result is not None and len(def_result.results) > 1:
126126
raise JujuAPIError("expected one result")
127-
return defResult.results[0].result.get("public-address", None)
127+
return def_result.results[0].result.get("public-address", None)
128128

129129
async def resolved(self, retry=False):
130130
"""Mark unit errors resolved.
@@ -411,7 +411,7 @@ async def is_leader_from_status(self):
411411
if not is_subordinate:
412412
continue
413413

414-
for key, unit in app_data.units.items():
414+
for unit in app_data.units.values():
415415
if unit.subordinates and unit.subordinates.get(self.name):
416416
is_leader = unit.subordinates[self.name].leader
417417
return is_leader if is_leader else False

juju/utils.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,15 @@ class IdQueue:
9696
def __init__(self, maxsize=0):
9797
self._queues = defaultdict(partial(jasyncio.Queue, maxsize))
9898

99-
async def get(self, id):
100-
value = await self._queues[id].get()
101-
del self._queues[id]
99+
async def get(self, id_):
100+
value = await self._queues[id_].get()
101+
del self._queues[id_]
102102
if isinstance(value, Exception):
103103
raise value
104104
return value
105105

106-
async def put(self, id, value):
107-
await self._queues[id].put(value)
106+
async def put(self, id_, value):
107+
await self._queues[id_].put(value)
108108

109109
async def put_all(self, value):
110110
for queue in self._queues.values():
@@ -176,7 +176,7 @@ async def run_with_interrupt(task, *events, log=None):
176176
task = jasyncio.create_task_with_handler(task, "tmp", log)
177177
event_tasks = [jasyncio.ensure_future(event.wait()) for event in events]
178178
done, pending = await jasyncio.wait(
179-
[task] + event_tasks, return_when=jasyncio.FIRST_COMPLETED
179+
[task, *event_tasks], return_when=jasyncio.FIRST_COMPLETED
180180
)
181181
for f in pending:
182182
f.cancel() # cancel unfinished tasks
@@ -194,6 +194,8 @@ async def run_with_interrupt(task, *events, log=None):
194194

195195

196196
class Addrs(univ.SequenceOf):
197+
"""Internal."""
198+
197199
componentType = char.PrintableString()
198200

199201

@@ -215,7 +217,8 @@ class RegistrationInfo(univ.Sequence):
215217
def generate_user_controller_access_token(
216218
username, controller_endpoints, secret_key, controller_name
217219
):
218-
""" " Implement in python what is currently done in GO
220+
"""Implement in python what is currently done in GO.
221+
219222
https://github.com/juju/juju/blob/a5ab92e/cmd/juju/user/utils.go#L16
220223
221224
:param username: name of the user to register
@@ -502,7 +505,9 @@ def user_requested(series_arg, supported_series, force):
502505
def series_selector(
503506
series_arg="", charm_url=None, model_config=None, supported_series=[], force=False
504507
):
505-
"""series_selector corresponds to the CharmSeries() in
508+
"""Select series to deploy on.
509+
510+
series_selector corresponds to the CharmSeries() in
506511
https://github.com/juju/juju/blob/develop/core/charm/series_selector.go
507512
508513
determines what series to use with a charm.

pyproject.toml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,12 +83,44 @@ select = [
8383
"D",
8484
]
8585
ignore = [
86+
# juju.secrets is a part of public API, can't rename or remove it now
87+
"A005",
8688
# FIXME: change the codegen to remove the schema from auto-generate classes
8789
"RUF012",
8890
# FIXME: change the codegen to insert a period at the end of the docstring
8991
"D415",
92+
# FIXME: quite a few mutable default arguments should be refactored
93+
"B006",
94+
# FIXME: raise from
95+
"B904",
96+
# FIXME: a bunch of missing docstrings
97+
"D100",
98+
"D101",
99+
"D102",
100+
"D103",
101+
"D105",
102+
"D107",
103+
# FIXME: a bunch of docstrings without headlines
104+
"D205",
90105
# FIXME: manually rewrite docstring headlines to git on one line
91106
"D400",
107+
"D401",
108+
# FIXME: run `uvx docformatter` to reformat docstrings
109+
# Manual fixes are needed for string literals and f-strings
110+
"E501",
111+
# FIXME: there are some mixedCase members
112+
"N815",
113+
# try-except in a loop; hardly an issue in async functions
114+
"PERF203",
115+
# FIXME: validate that we use yaml safely
116+
"S506",
117+
# FIXME: try/except: pass is OK
118+
# Note: swallowing CancelledError is most likely a bug
119+
"SIM105",
120+
# FIXME: refactor if-else
121+
"SIM108",
122+
# % format is just fine
123+
"UP031",
92124
]
93125

94126
[tool.ruff.lint.per-file-ignores]

0 commit comments

Comments
 (0)