API-Docker
view release on metacpan or search on metacpan
lib/API/Docker/Role/Entity/Config.pm view on Meta::CPAN
# generated classes are written from a specification that grows fields
# without asking. None of the five names collides today; a future one says so
# on the first `use`. `version_index` is the one to watch: the class already
# declares `version`.
{
my @provided = Package::Stash->new(__PACKAGE__)->list_all_symbols('CODE');
for my $class ('API::Docker::Type::Config') {
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::Config - Config operations, on the generated config type
=head1 VERSION
version 0.004
=head1 SYNOPSIS
my $docker = API::Docker->new;
my ($config) = @{ $docker->configs->list };
say $config->id;
say $config->spec->name;
say $config->spec->data; # still base64, as the daemon sent it
say $config->decoded_data; # the bytes
my %spec = %{ $config->spec->TO_JSON };
delete $spec{Data}; # already base64 -- see update
$spec{Labels} = { app => 'web' };
$config->update(%spec);
$config->remove;
=head1 DESCRIPTION
The convenience methods of a Docker config. This role is composed, at load
time, into L<API::Docker::Type::Config>, the generated class the daemon
answers config requests with -- the same definition for C<GET /configs> and
C<GET /configs/{id}>, so L<API::Docker::API::Configs/list> and
L<API::Docker::API::Configs/inspect> hand back one class and there is no
list-versus-inspect shape to keep apart.
A config is a secret whose value can be read back: the daemon returns it in
C<< spec->data >> as base64, where a secret returns no payload at all --
L<API::Docker::Role::Entity::Secret/"There is no accessor for the value">.
L</decoded_data> is the accessor for it.
=head2 Decoding is offered here, not in the API class
L<API::Docker::API::Configs> hands back the daemon's response with nothing
rewritten, which is the rule the whole distribution follows -- so
C<< $config->spec->data >> is the base64 string the engine sent, unchanged,
and stays that way. L</decoded_data> does not touch it either: it decodes on
demand and returns the bytes, leaving the spec verbatim for anyone who wants
to compare it against the wire or hand it back.
That is the whole reason the accessor belongs on the entity rather than on
the API class: an entity may offer a derived view of a response, an API
method may not silently replace one.
=head2 The spec goes back as a whole
C<< $config->spec >> is an L<API::Docker::Type::ConfigSpec> object rather
than the raw HashRef the hand-written entity kept, so the idiom for an update
is C<< %{ $config->spec->TO_JSON } >>: C<TO_JSON> renders the spec back into
the daemon's own spelling, which is what L</update> puts in the request body.
Mind the C<Data> it brings with it -- see L</update>.
Why the methods are a role applied to a generated class rather than a class
of their own: L<API::Docker::Role::Entity/DESCRIPTION>.
=head2 decoded_data
my $text = $config->decoded_data;
The config's content: C<< $config->spec->data >> run through
L<MIME::Base64/decode_base64>. Returns nothing when the object carries no
C<Spec> or no C<Data> in it.
The result is B<raw bytes>, symmetric with what
L<API::Docker::API::Configs/create> takes -- decode the character set yourself
if the config holds text above C<U+007F>, for instance with
C<Encode::decode_utf8>.
The spec is left alone; see
L</"Decoding is offered here, not in the API class">.
=head2 version_index
my $index = $config->version_index;
The C<< ->index >> out of C<< ->version >>, which is what the daemon wants as
the C<version> query parameter on an update. Returns nothing when the object
carries no C<Version> -- including the case where the daemon sent one the
model could not use, which leaves the attribute unset and the raw value in
C<< ->unknown_fields->{Version} >>.
It is the version as of the moment this object was fetched, which is exactly
the token's meaning: an update built on a stale entity is refused by the
daemon rather than silently overwriting whatever changed in between.
=head2 inspect
my $fresh = $config->inspect;
Get fresh config information. Returns another L<API::Docker::Type::Config> --
the same class, since the daemon describes a config one way.
=head2 update
my %spec = %{ $config->spec->TO_JSON };
delete $spec{Data}; # already base64 -- see below
$spec{Labels} = { app => 'web' };
$config->update(%spec);
Update the config. Passes C<< ->id >> and, by default, L</version_index> to
L<API::Docker::API::Configs/update>; everything else is the spec and becomes
the request body.
The default is only a default. A C<version> key in the arguments is used
verbatim and removed before the spec goes out -- the spec's own fields are all
capitalised (C<Name>, C<Labels>, C<Data>, ...), so a lowercase C<version>
cannot collide with one:
$config->update(version => $index, %spec);
A C<Data> passed here is raw bytes and gets encoded on the way out, so the
C<Data> that C<< $config->spec->TO_JSON >> brings along -- already base64 --
would be encoded a second time. Drop it, or pass L</decoded_data> in its
place.
=head2 remove
$config->remove;
Remove the config. The daemon answers 204 with no body, so this returns
nothing.
=head1 SEE ALSO
=over
=item * L<API::Docker::API::Configs> - the operations these forward to
=item * L<API::Docker::Type::Config> - the fields C<list> and C<inspect>
return
=item * L<API::Docker::Role::Entity::Secret> - the same shape for a value
that cannot be read back
=item * L<API::Docker::Role::Entity> - why the methods live in a role
=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 1.657 second using v1.01-cache-2.11-cpan-d01c6094234 )