Use new Secrets API (#1312)

* Use new Secrets API.

* Improve marking values algorithm.

* Avoid booleans, that are also integers in Python.

* Update changes from c.g.

* Add changelog fragment.

* Reformat.
This commit is contained in:
Felix Fontein
2026-09-28 22:37:53 +02:00
committed by GitHub
parent a361312a7e
commit 2e89484036
3 changed files with 67 additions and 5 deletions
@@ -0,0 +1,2 @@
minor_changes:
- "docker_swarm - on ansible-core 2.22+, the ``Manager`` and ``Worker`` join tokens and ``UnlockKey`` are marked as secrets (https://github.com/ansible-collections/community.docker/pull/1312)."
+49
View File
@@ -0,0 +1,49 @@
# Copyright (c) 2026 Felix Fontein <felix@fontein.de>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
from __future__ import annotations
import typing as t
from collections.abc import Mapping, Sequence
try:
from ansible.module_utils.secrets import register_secret, register_secrets # type: ignore[import-not-found]
HAS_SECRETS_API = True
except ImportError:
HAS_SECRETS_API = False
_T = t.TypeVar("_T")
def _collect_recursively(
value: t.Any, collected_values: list[str], *, int_to_string: bool = False
) -> None:
if isinstance(value, Mapping):
for v in value.items():
_collect_recursively(v, collected_values, int_to_string=int_to_string)
elif isinstance(value, str):
collected_values.append(value)
elif isinstance(value, Sequence):
for v in value:
_collect_recursively(v, collected_values, int_to_string=int_to_string)
elif int_to_string and isinstance(value, int) and not isinstance(value, bool):
collected_values.append(str(value))
def mark_values_as_secrets(value: _T, *, int_to_string: bool = False) -> _T:
"""Register all strings appearing in the (potentially nested) data structure ``value`` as secrets."""
if HAS_SECRETS_API:
collected_values: list[str] = []
_collect_recursively(value, collected_values, int_to_string=int_to_string)
if collected_values:
register_secrets(collected_values)
return value
def mark_as_secret(value: str) -> str:
"""Register a string as a secret."""
if HAS_SECRETS_API:
value = register_secret(value)
return value
+16 -5
View File
@@ -262,21 +262,29 @@ swarm_facts:
Worker:
description:
- Token to join the cluster as a new *worker* node.
- B(Note:) if this value has been specified as O(join_token), the value here will not be the token, but C(VALUE_SPECIFIED_IN_NO_LOG_PARAMETER).
- B(Note:) for ansible-core before 2.22, if this value has been specified as O(join_token),
the value here will not be the token, but C(VALUE_SPECIFIED_IN_NO_LOG_PARAMETER).
If you pass O(join_token), make sure your playbook/role does not depend on this return value!
For ansible-core 2.22+, this value is always properly returned. It will be registered as a secret,
though, and thus cannot be shown with M(ansible.builtin.debug).
returned: success
type: str
example: SWMTKN-1--xxxxx
Manager:
description:
- Token to join the cluster as a new *manager* node.
- B(Note:) if this value has been specified as O(join_token), the value here will not be the token, but C(VALUE_SPECIFIED_IN_NO_LOG_PARAMETER).
- B(Note:) for ansible-core before 2.22, if this value has been specified as O(join_token),
the value here will not be the token, but C(VALUE_SPECIFIED_IN_NO_LOG_PARAMETER).
If you pass O(join_token), make sure your playbook/role does not depend on this return value!
For ansible-core 2.22+, this value is always properly returned. It will be registered as a secret,
though, and thus cannot be shown with M(ansible.builtin.debug).
returned: success
type: str
example: SWMTKN-1--xxxxx
UnlockKey:
description: The swarm unlock-key if O(autolock_managers=true).
description:
- The swarm unlock-key if O(autolock_managers=true).
- B(Note) that on ansible-core 2.22+, this will be registered as a secret.
returned: on success if O(autolock_managers=true) and swarm is initialised, or if O(autolock_managers) has changed.
type: str
example: SWMKEY-1-xxx
@@ -302,6 +310,9 @@ except ImportError:
from ansible_collections.community.docker.plugins.module_utils._common import (
RequestException,
)
from ansible_collections.community.docker.plugins.module_utils._secrets import (
mark_values_as_secrets,
)
from ansible_collections.community.docker.plugins.module_utils._swarm import (
AnsibleDockerSwarmClient,
)
@@ -563,8 +574,8 @@ class SwarmManager(DockerBaseClass):
self.differences.add("state", parameter="present", active="absent")
self.results["changed"] = True
self.results["swarm_facts"] = {
"JoinTokens": self.swarm_info.get("JoinTokens"),
"UnlockKey": self.swarm_info.get("UnlockKey"),
"JoinTokens": mark_values_as_secrets(self.swarm_info.get("JoinTokens")),
"UnlockKey": mark_values_as_secrets(self.swarm_info.get("UnlockKey")),
}
def __update_swarm(self) -> None: