API-Docker

 view release on metacpan or  search on metacpan

t/timeout_forwarding.t  view on Meta::CPAN

  [ 'secrets->list', 'GET /secrets',
    'secrets' => sub { $_[0]->list } ],
  [ 'secrets->inspect', 'GET /secrets/s1',
    'secrets' => sub { $_[0]->inspect('s1') } ],
  [ 'secrets->remove', 'DELETE /secrets/s1',
    'secrets' => sub { $_[0]->remove('s1') } ],

  # -- configs -------------------------------------------------------------
  [ 'configs->list', 'GET /configs',
    'configs' => sub { $_[0]->list } ],
  [ 'configs->inspect', 'GET /configs/cf1',
    'configs' => sub { $_[0]->inspect('cf1') } ],
  [ 'configs->remove', 'DELETE /configs/cf1',
    'configs' => sub { $_[0]->remove('cf1') } ],

  # -- exec ----------------------------------------------------------------
  [ 'exec->start', 'POST /exec/e1/start',
    'exec' => sub { $_[0]->start('e1') } ],
  [ 'exec->resize', 'POST /exec/e1/resize',
    'exec' => sub { $_[0]->resize('e1', h => 40, w => 120) } ],
  [ 'exec->inspect', 'GET /exec/e1/json',
    'exec' => sub { $_[0]->inspect('e1') } ],

  # -- system --------------------------------------------------------------
  [ 'system->info', 'GET /info',
    'system' => sub { $_[0]->info } ],
  [ 'system->version', 'GET /version',
    'system' => sub { $_[0]->version } ],
  [ 'system->ping', 'GET /_ping',
    'system' => sub { $_[0]->ping } ],
  [ 'system->events', 'GET /events',
    'system' => sub { $_[0]->events } ],
  [ 'system->df', 'GET /system/df',
    'system' => sub { $_[0]->df } ],
  [ 'system->auth', 'POST /auth',
    'system' => sub { $_[0]->auth(username => 'u', password => 'p') } ],

  # -- plugins -------------------------------------------------------------
  [ 'plugins->list', 'GET /plugins',
    'plugins' => sub { $_[0]->list } ],
  [ 'plugins->privileges', 'GET /plugins/privileges',
    'plugins' => sub { $_[0]->privileges('p') } ],
  [ 'plugins->install', 'POST /plugins/pull',
    'plugins' => sub { $_[0]->install('p', privileges => []) } ],
  [ 'plugins->install privileges pre-flight', 'GET /plugins/privileges',
    'plugins' => sub { $_[0]->install('p', accept_privileges => 1) } ],
  [ 'plugins->inspect', 'GET /plugins/p/json',
    'plugins' => sub { $_[0]->inspect('p') } ],
  [ 'plugins->remove', 'DELETE /plugins/p',
    'plugins' => sub { $_[0]->remove('p') } ],
  [ 'plugins->enable', 'POST /plugins/p/enable',
    'plugins' => sub { $_[0]->enable('p') } ],
  [ 'plugins->disable', 'POST /plugins/p/disable',
    'plugins' => sub { $_[0]->disable('p') } ],
  [ 'plugins->upgrade', 'POST /plugins/p/upgrade',
    'plugins' => sub { $_[0]->upgrade('p', privileges => []) } ],
  [ 'plugins->upgrade privileges pre-flight', 'GET /plugins/privileges',
    'plugins' => sub { $_[0]->upgrade('p', accept_privileges => 1) } ],
  [ 'plugins->push', 'POST /plugins/p/push',
    'plugins' => sub { $_[0]->push('p') } ],
  [ 'plugins->configure', 'POST /plugins/p/set',
    'plugins' => sub { $_[0]->configure('p', ['A=1']) } ],

  # -- distribution --------------------------------------------------------
  [ 'distribution->inspect', 'GET /distribution/alpine/json',
    'distribution' => sub { $_[0]->inspect('alpine') } ],
  [ 'distribution->exists', 'GET /distribution/alpine/json',
    'distribution' => sub { $_[0]->exists('alpine') } ],
);

# The option list the named endpoint was requested with, or a string saying
# why there is none -- which is_deeply then reports instead of an empty hash.
# @using is what the resource class is cloned with; empty means it is used as
# it comes off the client.
sub opts_for {
  my ($case, @using) = @_;
  my (undef, $want, $accessor, $code) = @$case;

  my $probe = Test::TimeoutForward::Probe->new(
    host => 'unix:///nonexistent-api-docker-74.sock', api_version => '1.41');

  my $resource = $probe->$accessor;
  $resource = $resource->using(@using) if @using;

  eval { $code->($resource); 1 }
    or return 'the call died before requesting anything: ' . $@;

  my @seen;
  for my $call (@{ $probe->calls }) {
    my $endpoint = $call->{method} . ' ' . $call->{path};
    push @seen, $endpoint;
    return $call->{opts} if $endpoint eq $want;
  }
  return "never requested $want (requested: " . join(', ', @seen) . ')';
}

# What of the two the request was actually given, in a shape is_deeply can
# report: the string opts_for returns when the endpoint was never reached is
# passed through rather than turned into an empty hash.
sub bounds_of {
  my ($opts) = @_;
  return $opts unless ref $opts eq 'HASH';
  return { map { exists $opts->{$_} ? ($_ => $opts->{$_}) : () }
    qw( read_timeout connect_timeout ) };
}

# ---------------------------------------------------------------------------
subtest 'both bounds reach the request the method makes' => sub {
  for my $case (@cases) {
    is_deeply bounds_of(opts_for($case, read_timeout => 3, connect_timeout => 7)),
      { read_timeout => 3, connect_timeout => 7 },
      $case->[0] . ' carries both';
  }
};

# The subtlety `exists` buys, and the one a `? :` on truth would lose: 0 is
# "wait as long as it takes", which is how a client-wide default is turned off
# for a run of calls. Carried on truth it would vanish here and the client
# attribute would win -- the opposite of what the caller asked for.
subtest 'an explicit 0 is carried, not read as "no opinion"' => sub {
  for my $case (@cases) {
    is_deeply bounds_of(opts_for($case, read_timeout => 0, connect_timeout => 0)),



( run in 0.512 second using v1.01-cache-2.11-cpan-aadc1410aed )