Skip to content

Commit

Permalink
Create droppath option in ssm_parameter.py (#1756) (#2274)
Browse files Browse the repository at this point in the history
This is a backport of PR #1756 as merged into main (c535e63).
SUMMARY
In the event that there exists two parameters in Parameter Store path/to/params/foo/bar/param and path/to/params/x/y/param, a user attempting to recursively pull all parameters under the path/to/params path with the command {{ lookup('amazon.aws.aws_ssm', '/PATH/to/params', region='ap-southeast-2', shortnames=true, bypath=true, recursive=true ) }}" will be unable to use the shortnames argument without creating a conflict between the two param results.  Only one param key will exist in the resulting dictionary.
This is problematic for users that wish to lookup a parameter hierarchy with repetitive names in the final value of the parameter path. In this scenario, users are currently forced to use the fully qualified parameter name when interacting with their dictionary results.
This pull request introduces the droppath option,  which will drop the common lookup path from the names of all parameters. In the scenario above, the resulting dictionary would contain both a foo/bar/param and a /x/y/param  allowing users to refer to them by their minimally differentiated name.
ISSUE TYPE

Feature Pull Request

COMPONENT NAME

lookup

ADDITIONAL INFORMATION
Step by step
Setup

Create parameter path/to/params/foo/bar/param with value abc
Create parameter path/to/params/x/y/param with value 123

Run shortnames



name: return a dictionary of ssm parameters from a hierarchy path with shortened names (param instead of /PATH/to/param)
debug: msg="{{ lookup('amazon.aws.aws_ssm', '/PATH/to/params', region='ap-southeast-2', shortnames=true, bypath=true, recursive=true ) }}"


Observe result  {'param': '123'}

Run droppath



name: return a dictionary of ssm parameters from a hierarchy path with shortened names (param instead of /PATH/to/param)
debug: msg="{{ lookup('amazon.aws.aws_ssm', '/PATH/to/params', region='ap-southeast-2', droppath=true, bypath=true, recursive=true ) }}"


Observe result  {'/foo/bar/param': 'abc', '/x/y/param': '123'}

Run both



name: return a dictionary of ssm parameters from a hierarchy path with shortened names (param instead of /PATH/to/param)
debug: msg="{{ lookup('amazon.aws.aws_ssm', '/PATH/to/params', region='ap-southeast-2', droppath=true, shortnames = true, bypath=true, recursive=true ) }}"


Observe error shortnames and droppath are mutually exclusive. They cannot both be set to true.

Reviewed-by: Mark Chappell
  • Loading branch information
patchback[bot] committed Aug 30, 2024
1 parent 1d4d236 commit 91694ef
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 7 deletions.
3 changes: 3 additions & 0 deletions changelogs/fragments/add-droppath-option-to-ssm-lookup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
---
minor_changes:
- ssm parameter lookup - add new option ``droppath`` to drop the hierarchical search path from ssm parameter lookup results (https://github.com/ansible-collections/amazon.aws/pull/1756).
29 changes: 24 additions & 5 deletions plugins/lookup/ssm_parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,24 @@
default: false
type: boolean
shortnames:
description: Indicates whether to return the name only without path if using a parameter hierarchy.
description:
- Indicates whether to return the name only without path if using a parameter hierarchy.
- The O(shortnames) and O(droppath) options are mutually exclusive.
default: false
type: boolean
droppath:
description:
- Indicates whether to return the parameter name with the searched parameter heirarchy removed.
- The O(shortnames) and O(droppath) options are mutually exclusive.
default: false
type: boolean
version_added: 8.2.0
on_missing:
description:
- Action to take if the SSM parameter is missing.
- C(error) will raise a fatal error when the SSM parameter is missing.
- C(skip) will silently ignore the missing SSM parameter.
- C(warn) will skip over the missing SSM parameter but issue a warning.
- V(error) will raise a fatal error when the SSM parameter is missing.
- V(skip) will silently ignore the missing SSM parameter.
- V(warn) will skip over the missing SSM parameter but issue a warning.
default: error
type: string
choices: ['error', 'skip', 'warn']
Expand Down Expand Up @@ -112,9 +121,12 @@
- name: return a dictionary of ssm parameters from a hierarchy path
debug: msg="{{ lookup('amazon.aws.aws_ssm', '/PATH/to/params', region='ap-southeast-2', bypath=true, recursive=true ) }}"
- name: return a dictionary of ssm parameters from a hierarchy path with shortened names (param instead of /PATH/to/param)
- name: return a dictionary of ssm parameters from a hierarchy path with shortened names (param instead of /PATH/to/params/foo/bar/param)
debug: msg="{{ lookup('amazon.aws.aws_ssm', '/PATH/to/params', region='ap-southeast-2', shortnames=true, bypath=true, recursive=true ) }}"
- name: return a dictionary of ssm parameters from a hierarchy path with the heirarchy path dropped (foo/bar/param instead of /PATH/to/params/foo/bar/param)
debug: msg="{{ lookup('amazon.aws.aws_ssm', '/PATH/to/params', region='ap-southeast-2', droppath=true, bypath=true, recursive=true ) }}"
- name: Iterate over a parameter hierarchy (one iteration per parameter)
debug: msg='Key contains {{ item.key }} , with value {{ item.value }}'
loop: "{{ lookup('amazon.aws.aws_ssm', '/demo/', region='ap-southeast-2', bypath=True) | dict2items }}"
Expand Down Expand Up @@ -173,6 +185,9 @@ def run(self, terms, variables, **kwargs):
f'"on_denied" must be a string and one of "error", "warn" or "skip", not {on_denied}'
)

if self.get_option("shortnames") and self.get_option("droppath"):
raise AnsibleLookupError("shortnames and droppath are mutually exclusive. They cannot both be set to true.")

ret = []
ssm_dict = {}

Expand All @@ -193,6 +208,10 @@ def run(self, terms, variables, **kwargs):
for x in paramlist:
x["Name"] = x["Name"][x["Name"].rfind("/") + 1:] # fmt: skip

if self.get_option("droppath"):
for x in paramlist:
x["Name"] = x["Name"].replace(ssm_dict["Path"], "")

display.vvvv(f"AWS_ssm path lookup returned: {to_native(paramlist)}")

ret.append(
Expand Down
37 changes: 35 additions & 2 deletions tests/integration/targets/lookup_ssm_parameter/tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,21 @@
path_name: /{{ ssm_key_prefix }}/path
path_name_a: "{{ path_name }}/key_one"
path_shortname_a: key_one
path_droppath_name_a: /key_one
path_name_b: "{{ path_name }}/keyTwo"
path_shortname_b: keyTwo
path_droppath_name_b: /keyTwo
path_name_c: "{{ path_name }}/Nested/Key"
path_shortname_c: Key
path_droppath_name_c: /Nested/Key
path_name_d: "{{ path_name }}/AnotherNested/Key"
path_shortname_d: Key
path_droppath_name_d: /AnotherNested/Key
path_description: This is somewhere to store a set of keys
path_value_a: value_one
path_value_b: valueTwo
path_value_c: Value Three
path_value_d: value-fou
missing_name: "{{ path_name }}/IDoNotExist"
block:
# ============================================================
Expand Down Expand Up @@ -131,7 +138,14 @@
description: "{{ path_description }}"
value: "{{ path_value_c }}"

- name: Create nested key/value pair in aws parameter store (4)
ssm_parameter:
name: '{{ path_name_d }}'
description: '{{ path_description }}'
value: '{{ path_value_d }}'

# ============================================================

- name: Lookup a keys using bypath
ansible.builtin.set_fact:
lookup_value: "{{ lookup('amazon.aws.aws_ssm', path_name, bypath=True, wantlist=True, **connection_args ) | first }}"
Expand All @@ -154,7 +168,9 @@
- lookup_value[path_name_b] == path_value_b
- path_name_c in lookup_value
- lookup_value[path_name_c] == path_value_c
- lookup_value | length == 3
- path_name_d in lookup_value
- lookup_value[path_name_d] == path_value_d
- lookup_value | length == 4

- name: Lookup a keys using bypath and shortname
ansible.builtin.set_fact:
Expand All @@ -180,6 +196,21 @@
- lookup_value[path_shortname_c] == path_value_c
- lookup_value | length == 3

- name: Lookup a keys using bypath and recursive and droppath
ansible.builtin.set_fact:
lookup_value: "{{ lookup('amazon.aws.aws_ssm', path_name, bypath=True, recursive=True, droppath=True, wantlist=True, **connection_args ) | first }}"
- ansible.builtin.assert:
that:
- path_droppath_name_a in lookup_value
- lookup_value[path_droppath_name_a] == path_value_a
- path_droppath_name_b in lookup_value
- lookup_value[path_droppath_name_b] == path_value_b
- path_droppath_name_c in lookup_value
- lookup_value[path_droppath_name_c] == path_value_c
- path_droppath_name_d in lookup_value
- lookup_value[path_droppath_name_d] == path_value_d
- lookup_value | length == 4

# ============================================================

- name: Explicitly lookup two keys
Expand Down Expand Up @@ -259,7 +290,9 @@
- lookup_value[0][path_name_b] == path_value_b
- path_name_c in lookup_value[0]
- lookup_value[0][path_name_c] == path_value_c
- lookup_value[0] | length == 3
- path_name_d in lookup_value[0]
- lookup_value[0][path_name_d] == path_value_d
- lookup_value[0] | length == 4

always:
# ============================================================
Expand Down

0 comments on commit 91694ef

Please sign in to comment.