Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ndusan/release fixes #549

Merged
merged 2 commits into from
Oct 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions taf/tools/cli/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import click
import sys

from functools import partial, wraps
from logging import ERROR
Expand All @@ -23,6 +24,7 @@ def wrapper(*args, **kwargs):
except Exception as e:
if is_run_from_python_executable():
click.echo(f"An error occurred: {e}")
sys.exit(1)
else:
raise e

Expand Down
1 change: 1 addition & 0 deletions taf/tools/cli/taf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"metadata": "taf.tools.metadata.attach_to_group",
"roles": "taf.tools.roles.attach_to_group",
"yubikey": "taf.tools.yubikey.attach_to_group",
"scripts": "taf.tools.scripts.attach_to_group",
})
@click.version_option()
def taf():
Expand Down
50 changes: 50 additions & 0 deletions taf/tools/scripts/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import click

from pathlib import Path
from taf.log import taf_logger

import ast


def extract_global_variables(filename):
"""
Utility function to extract global variables from a Python file.
This is necessary because we want to execute the Python file in a separate process, and we need to pass the global variables to it.
TAF currently uses this when executing lifecycle handler scripts from an executable built from pyinstaller, which uses a frozen sys module.
"""
with open(filename, "r") as f:
tree = ast.parse(f.read(), filename=filename)

global_vars = {}

for node in ast.walk(tree):
try:
if isinstance(node, ast.Assign):
for target in node.targets:
if isinstance(target, ast.Name):
# We only extract simple variable assignments, not function definitions or imports
if isinstance(node.value, (ast.Constant, ast.List, ast.Dict, ast.Tuple, ast.Constant)):
# Convert the AST expression to Python objects
global_vars[target.id] = ast.literal_eval(node.value)
except Exception as e:
taf_logger.debug(f"Error extracting global variables from {filename}: {e}")
pass

global_vars["__file__"] = filename

return global_vars


def execute_command():
@click.command(help="Executes an arbitrary python script")
@click.argument("script_path")
def execute(script_path):
script_path = Path(script_path).resolve()
global_scopes = extract_global_variables(script_path)
with open(script_path, "r") as f:
exec(f.read(), global_scopes) # nosec: B102
return execute


def attach_to_group(group):
group.add_command(execute_command(), name='execute')
8 changes: 6 additions & 2 deletions taf/updater/lifecycle_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,12 @@ def execute_scripts(auth_repo, last_commit, scripts_rel_path, data, scripts_root
if Path(script_path).suffix == ".py":
if getattr(sys, "frozen", False):
# we are running in a pyinstaller bundle
taf_logger.warning(
"Warning: executing scripts from pyinstaller executable is not supported"
output = run(
f"{sys.executable}",
"scripts",
"execute",
script_path,
input=json_data,
)
else:
output = run(f"{sys.executable}", script_path, input=json_data)
Expand Down