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

Add execute --restart-request option #154

Merged
merged 4 commits into from
Jan 3, 2025
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
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,45 @@ request:
when: null
```

#### Option `--continue`, `-C`

This option is useful e.g. when a user wants to continue with a previously terminated `newa execute` session. It is assumed that a user will use this option together with `--state-dir` option because `newa` is going to re-use former data.

Example:

```
$ newa event --compose CentOS-Stream-9 jira --job-recipe path/to/recipe.yaml schedule execute report
Using --state-dir /var/tmp/newa/run-123
...
Ctrl+C # during the execute step
$ newa --state-dir /var/tmp/newa/run-123 execute --continue report
```

#### Option `--no-wait`

This option instructs `newa` to not to wait for TF request finishing. It is expected that a user will eventually follow up on this `newa` session later.

Example:

```
$ newa event --compose CentOS-Stream-9 jira --job-recipe path/to/recipe.yaml schedule execute --no-wait
Using --state-dir /var/tmp/newa/run-123
...
$ newa --state-dir /var/tmp/newa/run-123 execute --continue report
```

#### Option `--restart-request`, `-R`
This option can be used to reschedule specific NEWA request, specified by the request ID (e.g. `--restart-request REQ-1.2.1`). This option can be used multiple times. Implies `--continue`.

Example:
```
newa --prev-state-dir execute -R REQ-1.2.1 -R REQ-2.2.2 report
```

#### Option `--restart-result`
This option can be used to reschedule NEWA request that have ended with a particular result - `passed, failed, error`. For example, `--restart-result error`. This option can be used multiple times. Implies `--continue`.


### Subcommand `report`

This subcommand updates RP launch with recipe status and updates the respective Jira issue with a comment and a link to RP launch containing all test results.
Expand Down
2 changes: 2 additions & 0 deletions newa/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1733,7 +1733,9 @@ class CLIContext:
timestamp: str = ''
continue_execution: bool = False
no_wait: bool = False
restart_request: list[str] = field(factory=list)
restart_result: list[str] = field(factory=list)
new_state_dir: bool = False

def enter_command(self, command: str) -> None:
self.logger.handlers[0].formatter = logging.Formatter(
Expand Down
46 changes: 41 additions & 5 deletions newa/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,11 +200,13 @@ def main(click_context: click.Context,

ctx.logger.info(f'Using --state-dir={ctx.state_dirpath}')
if not ctx.state_dirpath.exists():
ctx.new_state_dir = True
ctx.logger.debug(f'State directory {ctx.state_dirpath} does not exist, creating...')
ctx.state_dirpath.mkdir(parents=True)

# extract YAML files from the given archive to state-dir
if extract_state_dir:
ctx.new_state_dir = False
if re.match('^https?://', extract_state_dir):
data = urllib.request.urlopen(extract_state_dir).read()
tf = tarfile.open(fileobj=io.BytesIO(data), mode='r:*')
Expand Down Expand Up @@ -938,16 +940,25 @@ def cmd_cancel(ctx: CLIContext) -> None:
)
@click.option(
'--continue',
'-C',
'_continue',
is_flag=True,
default=False,
help='Continue with the previous execution, expects --state-dir usage.',
)
@click.option('--restart-request',
'-R',
default=[],
multiple=True,
help=('Restart NEWA request with the given request ID. '
'Can be specified multiple times. Implies --continue. '
'Example: --restart-request REQ-1.2.1'),
)
@click.option('--restart-result',
default=[],
multiple=True,
help=('Restart finished TF jobs having the specified result.'
'Can be specified multiple times. Implies --continue.'
help=('Restart finished TF jobs having the specified result. '
'Can be specified multiple times. Implies --continue. '
'Example: --restart-result error'),
)
@click.option(
Expand All @@ -962,15 +973,25 @@ def cmd_execute(
workers: int,
_continue: bool,
no_wait: bool,
restart_request: list[str],
restart_result: list[str]) -> None:
ctx.enter_command('execute')
ctx.continue_execution = _continue
ctx.no_wait = no_wait

if restart_request:
ctx.restart_request = restart_request
ctx.continue_execution = True

if restart_result:
ctx.restart_result = restart_result
ctx.continue_execution = True

if ctx.continue_execution and ctx.new_state_dir:
ctx.logger.error(
'NEWA state-dir was not specified! Use --state-dir or similar option.')
sys.exit(1)

# initialize RP connection
rp_project = ctx.settings.rp_project
rp_url = ctx.settings.rp_url
Expand Down Expand Up @@ -1084,6 +1105,13 @@ def cmd_execute(
rp.finish_launch(launch_uuid)


def test_patterns_match(s: str, patterns: list[str]) -> tuple[bool, str]:
for pattern in patterns:
if s.strip() == pattern.strip():
return (True, pattern)
return (False, '')


def worker(ctx: CLIContext, schedule_file: Path) -> None:

# modify log message so it contains name of the processed file
Expand All @@ -1106,11 +1134,14 @@ def worker(ctx: CLIContext, schedule_file: Path) -> None:
if execute_job.execution.result and execute_job.execution.result in ctx.restart_result:
log(f'Restarting request {execute_job.request.id}'
f' with result {execute_job.execution.result}')
elif ctx.restart_request:
(match, pattern) = test_patterns_match(execute_job.request.id, ctx.restart_request)
if match:
log(f'Restarting request {execute_job.request.id} with ID matching {pattern}')
else:
start_new_request = False
else:
tf_request = TFRequest(api=execute_job.execution.request_api,
uuid=execute_job.execution.request_uuid)
start_new_request = False
skip_initial_sleep = True

if start_new_request:
log('initiating TF request')
Expand Down Expand Up @@ -1138,6 +1169,11 @@ def worker(ctx: CLIContext, schedule_file: Path) -> None:
command=command),
)
ctx.save_execute_job('execute-', execute_job)
else:
log(f'Re-using existing request {execute_job.request.id}')
tf_request = TFRequest(api=execute_job.execution.request_api,
uuid=execute_job.execution.request_uuid)
skip_initial_sleep = True

if ctx.no_wait:
log(f'Not waiting for TF request {tf_request.uuid} to finish (--no-wait set).')
Expand Down
Loading