Developer-Dashboard

 view release on metacpan or  search on metacpan

t/94-dockercompose-coverage.t  view on Meta::CPAN

# multi-file merge resolving a service correctly, only on `config` having
# already done so once, up front.
# ---------------------------------------------------------------------------
my $logbin = File::Spec->catdir( $home, 'logbin' );
make_path($logbin);
my $invocation_log = File::Spec->catfile( $home, 'docker-invocations.log' );
mkfile(
    File::Spec->catfile( $logbin, 'docker' ), <<"STUB" );
#!/bin/sh
printf '%s\\n' "\$*" >> '$invocation_log'
last=''
for a in "\$\@"; do last="\$a"; done
if [ "\$last" = 'config' ]; then
  case "\${P40_COMPOSE_OUTPUT:-valid}" in
    malformed) printf 'services: [\\n' ;;
    scalar) printf '%s\\n' '[]' ;;
    no_services) printf '%s\\n' '{}' ;;
    invalid_services) printf '%s\\n' 'services: []' ;;
    empty_service) printf '%s\\n' 'services:' '  "": {}' ;;
    dot_service) printf '%s\\n' 'services:' '  ".": {}' ;;
    dotdot_service) printf '%s\\n' 'services:' '  "..": {}' ;;
    unsafe_service) printf '%s\\n' 'services:' '  "../outside": {}' ;;
    *) printf 'services:\\n  merged-marker:\\n    image: stub\\n' ;;
  esac
fi
exit 0
STUB
chmod 0755, File::Spec->catfile( $logbin, 'docker' );

{
    unlink $invocation_log if -e $invocation_log;
    my $old = getcwd();
    chdir $repo or die $!;
    local $ENV{PATH} = "$logbin:$ENV{PATH}";
    my $result = $docker->run(
        addons   => ['mailhog'],
        args     => [ 'config', 'app' ],
        modes    => ['dev'],
        services => ['worker'],
    );
    chdir $old or die $!;

    is( $result->{exit_code}, 0, 'run with multiple layers still succeeds' );

    open my $log_fh, '<', $invocation_log or die "Unable to read $invocation_log: $!";
    my @lines = <$log_fh>;
    close $log_fh;
    chomp @lines;

    ok( scalar(@lines) >= 2, 'run invokes docker at least twice: once to materialize, once to execute' )
      or diag( explain \@lines );
    like( $lines[0], qr/(?:^| )config$/, 'first invocation is the materialize-via-config call' );
    ok( ( grep { /-f / } $lines[0] ), 'the materialize call carries the original multi -f layers' )
      or diag( explain \@lines );

    my $final_call = $lines[-1];
    my @f_flags = ( $final_call =~ /-f (\S+)/g );
    is( scalar(@f_flags), 1, 'the executed call passes exactly one -f, pointing at the merged file' )
      or diag( explain \@lines );
    ok( -f $f_flags[0], 'the single -f file the executed call names actually exists on disk' );
    my $merged_content = do { local ( @ARGV, $/ ) = $f_flags[0]; <> };
    like( $merged_content, qr/merged-marker/, 'the merged file holds the materialized config, not a raw layer file' );
    like( $final_call, qr/ app$/, 'the executed call still carries the original passthrough args (app)' );
}

# Operational commands must retain the invocation Compose root after layered
# files are materialized into a temporary merged file. Without an explicit
# project directory, Compose derives relative paths and the default project
# name from that temporary file instead of the user's local Compose project.
{
    my $old = getcwd();
    chdir $repo or die $!;
    local $ENV{PATH} = "$logbin:$ENV{PATH}";

    for my $action (
        [ up    => [ 'up', '-d', 'app' ] ],
        [ build => [ 'build', 'app' ] ],
        [ down  => ['down'] ],
    ) {
        unlink $invocation_log if -e $invocation_log;
        my ( $label, $args ) = @{$action};
        my $result = $docker->run( args => $args );
        is( $result->{exit_code}, 0, "$label operation succeeds after layered config materialization" );

        open my $log_fh, '<', $invocation_log or die "Unable to read $invocation_log: $!";
        my @lines = <$log_fh>;
        close $log_fh;
        chomp @lines;
        like( $lines[0] || '', qr/--project-directory \Q$repo\E/, "$label materialization uses the invocation Compose directory" );
        my $final_call = $lines[-1] || '';
        like(
            $final_call,
            qr/--project-directory \Q$repo\E/,
            "$label operation keeps the invocation directory as Compose project directory",
        );
        like( $final_call, qr/(?:^| )\Q$label\E(?: |$)/, "$label operation remains the requested Compose action" );
    }

    chdir $old or die $!;
}

{
    my $custom_project_dir = File::Spec->catdir( $home, 'explicit-compose-project' );
    make_path($custom_project_dir);
    my $old = getcwd();
    chdir $repo or die $!;
    local $ENV{PATH} = "$logbin:$ENV{PATH}";

    for my $project_option (
        [ separate => [ '--project-directory', $custom_project_dir ] ],
        [ equals   => [ "--project-directory=$custom_project_dir" ] ],
    ) {
        unlink $invocation_log if -e $invocation_log;
        my ( $label, $option_args ) = @{$project_option};
        $docker->run( args => [ @{$option_args}, 'up', 'app' ] );
        open my $log_fh, '<', $invocation_log or die "Unable to read $invocation_log: $!";
        my @lines = <$log_fh>;
        close $log_fh;
        chomp @lines;
        like( $lines[0] || '', qr/--project-directory(?:=| )\Q$custom_project_dir\E/, "explicit $label project directory also applies while materializing" );
        my $final_call = $lines[-1] || '';



( run in 0.494 second using v1.01-cache-2.11-cpan-ac8be02dad9 )