update ansible collections sops, docker and debops
All checks were successful
/ build (pull_request) Successful in 28s
/ Ansible Lint (push) Successful in 2m36s
/ Ansible Lint (pull_request) Successful in 2m41s

This commit is contained in:
chris 2026-09-21 22:26:20 +02:00
commit e31ee5e39c
Signed by: c6ristian
SSH key fingerprint: SHA256:B3m+yzpaxGXSEcDBpPHfvza/DNC0wuX+CKMeGq8wgak
910 changed files with 27667 additions and 19786 deletions

View file

@ -21,7 +21,7 @@ jobs:
name: "Run extra sanity tests"
steps:
- name: Check out collection
uses: actions/checkout@v5
uses: actions/checkout@v6
with:
persist-credentials: false
- name: Run nox

View file

@ -0,0 +1,14 @@
# Copyright (c) Ansible Project
# 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
[mypy]
# check_untyped_defs = True
# disallow_untyped_defs = True -- not yet feasible
# strict = True -- only try to enable once everything is typed
strict_equality = True
[mypy-ansible.*]
# ansible-core has partial typing information
follow_untyped_imports = True

View file

@ -2,157 +2,197 @@
**Topics**
- <a href="#v2-2-7">v2\.2\.7</a>
- <a href="#v2-4-0">v2\.4\.0</a>
- <a href="#release-summary">Release Summary</a>
- <a href="#minor-changes">Minor Changes</a>
- <a href="#v2-3-0">v2\.3\.0</a>
- <a href="#release-summary-1">Release Summary</a>
- <a href="#minor-changes-1">Minor Changes</a>
- <a href="#v2-2-7">v2\.2\.7</a>
- <a href="#release-summary-2">Release Summary</a>
- <a href="#known-issues">Known Issues</a>
- <a href="#v2-2-6">v2\.2\.6</a>
- <a href="#release-summary-1">Release Summary</a>
- <a href="#release-summary-3">Release Summary</a>
- <a href="#bugfixes">Bugfixes</a>
- <a href="#v2-2-5">v2\.2\.5</a>
- <a href="#release-summary-2">Release Summary</a>
- <a href="#release-summary-4">Release Summary</a>
- <a href="#bugfixes-1">Bugfixes</a>
- <a href="#v2-2-4">v2\.2\.4</a>
- <a href="#release-summary-3">Release Summary</a>
- <a href="#release-summary-5">Release Summary</a>
- <a href="#bugfixes-2">Bugfixes</a>
- <a href="#v2-2-3">v2\.2\.3</a>
- <a href="#release-summary-4">Release Summary</a>
- <a href="#minor-changes">Minor Changes</a>
- <a href="#release-summary-6">Release Summary</a>
- <a href="#minor-changes-2">Minor Changes</a>
- <a href="#bugfixes-3">Bugfixes</a>
- <a href="#v2-2-2">v2\.2\.2</a>
- <a href="#release-summary-5">Release Summary</a>
- <a href="#release-summary-7">Release Summary</a>
- <a href="#bugfixes-4">Bugfixes</a>
- <a href="#v2-2-1">v2\.2\.1</a>
- <a href="#release-summary-6">Release Summary</a>
- <a href="#release-summary-8">Release Summary</a>
- <a href="#bugfixes-5">Bugfixes</a>
- <a href="#v2-2-0">v2\.2\.0</a>
- <a href="#release-summary-7">Release Summary</a>
- <a href="#minor-changes-1">Minor Changes</a>
- <a href="#v2-1-0">v2\.1\.0</a>
- <a href="#release-summary-8">Release Summary</a>
- <a href="#minor-changes-2">Minor Changes</a>
- <a href="#v2-0-5">v2\.0\.5</a>
- <a href="#release-summary-9">Release Summary</a>
- <a href="#v2-0-4">v2\.0\.4</a>
- <a href="#minor-changes-3">Minor Changes</a>
- <a href="#v2-1-0">v2\.1\.0</a>
- <a href="#release-summary-10">Release Summary</a>
- <a href="#minor-changes-4">Minor Changes</a>
- <a href="#v2-0-5">v2\.0\.5</a>
- <a href="#release-summary-11">Release Summary</a>
- <a href="#v2-0-4">v2\.0\.4</a>
- <a href="#release-summary-12">Release Summary</a>
- <a href="#bugfixes-6">Bugfixes</a>
- <a href="#v2-0-3">v2\.0\.3</a>
- <a href="#release-summary-11">Release Summary</a>
- <a href="#release-summary-13">Release Summary</a>
- <a href="#bugfixes-7">Bugfixes</a>
- <a href="#v2-0-2">v2\.0\.2</a>
- <a href="#release-summary-12">Release Summary</a>
- <a href="#release-summary-14">Release Summary</a>
- <a href="#bugfixes-8">Bugfixes</a>
- <a href="#v2-0-1">v2\.0\.1</a>
- <a href="#release-summary-13">Release Summary</a>
- <a href="#release-summary-15">Release Summary</a>
- <a href="#v2-0-0">v2\.0\.0</a>
- <a href="#release-summary-14">Release Summary</a>
- <a href="#release-summary-16">Release Summary</a>
- <a href="#removed-features-previously-deprecated">Removed Features \(previously deprecated\)</a>
- <a href="#v1-9-1">v1\.9\.1</a>
- <a href="#release-summary-15">Release Summary</a>
- <a href="#release-summary-17">Release Summary</a>
- <a href="#bugfixes-9">Bugfixes</a>
- <a href="#v1-9-0">v1\.9\.0</a>
- <a href="#release-summary-16">Release Summary</a>
- <a href="#minor-changes-3">Minor Changes</a>
- <a href="#release-summary-18">Release Summary</a>
- <a href="#minor-changes-5">Minor Changes</a>
- <a href="#v1-8-2">v1\.8\.2</a>
- <a href="#release-summary-17">Release Summary</a>
- <a href="#release-summary-19">Release Summary</a>
- <a href="#deprecated-features">Deprecated Features</a>
- <a href="#v1-8-1">v1\.8\.1</a>
- <a href="#release-summary-18">Release Summary</a>
- <a href="#release-summary-20">Release Summary</a>
- <a href="#bugfixes-10">Bugfixes</a>
- <a href="#v1-8-0">v1\.8\.0</a>
- <a href="#release-summary-19">Release Summary</a>
- <a href="#minor-changes-4">Minor Changes</a>
- <a href="#release-summary-21">Release Summary</a>
- <a href="#minor-changes-6">Minor Changes</a>
- <a href="#bugfixes-11">Bugfixes</a>
- <a href="#v1-7-0">v1\.7\.0</a>
- <a href="#release-summary-20">Release Summary</a>
- <a href="#minor-changes-5">Minor Changes</a>
- <a href="#release-summary-22">Release Summary</a>
- <a href="#minor-changes-7">Minor Changes</a>
- <a href="#bugfixes-12">Bugfixes</a>
- <a href="#v1-6-7">v1\.6\.7</a>
- <a href="#release-summary-21">Release Summary</a>
- <a href="#release-summary-23">Release Summary</a>
- <a href="#bugfixes-13">Bugfixes</a>
- <a href="#v1-6-6">v1\.6\.6</a>
- <a href="#release-summary-22">Release Summary</a>
- <a href="#release-summary-24">Release Summary</a>
- <a href="#bugfixes-14">Bugfixes</a>
- <a href="#v1-6-5">v1\.6\.5</a>
- <a href="#release-summary-23">Release Summary</a>
- <a href="#release-summary-25">Release Summary</a>
- <a href="#bugfixes-15">Bugfixes</a>
- <a href="#v1-6-4">v1\.6\.4</a>
- <a href="#release-summary-24">Release Summary</a>
- <a href="#release-summary-26">Release Summary</a>
- <a href="#bugfixes-16">Bugfixes</a>
- <a href="#v1-6-3">v1\.6\.3</a>
- <a href="#release-summary-25">Release Summary</a>
- <a href="#release-summary-27">Release Summary</a>
- <a href="#known-issues-1">Known Issues</a>
- <a href="#v1-6-2">v1\.6\.2</a>
- <a href="#release-summary-26">Release Summary</a>
- <a href="#release-summary-28">Release Summary</a>
- <a href="#bugfixes-17">Bugfixes</a>
- <a href="#v1-6-1">v1\.6\.1</a>
- <a href="#release-summary-27">Release Summary</a>
- <a href="#release-summary-29">Release Summary</a>
- <a href="#bugfixes-18">Bugfixes</a>
- <a href="#v1-6-0">v1\.6\.0</a>
- <a href="#release-summary-28">Release Summary</a>
- <a href="#minor-changes-6">Minor Changes</a>
- <a href="#release-summary-30">Release Summary</a>
- <a href="#minor-changes-8">Minor Changes</a>
- <a href="#v1-5-0">v1\.5\.0</a>
- <a href="#release-summary-29">Release Summary</a>
- <a href="#minor-changes-7">Minor Changes</a>
- <a href="#release-summary-31">Release Summary</a>
- <a href="#minor-changes-9">Minor Changes</a>
- <a href="#new-playbooks">New Playbooks</a>
- <a href="#new-roles">New Roles</a>
- <a href="#v1-4-1">v1\.4\.1</a>
- <a href="#release-summary-30">Release Summary</a>
- <a href="#release-summary-32">Release Summary</a>
- <a href="#bugfixes-19">Bugfixes</a>
- <a href="#v1-4-0">v1\.4\.0</a>
- <a href="#release-summary-31">Release Summary</a>
- <a href="#minor-changes-8">Minor Changes</a>
- <a href="#v1-3-0">v1\.3\.0</a>
- <a href="#release-summary-32">Release Summary</a>
- <a href="#minor-changes-9">Minor Changes</a>
- <a href="#v1-2-3">v1\.2\.3</a>
- <a href="#release-summary-33">Release Summary</a>
- <a href="#v1-2-2">v1\.2\.2</a>
- <a href="#minor-changes-10">Minor Changes</a>
- <a href="#v1-3-0">v1\.3\.0</a>
- <a href="#release-summary-34">Release Summary</a>
- <a href="#minor-changes-11">Minor Changes</a>
- <a href="#v1-2-3">v1\.2\.3</a>
- <a href="#release-summary-35">Release Summary</a>
- <a href="#v1-2-2">v1\.2\.2</a>
- <a href="#release-summary-36">Release Summary</a>
- <a href="#bugfixes-20">Bugfixes</a>
- <a href="#v1-2-1">v1\.2\.1</a>
- <a href="#release-summary-35">Release Summary</a>
- <a href="#release-summary-37">Release Summary</a>
- <a href="#v1-2-0">v1\.2\.0</a>
- <a href="#release-summary-36">Release Summary</a>
- <a href="#minor-changes-10">Minor Changes</a>
- <a href="#release-summary-38">Release Summary</a>
- <a href="#minor-changes-12">Minor Changes</a>
- <a href="#bugfixes-21">Bugfixes</a>
- <a href="#v1-1-0">v1\.1\.0</a>
- <a href="#release-summary-37">Release Summary</a>
- <a href="#minor-changes-11">Minor Changes</a>
- <a href="#release-summary-39">Release Summary</a>
- <a href="#minor-changes-13">Minor Changes</a>
- <a href="#new-plugins">New Plugins</a>
- <a href="#filter">Filter</a>
- <a href="#v1-0-6">v1\.0\.6</a>
- <a href="#release-summary-38">Release Summary</a>
- <a href="#release-summary-40">Release Summary</a>
- <a href="#bugfixes-22">Bugfixes</a>
- <a href="#v1-0-5">v1\.0\.5</a>
- <a href="#release-summary-39">Release Summary</a>
- <a href="#release-summary-41">Release Summary</a>
- <a href="#bugfixes-23">Bugfixes</a>
- <a href="#v1-0-4">v1\.0\.4</a>
- <a href="#release-summary-40">Release Summary</a>
- <a href="#release-summary-42">Release Summary</a>
- <a href="#security-fixes">Security Fixes</a>
- <a href="#v1-0-3">v1\.0\.3</a>
- <a href="#release-summary-41">Release Summary</a>
- <a href="#release-summary-43">Release Summary</a>
- <a href="#bugfixes-24">Bugfixes</a>
- <a href="#v1-0-2">v1\.0\.2</a>
- <a href="#release-summary-42">Release Summary</a>
- <a href="#v1-0-1">v1\.0\.1</a>
- <a href="#release-summary-43">Release Summary</a>
- <a href="#v1-0-0">v1\.0\.0</a>
- <a href="#release-summary-44">Release Summary</a>
- <a href="#minor-changes-12">Minor Changes</a>
- <a href="#v0-2-0">v0\.2\.0</a>
- <a href="#v1-0-1">v1\.0\.1</a>
- <a href="#release-summary-45">Release Summary</a>
- <a href="#minor-changes-13">Minor Changes</a>
- <a href="#v0-1-0">v0\.1\.0</a>
- <a href="#v1-0-0">v1\.0\.0</a>
- <a href="#release-summary-46">Release Summary</a>
- <a href="#minor-changes-14">Minor Changes</a>
- <a href="#v0-2-0">v0\.2\.0</a>
- <a href="#release-summary-47">Release Summary</a>
- <a href="#minor-changes-15">Minor Changes</a>
- <a href="#v0-1-0">v0\.1\.0</a>
- <a href="#release-summary-48">Release Summary</a>
- <a href="#new-plugins-1">New Plugins</a>
- <a href="#lookup">Lookup</a>
- <a href="#vars">Vars</a>
- <a href="#new-modules">New Modules</a>
<a id="v2-4-0"></a>
## v2\.4\.0
<a id="release-summary"></a>
### Release Summary
Feature release\.
<a id="minor-changes"></a>
### Minor Changes
* Support OpenSuSE Tumbleweed \(and probably also Leap\) in the community\.sops\.install role\. Right now only Tumbleweed is tested in CI\, so support for Leap has not been verified \([https\://github\.com/ansible\-collections/community\.sops/pull/299](https\://github\.com/ansible\-collections/community\.sops/pull/299)\)\.
<a id="v2-3-0"></a>
## v2\.3\.0
<a id="release-summary-1"></a>
### Release Summary
Feature release\.
The main new feature of this release is ansible\-core 2\.21 support for <code>community\.sops\.load\_vars</code>\.
ansible\-core 2\.21 is the first version to explicitly allow action plugins to set variables\,
which finally allows <code>community\.sops\.load\_vars</code> to set variables the same way as
<code>ansible\.builtin\.include\_vars</code>\.
<a id="minor-changes-1"></a>
### Minor Changes
* all modules and plugins \- allow retrieving private age keys and private SSH keys through commands with the new <code>age\_key\_cmd</code> and <code>age\_ssh\_private\_key\_cmd</code> options \([https\://github\.com/ansible\-collections/community\.sops/issues/282](https\://github\.com/ansible\-collections/community\.sops/issues/282)\, [https\://github\.com/ansible\-collections/community\.sops/pull/286](https\://github\.com/ansible\-collections/community\.sops/pull/286)\)\.
* all modules and plugins \- allow to configure GCP access with the <code>gcp\_oauth\_access\_token</code> and <code>gcp\_kms\_client\_type</code> options \([https\://github\.com/ansible\-collections/community\.sops/issues/282](https\://github\.com/ansible\-collections/community\.sops/issues/282)\, [https\://github\.com/ansible\-collections/community\.sops/pull/286](https\://github\.com/ansible\-collections/community\.sops/pull/286)\)\.
* load\_vars \- now supports ansible\-core 2\.21\'s way of actually loading variables\, instead of returning <code>ansible\_facts</code>\. The behavior for this can be controlled through the new <code>return\_method</code> option\, which is by default set to <code>auto</code>\. On ansible\-core 2\.21\+\, <code>auto</code> behaves the same as <code>vars\-only</code> \(return proper variables\)\, and for ansible\-core before 2\.21 the same as <code>facts\-only</code> \(return <code>ansible\_facts</code>\) \([https\://github\.com/ansible\-collections/community\.sops/pull/283](https\://github\.com/ansible\-collections/community\.sops/pull/283)\)\.
* sops\_encrypt \- support providing HuaweiCloud KMS key IDs with the <code>huawei\_cloud\_kms</code> option \([https\://github\.com/ansible\-collections/community\.sops/issues/282](https\://github\.com/ansible\-collections/community\.sops/issues/282)\, [https\://github\.com/ansible\-collections/community\.sops/pull/286](https\://github\.com/ansible\-collections/community\.sops/pull/286)\)\.
<a id="v2-2-7"></a>
## v2\.2\.7
<a id="release-summary"></a>
<a id="release-summary-2"></a>
### Release Summary
Maintenance release\.
@ -165,7 +205,7 @@ Maintenance release\.
<a id="v2-2-6"></a>
## v2\.2\.6
<a id="release-summary-1"></a>
<a id="release-summary-3"></a>
### Release Summary
Bugfix and maintenance release\.
@ -180,7 +220,7 @@ Bugfix and maintenance release\.
<a id="v2-2-5"></a>
## v2\.2\.5
<a id="release-summary-2"></a>
<a id="release-summary-4"></a>
### Release Summary
Maintenance release\.
@ -194,7 +234,7 @@ Maintenance release\.
<a id="v2-2-4"></a>
## v2\.2\.4
<a id="release-summary-3"></a>
<a id="release-summary-5"></a>
### Release Summary
Maintenance release\.
@ -207,12 +247,12 @@ Maintenance release\.
<a id="v2-2-3"></a>
## v2\.2\.3
<a id="release-summary-4"></a>
<a id="release-summary-6"></a>
### Release Summary
Maintenance release\.
<a id="minor-changes"></a>
<a id="minor-changes-2"></a>
### Minor Changes
* Note that some new code in <code>plugins/module\_utils/\_six\.py</code> is MIT licensed \([https\://github\.com/ansible\-collections/community\.sops/pull/268](https\://github\.com/ansible\-collections/community\.sops/pull/268)\)\.
@ -225,7 +265,7 @@ Maintenance release\.
<a id="v2-2-2"></a>
## v2\.2\.2
<a id="release-summary-5"></a>
<a id="release-summary-7"></a>
### Release Summary
Bugfix release\.
@ -239,7 +279,7 @@ Bugfix release\.
<a id="v2-2-1"></a>
## v2\.2\.1
<a id="release-summary-6"></a>
<a id="release-summary-8"></a>
### Release Summary
Bugfix release\.
@ -252,12 +292,12 @@ Bugfix release\.
<a id="v2-2-0"></a>
## v2\.2\.0
<a id="release-summary-7"></a>
<a id="release-summary-9"></a>
### Release Summary
Feature release\.
<a id="minor-changes-1"></a>
<a id="minor-changes-3"></a>
### Minor Changes
* load\_vars \- expressions can now be lazily evaluated when using ansible\-core 2\.19 or newer \([https\://github\.com/ansible\-collections/community\.sops/pull/229](https\://github\.com/ansible\-collections/community\.sops/pull/229)\)\.
@ -265,12 +305,12 @@ Feature release\.
<a id="v2-1-0"></a>
## v2\.1\.0
<a id="release-summary-8"></a>
<a id="release-summary-10"></a>
### Release Summary
Feature release\.
<a id="minor-changes-2"></a>
<a id="minor-changes-4"></a>
### Minor Changes
* Now supports specifying SSH private keys for age with the new <code>age\_ssh\_private\_keyfile</code> option \([https\://github\.com/ansible\-collections/community\.sops/pull/241](https\://github\.com/ansible\-collections/community\.sops/pull/241)\)\.
@ -278,7 +318,7 @@ Feature release\.
<a id="v2-0-5"></a>
## v2\.0\.5
<a id="release-summary-9"></a>
<a id="release-summary-11"></a>
### Release Summary
Maintenance release with updated SOPS version test coverage\.
@ -286,7 +326,7 @@ Maintenance release with updated SOPS version test coverage\.
<a id="v2-0-4"></a>
## v2\.0\.4
<a id="release-summary-10"></a>
<a id="release-summary-12"></a>
### Release Summary
Maintenance release with Data Tagging support\.
@ -299,7 +339,7 @@ Maintenance release with Data Tagging support\.
<a id="v2-0-3"></a>
## v2\.0\.3
<a id="release-summary-11"></a>
<a id="release-summary-13"></a>
### Release Summary
Bugfix release\.
@ -312,7 +352,7 @@ Bugfix release\.
<a id="v2-0-2"></a>
## v2\.0\.2
<a id="release-summary-12"></a>
<a id="release-summary-14"></a>
### Release Summary
Bugfix release\.
@ -325,7 +365,7 @@ Bugfix release\.
<a id="v2-0-1"></a>
## v2\.0\.1
<a id="release-summary-13"></a>
<a id="release-summary-15"></a>
### Release Summary
Maintenance release with updated documentation\.
@ -333,7 +373,7 @@ Maintenance release with updated documentation\.
<a id="v2-0-0"></a>
## v2\.0\.0
<a id="release-summary-14"></a>
<a id="release-summary-16"></a>
### Release Summary
Major verison that drops support for End of Life Ansible/ansible\-base/ansible\-core versions\.
@ -346,7 +386,7 @@ Major verison that drops support for End of Life Ansible/ansible\-base/ansible\-
<a id="v1-9-1"></a>
## v1\.9\.1
<a id="release-summary-15"></a>
<a id="release-summary-17"></a>
### Release Summary
Bugfix release\.
@ -359,12 +399,12 @@ Bugfix release\.
<a id="v1-9-0"></a>
## v1\.9\.0
<a id="release-summary-16"></a>
<a id="release-summary-18"></a>
### Release Summary
Feature release\.
<a id="minor-changes-3"></a>
<a id="minor-changes-5"></a>
### Minor Changes
* decrypt filter plugin \- now supports the input and output type <code>ini</code> \([https\://github\.com/ansible\-collections/community\.sops/pull/204](https\://github\.com/ansible\-collections/community\.sops/pull/204)\)\.
@ -374,7 +414,7 @@ Feature release\.
<a id="v1-8-2"></a>
## v1\.8\.2
<a id="release-summary-17"></a>
<a id="release-summary-19"></a>
### Release Summary
Maintenance release with updated documentation and changelog\.
@ -387,7 +427,7 @@ Maintenance release with updated documentation and changelog\.
<a id="v1-8-1"></a>
## v1\.8\.1
<a id="release-summary-18"></a>
<a id="release-summary-20"></a>
### Release Summary
Bugfix release\.
@ -400,12 +440,12 @@ Bugfix release\.
<a id="v1-8-0"></a>
## v1\.8\.0
<a id="release-summary-19"></a>
<a id="release-summary-21"></a>
### Release Summary
Feature release for supporting improvements coming with SOPS 3\.9\.0\.
<a id="minor-changes-4"></a>
<a id="minor-changes-6"></a>
### Minor Changes
* Detect SOPS 3\.9\.0 and use new <code>decrypt</code> and <code>encrypt</code> subcommands \([https\://github\.com/ansible\-collections/community\.sops/pull/190](https\://github\.com/ansible\-collections/community\.sops/pull/190)\)\.
@ -419,12 +459,12 @@ Feature release for supporting improvements coming with SOPS 3\.9\.0\.
<a id="v1-7-0"></a>
## v1\.7\.0
<a id="release-summary-20"></a>
<a id="release-summary-22"></a>
### Release Summary
Bugfix and feature release to fix installation issues with SOPS 3\.9\.0\.
<a id="minor-changes-5"></a>
<a id="minor-changes-7"></a>
### Minor Changes
* sops vars plugin \- allow to configure the valid extensions with an <code>ansible\.cfg</code> entry or with an environment variable \([https\://github\.com/ansible\-collections/community\.sops/pull/185](https\://github\.com/ansible\-collections/community\.sops/pull/185)\)\.
@ -437,7 +477,7 @@ Bugfix and feature release to fix installation issues with SOPS 3\.9\.0\.
<a id="v1-6-7"></a>
## v1\.6\.7
<a id="release-summary-21"></a>
<a id="release-summary-23"></a>
### Release Summary
Bugfix release\.
@ -450,7 +490,7 @@ Bugfix release\.
<a id="v1-6-6"></a>
## v1\.6\.6
<a id="release-summary-22"></a>
<a id="release-summary-24"></a>
### Release Summary
Make fully compatible with and test against sops 3\.8\.0\.
@ -463,7 +503,7 @@ Make fully compatible with and test against sops 3\.8\.0\.
<a id="v1-6-5"></a>
## v1\.6\.5
<a id="release-summary-23"></a>
<a id="release-summary-25"></a>
### Release Summary
Make compatible with and test against sops 3\.8\.0\-rc\.1\.
@ -477,7 +517,7 @@ Make compatible with and test against sops 3\.8\.0\-rc\.1\.
<a id="v1-6-4"></a>
## v1\.6\.4
<a id="release-summary-24"></a>
<a id="release-summary-26"></a>
### Release Summary
Maintenance/bugfix release for the move of sops to the new [getsops GitHub organization](https\://github\.com/getsops)\.
@ -490,7 +530,7 @@ Maintenance/bugfix release for the move of sops to the new [getsops GitHub organ
<a id="v1-6-3"></a>
## v1\.6\.3
<a id="release-summary-25"></a>
<a id="release-summary-27"></a>
### Release Summary
Maintenance release with updated documentation\.
@ -511,7 +551,7 @@ for the rendered HTML version of the documentation of the latest release\.
<a id="v1-6-2"></a>
## v1\.6\.2
<a id="release-summary-26"></a>
<a id="release-summary-28"></a>
### Release Summary
Maintenance release\.
@ -524,7 +564,7 @@ Maintenance release\.
<a id="v1-6-1"></a>
## v1\.6\.1
<a id="release-summary-27"></a>
<a id="release-summary-29"></a>
### Release Summary
Maintenance release\.
@ -538,12 +578,12 @@ Maintenance release\.
<a id="v1-6-0"></a>
## v1\.6\.0
<a id="release-summary-28"></a>
<a id="release-summary-30"></a>
### Release Summary
Feature release improving the installation role\.
<a id="minor-changes-6"></a>
<a id="minor-changes-8"></a>
### Minor Changes
* install role \- add <code>sops\_github\_latest\_detection</code> option that allows to configure which method to use for detecting the latest release on GitHub\. By default \(<code>auto</code>\) first tries to retrieve a list of recent releases using the API\, and if that fails due to rate limiting\, tries to obtain the latest GitHub release from a semi\-documented URL \([https\://github\.com/ansible\-collections/community\.sops/pull/133](https\://github\.com/ansible\-collections/community\.sops/pull/133)\)\.
@ -553,12 +593,12 @@ Feature release improving the installation role\.
<a id="v1-5-0"></a>
## v1\.5\.0
<a id="release-summary-29"></a>
<a id="release-summary-31"></a>
### Release Summary
Feature release\.
<a id="minor-changes-7"></a>
<a id="minor-changes-9"></a>
### Minor Changes
* Automatically install GNU Privacy Guard \(GPG\) in execution environments\. To install Mozilla sops a manual step needs to be added to the EE definition\, see the collection\'s documentation for details \([https\://github\.com/ansible\-collections/community\.sops/pull/98](https\://github\.com/ansible\-collections/community\.sops/pull/98)\)\.
@ -577,7 +617,7 @@ Feature release\.
<a id="v1-4-1"></a>
## v1\.4\.1
<a id="release-summary-30"></a>
<a id="release-summary-32"></a>
### Release Summary
Maintenance release to improve compatibility with future ansible\-core releases\.
@ -590,12 +630,12 @@ Maintenance release to improve compatibility with future ansible\-core releases\
<a id="v1-4-0"></a>
## v1\.4\.0
<a id="release-summary-31"></a>
<a id="release-summary-33"></a>
### Release Summary
Feature release\.
<a id="minor-changes-8"></a>
<a id="minor-changes-10"></a>
### Minor Changes
* Allow to specify age keys as <code>age\_key</code>\, or age keyfiles as <code>age\_keyfile</code> \([https\://github\.com/ansible\-collections/community\.sops/issues/116](https\://github\.com/ansible\-collections/community\.sops/issues/116)\, [https\://github\.com/ansible\-collections/community\.sops/pull/117](https\://github\.com/ansible\-collections/community\.sops/pull/117)\)\.
@ -604,12 +644,12 @@ Feature release\.
<a id="v1-3-0"></a>
## v1\.3\.0
<a id="release-summary-32"></a>
<a id="release-summary-34"></a>
### Release Summary
Feature release\.
<a id="minor-changes-9"></a>
<a id="minor-changes-11"></a>
### Minor Changes
* All software licenses are now in the <code>LICENSES/</code> directory of the collection root\, and the collection repository conforms to the [REUSE specification](https\://reuse\.software/spec/) except for the changelog fragments \([https\://github\.com/ansible\-collections/community\.crypto/sops/108](https\://github\.com/ansible\-collections/community\.crypto/sops/108)\, [https\://github\.com/ansible\-collections/community\.sops/pull/113](https\://github\.com/ansible\-collections/community\.sops/pull/113)\)\.
@ -618,7 +658,7 @@ Feature release\.
<a id="v1-2-3"></a>
## v1\.2\.3
<a id="release-summary-33"></a>
<a id="release-summary-35"></a>
### Release Summary
Fix formatting bug in documentation\. No code changes\.
@ -626,7 +666,7 @@ Fix formatting bug in documentation\. No code changes\.
<a id="v1-2-2"></a>
## v1\.2\.2
<a id="release-summary-34"></a>
<a id="release-summary-36"></a>
### Release Summary
Maintenance release\.
@ -639,7 +679,7 @@ Maintenance release\.
<a id="v1-2-1"></a>
## v1\.2\.1
<a id="release-summary-35"></a>
<a id="release-summary-37"></a>
### Release Summary
Maintenance release with updated documentation\.
@ -647,14 +687,14 @@ Maintenance release with updated documentation\.
<a id="v1-2-0"></a>
## v1\.2\.0
<a id="release-summary-36"></a>
<a id="release-summary-38"></a>
### Release Summary
Collection release for inclusion in Ansible 4\.9\.0 and 5\.1\.0\.
This release contains a change allowing to configure generic plugin options with ansible\.cfg keys and env variables\.
<a id="minor-changes-10"></a>
<a id="minor-changes-12"></a>
### Minor Changes
* sops lookup and vars plugin \- allow to configure almost all generic options by ansible\.cfg entries and environment variables \([https\://github\.com/ansible\-collections/community\.sops/pull/81](https\://github\.com/ansible\-collections/community\.sops/pull/81)\)\.
@ -667,12 +707,12 @@ This release contains a change allowing to configure generic plugin options with
<a id="v1-1-0"></a>
## v1\.1\.0
<a id="release-summary-37"></a>
<a id="release-summary-39"></a>
### Release Summary
A minor release for inclusion in Ansible 4\.2\.0\.
<a id="minor-changes-11"></a>
<a id="minor-changes-13"></a>
### Minor Changes
* Avoid internal ansible\-core module\_utils in favor of equivalent public API available since at least Ansible 2\.9 \([https\://github\.com/ansible\-collections/community\.sops/pull/73](https\://github\.com/ansible\-collections/community\.sops/pull/73)\)\.
@ -688,7 +728,7 @@ A minor release for inclusion in Ansible 4\.2\.0\.
<a id="v1-0-6"></a>
## v1\.0\.6
<a id="release-summary-38"></a>
<a id="release-summary-40"></a>
### Release Summary
This release makes the collection compatible to the latest beta release of ansible\-core 2\.11\.
@ -702,7 +742,7 @@ This release makes the collection compatible to the latest beta release of ansib
<a id="v1-0-5"></a>
## v1\.0\.5
<a id="release-summary-39"></a>
<a id="release-summary-41"></a>
### Release Summary
This release fixes a bug that prevented correct YAML file to be created when the output was ending in <code>\.yaml</code>\.
@ -715,7 +755,7 @@ This release fixes a bug that prevented correct YAML file to be created when the
<a id="v1-0-4"></a>
## v1\.0\.4
<a id="release-summary-40"></a>
<a id="release-summary-42"></a>
### Release Summary
This is a security release\, fixing a potential information leak in the <code>community\.sops\.sops\_encrypt</code> module\.
@ -728,7 +768,7 @@ This is a security release\, fixing a potential information leak in the <code>co
<a id="v1-0-3"></a>
## v1\.0\.3
<a id="release-summary-41"></a>
<a id="release-summary-43"></a>
### Release Summary
This release include some fixes to Ansible docs and required changes for inclusion in Ansible\.
@ -742,7 +782,7 @@ This release include some fixes to Ansible docs and required changes for inclusi
<a id="v1-0-2"></a>
## v1\.0\.2
<a id="release-summary-42"></a>
<a id="release-summary-44"></a>
### Release Summary
Fix of 1\.0\.1 release which had no changelog entry\.
@ -750,7 +790,7 @@ Fix of 1\.0\.1 release which had no changelog entry\.
<a id="v1-0-1"></a>
## v1\.0\.1
<a id="release-summary-43"></a>
<a id="release-summary-45"></a>
### Release Summary
Re\-release of 1\.0\.0 to counteract error during release\.
@ -758,12 +798,12 @@ Re\-release of 1\.0\.0 to counteract error during release\.
<a id="v1-0-0"></a>
## v1\.0\.0
<a id="release-summary-44"></a>
<a id="release-summary-46"></a>
### Release Summary
First stable release\. This release is expected to be included in Ansible 3\.0\.0\.
<a id="minor-changes-12"></a>
<a id="minor-changes-14"></a>
### Minor Changes
* All plugins and modules\: allow to pass generic sops options with new options <code>config\_path</code>\, <code>enable\_local\_keyservice</code>\, <code>keyservice</code>\. Also allow to pass AWS parameters with options <code>aws\_profile</code>\, <code>aws\_access\_key\_id</code>\, <code>aws\_secret\_access\_key</code>\, and <code>aws\_session\_token</code> \([https\://github\.com/ansible\-collections/community\.sops/pull/47](https\://github\.com/ansible\-collections/community\.sops/pull/47)\)\.
@ -772,12 +812,12 @@ First stable release\. This release is expected to be included in Ansible 3\.0\.
<a id="v0-2-0"></a>
## v0\.2\.0
<a id="release-summary-45"></a>
<a id="release-summary-47"></a>
### Release Summary
This release adds features for the lookup and vars plugins\.
<a id="minor-changes-13"></a>
<a id="minor-changes-15"></a>
### Minor Changes
* community\.sops\.sops lookup plugin \- add <code>empty\_on\_not\_exist</code> option which allows to return an empty string instead of an error when the file does not exist \([https\://github\.com/ansible\-collections/community\.sops/pull/33](https\://github\.com/ansible\-collections/community\.sops/pull/33)\)\.
@ -787,7 +827,7 @@ This release adds features for the lookup and vars plugins\.
<a id="v0-1-0"></a>
## v0\.1\.0
<a id="release-summary-46"></a>
<a id="release-summary-48"></a>
### Release Summary
First release of the <code>community\.sops</code> collection\!

View file

@ -4,6 +4,40 @@ Community SOPS Release Notes
.. contents:: Topics
v2.4.0
======
Release Summary
---------------
Feature release.
Minor Changes
-------------
- Support OpenSuSE Tumbleweed (and probably also Leap) in the community.sops.install role. Right now only Tumbleweed is tested in CI, so support for Leap has not been verified (https://github.com/ansible-collections/community.sops/pull/299).
v2.3.0
======
Release Summary
---------------
Feature release.
The main new feature of this release is ansible-core 2.21 support for ``community.sops.load_vars``.
ansible-core 2.21 is the first version to explicitly allow action plugins to set variables,
which finally allows ``community.sops.load_vars`` to set variables the same way as
``ansible.builtin.include_vars``.
Minor Changes
-------------
- all modules and plugins - allow retrieving private age keys and private SSH keys through commands with the new ``age_key_cmd`` and ``age_ssh_private_key_cmd`` options (https://github.com/ansible-collections/community.sops/issues/282, https://github.com/ansible-collections/community.sops/pull/286).
- all modules and plugins - allow to configure GCP access with the ``gcp_oauth_access_token`` and ``gcp_kms_client_type`` options (https://github.com/ansible-collections/community.sops/issues/282, https://github.com/ansible-collections/community.sops/pull/286).
- load_vars - now supports ansible-core 2.21's way of actually loading variables, instead of returning ``ansible_facts``. The behavior for this can be controlled through the new ``return_method`` option, which is by default set to ``auto``. On ansible-core 2.21+, ``auto`` behaves the same as ``vars-only`` (return proper variables), and for ansible-core before 2.21 the same as ``facts-only`` (return ``ansible_facts``) (https://github.com/ansible-collections/community.sops/pull/283).
- sops_encrypt - support providing HuaweiCloud KMS key IDs with the ``huawei_cloud_kms`` option (https://github.com/ansible-collections/community.sops/issues/282, https://github.com/ansible-collections/community.sops/pull/286).
v2.2.7
======

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
"collection_info": {
"namespace": "community",
"name": "sops",
"version": "2.2.7",
"version": "2.4.0",
"authors": [
"Edoardo Tenani"
],
@ -30,7 +30,7 @@
"name": "FILES.json",
"ftype": "file",
"chksum_type": "sha256",
"chksum_sha256": "d6a32bb2e00581e2d48d02e472b018d2e958cff2cacac32329d0375611666f34",
"chksum_sha256": "4ce3f8d4345f0cecb65fa594f67c1fdc9013ccd3d9233925c148aea6443120fe",
"format": 1
},
"format": 1

View file

@ -18,11 +18,18 @@ Please note that this collection does **not** support Windows targets.
## SOPS version compatibility
The following table shows which versions of SOPS were tested with which versions of the collection. Older (or newer) versions of SOPS can still work fine, it just means that we did not test them. In some cases, it could be that a minimal required version of SOPS is explicitly documented for a specific feature. This is the case from community.sops 1.8.0 on; from that version on the collection automatically detects the SOPS version to determine whether a feature is supported or not.
The following table shows which versions of SOPS are tested with the latest version of the collection (for the current major release branch). Older (or newer) versions of SOPS can still work fine, it just means that we did not test them. In some cases, it could be that a minimal required version of SOPS is explicitly documented for a specific feature. This is the case from community.sops 1.8.0 on; from that version on the collection automatically detects the SOPS version to determine whether a feature is supported or not.
|`community.sops` version|SOPS versions|
|SOPS release train|SOPS versions|
|---|---|
|`main` branch|`3.5.0`, `3.6.0`, `3.6.1`, `3.7.0`, `3.7.3`, `3.8.0`, `3.8.1`, `3.9.0`, `3.9.1`, `3.9.2`, `3.9.3`, `3.10.0`, `3.10.1`, `3.10.2`, `3.11.0`|
|`3.5.x`|`3.5.0` (latest)|
|`3.6.x`|`3.6.0`, `3.6.1` (latest)|
|`3.7.x`|`3.7.0`, `3.7.3` (latest)|
|`3.8.x`|`3.8.0`, `3.8.1` (latest)|
|`3.9.x`|`3.9.0`, `3.9.1`, `3.9.2`, `3.9.3`, `3.9.4` (latest)|
|`3.10.x`|`3.10.0`, `3.10.1`, `3.10.2` (latest)|
|`3.11.x`|`3.11.0` (latest)|
|`3.12.x`|`3.12.1`|
## Code of Conduct
@ -44,7 +51,7 @@ For more information about communication, see the [Ansible communication guide](
## Tested with Ansible
Tested with the current ansible-core 2.15, ansible-core 2.16, ansible-core 2.17, ansible-core 2.18, and ansible-core 2.19 releases and the current development version of ansible-core. Ansible versions before 2.15.0 are not supported.
Tested with the current ansible-core 2.15, ansible-core 2.16, ansible-core 2.17, ansible-core 2.18, ansible-core 2.19, ansible-core 2.20, ansible-core 2.21 releases, and the current development version of ansible-core. Ansible versions before 2.15.0 are not supported.
## External requirements

View file

@ -31,7 +31,12 @@ yamllint_config = ".yamllint"
yamllint_config_plugins = ".yamllint-docs"
yamllint_config_plugins_examples = ".yamllint-examples"
yamllint_config_extra_docs = ".yamllint-extra-docs"
run_mypy = false
run_mypy = true
mypy_config = ".mypy.ini"
mypy_extra_deps = [
"types-mock",
"types-PyYAML",
]
[sessions.docs_check]
validate_collection_refs="all"
@ -76,6 +81,13 @@ include_devel = true
[sessions.ansible_test_integration]
[sessions.ansible_test_integration.nice_docker_names]
"quay.io/ansible-community/test-image:debian-bullseye" = "Debian 11"
"quay.io/ansible-community/test-image:debian-bookworm" = "Debian 12"
"quay.io/ansible-community/test-image:debian-13-trixie" = "Debian 13"
"quay.io/ansible-community/test-image:archlinux" = "Arch Linux"
"quay.io/ansible-community/test-image:opensuse-tumbleweed" = "OpenSuSE Tumbleweed"
[sessions.ansible_test_integration.ansible_vars]
github_token = { type = "env", name = "GITHUB_TOKEN", unset_if_not_set = true }
@ -83,41 +95,53 @@ github_token = { type = "env", name = "GITHUB_TOKEN", unset_if_not_set = true }
session_name = "ansible-test-integration-main"
description = "Meta-session for all ansible-test-integration-main-* sessions."
session_name_template = "ansible-test-integration-main-{ansible_core}{dash_docker_short}{dash_override_sops_version}{dash_gha_arm_lower}"
display_name_template = "main+Ⓐ{ansible_core}+SOPS-{override_sops_version}{plus_docker_short}{plus_py_python_version}{plus_gha_arm}"
description_template = "Run main integration tests with ansible-core {ansible_core}, {docker_short}, SOPS {override_sops_version}{comma_gha_arm}"
display_name_template = "main+Ⓐ{ansible_core}+SOPS-{override_sops_version}{plus_docker_nice}{plus_py_python_version}{plus_gha_arm}"
description_template = "Run main integration tests with ansible-core {ansible_core}, {docker_nice}, SOPS {override_sops_version}{comma_gha_arm}"
target = "gha/main/"
gha_container = "ubuntu-latest"
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = ["ubuntu2204", "ubuntu2404", "fedora42"]
docker = ["ubuntu2604"]
# Cannot install 3.5.0 on Fedora 44 (digest algorithm used for RPM isn't accepted anymore)
ansible_vars = { override_sops_version = "3.5.0" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = ["ubuntu2204", "ubuntu2404", "fedora42"]
docker = ["ubuntu2404"]
# Cannot install 3.6.1 on Fedora 43 (digest algorithm used for RPM isn't accepted anymore)
ansible_vars = { override_sops_version = "3.6.1" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = ["ubuntu2204", "ubuntu2404", "fedora42"]
docker = ["fedora44"]
ansible_vars = { override_sops_version = "3.7.3" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = ["ubuntu2204", "ubuntu2404", "fedora42"]
docker = ["ubuntu2404"]
ansible_vars = { override_sops_version = "3.8.1" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = ["ubuntu2204", "ubuntu2404", "fedora42"]
ansible_vars = { override_sops_version = "3.9.3" }
docker = ["ubuntu2604"]
ansible_vars = { override_sops_version = "3.9.4" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = ["ubuntu2204", "ubuntu2404", "fedora42"]
docker = ["fedora44"]
ansible_vars = { override_sops_version = "3.10.2" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = ["ubuntu2404"]
ansible_vars = { override_sops_version = "3.11.0" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = ["ubuntu2604", "ubuntu2404", "fedora44"]
ansible_vars = { override_sops_version = "3.12.1" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "2.15"
docker = "ubuntu2004"
@ -174,14 +198,34 @@ ansible_core = "2.19"
docker = "fedora41"
ansible_vars = { override_sops_version = "3.10.2" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "2.20"
docker = "fedora42"
ansible_vars = { override_sops_version = "3.9.3" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "2.20"
docker = "ubuntu2404"
ansible_vars = { override_sops_version = "3.11.0" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "2.21"
docker = "fedora43"
ansible_vars = { override_sops_version = "3.12.2" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "2.21"
docker = "ubuntu2404"
ansible_vars = { override_sops_version = "3.12.1" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = "ubuntu2204"
docker = "ubuntu2604"
ansible_vars = { override_sops_version = "3.6.0" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = "ubuntu2204"
docker = "ubuntu2604"
ansible_vars = { override_sops_version = "3.7.0" }
[[sessions.ansible_test_integration.groups.sessions]]
@ -192,7 +236,7 @@ ansible_vars = { override_sops_version = "3.9.1" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = "quay.io/ansible-community/test-image:archlinux"
python_version = "3.13"
python_version = "3.14"
ansible_vars = { override_sops_version = "latest" }
[[sessions.ansible_test_integration.groups.sessions]]
@ -207,6 +251,12 @@ docker = "quay.io/ansible-community/test-image:debian-13-trixie"
python_version = "3.13"
ansible_vars = { override_sops_version = "latest" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = "quay.io/ansible-community/test-image:opensuse-tumbleweed"
python_version = "3.13"
ansible_vars = { override_sops_version = "latest" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = "ubuntu2404"
@ -217,8 +267,8 @@ ansible_vars = { override_sops_version = "latest" }
session_name = "ansible-test-integration-install-1"
description = "Meta-session for all ansible-test-integration-install-1-* sessions."
session_name_template = "ansible-test-integration-install-1-{ansible_core}{dash_docker_short}{dash_gha_arm_lower}"
display_name_template = "install-1+Ⓐ{ansible_core}{plus_docker_short}{plus_py_python_version}{plus_gha_arm}"
description_template = "Run install role integration tests (specific SOPS version) with ansible-core {ansible_core}, {docker_short}{comma_gha_arm}"
display_name_template = "install-1+Ⓐ{ansible_core}{plus_docker_nice}{plus_py_python_version}{plus_gha_arm}"
description_template = "Run install role integration tests (specific SOPS version) with ansible-core {ansible_core}, {docker_nice}{comma_gha_arm}"
target = "gha/install/1/"
gha_container = "ubuntu-latest"
@ -244,17 +294,21 @@ ansible_vars = { github_latest_detection = "auto" }
session_name = "ansible-test-integration-install-2"
description = "Meta-session for all ansible-test-integration-install-2-* sessions."
session_name_template = "ansible-test-integration-install-2-{ansible_core}{dash_docker_short}{dash_gha_arm_lower}"
display_name_template = "install-2+Ⓐ{ansible_core}{plus_docker_short}{plus_py_python_version}{plus_gha_arm}"
description_template = "Run install role integration tests (localhost vs. remote host) with ansible-core {ansible_core}, {docker_short}{comma_gha_arm}"
display_name_template = "install-2+Ⓐ{ansible_core}{plus_docker_nice}{plus_py_python_version}{plus_gha_arm}"
description_template = "Run install role integration tests (localhost vs. remote host) with ansible-core {ansible_core}, {docker_nice}{comma_gha_arm}"
target = "gha/install/2/"
gha_container = "ubuntu-latest"
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
# NOTE: We need something with split-controller testing!
# ansbile-core devel currently does not seem to have targets we can use.
ansible_core = "2.21"
docker = "ubuntu2204"
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
# NOTE: We need something with split-controller testing!
# ansbile-core devel currently does not seem to have targets we can use.
ansible_core = "2.21"
docker = "ubuntu2204"
gha_container = "ubuntu-24.04-arm"
ansible_vars = { github_latest_detection = "auto" }
@ -263,14 +317,20 @@ ansible_vars = { github_latest_detection = "auto" }
session_name = "ansible-test-integration-install-3"
description = "Meta-session for all ansible-test-integration-install-3-* sessions."
session_name_template = "ansible-test-integration-install-3-{ansible_core}{dash_docker_short}{dash_gha_arm_lower}"
display_name_template = "install-3+Ⓐ{ansible_core}{plus_docker_short}{plus_py_python_version}{plus_gha_arm}"
description_template = "Run install role integration tests (latest SOPS version) with ansible-core {ansible_core}, {docker_short}{comma_gha_arm}"
display_name_template = "install-3+Ⓐ{ansible_core}{plus_docker_nice}{plus_py_python_version}{plus_gha_arm}"
description_template = "Run install role integration tests (latest SOPS version) with ansible-core {ansible_core}, {docker_nice}{comma_gha_arm}"
target = "gha/install/3/"
gha_container = "ubuntu-latest"
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = "quay.io/ansible-community/test-image:archlinux"
python_version = "3.14"
ansible_vars = { github_latest_detection = "auto" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = "quay.io/ansible-community/test-image:opensuse-tumbleweed"
python_version = "3.13"
ansible_vars = { github_latest_detection = "auto" }
@ -298,13 +358,23 @@ docker = "fedora41"
ansible_vars = { github_latest_detection = "auto" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
ansible_core = "2.20"
docker = "fedora42"
ansible_vars = { github_latest_detection = "auto" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "2.21"
docker = "fedora43"
ansible_vars = { github_latest_detection = "auto" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = "ubuntu2204"
docker = "fedora44"
ansible_vars = { github_latest_detection = "auto" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = "ubuntu2604"
ansible_vars = { github_latest_detection = "api" }
[[sessions.ansible_test_integration.groups.sessions]]
@ -318,25 +388,35 @@ docker = "alpine321"
ansible_vars = { github_latest_detection = "auto" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
ansible_core = "2.20"
docker = "alpine322"
ansible_vars = { github_latest_detection = "auto" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "2.21"
docker = "alpine323"
ansible_vars = { github_latest_detection = "auto" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = "alpine322"
docker = "alpine323"
ansible_vars = { github_latest_detection = "auto" }
[[sessions.ansible_test_integration.groups.sessions]]
ansible_core = "devel"
docker = "alpine323"
gha_container = "ubuntu-24.04-arm"
ansible_vars = { github_latest_detection = "auto" }
[[sessions.ee_check.execution_environments]]
name = "devel-ubi-9"
description = "ansible-core devel @ RHEL UBI 9"
name = "devel-ubi-10"
description = "ansible-core devel @ RHEL UBI 10"
test_playbooks = ["tests/ee/all.yml"]
config.images.base_image.name = "docker.io/redhat/ubi9:latest"
config.images.base_image.name = "docker.io/redhat/ubi10:latest"
config.dependencies.ansible_core.package_pip = "https://github.com/ansible/ansible/archive/devel.tar.gz"
config.dependencies.ansible_runner.package_pip = "ansible-runner"
config.dependencies.python_interpreter.package_system = "python3.12 python3.12-pip python3.12-wheel python3.12-cryptography"
config.dependencies.python_interpreter.python_path = "/usr/bin/python3.12"
config.dependencies.python_interpreter.package_system = "python3.14 python3.14-pip python3.14-cryptography"
config.dependencies.python_interpreter.python_path = "/usr/bin/python3.14"
config.additional_build_steps.append_final = [
"RUN ansible-playbook -v community.sops.install_localhost",
]

View file

@ -604,3 +604,101 @@ releases:
- 2.2.7.yml
- ansible-core-2.20-warning.yml
release_date: '2025-11-02'
2.3.0-b1:
changes:
minor_changes:
- load_vars - now supports ansible-core 2.21's way of actually loading variables,
instead of returning ``ansible_facts``. The behavior for this can be controlled
through the new ``return_method`` option, which is by default set to ``auto``.
On ansible-core 2.21+, ``auto`` behaves the same as ``vars-only`` (return
proper variables), and for ansible-core before 2.21 the same as ``facts-only``
(return ``ansible_facts``) (https://github.com/ansible-collections/community.sops/pull/283).
release_summary: 'This is a pre-release for community.sops 2.3.0.
The main new feature of this release is ansible-core 2.21 support for ``community.sops.load_vars``.
ansible-core 2.21 is the first version to explicitly allow action plugins
to set variables,
which finally allows ``community.sops.load_vars`` to set variables the same
way as
``ansible.builtin.include_vars``.
Since this interface is brand-new and changes might still happen until the
final ansible-core 2.21
release, this is a pre-release.'
fragments:
- 2.3.0-b1.yml
- 283-load-vars-as-vars.yml
release_date: '2026-04-07'
2.3.0-b2:
changes:
minor_changes:
- all modules and plugins - allow retrieving private age keys and private
SSH keys through commands with the new ``age_key_cmd`` and ``age_ssh_private_key_cmd``
options (https://github.com/ansible-collections/community.sops/issues/282,
https://github.com/ansible-collections/community.sops/pull/286).
- all modules and plugins - allow to configure GCP access with the ``gcp_oauth_access_token``
and ``gcp_kms_client_type`` options (https://github.com/ansible-collections/community.sops/issues/282,
https://github.com/ansible-collections/community.sops/pull/286).
- sops_encrypt - support providing HuaweiCloud KMS key IDs with the ``huawei_cloud_kms``
option (https://github.com/ansible-collections/community.sops/issues/282,
https://github.com/ansible-collections/community.sops/pull/286).
release_summary: 'This is a pre-release for community.sops 2.3.0.
The main new features of this release are ansible-core 2.21 support for ``community.sops.load_vars``
and improved argument checking for the ``community.sops.decrypt`` filter.
Also the handling of the ``sops_binary`` option for the lookup and vars plugin
have been improved.
ansible-core 2.21 is the first version to explicitly allow action plugins
to set variables,
which finally allows ``community.sops.load_vars`` to set variables the same
way as
``ansible.builtin.include_vars``.
Since this interface is brand-new and changes might still happen until the
final ansible-core 2.21
release, this is a pre-release.'
fragments:
- 2.3.0-b2.yml
- 286-options.yml
release_date: '2026-04-15'
2.3.0:
changes:
release_summary: 'Feature release.
The main new feature of this release is ansible-core 2.21 support for ``community.sops.load_vars``.
ansible-core 2.21 is the first version to explicitly allow action plugins
to set variables,
which finally allows ``community.sops.load_vars`` to set variables the same
way as
``ansible.builtin.include_vars``.'
fragments:
- 2.3.0.yml
release_date: '2026-04-19'
2.4.0:
changes:
minor_changes:
- Support OpenSuSE Tumbleweed (and probably also Leap) in the community.sops.install
role. Right now only Tumbleweed is tested in CI, so support for Leap has
not been verified (https://github.com/ansible-collections/community.sops/pull/299).
release_summary: Feature release.
fragments:
- 2.4.0.yml
- 299-opensuse.yml
release_date: '2026-06-14'

View file

@ -4,6 +4,7 @@
from __future__ import annotations
import typing as t
from collections.abc import Sequence, Mapping
from ansible.module_utils.common.text.converters import to_native
@ -19,10 +20,19 @@ try:
except ImportError:
HAS_DATATAGGING = False
try:
from ansible.plugins.action import VariableLayer # type: ignore[attr-defined]
HAS_REGISTER_HOST_VARIABLES = True
except ImportError:
HAS_REGISTER_HOST_VARIABLES = False
if t.TYPE_CHECKING:
from ansible_collections.community.sops.plugins.plugin_utils.action_module import AnsibleActionModule
display = Display()
def _make_safe(value):
def _make_safe(value: t.Any) -> t.Any:
if HAS_DATATAGGING and isinstance(value, str):
return _trust_as_template(value)
return value
@ -30,7 +40,7 @@ def _make_safe(value):
class ActionModule(ActionModuleBase):
def _load(self, filename, module):
def _load(self, filename: str, module: AnsibleActionModule) -> dict:
def get_option_value(argument_name):
return module.params.get(argument_name)
@ -71,6 +81,7 @@ class ActionModule(ActionModuleBase):
file=dict(type='path', required=True),
name=dict(type='str'),
expressions=dict(type='str', default='ignore', choices=['ignore', 'evaluate-on-load', 'lazy-evaluation']),
return_method=dict(type='str', default='auto', choices=['auto', 'facts-only', 'vars-only']),
),
)
argument_spec.argument_spec.update(get_sops_argument_spec())
@ -81,7 +92,15 @@ class ActionModule(ActionModuleBase):
if expressions == 'lazy-evaluation' and not HAS_DATATAGGING:
module.fail_json(msg='expressions=lazy-evaluation requires ansible-core 2.19+ with Data Tagging support.')
data = dict()
return_method_str = module.params['return_method']
if return_method_str == 'auto':
return_as_facts = not HAS_REGISTER_HOST_VARIABLES
else:
return_as_facts = return_method_str == 'facts-only'
if not HAS_REGISTER_HOST_VARIABLES and not return_as_facts:
module.fail_json(msg='return_method=vars-only requires ansible-core 2.21+')
data = {}
files = []
try:
filename = self._find_needle('vars', module.params['file'])
@ -94,8 +113,7 @@ class ActionModule(ActionModuleBase):
if name is None:
value = data
else:
value = dict()
value[name] = data
value = {name: data}
if expressions == 'evaluate-on-load':
value = self._evaluate(value)
@ -103,8 +121,14 @@ class ActionModule(ActionModuleBase):
if expressions == 'lazy-evaluation':
value = self._make_safe(value)
module.exit_json(
ansible_included_var_files=files,
ansible_facts=value,
_ansible_no_log=True,
)
result = {
'ansible_included_var_files': files,
'_ansible_no_log': True,
}
if return_as_facts:
result['ansible_facts'] = value
else:
self.register_host_variables(variables=value, layer=VariableLayer.INCLUDE_VARS)
module.exit_json(**result)

View file

@ -34,6 +34,15 @@ options:
- Requires SOPS 3.7.0+.
type: path
version_added: 1.4.0
age_key_cmd:
description:
- A command that SOPS will execute to obtain an age private key that SOPS can use to decrypt encrypted files.
- Will be set as the E(SOPS_AGE_KEY_CMD) environment variable when calling SOPS.
- Requires SOPS 3.10.0+.
- When running this command and when SOPS 3.12.0+ is used, SOPS will set the E(SOPS_AGE_RECIPIENT) variable
to the identity of the key it wants to use to decrypt.
type: str
version_added: 2.3.0
age_ssh_private_keyfile:
description:
- The file containing the SSH private key that SOPS can use to decrypt encrypted files.
@ -42,6 +51,15 @@ options:
- Requires SOPS 3.10.0+.
type: path
version_added: 1.4.0
age_ssh_private_key_cmd:
description:
- A command that SOPS will execute to obtain an SSH private key that SOPS can use to decrypt encrypted files.
- Will be set as the E(SOPS_AGE_SSH_PRIVATE_KEY_CMD) environment variable when calling SOPS.
- When running this command, SOPS will set the E(SOPS_AGE_RECIPIENT) variable to the identity of the key
it wants to use to decrypt.
- Requires SOPS 3.12.0+.
type: str
version_added: 2.3.0
aws_profile:
description:
- The AWS profile to use for requests to AWS.
@ -66,6 +84,23 @@ options:
- Sets the environment variable E(AWS_SESSION_TOKEN) for the SOPS call.
type: str
version_added: 1.0.0
gcp_oauth_access_token:
description:
- Provide a Google Cloud OAauth token.
- Will be set as the E(GOOGLE_OAUTH_ACCESS_TOKEN) environment variable when calling SOPS.
- Requires SOPS 3.10.0+.
type: str
version_added: 3.2.0
gcp_kms_client_type:
description:
- Determine which client to use to communicate with Google Cloud Services.
- Will be set as the E(SOPS_GCP_KMS_CLIENT_TYPE) environment variable when calling SOPS.
- Requires SOPS 3.12.0+.
type: str
choices:
rest: Use REST client
grpc: Use gRPC client
version_added: 3.2.0
config_path:
description:
- Path to the SOPS configuration file.
@ -90,6 +125,12 @@ options:
version_added: 1.0.0
"""
ANSIBLE_PLUGIN = r'''
options:
sops_binary:
type: str
'''
ANSIBLE_VARIABLES = r'''
options:
sops_binary:
@ -101,9 +142,15 @@ options:
age_keyfile:
vars:
- name: sops_age_keyfile
age_key_cmd:
vars:
- name: sops_age_key_cmd
age_ssh_private_keyfile:
vars:
- name: sops_age_ssh_private_keyfile
age_ssh_private_key_cmd:
vars:
- name: sops_age_ssh_private_key_cmd
aws_profile:
vars:
- name: sops_aws_profile
@ -118,6 +165,12 @@ options:
- name: sops_session_token
- name: sops_aws_session_token
version_added: 1.2.0
gcp_oauth_access_token:
vars:
- name: sops_gcp_oauth_access_token
gcp_kms_client_type:
vars:
- name: sops_gcp_kms_client_type
config_path:
vars:
- name: sops_config_path
@ -141,9 +194,15 @@ options:
age_keyfile:
env:
- name: ANSIBLE_SOPS_AGE_KEYFILE
age_key_cmd:
env:
- name: ANSIBLE_SOPS_AGE_KEY_CMD
age_ssh_private_keyfile:
env:
- name: ANSIBLE_SOPS_AGE_SSH_PRIVATE_KEYFILE
age_ssh_private_key_cmd:
env:
- name: ANSIBLE_SOPS_AGE_SSH_PRIVATE_KEY_CMD
aws_profile:
env:
- name: ANSIBLE_SOPS_AWS_PROFILE
@ -160,6 +219,12 @@ options:
env:
- name: ANSIBLE_SOPS_AWS_SESSION_TOKEN
version_added: 1.2.0
gcp_oauth_access_token:
env:
- name: ANSIBLE_SOPS_GCP_OAUTH_ACCESS_TOKEN
gcp_kms_client_type:
env:
- name: ANSIBLE_SOPS_GCP_KMS_CLIENT_TYPE
config_path:
env:
- name: ANSIBLE_SOPS_CONFIG_PATH
@ -188,10 +253,18 @@ options:
ini:
- section: community.sops
key: age_keyfile
age_key_cmd:
ini:
- section: community.sops
key: age_key_cmd
age_ssh_private_keyfile:
ini:
- section: community.sops
key: age_ssh_private_keyfile
age_ssh_private_key_cmd:
ini:
- section: community.sops
key: age_ssh_private_key_cmd
aws_profile:
ini:
- section: community.sops
@ -210,6 +283,13 @@ options:
- section: community.sops
key: aws_session_token
version_added: 1.2.0
# We do not provide an INI key for
# gcp_oauth_access_token
# to make sure that secrets cannot be provided in ansible.ini. Use environment variables or another mechanism for that.
gcp_kms_client_type:
ini:
- section: community.sops
key: gcp_kms_client_type
config_path:
ini:
- section: community.sops
@ -272,6 +352,14 @@ options:
type: list
elements: str
version_added: 1.0.0
huawei_cloud_kms:
description:
- HuaweiCloud KMS key IDs to use.
- This corresponds to the SOPS C(--hckms) option.
- Requires SOPS 3.12.0+.
type: list
elements: str
version_added: 3.2.0
unencrypted_suffix:
description:
- Override the unencrypted key suffix.

View file

@ -52,7 +52,7 @@ def pick_latest_version(version_list):
version_list = [v for v in version_list if '-' not in v and '+' not in v]
if not version_list:
return ''
return sorted(version_list, key=LooseVersion, reverse=True)[0]
return max(version_list, key=LooseVersion)
class FilterModule:

View file

@ -108,6 +108,7 @@ from ansible.module_utils.common.text.converters import to_bytes, to_native
from ansible.utils.display import Display
from ansible_collections.community.sops.plugins.module_utils.sops import Sops, SopsError
from ansible_collections.community.sops.plugins.plugin_utils._args import wrap_get_option_value_check_types
_VALID_TYPES = set(['binary', 'json', 'yaml', 'dotenv', 'ini'])
@ -115,7 +116,8 @@ _VALID_TYPES = set(['binary', 'json', 'yaml', 'dotenv', 'ini'])
def decrypt_filter(data, input_type='yaml', output_type='yaml', sops_binary='sops', rstrip=True, decode_output=True,
aws_profile=None, aws_access_key_id=None, aws_secret_access_key=None, aws_session_token=None,
config_path=None, enable_local_keyservice=True, keyservice=None, age_key=None, age_keyfile=None, age_ssh_private_keyfile=None):
config_path=None, enable_local_keyservice=True, keyservice=None, age_key=None, age_keyfile=None, age_ssh_private_keyfile=None,
age_key_cmd=None, age_ssh_private_key_cmd=None, gcp_oauth_access_token=None, gcp_kms_client_type=None):
'''Decrypt sops-encrypted data.'''
# Check parameters
@ -150,16 +152,33 @@ def decrypt_filter(data, input_type='yaml', output_type='yaml', sops_binary='sop
return enable_local_keyservice
if argument_name == 'keyservice':
return keyservice
raise AssertionError('internal error: should not be reached')
if argument_name == 'age_key_cmd':
return age_key_cmd
if argument_name == 'age_ssh_private_key_cmd':
return age_ssh_private_key_cmd
if argument_name == 'gcp_oauth_access_token':
return gcp_oauth_access_token
if argument_name == 'gcp_kms_client_type':
return gcp_kms_client_type
raise AssertionError('internal error: should not be reached') # pragma: no cover
# Decode
data = to_bytes(data)
try:
output = Sops.decrypt(
None, content=data, display=Display(), rstrip=rstrip, decode_output=decode_output,
input_type=input_type, output_type=output_type, get_option_value=get_option_value)
None,
content=data,
display=Display(),
rstrip=rstrip,
decode_output=decode_output,
input_type=input_type,
output_type=output_type,
get_option_value=wrap_get_option_value_check_types(get_option_value, add_encrypt_specific=False),
)
except SopsError as e:
raise AnsibleFilterError(to_native(e))
except ValueError as e:
raise AnsibleFilterError(f"Error in community.sops.decrypt filter: {e}")
return output

View file

@ -67,6 +67,7 @@ options:
type: str
version_added: 1.9.0
extends_documentation_fragment:
- community.sops.sops.ansible_plugin # must come before community.sops.sops!
- community.sops.sops
- community.sops.sops.ansible_variables
- community.sops.sops.ansible_env
@ -116,9 +117,12 @@ _raw:
import base64
from ansible.errors import AnsibleLookupError
from ansible.plugins.lookup import LookupBase
from ansible.module_utils.common.text.converters import to_native
from ansible.module_utils.compat.version import LooseVersion
from ansible.plugins.lookup import LookupBase
from ansible.release import __version__ as ansible_version
from ansible_collections.community.sops.plugins.module_utils.sops import Sops, SopsError
from ansible_collections.community.sops.plugins.plugin_utils._args import wrap_get_option_value_plugin_path
from ansible.utils.display import Display
display = Display()
@ -137,8 +141,25 @@ class LookupModule(LookupBase):
ret = []
def get_option_value(argument_name):
return self.get_option(argument_name)
try:
sops_binary, sops_binary_origin = self.get_option_and_origin("sops_binary")
if sops_binary is None and (
LooseVersion(ansible_version) < LooseVersion("2.18.8")
or
LooseVersion(ansible_version) == LooseVersion("2.19.0")
):
# Ansible-core < 2.18.8 and 2.19.0 are broken: https://github.com/ansible/ansible/issues/85480
sops_binary = self.get_option("sops_binary")
sops_binary_origin = "Direct"
except AttributeError:
# Ansible-core 2.15 has no get_option_and_origin()!
sops_binary = self.get_option("sops_binary")
sops_binary_origin = "Direct"
get_option_value = wrap_get_option_value_plugin_path(
self.get_option,
sops_binary=sops_binary,
sops_binary_origin=sops_binary_origin,
)
for term in terms:
display.debug("Sops lookup term: %s" % term)

View file

@ -96,11 +96,15 @@ def _create_env_variable(argument_name):
GENERAL_OPTIONS = {
'age_key': _create_env_variable('SOPS_AGE_KEY'),
'age_keyfile': _create_env_variable('SOPS_AGE_KEY_FILE'),
'age_key_cmd': _create_env_variable('SOPS_AGE_KEY_CMD'),
'age_ssh_private_keyfile': _create_env_variable('SOPS_AGE_SSH_PRIVATE_KEY_FILE'),
'age_ssh_private_key_cmd': _create_env_variable('SOPS_AGE_SSH_PRIVATE_KEY_CMD'),
'aws_profile': _create_single_arg('--aws-profile'),
'aws_access_key_id': _create_env_variable('AWS_ACCESS_KEY_ID'),
'aws_secret_access_key': _create_env_variable('AWS_SECRET_ACCESS_KEY'),
'aws_session_token': _create_env_variable('AWS_SESSION_TOKEN'),
'gcp_oauth_access_token': _create_env_variable('GOOGLE_OAUTH_ACCESS_TOKEN'),
'gcp_kms_client_type': _create_env_variable('SOPS_GCP_KMS_CLIENT_TYPE'),
'config_path': _create_single_arg('--config', pre=True),
'enable_local_keyservice': _create_boolean('--enable-local-keyservice=false', invert=True),
'keyservice': _create_repeated('--keyservice'),
@ -114,6 +118,7 @@ ENCRYPT_OPTIONS = {
'azure_kv': _create_comma_separated('--azure-kv'),
'hc_vault_transit': _create_comma_separated('--hc-vault-transit'),
'pgp': _create_comma_separated('--pgp'),
'huawei_cloud_kms': _create_comma_separated('--hckms'),
'unencrypted_suffix': _create_single_arg('--unencrypted-suffix'),
'encrypted_suffix': _create_single_arg('--encrypted-suffix'),
'unencrypted_regex': _create_single_arg('--unencrypted-regex'),
@ -289,7 +294,7 @@ class SopsRunner(object):
raise SopsError(path, 0, 'Cannot decode filestatus result: %s' % exc, operation='inspect')
_SOPS_RUNNER_CACHE = dict()
_SOPS_RUNNER_CACHE = dict() # type: dict[str, SopsRunner]
class Sops():
@ -357,9 +362,17 @@ def get_sops_argument_spec(add_encrypt_specific=False):
'age_keyfile': {
'type': 'path',
},
'age_key_cmd': {
'type': 'str',
'no_log': False,
},
'age_ssh_private_keyfile': {
'type': 'path',
},
'age_ssh_private_key_cmd': {
'type': 'str',
'no_log': False,
},
'aws_profile': {
'type': 'str',
},
@ -374,6 +387,14 @@ def get_sops_argument_spec(add_encrypt_specific=False):
'type': 'str',
'no_log': True,
},
'gcp_oauth_access_token': {
'type': 'str',
'no_log': True,
},
'gcp_kms_client_type': {
'type': 'str',
'choices': ['rest', 'grpc'],
},
'config_path': {
'type': 'path',
},
@ -412,6 +433,10 @@ def get_sops_argument_spec(add_encrypt_specific=False):
'type': 'list',
'elements': 'str',
},
'huawei_cloud_kms': {
'type': 'list',
'elements': 'str',
},
'unencrypted_suffix': {
'type': 'str',
},

View file

@ -42,6 +42,23 @@ options:
- ignore
- evaluate-on-load
- lazy-evaluation
return_method:
description:
- Determine how to return the results.
- Because of limitations of ansible-core < 2.21, the results were returned as Ansible facts.
Since ansible-core 2.21, it is possible to actually set variables, similar to how M(ansible.builtin.include_vars)
is working.
type: str
default: auto
choices:
auto:
- Return the results as facts for ansible-core < 2.21, and as variables for ansible-core >= 2.21.
facts-only:
- Return the results always as facts.
vars-only:
- Return the results always as variables.
- Fails for ansible-core < 2.21.
version_added: 2.3.0
extends_documentation_fragment:
- community.sops.sops
- community.sops.attributes
@ -61,7 +78,9 @@ attributes:
details:
- This action does not modify state.
facts:
support: full
support: partial
details:
- Only returns facts if O(return_method=facts-only), or O(return_method=auto) for ansible-core < 2.21.
idempotent:
support: N/A
details:
@ -105,7 +124,7 @@ EXAMPLES = r"""
RETURN = r"""
ansible_facts:
description: Variables that were included and their values.
returned: success
returned: success, and O(return_method=facts-only), or O(return_method=auto) for ansible-core < 2.21
type: dict
sample: {'variable': 'value'}
ansible_included_var_files:

View file

@ -110,7 +110,7 @@ try:
except ImportError:
YAML_IMP_ERR = traceback.format_exc()
HAS_YAML = False
yaml = None
yaml = None # type: ignore[assignment] # use better type later...
def get_data_type(module):
@ -122,7 +122,7 @@ def get_data_type(module):
return 'json'
if module.params['content_yaml'] is not None:
return 'yaml'
module.fail_json(msg='Internal error: unknown content type')
module.fail_json(msg='Internal error: unknown content type') # pragma: no cover
def compare_encoded_content(module, binary_data, content):
@ -144,7 +144,7 @@ def compare_encoded_content(module, binary_data, content):
except Exception:
# Treat parsing errors as content not equal
return False
module.fail_json(msg='Internal error: unknown content type')
module.fail_json(msg='Internal error: unknown content type') # pragma: no cover
def get_encoded_type_content(module, binary_data):
@ -156,7 +156,7 @@ def get_encoded_type_content(module, binary_data):
return 'json', json.dumps(module.params['content_json']).encode('utf-8')
if module.params['content_yaml'] is not None:
return 'yaml', yaml.safe_dump(module.params['content_yaml']).encode('utf-8')
module.fail_json(msg='Internal error: unknown content type')
module.fail_json(msg='Internal error: unknown content type') # pragma: no cover
def main():

View file

@ -0,0 +1,110 @@
# 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
# Note that this module util is **PRIVATE** to the collection. It can have breaking changes at any time.
# Do not use this from other collections or standalone plugins/modules!
from __future__ import annotations
import os
import typing as t
from ansible.module_utils.common.text.converters import to_bytes as _to_bytes
from ansible.module_utils.common.validation import check_type_bool as _check_type_bool
from ansible.module_utils.common.validation import check_type_dict as _check_type_dict
from ansible.module_utils.common.validation import check_type_int as _check_type_int
from ansible.module_utils.common.validation import check_type_float as _check_type_float
from ansible.module_utils.common.validation import check_type_list as _check_type_list
from ansible.module_utils.common.validation import check_type_path as _check_type_path
from ansible.module_utils.common.validation import check_type_str as _check_type_str
from ansible.utils.path import unfrackpath as _unfrackpath
from ansible_collections.community.sops.plugins.module_utils.sops import get_sops_argument_spec as _get_sops_argument_spec
if t.TYPE_CHECKING:
from collections.abc import Callable, Mapping # pragma: no cover
def wrap_get_option_value(
get_option_value: Callable[[str], t.Any],
*,
overrides: Mapping[str, t.Any],
) -> Callable[[str], t.Any]:
def new_get_option_value(option: str) -> t.Any:
if option in overrides:
return overrides[option]
return get_option_value(option)
return new_get_option_value
def wrap_get_option_value_plugin_path(
get_option_value: Callable[[str], t.Any],
*,
sops_binary: t.Any,
sops_binary_origin: str | None = "Direct",
) -> Callable[[str], t.Any]:
if isinstance(sops_binary, str):
candidate = sops_binary
# ansible.config.manager.resolve_path() handles {{CWD}}:
if "{{CWD}}" in candidate:
candidate = candidate.replace("{{CWD}}", os.getcwd())
basedir = sops_binary_origin if sops_binary_origin and os.path.isabs(sops_binary_origin) and os.path.exists(_to_bytes(sops_binary_origin)) else None
candidate = _unfrackpath(candidate, follow=False, basedir=basedir)
# Check whether the candidate is a file:
if os.path.isfile(candidate):
sops_binary = candidate
else:
# If not, fall back to what a module would do with the path
sops_binary = os.path.expanduser(os.path.expandvars(sops_binary))
overrides = {"sops_binary": sops_binary}
return wrap_get_option_value(get_option_value, overrides=overrides)
_TYPE_CHECKS = {
"dict": _check_type_dict,
"bool": _check_type_bool,
"int": _check_type_int,
"float": _check_type_float,
"str": lambda value: _check_type_str(value, allow_conversion=False),
"path": lambda value: _check_type_path(_check_type_str(value, allow_conversion=False)),
}
def _ensure_type_impl(value: t.Any, *, option_type: str) -> t.Any:
return _TYPE_CHECKS[option_type](value)
def _ensure_type(value: t.Any, *, option_type: str, elements_type: str | None, sensitive: bool) -> t.Any:
if value is None:
return None
if option_type != "list":
return _ensure_type_impl(value, option_type=option_type)
value = _check_type_list(value)
if elements_type is None:
# Our options do not have a list without 'elements', so this is unreachable.
# We still want to keep this code though...
return value # pragma: no cover
return [_ensure_type_impl(v, option_type=elements_type) for v in value]
def wrap_get_option_value_check_types(
get_option_value: Callable[[str], t.Any],
*,
add_encrypt_specific: bool,
) -> Callable[[str], t.Any]:
overrides: dict[str, t.Any] = {}
for option, data in _get_sops_argument_spec(add_encrypt_specific=add_encrypt_specific).items():
value = get_option_value(option)
try:
value = _ensure_type(
value,
option_type=data.get("type", "str"),
elements_type=data.get("elements"),
sensitive=data.get("no_log", False),
)
except TypeError as exc:
raise ValueError(f"option {option} has invalid value: {exc}")
overrides[option] = value
return wrap_get_option_value(get_option_value, overrides=overrides)

View file

@ -16,6 +16,7 @@ from __future__ import annotations
import abc
import copy
import traceback
import typing as t
from ansible.errors import AnsibleError
from ansible.module_utils.basic import SEQUENCETYPE, remove_values
@ -25,8 +26,14 @@ from ansible.plugins.action import ActionBase
from ansible.module_utils.common.arg_spec import ArgumentSpecValidator
from ansible.module_utils.errors import UnsupportedError
if t.TYPE_CHECKING:
from collections.abc import Callable
safe_eval: Callable[[t.Any, t.Any, t.Any], t.Any] | None
try:
from ansible.module_utils.common.validation import (
from ansible.module_utils.common.validation import ( # type: ignore[no-redef]
safe_eval,
)
except ImportError:
@ -207,7 +214,7 @@ class ActionModuleBase(ActionBase, metaclass=abc.ABCMeta):
argument_spec, kwargs = self.setup_module()
module = argument_spec.create_ansible_module_helper(AnsibleActionModule, (self, ), **kwargs)
self.run_module(module)
raise AnsibleError('Internal error: action module did not call module.exit_json()')
raise AnsibleError('Internal error: action module did not call module.exit_json()') # pragma: no cover
except _ModuleExitException as mee:
result.update(mee.result)
return result

View file

@ -87,6 +87,7 @@ options:
- name: ANSIBLE_VARS_SOPS_PLUGIN_HANDLE_UNENCRYPTED_FILES
extends_documentation_fragment:
- ansible.builtin.vars_plugin_staging
- community.sops.sops.ansible_plugin # must come before community.sops.sops!
- community.sops.sops
- community.sops.sops.ansible_env
- community.sops.sops.ansible_ini
@ -101,6 +102,7 @@ seealso:
"""
import os
import typing as t
from collections.abc import Sequence, Mapping
from ansible.errors import AnsibleParserError
@ -111,6 +113,7 @@ from ansible.plugins.vars import BaseVarsPlugin
from ansible.utils.display import Display
from ansible.utils.vars import combine_vars
from ansible_collections.community.sops.plugins.module_utils.sops import Sops, SopsError
from ansible_collections.community.sops.plugins.plugin_utils._args import wrap_get_option_value_plugin_path
try:
from ansible.template import trust_as_template as _trust_as_template
@ -121,11 +124,11 @@ except ImportError:
display = Display()
FOUND = {}
DECRYPTED = {}
FOUND: dict[str, list[str]] = {}
DECRYPTED: dict[str, bytes] = {}
def _make_safe(value):
def _make_safe(value: t.Any) -> t.Any:
if isinstance(value, str):
# must come *before* Sequence, as strings are also instances of Sequence
if HAS_DATATAGGING and isinstance(value, str):
@ -148,8 +151,17 @@ class VarsModule(BaseVarsPlugin):
super().get_vars(loader, path, entities)
def get_option_value(argument_name):
return self.get_option(argument_name)
try:
sops_binary, sops_binary_origin = self.get_option_and_origin("sops_binary")
except AttributeError:
# Ansible-core 2.15 has no get_option_and_origin()!
sops_binary = self.get_option("sops_binary")
sops_binary_origin = "Direct"
get_option_value = wrap_get_option_value_plugin_path(
self.get_option,
sops_binary=sops_binary,
sops_binary_origin=sops_binary_origin,
)
if cache is None:
cache = self.get_option('cache')

View file

@ -4,4 +4,4 @@ SPDX-License-Identifier: GPL-3.0-or-later
SPDX-FileCopyrightText: 2022, Felix Fontein
-->
See [the documentation](https://docs.ansible.com/ansible/devel/collections/community/sops/).
See [the documentation](https://docs.ansible.com/projects/ansible/devel/collections/community/sops/).

View file

@ -17,6 +17,7 @@ argument_specs:
Debian 10 (Buster) or newer,
Fedora (new enough),
RHEL 7 or newer,
OpenSuSE Tumbleweed (and probably also Leap),
Ubuntu 16.04 or newer LTS versions
- The Ansible facts C(ansible_facts.architecture), C(ansible_facts.distribution), C(ansible_facts.distribution_major_version),
C(ansible_facts.distribution_version), and C(ansible_facts.os_family) are expected to be present if O(sops_install_on_localhost) is V(false).
@ -101,3 +102,4 @@ argument_specs:
- Fedora (new enough)
- RHEL 7 or newer
- Ubuntu 16.04 or newer LTS versions
- OpenSuSE Tumbleweed (and probably also Leap)

View file

@ -0,0 +1,38 @@
---
# Copyright (c) Ansible Project
# 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
_community_sops_install_system_has_system: true
_community_sops_install_system_has_system_latest_only: true
_community_sops_install_system_has_github: true
_community_sops_install_allow_downgrade: true
_community_sops_install_system_packages:
- gpg2
_community_sops_install_system_packages_unsigned: []
_community_sops_install_system_package_deb_github: false
_community_sops_install_system_packages_github: []
_community_sops_install_system_packages_unsigned_github:
- >-
https://github.com/getsops/sops/releases/download/v{{
_community_sops_install_effective_sops_version
}}/sops-{{
(_community_sops_install_effective_sops_version is version('3.6.0', '<')) | ternary('v', '')
}}{{
_community_sops_install_effective_sops_version.replace('-', '.')
}}{{
(
_community_sops_install_effective_sops_version is version('3.8.0', '<') or
_community_sops_install_effective_sops_version is version('3.9.0', '>=')
) | ternary('-1', '')
}}.{{
ansible_facts.architecture
}}.rpm
_community_sops_install_system_package_deb_system: false
_community_sops_install_system_packages_system:
- sops
_community_sops_install_system_packages_unsigned_system: []

View file

@ -5,26 +5,39 @@
- when: sops_installed
block:
- name: Test bad parameter detection (1/2)
- name: Test bad parameter detection (1/3)
set_fact:
sops_bad_input_type: "{{ 'this-is-not: a sops file' | community.sops.decrypt(input_type='foo') }}"
ignore_errors: true
register: sops_bad_input_type
- name: Test bad parameter detection (2/2)
- name: Test bad parameter detection (2/3)
set_fact:
sops_bad_output_type: "{{ 'this-is-not: a sops file' | community.sops.decrypt(output_type=23) }}"
ignore_errors: true
register: sops_bad_output_type
- name: Test bad parameter detection (3/3)
set_fact:
sops_bad_output_type: "{{ 'this-is-not: a sops file' | community.sops.decrypt(sops_binary=42) }}"
ignore_errors: true
register: sops_bad_binary
- assert:
that:
- "sops_bad_input_type is failed"
- "'input_type must be one of' in sops_bad_input_type.msg"
- "'; got \"foo\"' in sops_bad_input_type.msg"
- >-
'input_type must be one of' in sops_bad_input_type.msg
- >-
'; got "foo"' in sops_bad_input_type.msg
- "sops_bad_output_type is failed"
- "'output_type must be one of' in sops_bad_output_type.msg"
- "'; got \"23\"' in sops_bad_output_type.msg"
- >-
'output_type must be one of' in sops_bad_output_type.msg
- >-
'; got "23"' in sops_bad_output_type.msg
- "sops_bad_binary is failed"
- >-
"Error in community.sops.decrypt filter: option sops_binary has invalid value: '42' is not a string and conversion is not allowed" in sops_bad_binary.msg
- name: Test decrypt of non-sops file
set_fact:

View file

@ -46,7 +46,7 @@
that:
- "'sops metadata not found' in load_vars_wrong_file.msg"
- name: Test load_vars with simple file into variable
- name: Test load_vars with simple file into variable (1/3)
community.sops.load_vars:
file: simple.sops.yaml
name: dest_variable
@ -55,10 +55,65 @@
- assert:
that:
- load_vars_simple is success
- "load_vars_simple.ansible_facts == {'dest_variable': {'foo': 'bar'}}"
- >-
ansible_version.full is version('2.21', '>=') or
load_vars_simple.ansible_facts == {'dest_variable': {'foo': 'bar'}}
- >-
ansible_version.full is version('2.21', '<') or
'ansible_facts' not in load_vars_simple
- dest_variable.foo == 'bar'
- foo is undefined
- name: Test load_vars with simple file into variable (2/3)
community.sops.load_vars:
file: simple.sops.yaml
name: dest_variable_2
return_method: facts-only
register: load_vars_simple_2
- assert:
that:
- load_vars_simple_2 is success
- >-
load_vars_simple_2.ansible_facts == {'dest_variable_2': {'foo': 'bar'}}
- ansible_facts.dest_variable_2.foo == 'bar'
- >-
ansible_version.full is version('2.24', '>=') or
dest_variable_2.foo == 'bar'
register: load_vars_simple_2_assert
- name: Show deprecations
debug:
msg: "{{ load_vars_simple_2_assert.deprecations | default([]) }}"
- when: ansible_version.full is version('2.20', '>=') and ansible_version.full is version('2.24', '<')
assert:
that:
- load_vars_simple_2_assert.deprecations | length > 0
- load_vars_simple_2_assert.deprecations | map(attribute='msg') | select('ansible.builtin.regex', 'INJECT_FACTS_AS_VARS') | length > 0
- name: Test load_vars with simple file into variable (3/3)
community.sops.load_vars:
file: simple.sops.yaml
name: dest_variable_3
return_method: vars-only
register: load_vars_simple_3
ignore_errors: true
- when: ansible_version.full is version('2.21', '>=')
assert:
that:
- load_vars_simple_3 is success
- >-
"ansible_facts" not in load_vars_simple_3
- dest_variable_3.foo == 'bar'
- when: ansible_version.full is version('2.21', '<')
assert:
that:
- load_vars_simple_3 is failed
- load_vars_simple_3.msg == "return_method=vars-only requires ansible-core 2.21+"
- name: Test load_vars with empty file
community.sops.load_vars:
file: empty.sops.json
@ -67,7 +122,9 @@
- assert:
that:
- load_vars_empty is success
- load_vars_empty.ansible_facts | length == 0
- >-
ansible_version.full is version('2.21', '>=') or
(load_vars_empty.ansible_facts | length == 0)
- name: Test load_vars with simple file into global namespace
community.sops.load_vars:
@ -77,7 +134,9 @@
- assert:
that:
- load_vars_simple_global is success
- "load_vars_simple_global.ansible_facts == {'foo': 'bar'}"
- >-
ansible_version.full is version('2.21', '>=') or
load_vars_simple_global.ansible_facts == {'foo': 'bar'}
- foo == 'bar'
- name: Test load_vars with expressions ignored

View file

@ -41,12 +41,14 @@
- name: Test simple lookup
set_fact:
sops_success: "{{ lookup('community.sops.sops', 'simple.sops.yaml') }}"
sops_success_2: "{{ lookup('community.sops.sops', 'simple.sops.yaml', sops_binary='sops') }}"
register: sops_lookup_simple
- assert:
that:
- "sops_lookup_simple is success"
- "sops_success == 'foo: bar'"
- "sops_success_2 == 'foo: bar'"
- name: Test extract
set_fact:

View file

@ -6,10 +6,10 @@
- name: Show some basic system info
debug:
msg: |
Architecture: {{ ansible_architecture }}
OS family: {{ ansible_os_family }}
Distribution: {{ ansible_distribution }}
Distribution version: {{ ansible_distribution_version }}
Architecture: {{ ansible_facts.architecture }}
OS family: {{ ansible_facts.os_family }}
Distribution: {{ ansible_facts.distribution }}
Distribution version: {{ ansible_facts.distribution_version }}
- name: Install latest sops
include_role:

View file

@ -6,10 +6,10 @@
- name: Show some basic system info
debug:
msg: |
Architecture: {{ ansible_architecture }}
OS family: {{ ansible_os_family }}
Distribution: {{ ansible_distribution }}
Distribution version: {{ ansible_distribution_version }}
Architecture: {{ ansible_facts.architecture }}
OS family: {{ ansible_facts.os_family }}
Distribution: {{ ansible_facts.distribution }}
Distribution version: {{ ansible_facts.distribution_version }}
- vars:
sops_version_1: "{{ '3.7.3' if ansible_architecture == 'x86_64' else '3.9.2' }}"

View file

@ -6,10 +6,10 @@
- name: Show some basic system info
debug:
msg: |
Architecture: {{ ansible_architecture }}
OS family: {{ ansible_os_family }}
Distribution: {{ ansible_distribution }}
Distribution version: {{ ansible_distribution_version }}
Architecture: {{ ansible_facts.architecture }}
OS family: {{ ansible_facts.os_family }}
Distribution: {{ ansible_facts.distribution }}
Distribution version: {{ ansible_facts.distribution_version }}
- vars:
sops_version_1: "{{ '3.7.3' if ansible_architecture == 'x86_64' else '3.9.2' }}"

View file

@ -3,7 +3,7 @@
# 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
- when: ansible_os_family == "Archlinux"
- when: ansible_facts.os_family == "Archlinux"
block:
- name: ArchLinux specific setup
include_tasks: archlinux.yml

View file

@ -7,4 +7,3 @@
file:
path: "{{ remote_tmp_dir }}"
state: absent
no_log: true

View file

@ -8,7 +8,7 @@
# and should not be used as examples of how to write Ansible roles #
####################################################################
- name: make sure we have the ansible_os_family and ansible_distribution_version facts
- name: make sure we have the ansible_facts.os_family and ansible_facts.distribution_version facts
setup:
gather_subset: distribution
when: ansible_facts == {}
@ -16,5 +16,5 @@
- include_tasks: "{{ lookup('first_found', files)}}"
vars:
files:
- "{{ ansible_os_family | lower }}.yml"
- "{{ ansible_facts.os_family | lower }}.yml"
- "default.yml"

View file

@ -6,10 +6,10 @@
- name: Show some basic system info
debug:
msg: |
Architecture: {{ ansible_architecture }}
OS family: {{ ansible_os_family }}
Distribution: {{ ansible_distribution }}
Distribution version: {{ ansible_distribution_version }}
Architecture: {{ ansible_facts.architecture }}
OS family: {{ ansible_facts.os_family }}
Distribution: {{ ansible_facts.distribution }}
Distribution version: {{ ansible_facts.distribution_version }}
- name: Install SOPS on localhost
include_role:

View file

@ -6,10 +6,10 @@
- name: Show some basic system info
debug:
msg: |
Architecture: {{ ansible_architecture }}
OS family: {{ ansible_os_family }}
Distribution: {{ ansible_distribution }}
Distribution version: {{ ansible_distribution_version }}
Architecture: {{ ansible_facts.architecture }}
OS family: {{ ansible_facts.os_family }}
Distribution: {{ ansible_facts.distribution }}
Distribution version: {{ ansible_facts.distribution_version }}
- name: Test whether sops is installed
command: sops --help

View file

@ -1,3 +1,7 @@
plugins/lookup/sops.py validate-modules:invalid-documentation # choices as dict
plugins/modules/load_vars.py validate-modules:invalid-documentation # choices as dict
plugins/modules/sops_encrypt.py validate-modules:invalid-documentation # choices as dict
plugins/vars/sops.py validate-modules:invalid-documentation # choices as dict
tests/integration/targets/filter_decrypt/files/hidden-binary.yaml yamllint:error
tests/integration/targets/filter_decrypt/files/hidden-json.yaml yamllint:error
tests/integration/targets/lookup_sops/files/hidden-binary.yaml yamllint:error

View file

@ -1,3 +1,7 @@
plugins/lookup/sops.py validate-modules:invalid-documentation # choices as dict
plugins/modules/load_vars.py validate-modules:invalid-documentation # choices as dict
plugins/modules/sops_encrypt.py validate-modules:invalid-documentation # choices as dict
plugins/vars/sops.py validate-modules:invalid-documentation # choices as dict
tests/integration/targets/filter_decrypt/files/hidden-binary.yaml yamllint:error
tests/integration/targets/filter_decrypt/files/hidden-json.yaml yamllint:error
tests/integration/targets/lookup_sops/files/hidden-binary.yaml yamllint:error

View file

@ -1,3 +1,4 @@
plugins/module_utils/sops.py pylint:ansible-bad-function
tests/integration/targets/filter_decrypt/files/hidden-binary.yaml yamllint:error
tests/integration/targets/filter_decrypt/files/hidden-json.yaml yamllint:error
tests/integration/targets/lookup_sops/files/hidden-binary.yaml yamllint:error

View file

@ -0,0 +1,5 @@
plugins/module_utils/sops.py pylint:ansible-bad-function
tests/integration/targets/filter_decrypt/files/hidden-binary.yaml yamllint:error
tests/integration/targets/filter_decrypt/files/hidden-json.yaml yamllint:error
tests/integration/targets/lookup_sops/files/hidden-binary.yaml yamllint:error
tests/integration/targets/lookup_sops/files/hidden-json.yaml yamllint:error

View file

@ -0,0 +1,3 @@
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
SPDX-FileCopyrightText: Ansible Project