~mclehman/guestctl

6053daccd97e65d0c636a146cb8a57634b5c4f2a — 0xFORDCOMMA 1 year, 7 months ago 850cd39
Implement forward-compatible self-management system.
M META6.json => META6.json +1 -0
@@ 10,6 10,7 @@
        "templates/dockerfile.tmpl",
        "templates/docker-compose.tmpl",
        "templates/user.tmpl",
        "templates/meta.tmpl",
        "templates/sshd_config.tmpl"
    ],
    "version" : "0.1.2",

M bin/guestctl => bin/guestctl +13 -5
@@ 65,6 65,10 @@ multi MAIN($guest, GuestAction $action, *@args) {
            my $user = "$guest-dir/user".IO.slurp.chomp;
            my $home-dir = "/home/$user";
            run <<docker exec -it -u $user -w $home-dir $container-id bash>>;
            CATCH {
                # Absorb unsuccessful docker exits in the case that the guest triggers a commit or rollback.
                default { }
            }
        }

        when (Commit, Running) {


@@ 75,7 79,7 @@ multi MAIN($guest, GuestAction $action, *@args) {
            note qq{Committing guest "$guest" to image $committed-image.};
            transparent-run <<docker commit $container-id $committed-image>>, :proceed;
            transparent-run <<docker tag $committed-image $live-image>>, :proceed;
            transparent-run <<docker-compose up -d>>, cwd => $guest-dir;
            transparent-run <<docker-compose up -d>>, cwd => $guest-dir, :proceed;
        }

        default {


@@ 123,8 127,6 @@ multi MAIN("new", $guest) {
        exit 1;
    }

    my $template-dir = $guests-dir.IO.add: ".skeleton";

    my $guest-dir = $guests-dir.IO.add: $guest;
    mkdir $guest-dir;
    my $ssh-dir = $guest-dir.add: "ssh";


@@ 159,10 161,16 @@ multi MAIN("new", $guest) {
                         };

    my %variables = gen-template-vars @prompt-entries, $guest;
    my @template-files = load-template-files $template-dir;

    # Effectful: instantiate and write out template files in new guest directory.
    instantiate-template-files @template-files, %variables, $guest-dir;
    instantiate-template-files load-template-files, %variables, $guest-dir;

    # Set up self-management key and command.
    transparent-run <<ssh-keygen -t rsa -N "" -f {$guest-dir.add: "ssh/id_meta"}>>, :proceed;
    my $public-key = $guest-dir.add("ssh/id_meta.pub").slurp;
    my $management-key-entry = qq{command="env guestctl-meta $guest \${SSH_ORIGINAL_COMMAND}"} ~ " " ~ $public-key;
    my $guest-management-keys-file = "%*ENV<HOME>/.ssh/guest_management_keys".IO;
    $guest-management-keys-file.spurt: "\n" ~ $management-key-entry, :append;

    my ($guest-base-image, $guest-live-image) = "guest-$guest" <<~>> <:base :live>;
    transparent-run <<docker build -t $guest-base-image $guest-dir>>, :proceed;

A bin/guestctl-meta => bin/guestctl-meta +17 -0
@@ 0,0 1,17 @@
#!/usr/bin/env perl6

multi MAIN($guest, "commit") {
    run <<guestctl $guest commit>>;
}

multi MAIN($guest, "rollback", $image-tag) {
    run <<guestctl $guest rollback $image-tag>>;
}

multi MAIN($guest, "snapshots") {
    run <<guestctl $guest snapshots>>;
}

multi MAIN($guest, "restart") {
    run <<guestctl $guest restart>>;
}

M lib/App/Guestctl/Templates.pm6 => lib/App/Guestctl/Templates.pm6 +5 -2
@@ 30,15 30,18 @@ sub gen-template-vars(@prompt-entries, $guest) is export {
    # input as well as the new guest handle.
    my %template-vars = |%builtin-templates{%responses<base>},
                        |%responses,
                        :$guest;
                        :$guest,
                        management_user => run(<whoami>, :out).out.slurp.chomp;
        "templates/user.tmpl",

    return %template-vars;
}

sub load-template-files($template-dir) is export {
sub load-template-files() is export {
    return ("Dockerfile"         => %?RESOURCES<templates/dockerfile.tmpl>.slurp,
            "docker-compose.yml" => %?RESOURCES<templates/docker-compose.tmpl>.slurp,
            "user"               => %?RESOURCES<templates/user.tmpl>.slurp,
            "meta"               => %?RESOURCES<templates/meta.tmpl>.slurp,
            "ssh/sshd_config"    => %?RESOURCES<templates/sshd_config.tmpl>.slurp);
}


M resources/templates/dockerfile.tmpl => resources/templates/dockerfile.tmpl +12 -6
@@ 1,16 1,22 @@
FROM {{ base_image }}

RUN {{ package_manager }} {{ package_manager_update }} && {{ package_manager }} {{ package_manager_install }} {{ noconfirm }} {{ ssh_server }} sudo vim {{ aux_packages }}
RUN useradd -m {{ user }} && echo '{{ user }}:{{ temporarypassword }}' chpasswd
RUN groupadd -f sudo && gpasswd -a {{ user }} sudo && echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]

COPY ssh/sshd_config /etc/ssh/sshd_config
COPY meta /usr/bin/meta
RUN chmod a+x /usr/bin/meta

RUN {{ package_manager }} {{ package_manager_update }} && {{ package_manager }} {{ package_manager_install }} {{ noconfirm }} {{ ssh_server }} sudo vim iproute2 {{ aux_packages }}
RUN ssh-keygen -A

RUN useradd -m {{ user }} && echo '{{ user }}:{{ temporarypassword }}' chpasswd
RUN groupadd -f sudo && gpasswd -a {{ user }} sudo && echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

RUN mkdir -p /home/{{ user }}/.ssh
RUN echo '{{ ssh_key }}' > /home/{{ user }}/.ssh/authorized_keys
COPY ssh/sshd_config /etc/ssh/sshd_config

{{ aux_dockerfile }}

EXPOSE 22
CMD ["/usr/sbin/sshd", "-D"]
COPY ssh/id_meta /home/{{ user }}/.ssh/id_meta
RUN chown -R {{ user }}:{{ user }} /home/{{ user }}/.ssh

A resources/templates/meta.tmpl => resources/templates/meta.tmpl +3 -0
@@ 0,0 1,3 @@
#!/bin/sh

ssh -i ~/.ssh/id_meta {{ management_user }}@$(ip route list | grep default | awk '{ print $3 }') $@