API-Docker
view release on metacpan or search on metacpan
lib/API/Docker/Role/Entity/Container.pm view on Meta::CPAN
package API::Docker::Role::Entity::Container;
# ABSTRACT: Container operations, on the generated container types
our $VERSION = '0.004';
use Moo::Role;
with 'API::Docker::Role::Entity';
requires 'id';
use API::Docker::Type::ContainerInspectResponse;
use API::Docker::Type::ContainerSummary;
use Carp qw( croak );
use Package::Stash;
use Scalar::Util qw( blessed );
use namespace::clean;
sub start {
my ($self) = @_;
return $self->client->containers->start($self->id);
}
sub stop {
my ($self, %opts) = @_;
return $self->client->containers->stop($self->id, %opts);
}
sub restart {
my ($self, %opts) = @_;
return $self->client->containers->restart($self->id, %opts);
}
sub kill {
my ($self, %opts) = @_;
return $self->client->containers->kill($self->id, %opts);
}
sub remove {
my ($self, %opts) = @_;
return $self->client->containers->remove($self->id, %opts);
}
sub logs {
my ($self, %opts) = @_;
return $self->client->containers->logs($self->id, %opts);
}
sub attach {
my ($self, %opts) = @_;
return $self->client->containers->attach($self->id, %opts);
}
sub inspect {
my ($self) = @_;
return $self->client->containers->inspect($self->id);
}
sub pause {
my ($self) = @_;
return $self->client->containers->pause($self->id);
}
sub unpause {
my ($self) = @_;
return $self->client->containers->unpause($self->id);
}
sub top {
my ($self, %opts) = @_;
return $self->client->containers->top($self->id, %opts);
}
sub stats {
my ($self, %opts) = @_;
return $self->client->containers->stats($self->id, %opts);
}
sub changes {
my ($self) = @_;
return $self->client->containers->changes($self->id);
}
sub export {
my ($self) = @_;
return $self->client->containers->export($self->id);
}
sub resize {
my ($self, %opts) = @_;
return $self->client->containers->resize($self->id, %opts);
}
sub get_archive {
my ($self, %opts) = @_;
return $self->client->containers->get_archive($self->id, %opts);
lib/API/Docker/Role/Entity/Container.pm view on Meta::CPAN
# --- composition -----------------------------------------------------------
#
# Here rather than in API::Docker::API::Containers, which is the other
# candidate: loading this role is then what puts the methods on the classes,
# and there is no program in which an API::Docker::Type::ContainerSummary has
# ->start and another in which it does not, depending on which module was
# loaded first.
#
# The clash check is not decoration. Moo composes a role into a class the
# class-wins way, so a generated accessor of the same name as a method here
# would silently keep its place and the method would be missing -- and the
# generated classes are written from a specification that grows fields
# without asking. None of the 19 names collides today; a future one says so
# on the first `use`.
{
my @provided = Package::Stash->new(__PACKAGE__)->list_all_symbols('CODE');
for my $class (
'API::Docker::Type::ContainerSummary',
'API::Docker::Type::ContainerInspectResponse',
) {
my $fields = $class->docker_attributes;
my @clash = sort grep { $fields->{$_} } @provided;
croak __PACKAGE__ . ': ' . $class . ' declares ' . join(', ', @clash)
. ' as a daemon field; the generated accessor would win over the '
. 'method of that name and it would be missing without a word'
if @clash;
Moo::Role->apply_roles_to_package($class, __PACKAGE__);
}
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
API::Docker::Role::Entity::Container - Container operations, on the generated container types
=head1 VERSION
version 0.004
=head1 SYNOPSIS
my $docker = API::Docker->new;
# from list: an API::Docker::Type::ContainerSummary
my ($container) = @{ $docker->containers->list };
say $container->id;
say $container->status; # "Up 2 hours"
say $container->state; # "running"
$container->start;
$container->stop(timeout => 10);
my $logs = $container->logs(tail => 100);
$container->remove(force => 1);
# from inspect: an API::Docker::Type::ContainerInspectResponse, where
# the same methods work and `state` is an object
my $full = $docker->containers->inspect($container->id);
say $full->state->status;
say $full->state->exit_code;
if ($full->is_running) { ... }
=head1 DESCRIPTION
The convenience methods of a container. This role is composed, at load time,
into the two generated classes the daemon answers container requests with:
=over
=item * L<API::Docker::Type::ContainerSummary> -- one entry of
C<GET /containers/json>, what L<API::Docker::API::Containers/list> returns
=item * L<API::Docker::Type::ContainerInspectResponse> -- the body of
C<GET /containers/{id}/json>, what L<API::Docker::API::Containers/inspect>
returns
=back
Every method here forwards to L<API::Docker::API::Containers> with the
container's own C<id> and returns whatever that method returns; the options
are that method's options, undocumented here on purpose so there is one
place to correct when the engine's are found to be something else.
The fields differ between the two classes -- see
L<API::Docker::API::Containers/"The two container shapes"> for the
differences that have bitten. L</is_running> is the one method that reads
both shapes.
Why the methods are a role applied to generated classes rather than a class
of their own: L<API::Docker::Role::Entity/DESCRIPTION>.
=head2 start
$container->start;
say 'was already running' unless $container->start;
Start the container. Returns 1 when it was started and 0 when it was already
running. Delegates to L<API::Docker::API::Containers/start>, which documents
what that 0 replaces.
=head2 stop
$container->stop(timeout => 10);
Stop the container. Returns 1 when it was stopped and 0 when it was already
stopped. Delegates to L<API::Docker::API::Containers/stop>.
=head2 restart
$container->restart;
Restart the container. Returns 1/0 as L<API::Docker::API::Containers/restart>
does; no engine measured here answers a restart with 304, so it is 1.
=head2 kill
$container->kill(signal => 'SIGTERM');
Send a signal to the container.
=head2 remove
$container->remove(force => 1);
Remove the container.
=head2 logs
my $logs = $container->logs(tail => 100);
# or follow it, one frame at a time
$container->logs(follow => 1, tail => 0,
on_frame => sub { print $_[0]{data} });
Get container logs. Every option goes to
L<API::Docker::API::Containers/logs>, C<follow> and C<on_frame> included; with
a callback the return value is that method's summary HashRef rather than the
frames.
=head2 attach
my $frames = $container->attach;
Attach to the container's output and return the frames, one-way. Every option
goes to L<API::Docker::API::Containers/attach>, C<on_frame> included; with a
callback the return value is that method's summary HashRef rather than the
frames. Without options it replays what the container already wrote and
returns; C<< stream => 1 >> on a container that is not running never
returns -- not even with a callback -- see
L<API::Docker::API::Containers/"The defaults follow the engine">.
B<The container must be running.> Attaching to one that has already exited
destroys its exit status on Podman, so the call checks first and croaks rather
than attaching; L</logs> is how a finished container's output is read.
C<< require_running => 0 >> attaches anyway. The check is a pre-flight one and
does not close the race against a container stopping underneath it -- see
L<API::Docker::API::Containers/"This method refuses a container that is not running">.
=head2 inspect
my $updated = $container->inspect;
Get fresh container information. Returns an
L<API::Docker::Type::ContainerInspectResponse> whatever the invocant was, so
this is also how a C<list> entry is turned into the full shape.
=head2 pause
$container->pause;
Pause all processes in the container. Returns 1/0 as
L<API::Docker::API::Containers/pause> does; an already-paused container is an
error there, not a 0.
=head2 unpause
$container->unpause;
Unpause the container. Returns 1/0 as
L<API::Docker::API::Containers/unpause> does.
=head2 top
my $processes = $container->top;
List running processes in the container.
=head2 stats
my $stats = $container->stats;
# or follow the readings
$container->stats(stream => 1, on_event => sub { ... });
Get resource usage statistics. Every option goes to
L<API::Docker::API::Containers/stats>, C<stream> and C<on_event> included;
with a callback the return value is that method's summary HashRef rather than
the readings.
=head2 changes
for my $change (@{ $container->changes }) { ... }
Paths that differ from the image, as C<< { Path => ..., Kind => ... } >>.
Delegates to L<API::Docker::API::Containers/changes>, which documents what the
three C<Kind> numbers mean.
=head2 export
my $tar = $container->export;
The container's filesystem as raw tar bytes.
=head2 resize
( run in 0.358 second using v1.01-cache-2.11-cpan-4ef0a570458 )