API-Docker

 view release on metacpan or  search on metacpan

t/containers_endpoints.t  view on Meta::CPAN

  ok $seen{raw}, 'the request asked the transport for raw bytes';
  ok !$seen{ndjson}, 'and not for a decoded event stream';
  is_deeply $seen{params}, { path => '/etc/hostname' },
    'path is the only query parameter';
  is $out, $TAR, 'the daemon bytes come back verbatim';
  is length($out), length($TAR), 'no truncation';
};

subtest 'get_archive: raw bytes survive the real _request' => sub {
  my $t = fake_client();
  $t->canned([200, 'OK', { 'content-type' => 'application/x-tar' }, $TAR]);

  my $out = $t->containers->get_archive('deadbeef', path => '/var/log/app.log');

  is $out, $TAR, 'byte-exact through _request';
  is $t->request_line,
    'GET /v1.41/containers/deadbeef/archive?path=/var/log/app.log HTTP/1.1',
    'GET on the versioned path, the path parameter keeping its slashes';
};

subtest 'get_archive: a body that looks like JSON is still not decoded' => sub {

t/containers_endpoints.t  view on Meta::CPAN

  is_deeply $t->containers->attach('deadbeef', require_running => 0), [],
    'a container that wrote nothing gives no frames, not undef';
};

# ===========================================================================
# karr k23 -- changes, export, resize
# ===========================================================================

subtest 'changes: the diff, and what the Kind numbers are' => sub {
  my $t = fake_client();
  $t->canned([200, 'OK', { 'content-type' => 'application/json' },
    '[{"Path":"/etc/hostname","Kind":0},{"Path":"/tmp/new","Kind":1},'
    . '{"Path":"/etc/gone","Kind":2}]']);

  my $changes = $t->containers->changes('deadbeef');

  is $t->request_line, 'GET /v1.41/containers/deadbeef/changes HTTP/1.1',
    'GET on the changes path, no query parameters';
  is ref $changes, 'ARRAY', 'an ArrayRef';
  is scalar @$changes, 3, 'one entry per changed path';
  is_deeply $changes->[0], { Path => '/etc/hostname', Kind => 0 }, '0 is modified';

t/containers_endpoints.t  view on Meta::CPAN

  my $err = do { local $@; eval { $t->containers->changes }; $@ };
  like $err, qr/Container ID required/, 'a missing id croaks';
};

subtest 'changes: a container with nothing changed is an empty ArrayRef' => sub {
  # The engine answers that case with a JSON null. The transport decodes any
  # JSON body, scalars included (karr k30), so a null body reaches this
  # method as undef -- which a caller iterating the result would dereference
  # and die on just the same.
  my $t = fake_client();
  $t->canned([200, 'OK', { 'content-type' => 'application/json' }, 'null']);

  is_deeply $t->containers->changes('deadbeef'), [],
    'a null body is normalised to an empty ArrayRef, not left as undef';

  $t->canned([204, 'No Content', {}, '']);
  is_deeply $t->containers->changes('deadbeef'), [],
    'and so is an empty body';
};

subtest 'export: raw tar bytes, never decoded' => sub {
  my $t = fake_client();
  $t->canned([200, 'OK', { 'content-type' => 'application/x-tar' }, $TAR]);

  my $out = $t->containers->export('deadbeef');

  is $t->request_line, 'GET /v1.41/containers/deadbeef/export HTTP/1.1',
    'GET on the export path';
  is $out, $TAR, 'byte-exact';
  is length($out), length($TAR), 'no truncation';

  $t->canned([200, 'OK', {}, '{"Id":"not really a tar"}']);
  is ref $t->containers->export('deadbeef'), '',

t/images_build_prune.t  view on Meta::CPAN

    'all three parameters present, sorted by key';
};

# ---------------------------------------------------------------------------
subtest 'the Podman 404 croaks with the plain-text body' => sub {
  # Podman 5.4.2 does not implement /build/prune and answers text/plain,
  # so there is no {"message":...} for the transport to unwrap. A caller that
  # must work on both engines reads this as "no build cache here".
  my $t = fake_client();
  $t->canned([404, 'Not Found',
    { 'content-type' => 'text/plain; charset=utf-8' }, "Not Found\n"]);

  my $err = do { local $@; eval { $t->images->build_prune(all => 1) }; $@ };
  like $err, qr/Docker API error \(404\)/, 'it croaks rather than returning undef';
  like $err, qr/Not Found/, 'with the plain body, since it is not JSON to unwrap';
};

done_testing;

t/images_tar.t  view on Meta::CPAN

  is $out, $TAR, 'the daemon bytes come back verbatim';
  is length($out), length($TAR), 'no truncation';

  my $err = do { local $@; eval { $docker->images->get }; $@ };
  like $err, qr/Image name required/, 'a missing name croaks';
};

# ---------------------------------------------------------------------------
subtest 'get: raw bytes survive the real _request' => sub {
  my $t = fake_client();
  $t->canned([200, 'OK', { 'content-type' => 'application/octet' }, $TAR]);

  my $out = $t->images->get('alpine:3');

  is $out, $TAR, 'byte-exact through _request';
  like $t->written, qr{\AGET /v1\.41/images/alpine:3/get HTTP/1\.1\r\n},
    'the request line keeps the colon in the image reference';
};

subtest 'get: a body that looks like JSON is still not decoded' => sub {
  # The transport tries decode_json on any body starting with { or [ unless

t/images_tar.t  view on Meta::CPAN

    'the digest @ is percent-encoded, the colon after sha256 is not';
  like $line, qr{names=has%20space}, 'a space is encoded';

  my $err = do { local $@; eval { $t->images->get_all }; $@ };
  like $err, qr/At least one image name required/, 'no names croaks';
};

# ---------------------------------------------------------------------------
subtest 'load: sends the tar as the body and decodes the progress stream' => sub {
  my $t = fake_client();
  $t->canned([200, 'OK', { 'content-type' => 'application/json' }, $STREAM]);

  my $events = $t->images->load($TAR);

  is ref $events, 'ARRAY', 'an ArrayRef of events, as for build and pull';
  is scalar @$events, 1, 'the captured stream carried one object';
  like $events->[0]{stream}, qr/^Loaded image: /, 'and it names what was loaded';

  my $req = $t->written;
  like $req, qr{\APOST /v1\.41/images/load HTTP/1\.1\r\n},
    'no query string when quiet was not asked for';

t/role_http.t  view on Meta::CPAN

  my $raw = "HTTP/1.1 200 OK\r\n"
    . "Content-Type: application/json\r\n"
    . "X-Mixed-CASE:   value with spaces  \r\n"
    . "Content-Length: 2\r\n"
    . "\r\n"
    . "{}";
  my $fh = string_handle($raw);
  my $resp = $client->_read_response($fh);
  my $headers = $resp->[2];

  is $headers->{'content-type'}, 'application/json',
    'an already-lowercase key is kept';
  is $headers->{'x-mixed-case'}, 'value with spaces  ',
    'a mixed-case key is lowercased; leading space after the colon is '
    . 'trimmed, the rest of the value is kept verbatim (trailing spaces too)';
  is $headers->{'content-length'}, '2', 'colon splits key from value';
  is $resp->[3], '{}', 'body still decoded via content-length';
};

subtest '_read_response: chunked body' => sub {
  my $raw = "HTTP/1.1 200 OK\r\n"



( run in 2.713 seconds using v1.01-cache-2.11-cpan-800906f7e73 )