API-Docker
view release on metacpan or search on metacpan
Makefile.PL view on Meta::CPAN
"Log::Any" => 0,
"MIME::Base64" => 0,
"Moo" => 0,
"Path::Tiny" => 0,
"Test::More" => 0,
"URI" => 0,
"namespace::clean" => 0
);
unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) {
delete $WriteMakefileArgs{TEST_REQUIRES};
delete $WriteMakefileArgs{BUILD_REQUIRES};
$WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs;
}
delete $WriteMakefileArgs{CONFIGURE_REQUIRES}
unless eval { ExtUtils::MakeMaker->VERSION(6.52) };
WriteMakefile(%WriteMakefileArgs);
lib/API/Docker/Role/HTTP.pm view on Meta::CPAN
close $sock;
$self->_clear_socket;
my ($status_code, $status_text, $headers, $body) = @$response;
$log->debugf("Response: %s %s", $status_code, $status_text);
if ($status_code >= 400) {
my $error_msg = $body;
if ($body && $body =~ /^\s*[\{\[]/) {
eval {
my $data = decode_json($body);
$error_msg = $data->{message} // $body;
};
}
croak "Docker API error ($status_code): $error_msg";
}
if ($status_code == 204 || !defined($body) || $body eq '') {
return undef;
}
if ($body =~ /^\s*[\{\[]/) {
my $result = eval { decode_json($body) };
return $result if defined $result;
# Streaming endpoints (e.g. /build, /images/create) return
# newline-delimited JSON objects. Parse each line separately.
my @objects;
for my $line (split /\r?\n/, $body) {
next unless $line =~ /\S/;
my $obj = eval { decode_json($line) };
push @objects, $obj if defined $obj;
}
return \@objects if @objects;
}
return $body;
}
sub _read_response {
my ($self, $sock) = @_;
t/containers.t view on Meta::CPAN
$docker->containers->remove($id);
pass('container removed');
};
# --- Validation Tests (always run, no Docker needed) ---
subtest 'container ID required' => sub {
my $docker = test_docker();
eval { $docker->containers->inspect(undef) };
like($@, qr/Container ID required/, 'croak on missing ID for inspect');
eval { $docker->containers->start(undef) };
like($@, qr/Container ID required/, 'croak on missing ID for start');
eval { $docker->containers->stop(undef) };
like($@, qr/Container ID required/, 'croak on missing ID for stop');
};
done_testing;
substr($header, 148, 8, sprintf('%06o', $checksum) . "\0 ");
my $tar = $header;
$tar .= $dockerfile;
$tar .= "\0" x (512 - ($size % 512)) if $size % 512;
$tar .= "\0" x 1024;
my $tag = 'api-docker-test-build:latest';
my $result = $docker->images->build(context => $tar, t => $tag, q => 1);
ok($result, 'build returned result');
register_cleanup(sub { eval { $docker->images->remove($tag, force => 1) } });
} else {
my $result = $docker->images->build(
context => 'fake-tar-data',
t => 'myapp:latest',
dockerfile => 'Dockerfile',
);
ok($result, 'build returned a result');
like($result->{stream}, qr/Successfully built/, 'build output contains success');
$docker->images->pull(fromImage => 'nginx', tag => 'latest');
my $removed = $docker->images->remove('nginx:latest');
is(ref $removed, 'ARRAY', 'remove returns array of actions');
}
};
# --- Validation Tests (always run, no Docker needed) ---
subtest 'build requires context' => sub {
my $docker = test_docker();
eval { $docker->images->build(t => 'myapp:latest') };
like($@, qr/Build context required/, 'croak on missing context');
};
subtest 'image name required' => sub {
my $docker = test_docker();
eval { $docker->images->inspect(undef) };
like($@, qr/Image name required/, 'croak on missing name for inspect');
eval { $docker->images->remove(undef) };
like($@, qr/Image name required/, 'croak on missing name for remove');
};
done_testing;
t/lib/Test/API/Docker/Mock.pm view on Meta::CPAN
sub check_live_access {
return unless is_live();
my $host = $ENV{API_DOCKER_TEST_HOST};
if ($host =~ m{^unix://(.+)$}) {
unless (-S $1) {
plan skip_all => "Docker socket $1 not available";
}
}
eval {
require API::Docker;
my $docker = API::Docker->new(host => $host);
my $result = $docker->system->ping;
die "ping failed" unless $result eq 'OK';
};
if ($@) {
plan skip_all => "Docker daemon not reachable at $host: $@";
}
}
sub register_cleanup {
my ($code) = @_;
push @_cleanups, $code;
}
sub _run_cleanups {
for my $cleanup (reverse @_cleanups) {
eval { $cleanup->() };
warn "Cleanup failed: $@" if $@;
}
@_cleanups = ();
}
sub test_docker {
my (%routes) = @_;
if (is_live()) {
require API::Docker;
t/networks.t view on Meta::CPAN
);
my $name = 'api-docker-test-net-' . $$;
my $result = $docker->networks->create(
Name => is_live() ? $name : 'test-net',
Driver => 'bridge',
);
ok($result->{Id}, 'created network has Id');
my $id = is_live() ? $result->{Id} : 'mock-net-123';
register_cleanup(sub { eval { $docker->networks->remove($id) } }) if is_live();
my $network = $docker->networks->inspect($id);
isa_ok($network, 'API::Docker::Network');
ok($network->Name, 'has Name');
unless (is_live()) {
$docker->networks->connect($id, Container => 'abc123');
pass('connect completed');
$docker->networks->disconnect($id, Container => 'abc123');
t/networks.t view on Meta::CPAN
$docker->networks->remove($id);
pass('network removed');
};
# --- Validation Tests (always run, no Docker needed) ---
subtest 'network ID required' => sub {
my $docker = test_docker();
eval { $docker->networks->inspect(undef) };
like($@, qr/Network ID required/, 'croak on missing ID for inspect');
eval { $docker->networks->remove(undef) };
like($@, qr/Network ID required/, 'croak on missing ID for remove');
};
subtest 'connect requires container' => sub {
my $docker = test_docker();
eval { $docker->networks->connect('net1') };
like($@, qr/Container required/, 'croak on missing container for connect');
};
done_testing;
t/volumes.t view on Meta::CPAN
Options => {},
},
'DELETE /volumes/test-vol' => undef,
);
my $name = is_live() ? 'api-docker-test-vol-' . $$ : 'test-vol';
my $volume = $docker->volumes->create(Name => $name);
isa_ok($volume, 'API::Docker::Volume');
ok($volume->Name, 'created volume has Name');
register_cleanup(sub { eval { $docker->volumes->remove($name, force => 1) } }) if is_live();
my $inspected = $docker->volumes->inspect($name);
isa_ok($inspected, 'API::Docker::Volume');
is($inspected->Driver, 'local', 'volume driver is local');
$docker->volumes->remove($name);
pass('volume removed');
};
# --- Validation Tests (always run, no Docker needed) ---
subtest 'volume name required' => sub {
my $docker = test_docker();
eval { $docker->volumes->inspect(undef) };
like($@, qr/Volume name required/, 'croak on missing name for inspect');
eval { $docker->volumes->remove(undef) };
like($@, qr/Volume name required/, 'croak on missing name for remove');
};
done_testing;
( run in 0.721 second using v1.01-cache-2.11-cpan-98e64b0badf )