API-Docker
view release on metacpan or search on metacpan
t/secrets_configs.t view on Meta::CPAN
use strict;
use warnings;
use Test::More;
use MIME::Base64 qw( decode_base64 );
use API::Docker::Role::Entity::Config;
use API::Docker::Role::Entity::Secret;
use API::Docker::Error::HTTP;
use lib 't/lib';
use Test::API::Docker::Mock;
check_live_access();
# Most of what this file asserts is the shape of the *outgoing* request --
# that Data leaves as base64 and that Version.Index leaves as the `version`
# query parameter. Neither is visible from a response, so those subtests are
# mock-only and say so rather than passing vacuously against a daemon.
my $REQUEST_SHAPE = 'asserts the outgoing request; only the mock can see it';
# The Engine API reference's shape for a config, kept inline instead of in
# t/fixtures/: the files there are captured from a real daemon, and no engine
# reachable from this repo serves /configs. Podman answers the collection GET
# (/configs) with a plain-text "Not Found" 404, unchanged since it was first
# measured on 5.4.2 / API 1.41 -- but every item-scoped route under it
# (create, inspect, update, remove) answers 503 JSON instead, not the same
# 404 (re-measured live, Podman 5.8.4 / API 1.44, karr k62; see the
# $CONFIGS_UNSERVED comment below for the detail). No engine serving
# /configs was at hand when this was written, so there is no
# configs_list.json: a hand-rolled file dressed up as a capture would be
# worse than none.
my $CONFIG = {
ID => 'ktnbjxoalbkvbvedmg1urrz8h',
Version => { Index => 11 },
CreatedAt => '2016-11-05T01:20:17.327670065Z',
UpdatedAt => '2016-11-05T01:20:17.327670065Z',
Spec => {
Name => 'server.conf',
Labels => { 'com.example.some-label' => 'some-value' },
Data => 'bGlzdGVuIDgwODA7Cg==',
},
};
# --- Read paths -------------------------------------------------------------
subtest 'secrets list' => sub {
my $docker = test_docker('GET /secrets' => load_fixture('secrets_list'));
my $secrets = eval { $docker->secrets->list };
if (my $err = $@) {
die $err unless is_live() && ref($err) && $err->isa('API::Docker::Error::HTTP')
&& $err->status == 503;
# Docker serves /secrets only on an initialised swarm manager; a plain
# single-node install -- the normal state of a development machine, and
# what this daemon is -- answers 503 "This node is not a swarm manager"
# here instead of a list (measured live, Docker 29.7.2 / API 1.55).
# `docker swarm init` would clear it, but that is a real change to the
# host's networking (an overlay network, a firewall rule) that no test
# may make, so this is a skip and not a workaround. Reacting to the
# status rather than pre-checking GET /info's Swarm.LocalNodeState is
# deliberate: Podman answers "inactive" there too, despite serving
# /secrets from its own local secret store with no swarm involved --
# a pre-check on that field would skip the one live engine this subtest
# actually covers (measured live, Podman 5.4.2 / API 1.41).
plan skip_all => "daemon refuses /secrets outside a swarm (503): $err";
}
is(ref $secrets, 'ARRAY', 'list returns an ArrayRef');
return if is_live();
is(scalar @$secrets, 2, 'two secrets in the fixture');
isa_ok($secrets->[0], 'API::Docker::Type::Secret', 'entries are wrapped and the first one');
isa_ok($secrets->[1], 'API::Docker::Type::Secret', 'so is the second');
is($secrets->[0]->id, '28497238e77f873904ff31cb2', 'id off the entity');
is($secrets->[0]->spec->name, 'db-password', 'first secret name');
is($secrets->[0]->version_index, 1, 'version_index reaches the Version.Index that update needs');
is($secrets->[0]->created_at, '2026-08-27T05:01:40.791536705Z', 'created_at is carried');
( run in 1.011 second using v1.01-cache-2.11-cpan-a49fcb8fa48 )