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 )