API-Docker

 view release on metacpan or  search on metacpan

lib/API/Docker/Role/Entity.pm  view on Meta::CPAN



1;

__END__

=pod

=encoding UTF-8

=head1 NAME

API::Docker::Role::Entity - The client reference an entity delegates through

=head1 VERSION

version 0.004

=head1 SYNOPSIS

    package API::Docker::Role::Entity::Container;
    use Moo::Role;
    with 'API::Docker::Role::Entity';
    requires 'id';
    use API::Docker::Type::ContainerSummary;
    use namespace::clean;

    sub start {
      my ($self) = @_;
      return $self->client->containers->start($self->id);
    }

    # at the bottom of the same file: the methods land on the generated class
    Moo::Role->apply_roles_to_package(
      'API::Docker::Type::ContainerSummary', __PACKAGE__);

=head1 DESCRIPTION

An entity is a generated L<API::Docker::Type> class that has been given the
convenience methods of its resource -- C<< $container->start >>,
C<< $container->logs >>, C<< $image->remove >>. The methods live in a role
that is applied to the generated class at load time; they are never written
into the generated file.

=head2 Why the methods are not in the generated class

They cannot be. C<maint/spec-to-type.pl --verify> renders every class under
C<lib/API/Docker/Type/> out of C<spec/v1.51.yaml> and requires the result to
match what is shipped B<byte for byte> (F<t/spec_to_type.t>), and the
generator refuses to overwrite a file that exists. A hand-added C<with> line
or method in one of those files fails the suite; there is no mode of the
generator that would put it back.

=head2 Why a role, and not a class that contains the type object

Because the daemon answers C<GET /containers/json> and
C<GET /containers/{id}/json> with two different definitions, which are two
different generated classes -- L<API::Docker::Type::ContainerSummary> and
L<API::Docker::Type::ContainerInspectResponse>. Both need the same methods.

A wrapper class holding a type object would be a second model beside the
generated one: every field access would have to be forwarded, and
C<< $container->state >> would return either the wrapper's idea of a state
or the type object's, depending on which one the caller happened to hold.
Composing a role into both generated classes leaves exactly one model.
C<< $docker->containers->list >> hands back real
L<API::Docker::Type::ContainerSummary> objects, C<TO_JSON> still produces
the daemon's own spelling, and the methods are written once.

Applying the role to each B<object> instead (C<apply_roles_to_object>) would
also work and was rejected: it reblesses every entity into a generated
subclass, which costs something per object and makes C<ref> report a name no
documentation mentions.

=head2 What this role contributes

The half every entity shares: the client the methods delegate through. The
resource-specific methods are in a role per resource, which composes this
one.

=head2 client

The L<API::Docker> client, held as a C<weak_ref> -- the client owns the
resource classes, which produce the entities, so a strong reference here
would close the cycle.

Being weak, it is C<undef> as soon as nothing else holds the client:
C<< API::Docker->new->containers->list >> returns entities whose C<client>
has already gone, and the first delegating call on one of them dies. Keep
the client in a live variable.

=head1 SEE ALSO

=over

=item * L<API::Docker::Role::Entity::Container> - the container entity

=item * L<API::Docker::Role::Type> - the generated classes' own behaviour

=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



( run in 1.112 second using v1.01-cache-2.11-cpan-d01c6094234 )