API-Docker

 view release on metacpan or  search on metacpan

lib/API/Docker/API/System.pm  view on Meta::CPAN


  my $config = defined $opts{auth}
    ? $self->_registry_auth_config($opts{auth})
    : { map { $_ => $opts{$_} } @flat };

  # Stricter than the engine, deliberately. An empty AuthConfig is a valid
  # body -- Podman answers it 500 'getting username and password: cannot
  # prompt for username without stdin' -- but a credential check with no
  # credentials in it is a caller bug, and answering it with the engine's
  # message would hide that.
  croak __PACKAGE__ . '->auth requires credentials: pass username/password, '
    . 'identitytoken, or auth => $config' unless keys %$config;

  return $self->client->post('/auth', $config,
    %{ $self->_request_options },
    (exists $opts{response} ? (response => $opts{response}) : ()));
}



1;

__END__

=pod

=encoding UTF-8

=head1 NAME

API::Docker::API::System - Docker Engine System API

=head1 VERSION

version 0.004

=head1 SYNOPSIS

    my $docker = API::Docker->new;

    # System information
    my $info = $docker->system->info;
    say "Docker version: " . $info->{ServerVersion};

    # API version
    my $version = $docker->system->version;
    say "API version: " . $version->{ApiVersion};

    # Health check
    my $pong = $docker->system->ping;

    # Monitor events
    my $events = $docker->system->events(
        since => time() - 3600,
    );

    # Disk usage
    my $df = $docker->system->df;

    # Check registry credentials before doing the work that needs them
    my $login = $docker->system->auth(
        username      => 'me',
        password      => 'secret',
        serveraddress => 'ghcr.io',
    );
    say $login->{Status};   # Login Succeeded

=head1 DESCRIPTION

This module provides access to Docker system-level operations including daemon
information, version detection, health checks, and event monitoring.

Accessed via C<< $docker->system >>, or through
L<API::Docker::Role::Using/using> for a run of calls that needs its own
transport bound: C<< $docker->system->using(read_timeout => 5) >>.

=head2 client

Reference to L<API::Docker> client. Weak reference to avoid circular dependencies.

=head2 info

    my $info = $system->info;

Get system-wide information about the Docker daemon.

Returns hashref with keys including:

=over

=item * C<ServerVersion> - Docker version

=item * C<Containers> - Total number of containers

=item * C<Images> - Total number of images

=item * C<Driver> - Storage driver

=item * C<MemTotal> - Total memory

=back

=head2 version

    my $version = $system->version;

Get version information about the Docker daemon and API.

Returns hashref with keys including C<ApiVersion>, C<Version>, C<GitCommit>,
C<GoVersion>, C<Os>, and C<Arch>.

=head2 ping

    my $pong = $system->ping;

Health check endpoint. Returns C<OK> string if daemon is responsive.

=head2 events

    my $events = $system->events(
        since   => 1234567890,
        until   => 1234567900,
        filters => { type => ['container'] },
    );

Get events from the Docker daemon. Returns an ArrayRef of events, one per

lib/API/Docker/API/System.pm  view on Meta::CPAN

Options:

=over

=item * C<since> - Show events created since this timestamp

=item * C<until> - Show events created before this timestamp

=item * C<filters> - HashRef of filter name to ArrayRef of string values, e.g.
C<< { type => ['container', 'image'] } >>. Shape-checked and normalised by
L<API::Docker::Role::Filters>; the daemon validates the names here, so a
misspelt one is a failed request rather than a quiet no-match

=item * C<on_event> - CodeRef called with each event as it arrives, instead of
the ArrayRef being collected and returned; see below

=back

=head2 Following the feed

An unbounded C</events> is the endpoint this client could not use at all.
Pass C<on_event> and the events are handed over one at a time as the daemon
sends them:

    my $summary = $system->events(
        since    => time - 60,
        on_event => sub {
            my ($event, $stop) = @_;
            say $event->{status};
            $stop->() if $event->{status} eq 'destroy';
        },
    );

    $summary;   # { delivered => 12, stopped => 1 }

With a callback the return value is that summary HashRef, not the events:
C<delivered> is how many went to the callback, C<stopped> is 1 when the
callback ended the feed and 0 when the daemon did. Nothing is accumulated --
a feed that runs for a day must not cost memory in proportion to how long it
ran, and the callback has been handed every event already. See
L<API::Docker::Role::HTTP/"Streaming a response as it arrives">.

Measured against the rootless Podman socket (5.4.2, API 1.41): with C<since>
and no C<until>, this returned in 0.3 seconds as soon as the callback said
stop, where the same call without one was still running when it was killed
after 22 seconds.

The callback never croaks on the content of the feed either: C<croak_on_error>
is off here on both paths, for the reason above.

=head2 df

    my $usage = $system->df;

Get data usage information (disk usage by images, containers, and volumes).

Returns hashref with C<LayersSize>, C<Images>, C<Containers>, and C<Volumes> arrays.

=head2 auth

    my $login = $system->auth(
        username      => 'me',
        password      => 'secret',
        serveraddress => 'ghcr.io',
    );

    # Or hand over the same auth argument images->push takes
    $system->auth(auth => $auth);

Check a set of registry credentials against the registry, without pulling or
pushing anything. Returns the decoded C<< POST /auth >> response, a HashRef
with C<Status> (C<Login Succeeded>) and, where the registry issues one,
C<IdentityToken>.

B<Bad credentials croak.> The engine answers a failed check with an error
status, and the transport croaks on any status at or above 400, so a
successful return I<is> the answer -- there is no false value to test. That
is what makes this useful as a pre-flight check: call it before building and
tagging an image, and a stale credential fails the run where it is cheap
rather than halfway through a push.

To tell one failure from another, eval and read the status:

    my %res;
    eval { $docker->system->auth(auth => $auth, response => \%res); 1 }
      or do {
        die "registry rejected the credentials" if $res{status} == 401;
        die "could not reach the registry: $@";
      };

Options -- the AuthConfig keys the engine defines, all optional
individually, but at least one is required:

=over

=item * C<username> - Registry account name

=item * C<password> - Its password or token

=item * C<email> - Legacy field, accepted and ignored by current registries

=item * C<serveraddress> - Registry to check against, e.g. C<ghcr.io>.
Omitted, the engine uses its default registry

=item * C<identitytoken> - Bearer token, instead of username and password

=item * C<auth> - The whole AuthConfig at once, in any shape
L<API::Docker::API::Images/push> accepts it: a HashRef, a JSON object, or a
base64url-encoded one. Cannot be combined with the keys above

=item * C<response> - HashRef the status line and the response headers are
written into, as for L<API::Docker::Role::HTTP/get>

=back

Passing neither C<auth> nor any credential key croaks before the request is
made.

=head3 What Podman answers

Measured against the rootless Podman socket (5.4.2, API 1.41): the endpoint
exists, but a failed check is B<500 Internal Server Error>, not Docker's 401,
and the message is the registry's own text wrapped by Podman --
C<< {"message":"login attempt to 127.0.0.1:1 failed with status: ..."} >>.
An empty AuthConfig answers
C<< {"message":"login attempt to  failed with status: getting username and
password: cannot prompt for username without stdin"} >>, also 500. So the
croak is reliable on both engines while the status behind it is not: test the
outcome, not the number.

=head1 SEE ALSO

=over

=item * L<API::Docker> - Main Docker client

=back

=head1 SUPPORT

=head2 Issues

Please report bugs and feature requests on GitHub at
L<https://github.com/Getty/p5-api-docker/issues>.

=head1 CONTRIBUTING

Contributions are welcome! Please fork the repository and submit a pull request.

=head1 AUTHOR

Torsten Raudssus <getty@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by Torsten Raudssus <torsten@raudssus.de> L<https://raudssus.de/>.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut



( run in 0.448 second using v1.01-cache-2.11-cpan-4ef0a570458 )