Project: sparky-rocky

Build now

Configuration

sparrowdo:
  localhost: true
  no_sudo: true
  tags: stage=main 
allow_manual_run: true  
vars:
  -
      name: repo
      type: select
      values: "%qemu_test.git.repo%"
  -
      name: branch
      type: select
      values: "%qemu_test.git.branch%"
  -
      name: use_case_repo
      values: "%qemu_test.use_case_repo%"
      type: select
  -
      name: qemu_binary
      type: select
      values: "%qemu_test.qemu.binary%"
  -
      name: qemu_machine
      type: input
      default: "%qemu_test.qemu.machine%"

  -
      name: ssh_key_path
      values: "%qemu_test.ssh_key_path%"
      type: select

  -
      name: skip_bootstrap
      type: checkbox
      default: true
  -
      name: qemu_new_session
      type: checkbox
      default: true

  -
      name: qemu_shut
      type: checkbox
      default: false
  -
      name: dump_task_code
      type: checkbox
      default: false

Job

#!raku

use Sparky::JobApi;

class Pipeline

does Sparky::JobApi::Role

{

  method stage-main {

    directory "scm";

    my $repo = tags()<repo>.subst(/^^ \s* "~/" /,%*ENV<HOME> ~ "/");
    my $use_case_repo = tags()<use_case_repo>.subst(/^^ \s* "~/" /,%*ENV<HOME> ~ "/");

    if $repo.IO ~~ :d {
      bash "cp -r {$repo}/* scm/";
    } else {
      git-scm tags()<repo>, %(
        to => "scm",
        branch => tags()<branch>,
      );
    }

    directory "use_case_repo";

    file-delete "use_case_repo.tar";

    if $use_case_repo.IO ~~ :d {
      say "archiving {$use_case_repo} files to use_case_repo.tar";
      bash "tar cf {$*CWD}/use_case_repo.tar -C {$use_case_repo} .";
    } else {
      git-scm tags()<use_case_repo>, %(
        to => "use_case_repo",
        branch => "HEAD",
      );
      say "(git) archiving {tags()<use_case_repo>} files to use_case_repo.tar";
      bash "git archive --format=tar  -o {$*CWD}/use_case_repo.tar HEAD", %(
        cwd => "{$*CWD}/use_case_repo",
      );
    }

    my $me = Sparky::JobApi.new: :mine;

    $me.put-file("{$*CWD}/use_case_repo.tar","use_case_repo.tar");

    if tags()<qemu_new_session> {

      task-run "scm/tasks/stop-qemu-box", %(
        qemu_binary => tags()<qemu_binary>,
      );

      # spawns a child job
      
      my $j = self.new-job: :project<qemu-session>;

      $j.queue({
        description => "start qemu session",
        tags => %(
          stage => "qemu-session",
          distro_url => config()<distro_url>,
          repo => $repo,
          branch => tags()<branch>,
          download_distro => config()<download_distro> ?? "yes" !! "no",
          qemu_binary => tags()<qemu_binary>,
          ssh_key_path => tags()<ssh_key_path>.subst(/^^ \s* "~/" /,%*ENV<HOME> ~ "/"),
          qemu_machine => tags()<qemu_machine>,
        ),
      });

      say "queue qemu-session job, ",$j.info.raku;

      say "wait till qemu box is ready";
      
      my $ssh-ok = False;

      for 1 .. 40 -> $i {
        my $s = task-run "scm/tasks/check-ssh", %(
          :host<127.0.0.1>,
          :port<10022>,
          :user<admin>,
        ); 
        if $s<state> eq "alive" {
          $ssh-ok = True;
          last;
        }
        sleep(10);
        say "[$i] ...";

        say "qemu-session job status: ", $j.status;

        unless $j.status eq "RUNNING" {
          say "qemu box is not good, stopping qemu session and exiting ...";
          task-run "scm/tasks/stop-qemu-box", %(
            qemu_binary => tags()<qemu_binary>,
          );
          exit(1); 
        }
      }

      if $j.status eq "FAIL" or $ssh-ok == False {
        say "qemu box is not good";
        task-run "scm/tasks/stop-qemu-box", %(
          qemu_binary => tags()<qemu_binary>,
        );
        exit(1);
      }

      unless tags()<skip_bootstrap> {

        $j = Sparky::JobApi.new: :project<qemu-bootstrap>;
        
        $j.queue({
          description => "bootstrap qemu box",
          tags => %(
            stage => "qemu-bootstrap",
          ),
          sparrowdo => %(
            :bootstrap,
            ssh_user => "admin",
            ssh_port => 10022,
            host => "127.0.0.1",
          ),
        });

        say "queue bootstrap qemu job, ",$j.info.raku;

        say "wait up to 20 munutes till bootstrap has finished";

        my $st = self.wait-job($j, %( :1200timeout ) );

        unless $st<OK> {
          say "qemu box is not good, stopping qemu session and exiting ...";
          task-run "scm/tasks/stop-qemu-box", %(
            qemu_binary => tags()<qemu_binary>,
          );
          exit(1);      
        }
      }
    }

    say "run use case scenario on qemu box";

    my $j = Sparky::JobApi.new: :project<qemu-use-case>;
      
    $j.queue({
      description => "use case scenario",
      tags => %(
        stage => "use-case",
        dump_task_code => tags()<dump_task_code> ?? "on" !! "off",
        parent_job_id => tags()<SPARKY_JOB_ID>,
        parent_job_name => tags()<SPARKY_PROJECT>,
      ),
      sparrowdo => %(
        ssh_user => "admin",
        ssh_port => 10022,
        host => "127.0.0.1",
        :no_sudo,
        #:debug,
      ),
    });

    say "queue use case job, ",$j.info.raku;

    say "wait up to 15 minutes till use case scenario has finished";

    my $st = self.wait-job($j, %( :900timeout ) );

    # check if child job send us any message
    my $jdata = $me.get-stash();

    if $jdata<need-reboot> {
       say "reboot signal recieved from child job, reboot qemu box";
       my $j = Sparky::JobApi.new: :project<qemu-reboot>;
       $j.queue({
          description => "reboot qemu box",
          tags => %(
            stage => "qemu-reboot",
          ),
          sparrowdo => %(
            ssh_user => "admin",
            ssh_port => 10022,
            host => "127.0.0.1",
            :no_sudo,
            #:debug,
          ),
        });

        say "queue qemu-reboot job, ",$j.info.raku;

        say "wait up to 7 minutes till reboot has finished";

        my $st = self.wait-job($j, %( :420timeout ) );

        unless $st<OK> {
          say "qemu box is not good, stopping qemu session and exiting ...";
          task-run "scm/tasks/stop-qemu-box", %(
            qemu_binary => tags()<qemu_binary>,
          );
          exit(1);      
        }

        sleep(15); # wait till VM has rebooted 

        my $ssh-ok = False;

        for 1 .. 40 -> $i {
          my $s = task-run "scm/tasks/check-ssh", %(
            :host<127.0.0.1>,
            :port<10022>,
            :user<admin>,
          ); 
          if $s<state> eq "alive" {
            $ssh-ok = True;
            last;
          }
          sleep(10);
          say "[$i] ...";
        }

        if $ssh-ok == True {

          say "machine successfully rebooted, run use case scenario on qemu box";

          my $j = Sparky::JobApi.new: :project<qemu-use-case>;
      
          $j.queue({
            description => "use case scenario",
            tags => %(
                stage => "use-case",
                dump_task_code => tags()<dump_task_code> ?? "on" !! "off",
                parent_job_id => tags()<SPARKY_JOB_ID>,
                parent_job_name => tags()<SPARKY_PROJECT>,
                :reboot-ok,
            ),
            sparrowdo => %(
              ssh_user => "admin",
              ssh_port => 10022,
              host => "127.0.0.1",
              :no_sudo,
              #:debug,
            ),
          });

          say "queue use case job, ",$j.info.raku;

          say "wait up to 15 minutes till use case scenario has finished";

          my $st = self.wait-job($j, %( :900timeout ) );

          if tags()<qemu_shut> {
            task-run "scm/tasks/stop-qemu-box", %(
              qemu_binary => tags()<qemu_binary>,
            );
          }
        } else {
          # handle case when vm has not showed up after reboot
          say "qemu box is not good, stopping qemu session and exiting ...";
          task-run "scm/tasks/stop-qemu-box", %(
            qemu_binary => tags()<qemu_binary>,
          );
          exit(1); 
        }
      # reboot is not required, just stop VM in case qemu_shut is enabled  
    } elsif tags()<qemu_shut> {
        task-run "scm/tasks/stop-qemu-box", %(
          qemu_binary => tags()<qemu_binary>,
        );
    }
  }

  method stage-qemu-session {

    directory "scm";

    my $repo = tags()<repo>.subst(/^^ \s* "~/" /,%*ENV<HOME> ~ "/");

    if $repo.IO ~~ :d {
      bash "cp -r {$repo}/* scm/";
    } else {
      git-scm tags()<repo>, %(
        to => "scm",
        branch => tags()<branch>,
      );
    }

    task-run "scm/tasks/setup-qemu-image", %(
      distro_url => tags()<distro_url>,
      ssh_key_path => tags()<ssh_key_path>,
    );

    bash "ls -lth {%*ENV<HOME>}/rocky-linux-distro";

    task-run "scm/tasks/run-qemu-box", %(
      iso => "{%*ENV<HOME>}/rocky-linux-distro/distro.qcow2",
      seed => "/tmp/init.iso",
      qemu_binary => tags()<qemu_binary>,
      machine => tags()<qemu_machine>,
    );

  }

  method stage-qemu-bootstrap {
    say "hello from RockyLinux";
  }

  method stage-use-case {

    directory "scm";
    
    bash "echo OK";

    my $job = Sparky::JobApi.new(
      api => "http://10.0.2.2:4000",
      project  => tags()<parent_job_name>,
      job-id => tags()<parent_job_id>,
    );

    my $blob = $job.get-file("use_case_repo.tar");

    my $fh = open "scm/use_case_repo.tar", :w, :bin;
    $fh.write($blob);
    $fh.close;

    bash "tar -xf use_case_repo.tar  && ls -l", %(
      cwd => "{$*CWD}/scm",
      description => "unpack use_case_repo.tar",
    );

    if "scm/main.raku".IO ~~ :e {
      say "load scenario from main.raku";
      chdir "scm/";
      if tags()<dump_task_code> eq "on" {
        say "enable dump_task_code ...";
        %*ENV<SP6_DUMP_TASK_CODE> = 1;
      }
      EVALFILE "main.raku";
    } else {
        warn "no file main.raku found, nothing to do"
    }

  }

  method stage-qemu-reboot {

    say "rebooting machine ...";

    task-run "reboot", "reboot";
    
  }
 
}

Pipeline.new.run;