Skip to content

Commit 002d45d

Browse files
Format
1 parent fa51683 commit 002d45d

9 files changed

Lines changed: 66 additions & 39 deletions

File tree

leverage/modules/auth.py

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ def authenticate(command):
131131
def some_command(tf: TFRunner, paths: PathsHandler, args):
132132
# command logic
133133
"""
134+
134135
@wraps(command)
135136
def new_command(*args, **kwargs):
136137
ctx = click.get_current_context()
@@ -251,6 +252,7 @@ def refresh_layer_credentials(paths: PathsHandler):
251252
)
252253
logger.info(f"Credentials for {account_name} account written successfully.")
253254

255+
254256
def refresh_layer_credentials_mfa(paths: PathsHandler):
255257
tf_profile, raw_profiles = get_profiles(paths)
256258
config_updater = ConfigUpdater()
@@ -271,7 +273,11 @@ def refresh_layer_credentials_mfa(paths: PathsHandler):
271273
layer_profile = tf_profile if raw_profile in ("${var.profile}", "each.value.profile") else None
272274

273275
# replace variables with their corresponding values
274-
profile_name = raw_profile.replace("${var.profile}", tf_profile).replace("${var.project}", paths.project).replace("each.value.profile", tf_profile)
276+
profile_name = (
277+
raw_profile.replace("${var.profile}", tf_profile)
278+
.replace("${var.project}", paths.project)
279+
.replace("each.value.profile", tf_profile)
280+
)
275281

276282
# if layer_profile wasn't set, use profile_name
277283
if layer_profile is None:
@@ -286,14 +292,17 @@ def refresh_layer_credentials_mfa(paths: PathsHandler):
286292
raise ExitError(
287293
40,
288294
f"Credentials for profile {profile_name} have not been properly configured. Please check your configuration.\n"
289-
f"Check the following link for possible solutions: https://leverage.binbash.co/user-guide/troubleshooting/credentials/")
290-
295+
f"Check the following link for possible solutions: https://leverage.binbash.co/user-guide/troubleshooting/credentials/",
296+
)
297+
291298
cache_file = paths.aws_cache_dir / profile_name
292299
if cache_file.exists():
293300
logger.debug(f"Found cached credentials in {cache_file}.")
294301
cached_credentials = json.loads(cache_file.read_text())
295-
296-
expiration = datetime.strptime(cached_credentials.get("Expiration"), "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=tzutc())
302+
303+
expiration = datetime.strptime(cached_credentials.get("Expiration"), "%Y-%m-%dT%H:%M:%SZ").replace(
304+
tzinfo=tzutc()
305+
)
297306
renewal = datetime.now(tzutc()) + timedelta(seconds=(30 * 60))
298307
if renewal < expiration:
299308
logger.info("Using cached credentials.")
@@ -302,10 +311,7 @@ def refresh_layer_credentials_mfa(paths: PathsHandler):
302311
else:
303312
logger.debug("No cached credentials found.")
304313

305-
client_session = boto3.Session(
306-
botocore_session=session,
307-
profile_name=source_profile
308-
)
314+
client_session = boto3.Session(botocore_session=session, profile_name=source_profile)
309315
client = client_session.client("sts")
310316
credentials = None
311317
for _ in range(3):
@@ -315,7 +321,9 @@ def refresh_layer_credentials_mfa(paths: PathsHandler):
315321
raise ExitError(1, "Aborted by user.")
316322

317323
try:
318-
logger.debug(f"Assuming role {role_arn} for {profile_name} profile with serial {mfa_serial} and token code {mfa_token_code}")
324+
logger.debug(
325+
f"Assuming role {role_arn} for {profile_name} profile with serial {mfa_serial} and token code {mfa_token_code}"
326+
)
319327
credentials = client.assume_role(
320328
RoleArn=role_arn,
321329
SourceIdentity=source_profile,
@@ -342,15 +350,15 @@ def refresh_layer_credentials_mfa(paths: PathsHandler):
342350
elif error.response["Error"]["Code"] == "ExpiredToken":
343351
logger.error("Token has expired. Please try again.")
344352
continue
345-
elif error.response["Error"]["Code"] == "ValidationError" and "Invalid length for parameter TokenCode" in error.response["Error"]["Message"]:
353+
elif (
354+
error.response["Error"]["Code"] == "ValidationError"
355+
and "Invalid length for parameter TokenCode" in error.response["Error"]["Message"]
356+
):
346357
logger.error("Invalid token length, it must be 6 digits long. Please try again.")
347358
continue
348359
elif "An error occurred" in error.response["Error"]["Message"]:
349-
raise ExitError(
350-
50,
351-
f"Error assuming role: {error}"
352-
)
353-
360+
raise ExitError(50, f"Error assuming role: {error}")
361+
354362
if credentials is None:
355363
raise ExitError(60, "Failed to get credentials after 3 attempts. Please try again later.")
356364

leverage/modules/kubectl.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,10 @@ def kubectl(context, state, args):
5353
)
5454

5555
authenticate = pass_paths(lambda paths: perform_authentication(paths))
56-
_handle_subcommand(
57-
context=context, runner=state.runner, args=args, pre_invocation_callback=authenticate
58-
)
56+
_handle_subcommand(context=context, runner=state.runner, args=args, pre_invocation_callback=authenticate)
5957

6058

61-
def _configure(environment: dict, ci: ClusterInfo = None,layer_path: Path = None):
59+
def _configure(environment: dict, ci: ClusterInfo = None, layer_path: Path = None):
6260
"""
6361
Add the given EKS cluster configuration to the .kube/ files.
6462
"""

leverage/modules/runner.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,15 +95,23 @@ def run(
9595
logger.debug(f"Working directory: {working_dir or Path.cwd()}")
9696
logger.debug(f"Additional environment variables: {merged_env_vars}")
9797

98-
process = subprocess.run(command, env=env, cwd=working_dir, capture_output=not interactive, text=not interactive)
98+
process = subprocess.run(
99+
command, env=env, cwd=working_dir, capture_output=not interactive, text=not interactive
100+
)
99101

100102
if raises and not interactive and process.returncode:
101-
raise ExitError(process.returncode, f"Command execution failed: {process.stderr.strip()}")
103+
raise ExitError(process.returncode, f"Command execution failed: {process.stderr.strip()}")
102104

103-
return process.returncode if interactive else (process.returncode, process.stdout.strip(), process.stderr.strip())
105+
return (
106+
process.returncode if interactive else (process.returncode, process.stdout.strip(), process.stderr.strip())
107+
)
104108

105109
def exec(
106-
self, *args: str, env_vars: Optional[Dict[str, str]] = None, working_dir: Optional[Path] = None, raises: bool = True
110+
self,
111+
*args: str,
112+
env_vars: Optional[Dict[str, str]] = None,
113+
working_dir: Optional[Path] = None,
114+
raises: bool = True,
107115
) -> Tuple[int, str, str]:
108116
"""
109117
Execute command with the binary in non-interactive mode (captures output).

leverage/modules/tfrunner.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,13 @@ def run(
7070
"""
7171
return super().run(*args, env_vars=env_vars, working_dir=working_dir, raises=raises)
7272

73-
def exec(self, *args: str, env_vars: Optional[Dict[str, str]] = None, working_dir: Optional[Path] = None, raises: bool = False):
73+
def exec(
74+
self,
75+
*args: str,
76+
env_vars: Optional[Dict[str, str]] = None,
77+
working_dir: Optional[Path] = None,
78+
raises: bool = False,
79+
):
7480
"""
7581
Execute the Terraform/OpenTofu binary in non-interactive mode (captures output).
7682

leverage/modules/utils.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@ def _handle_subcommand(
3636
pre_invocation_callback()
3737
exit_code = runner.run(*args)
3838
raise Exit(exit_code)
39-
39+
4040
subcommand = context.command.commands.get(subcommand)
4141
# Check that the subcommand arguments are valid
42-
subcommand.make_context(info_name=subcommand.name, args=list(args)[args.index(subcommand.name) + 1:], parent=context)
42+
subcommand.make_context(
43+
info_name=subcommand.name, args=list(args)[args.index(subcommand.name) + 1 :], parent=context
44+
)
4345
# Invoke wrapped command
4446
if not subcommand.params:
4547
context.invoke(subcommand)

leverage/path.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ def get_build_script_path(filename="build.py"):
129129
cur_path = cur_path.parent
130130

131131

132-
class PathsHandler: # TODO: Turn this class into a something that represents a leverage project
132+
class PathsHandler: # TODO: Turn this class into a something that represents a leverage project
133133
COMMON_TF_VARS = "common.tfvars"
134134
ACCOUNT_TF_VARS = "account.tfvars"
135135
BACKEND_TF_VARS = "backend.tfvars"
@@ -200,7 +200,7 @@ def aws_config_file(self):
200200
@property
201201
def aws_credentials_file(self):
202202
return self.aws_credentials_dir / "credentials"
203-
203+
204204
@property
205205
def aws_cache_dir(self):
206206
return self.aws_credentials_dir / "cache"

tests/conftest.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -121,10 +121,7 @@ def leverage_project(tmp_path):
121121
# Create account/config
122122
account_config = account_dir / "config"
123123
account_config.mkdir()
124-
(account_config / "account.tfvars").write_text(
125-
'environment = "account"\n'
126-
'sso_role = "test-sso-role"\n'
127-
)
124+
(account_config / "account.tfvars").write_text('environment = "account"\n' 'sso_role = "test-sso-role"\n')
128125
(account_config / "backend.tfvars").write_text(
129126
'profile = "bb-account-profile"\n'
130127
'bucket = "bb-account-terraform-backend"\n'
@@ -153,11 +150,11 @@ def leverage_project(tmp_path):
153150
security_base.mkdir()
154151
(security_base / "security-base.tf").write_text("# Security base configuration\n")
155152
(security_base / "config.tf").write_text(
156-
'terraform {\n'
153+
"terraform {\n"
157154
' backend "s3" {\n'
158155
' key = "account/us-east-1/security-base/terraform.tfstate"\n'
159-
' }\n'
160-
'}\n'
156+
" }\n"
157+
"}\n"
161158
)
162159
(security_base / "backend.tfvars").write_text(
163160
'profile = "bb-account-profile"\n'
@@ -168,6 +165,7 @@ def leverage_project(tmp_path):
168165

169166
return root
170167

168+
171169
@pytest.fixture
172170
def leverage_runner(monkeypatch):
173171
"""
@@ -218,6 +216,7 @@ def runner(leverage_directory):
218216

219217
return runner
220218

219+
221220
@pytest.fixture
222221
def leverage_context(leverage_project, monkeypatch):
223222
def context(verbose=True, build_script_name="build.py"):
@@ -238,4 +237,4 @@ def context(verbose=True, build_script_name="build.py"):
238237

239238
return click.Context(command=click.Command("leverage"), obj=state)
240239

241-
return context
240+
return context

tests/test_modules/test_kubectl.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from leverage import leverage
88
from leverage.modules.kubectl import _scan_clusters, ClusterInfo
99

10+
1011
def test_scan_clusters():
1112
"""
1213
Test that we can find valid metadata.yaml presents in the down the path of the filesystem tree where we are staying.
@@ -38,7 +39,9 @@ def test_discover(leverage_project):
3839
}
3940
cli_runner = CliRunner()
4041
with cli_runner.isolated_filesystem(leverage_project) as leverage_project_folder:
41-
with patch("leverage.modules.kubectl._scan_clusters", return_value=[(leverage_project_folder, mocked_cluster_data)]) as mkd_scan_clusters:
42+
with patch(
43+
"leverage.modules.kubectl._scan_clusters", return_value=[(leverage_project_folder, mocked_cluster_data)]
44+
) as mkd_scan_clusters:
4245
with patch("simple_term_menu.TerminalMenu") as mkd_show:
4346
mkd_show.return_value.show.return_value = 0 # simulate choosing the first result
4447
with patch("leverage.modules.kubectl._configure") as mkd_configure:

tests/test_modules/test_tf.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ def test_init_with_args(leverage_project, leverage_runner):
4646

4747
assert mocked_run.call_args_list[0][0][0] == "init"
4848
assert mocked_run.call_args_list[0][0][1] == "-migrate-state"
49-
assert mocked_run.call_args_list[0][0][2] == f"-backend-config={leverage_project / 'account' / 'config' / 'backend.tfvars'}"
49+
assert (
50+
mocked_run.call_args_list[0][0][2]
51+
== f"-backend-config={leverage_project / 'account' / 'config' / 'backend.tfvars'}"
52+
)
5053

5154

5255
@pytest.mark.parametrize(

0 commit comments

Comments
 (0)