Skip to content

[ENH] Allow to retry 2nd build_lab phase in case VPN connection was not configured or ansible failed. #1368

Open

Description

@cichyx96

I was able to finishing building 1 phase, then without configured wireguard i started building lab (2nd phase). Naturally, ansible was not able to connect to instances and failed in that case web app was showing it's in progress (hang) and it only allows to Abort. Once aborted the only option is to Destroy env, it would be handy if I could retry 2nd phase from UI.

Steps to reproduce:

  • complete 1st build phase with web app
  • do not configure VPN
  • run 2nd build phase with web app

Activity

  1. P4T12ICK commented on Feb 13, 2026

    @P4T12ICK
    Collaborator

    Great point. I will work on it.

  2. janderik commented on Jul 22, 2026

    @janderik

    Rather than destroying everything and rebuilding from scratch, a more resilient approach would be to track build phase state and allow targeted re-runs:

    1. Track phase state with a simple state machine:

    class BuildPhase(Enum):
        NOT_STARTED = "not_started"
        IN_PROGRESS = "in_progress"
        COMPLETED = "completed"
        FAILED = "failed"
    
    class BuildState:
        def __init__(self, state_file='build_state.json'):
            self.phases = {phase: BuildPhase.NOT_STARTED for phase in BuildPhase}
            self.state_file = state_file
    
        def mark_complete(self, phase):
            self.phases[phase] = BuildPhase.COMPLETED
            self.save()
    
        def mark_failed(self, phase):
            self.phases[phase] = BuildPhase.FAILED
            self.save()
    
        def failed_phase(self):
            for phase, status in self.phases.items():
                if status == BuildPhase.FAILED:
                    return phase
            return None

    2. Use Terraform's -target flag for partial re-runs:
    When resuming, only target the failed phase's resources instead of running terraform apply on everything:

    def resume_build(self):
        failed = self.build_state.failed_phase()
        if failed:
            targets = self.get_terraform_targets_for_phase(failed)
            target_args = ' '.join(f'-target={t}' for t in targets)
            run_command(f'terraform apply {target_args} -auto-approve')

    3. Separate phase tracking from resource destruction — keep the state file alongside terraform.tfstate so that attack_range destroy only removes resources for a specific phase if --phase is passed, rather than nuking the entire environment.

    This way, a user who hits a failure in phase 2 can resume from phase 2 without re-running (and potentially re-paying for) phase 1 resources.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions