Dist-Zilla-Plugin-Docker-API
view release on metacpan or search on metacpan
lib/Dist/Zilla/Plugin/Docker/API/Client.pm view on Meta::CPAN
},
);
has logger => (
is => 'ro',
required => 1,
);
has logger_fatal => (
is => 'ro',
required => 1,
);
has docker_config_path => (
is => 'ro',
lazy => 1,
builder => sub {
$ENV{DOCKER_CONFIG}
? Path::Tiny::path($ENV{DOCKER_CONFIG}, 'config.json')
: Path::Tiny::path($ENV{HOME} // '', '.docker', 'config.json');
},
);
has _docker_config => (
is => 'ro',
lazy => 1,
builder => sub {
my ($self) = @_;
my $path = $self->docker_config_path;
return {} unless $path && -r "$path";
my $data = eval { decode_json(Path::Tiny::path($path)->slurp_utf8) };
if ($@ || !$data) {
$self->logger->("Warning: cannot parse $path: $@") if $@;
return {};
}
return $data;
},
);
# Cheapest round trip that proves an engine is actually listening on the
# socket. Used by the plugin's before_build precheck, so a missing daemon
# is reported before Dist::Zilla does any work rather than after.
sub engine_info {
my ($self) = @_;
my $version = eval { $self->docker->system->version };
croak $@ if $@;
croak 'the engine returned no version information'
unless ref $version eq 'HASH';
my ($engine) = grep { ($_->{Name} // '') =~ /engine/i }
@{ $version->{Components} // [] };
return {
version => $version->{Version},
api_version => $version->{ApiVersion},
engine => $engine ? $engine->{Name} : undef,
};
}
# The engine's tag endpoint takes the repository and the tag as two separate
# parameters (POST /images/{name}/tag?repo=&tag=), so a full image reference
# has to be taken apart before it goes over the wire. Passing the whole thing
# as `repo` leaves `tag` empty and the engine fills in its own default:
# podman then rejects `example/app:1.0:latest` with a 500 and every version
# tag is quietly lost. Splitting happens here rather than in API::Docker,
# which mirrors the endpoint and should keep doing so.
sub _split_image_ref {
my ( $self, $ref ) = @_;
my $colon = rindex $ref, ':';
return ( $ref, undef ) if $colon < 0;
# A colon before the last slash belongs to a registry host:port, not to a
# tag: registry.example.com:5000/team/app carries no tag at all.
return ( $ref, undef ) if rindex($ref, '/') > $colon;
return ( substr($ref, 0, $colon), substr($ref, $colon + 1) );
}
sub build_image {
my ($self, %arg) = @_;
my $context = $arg{context_tar};
my $dockerfile = $arg{dockerfile} // 'Dockerfile';
my @tags = @{ $arg{tags} // [] };
my %labels = %{ $arg{labels} // {} };
my %buildargs = %{ $arg{buildargs} // {} };
my $pull = $arg{pull} // 0;
my $nocache = $arg{nocache} // 0;
my $rm = $arg{rm} // 1;
my $forcerm = $arg{forcerm} // 1;
my $target = $arg{target};
my $network_mode = $arg{network_mode};
my $platform = $arg{platform};
my $verbose = $arg{verbose} // 0;
my $docker = $self->docker;
my %build_opts = (
dockerfile => $dockerfile,
t => @tags ? $tags[0] : undef,
pull => $pull ? 1 : 0,
nocache => $nocache ? 1 : 0,
rm => $rm ? 1 : 0,
forcerm => $forcerm ? 1 : 0,
);
$build_opts{labels} = \%labels if %labels;
$build_opts{buildargs} = \%buildargs if %buildargs;
$build_opts{target} = $target if defined $target && length $target;
$build_opts{networkmode} = $network_mode if defined $network_mode && length $network_mode;
$build_opts{platform} = $platform if defined $platform && length $platform;
my $image_id;
my @processed_tags;
# Concise mode (default): only forward Dockerfile step headers â both the
# legacy builder ("Step N/M : ...") and BuildKit ("#N [N/M] ..."). Skip the
# noisy intermediate container chatter. Verbose mode forwards every line.
# The line buffer is used in both modes so the Dist::Zilla logger (which
# appends its own newline) doesn't get a stream chunk with a trailing \n.
my $line_buf = '';
my $progress_cb = sub {
my ($event) = @_;
if ($event->{errorDetail}) {
$self->logger_fatal->("Docker build error: " . $event->{errorDetail}{message});
}
( run in 1.624 second using v1.01-cache-2.11-cpan-cb04b646d8c )