mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
[PR #7587/1b9d437b backport][stable-8] New module git config info (#7638)
New module git config info (#7587)
Add new module git_config_info
(cherry picked from commit 1b9d437be8
)
Co-authored-by: Günther Grill <guenhter@users.noreply.github.com>
This commit is contained in:
parent
ee428ccd64
commit
ee7ba1a691
16 changed files with 406 additions and 1 deletions
2
.github/BOTMETA.yml
vendored
2
.github/BOTMETA.yml
vendored
|
@ -526,6 +526,8 @@ files:
|
|||
maintainers: russoz
|
||||
$modules/git_config.py:
|
||||
maintainers: djmattyg007 mgedmin
|
||||
$modules/git_config_info.py:
|
||||
maintainers: guenhter
|
||||
$modules/github_:
|
||||
maintainers: stpierre
|
||||
$modules/github_deploy_key.py:
|
||||
|
|
|
@ -20,7 +20,7 @@ author:
|
|||
requirements: ['git']
|
||||
short_description: Read and write git configuration
|
||||
description:
|
||||
- The M(community.general.git_config) module changes git configuration by invoking 'git config'.
|
||||
- The M(community.general.git_config) module changes git configuration by invoking C(git config).
|
||||
This is needed if you do not want to use M(ansible.builtin.template) for the entire git
|
||||
config file (for example because you need to change just C(user.email) in
|
||||
/etc/.git/config). Solutions involving M(ansible.builtin.command) are cumbersome or
|
||||
|
|
187
plugins/modules/git_config_info.py
Normal file
187
plugins/modules/git_config_info.py
Normal file
|
@ -0,0 +1,187 @@
|
|||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2023, Guenther Grill <grill.guenther@gmail.com>
|
||||
#
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import absolute_import, division, print_function
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: git_config_info
|
||||
author:
|
||||
- Guenther Grill (@guenhter)
|
||||
version_added: 8.1.0
|
||||
requirements: ['git']
|
||||
short_description: Read git configuration
|
||||
description:
|
||||
- The M(community.general.git_config_info) module reads the git configuration
|
||||
by invoking C(git config).
|
||||
extends_documentation_fragment:
|
||||
- community.general.attributes
|
||||
- community.general.attributes.info_module
|
||||
options:
|
||||
name:
|
||||
description:
|
||||
- The name of the setting to read.
|
||||
- If not provided, all settings will be returned as RV(config_values).
|
||||
type: str
|
||||
path:
|
||||
description:
|
||||
- Path to a git repository or file for reading values from a specific repo.
|
||||
- If O(scope) is V(local), this must point to a repository to read from.
|
||||
- If O(scope) is V(file), this must point to specific git config file to read from.
|
||||
- Otherwise O(path) is ignored if set.
|
||||
type: path
|
||||
scope:
|
||||
description:
|
||||
- Specify which scope to read values from.
|
||||
- If set to V(global), the global git config is used. O(path) is ignored.
|
||||
- If set to V(system), the system git config is used. O(path) is ignored.
|
||||
- If set to V(local), O(path) must be set to the repo to read from.
|
||||
- If set to V(file), O(path) must be set to the config file to read from.
|
||||
choices: [ "global", "system", "local", "file" ]
|
||||
default: "system"
|
||||
type: str
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
- name: Read a system wide config
|
||||
community.general.git_config_info:
|
||||
name: core.editor
|
||||
register: result
|
||||
|
||||
- name: Show value of core.editor
|
||||
ansible.builtin.debug:
|
||||
msg: "{{ result.config_value | default('(not set)', true) }}"
|
||||
|
||||
- name: Read a global config from ~/.gitconfig
|
||||
community.general.git_config_info:
|
||||
name: alias.remotev
|
||||
scope: global
|
||||
|
||||
- name: Read a project specific config
|
||||
community.general.git_config_info:
|
||||
name: color.ui
|
||||
scope: local
|
||||
path: /etc
|
||||
|
||||
- name: Read all global values
|
||||
community.general.git_config_info:
|
||||
scope: global
|
||||
|
||||
- name: Read all system wide values
|
||||
community.general.git_config_info:
|
||||
|
||||
- name: Read all values of a specific file
|
||||
community.general.git_config_info:
|
||||
scope: file
|
||||
path: /etc/gitconfig
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
---
|
||||
config_value:
|
||||
description: >
|
||||
When O(name) is set, a string containing the value of the setting in name. If O(name) is not set, empty.
|
||||
If a config key such as V(push.pushoption) has more then one entry, just the first one is returned here.
|
||||
returned: success if O(name) is set
|
||||
type: str
|
||||
sample: "vim"
|
||||
|
||||
config_values:
|
||||
description:
|
||||
- This is a dictionary mapping a git configuration setting to a list of its values.
|
||||
- When O(name) is not set, all configuration settings are returned here.
|
||||
- When O(name) is set, only the setting specified in O(name) is returned here.
|
||||
If that setting is not set, the key will still be present, and its value will be an empty list.
|
||||
returned: success
|
||||
type: dict
|
||||
sample:
|
||||
core.editor: ["vim"]
|
||||
color.ui: ["auto"]
|
||||
push.pushoption: ["merge_request.create", "merge_request.draft"]
|
||||
alias.remotev: ["remote -v"]
|
||||
'''
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
|
||||
def main():
|
||||
module = AnsibleModule(
|
||||
argument_spec=dict(
|
||||
name=dict(type="str"),
|
||||
path=dict(type="path"),
|
||||
scope=dict(required=False, type="str", default="system", choices=["global", "system", "local", "file"]),
|
||||
),
|
||||
required_if=[
|
||||
("scope", "local", ["path"]),
|
||||
("scope", "file", ["path"]),
|
||||
],
|
||||
required_one_of=[],
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
# We check error message for a pattern, so we need to make sure the messages appear in the form we're expecting.
|
||||
# Set the locale to C to ensure consistent messages.
|
||||
module.run_command_environ_update = dict(LANG='C', LC_ALL='C', LC_MESSAGES='C', LC_CTYPE='C')
|
||||
|
||||
name = module.params["name"]
|
||||
path = module.params["path"]
|
||||
scope = module.params["scope"]
|
||||
|
||||
run_cwd = path if scope == "local" else "/"
|
||||
args = build_args(module, name, path, scope)
|
||||
|
||||
(rc, out, err) = module.run_command(args, cwd=run_cwd, expand_user_and_vars=False)
|
||||
|
||||
if rc == 128 and "unable to read config file" in err:
|
||||
# This just means nothing has been set at the given scope
|
||||
pass
|
||||
elif rc >= 2:
|
||||
# If the return code is 1, it just means the option hasn't been set yet, which is fine.
|
||||
module.fail_json(rc=rc, msg=err, cmd=" ".join(args))
|
||||
|
||||
output_lines = out.strip("\0").split("\0") if out else []
|
||||
|
||||
if name:
|
||||
first_value = output_lines[0] if output_lines else ""
|
||||
config_values = {name: output_lines}
|
||||
module.exit_json(changed=False, msg="", config_value=first_value, config_values=config_values)
|
||||
else:
|
||||
config_values = text_to_dict(output_lines)
|
||||
module.exit_json(changed=False, msg="", config_value="", config_values=config_values)
|
||||
|
||||
|
||||
def build_args(module, name, path, scope):
|
||||
git_path = module.get_bin_path("git", True)
|
||||
args = [git_path, "config", "--includes", "--null", "--" + scope]
|
||||
|
||||
if scope == "file":
|
||||
args.append(path)
|
||||
|
||||
if name:
|
||||
args.extend(["--get-all", name])
|
||||
else:
|
||||
args.append("--list")
|
||||
|
||||
return args
|
||||
|
||||
|
||||
def text_to_dict(text_lines):
|
||||
config_values = {}
|
||||
for value in text_lines:
|
||||
k, v = value.split("\n", 1)
|
||||
if k in config_values:
|
||||
config_values[k].append(v)
|
||||
else:
|
||||
config_values[k] = [v]
|
||||
return config_values
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
1
tests/.gitignore
vendored
1
tests/.gitignore
vendored
|
@ -3,3 +3,4 @@
|
|||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
output/
|
||||
integration/inventory
|
||||
|
|
7
tests/integration/targets/git_config_info/aliases
Normal file
7
tests/integration/targets/git_config_info/aliases
Normal file
|
@ -0,0 +1,7 @@
|
|||
# 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
|
||||
|
||||
azp/posix/3
|
||||
skip/aix
|
||||
destructive
|
11
tests/integration/targets/git_config_info/files/gitconfig
Normal file
11
tests/integration/targets/git_config_info/files/gitconfig
Normal file
|
@ -0,0 +1,11 @@
|
|||
# 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
|
||||
|
||||
[credential "https://some.com"]
|
||||
username = yolo
|
||||
[user]
|
||||
name = foobar
|
||||
[push]
|
||||
pushoption = merge_request.create
|
||||
pushoption = merge_request.draft
|
7
tests/integration/targets/git_config_info/meta/main.yml
Normal file
7
tests/integration/targets/git_config_info/meta/main.yml
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
# 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
|
||||
|
||||
dependencies:
|
||||
- setup_remote_tmp_dir
|
|
@ -0,0 +1,26 @@
|
|||
---
|
||||
# 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
|
||||
|
||||
- import_tasks: "setup_file.yml"
|
||||
|
||||
- name: getting all system configs
|
||||
git_config_info:
|
||||
scope: system
|
||||
register: get_result1
|
||||
|
||||
- name: getting all system configs for a key
|
||||
git_config_info:
|
||||
name: user.name
|
||||
scope: system
|
||||
register: get_result2
|
||||
|
||||
- name: assert value is correct
|
||||
assert:
|
||||
that:
|
||||
- get_result1.config_value == ""
|
||||
- 'get_result1.config_values == {}'
|
||||
- get_result2.config_value == ""
|
||||
- 'get_result2.config_values == {"user.name": []}'
|
||||
...
|
|
@ -0,0 +1,19 @@
|
|||
---
|
||||
# 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
|
||||
|
||||
- include_tasks: "{{ item.import_file }}"
|
||||
|
||||
- name: getting all values (as list) for a file config
|
||||
git_config_info:
|
||||
scope: "{{ item.git_scope }}"
|
||||
path: "{{ item.git_file | default(omit) }}"
|
||||
register: get_result
|
||||
|
||||
- name: assert value is correct
|
||||
assert:
|
||||
that:
|
||||
- get_result.config_value == ""
|
||||
- 'get_result.config_values == {"credential.https://some.com.username": ["yolo"], "user.name": ["foobar"], "push.pushoption": ["merge_request.create", "merge_request.draft"]}'
|
||||
...
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
# 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
|
||||
|
||||
- include_tasks: "{{ item.import_file }}"
|
||||
|
||||
- name: getting only a single value (as string) from an option with multiple values in the git config file
|
||||
git_config_info:
|
||||
name: push.pushoption
|
||||
scope: "{{ item.git_scope }}"
|
||||
path: "{{ item.git_file | default(omit) }}"
|
||||
register: get_result
|
||||
|
||||
- name: assert value is correct
|
||||
assert:
|
||||
that:
|
||||
- get_result.config_value == "merge_request.create"
|
||||
- 'get_result.config_values == {"push.pushoption": ["merge_request.create", "merge_request.draft"]}'
|
||||
...
|
|
@ -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
|
||||
|
||||
- include_tasks: "{{ item.import_file }}"
|
||||
|
||||
- name: getting simple file value1
|
||||
git_config_info:
|
||||
name: user.name
|
||||
scope: "{{ item.git_scope }}"
|
||||
path: "{{ item.git_file | default(omit) }}"
|
||||
register: get_result1
|
||||
|
||||
- name: getting simple file value2
|
||||
git_config_info:
|
||||
name: "credential.https://some.com.username"
|
||||
scope: "{{ item.git_scope }}"
|
||||
path: "{{ item.git_file | default(omit) }}"
|
||||
register: get_result2
|
||||
|
||||
- name: getting not existing value
|
||||
git_config_info:
|
||||
name: "user.email"
|
||||
scope: "{{ item.git_scope }}"
|
||||
path: "{{ item.git_file | default(omit) }}"
|
||||
register: get_result3
|
||||
|
||||
- name: assert value is correct
|
||||
assert:
|
||||
that:
|
||||
- get_result1.config_value == "foobar"
|
||||
- 'get_result1.config_values == {"user.name": ["foobar"]}'
|
||||
- get_result2.config_value == "yolo"
|
||||
- 'get_result2.config_values == {"credential.https://some.com.username": ["yolo"]}'
|
||||
- get_result3.config_value == ""
|
||||
- 'get_result3.config_values == {"user.email": []}'
|
||||
...
|
33
tests/integration/targets/git_config_info/tasks/main.yml
Normal file
33
tests/integration/targets/git_config_info/tasks/main.yml
Normal file
|
@ -0,0 +1,33 @@
|
|||
---
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
# test code for the git_config_info module
|
||||
# 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
|
||||
|
||||
- name: setup
|
||||
import_tasks: setup.yml
|
||||
|
||||
- block:
|
||||
- include_tasks: get_simple_value.yml
|
||||
loop:
|
||||
- { import_file: setup_global.yml, git_scope: 'global' }
|
||||
- { import_file: setup_file.yml, git_scope: 'file', git_file: "{{ remote_tmp_dir }}/gitconfig_file" }
|
||||
|
||||
- include_tasks: get_multi_value.yml
|
||||
loop:
|
||||
- { import_file: setup_global.yml, git_scope: 'global' }
|
||||
- { import_file: setup_file.yml, git_scope: 'file', git_file: "{{ remote_tmp_dir }}/gitconfig_file" }
|
||||
|
||||
- include_tasks: get_all_values.yml
|
||||
loop:
|
||||
- { import_file: setup_global.yml, git_scope: 'global' }
|
||||
- { import_file: setup_file.yml, git_scope: 'file', git_file: "{{ remote_tmp_dir }}/gitconfig_file" }
|
||||
|
||||
- include_tasks: error_handling.yml
|
||||
when: git_installed is succeeded and git_version.stdout is version(git_version_supporting_includes, ">=")
|
||||
...
|
15
tests/integration/targets/git_config_info/tasks/setup.yml
Normal file
15
tests/integration/targets/git_config_info/tasks/setup.yml
Normal file
|
@ -0,0 +1,15 @@
|
|||
---
|
||||
# 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
|
||||
|
||||
- name: verify that git is installed so this test can continue
|
||||
command: which git
|
||||
register: git_installed
|
||||
ignore_errors: true
|
||||
|
||||
- name: get git version, only newer than {{git_version_supporting_includes}} has includes option
|
||||
shell: "git --version | grep 'git version' | sed 's/git version //'"
|
||||
register: git_version
|
||||
ignore_errors: true
|
||||
...
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
# 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
|
||||
|
||||
# ------
|
||||
# set up : set gitconfig with value
|
||||
- name: delete global config
|
||||
file:
|
||||
path: ~/.gitconfig
|
||||
state: absent
|
||||
|
||||
- name: set up file config
|
||||
copy:
|
||||
src: gitconfig
|
||||
dest: "{{ remote_tmp_dir }}/gitconfig_file"
|
|
@ -0,0 +1,16 @@
|
|||
---
|
||||
# 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
|
||||
|
||||
# ------
|
||||
# set up : set gitconfig with value
|
||||
- name: delete file config
|
||||
file:
|
||||
path: "{{ remote_tmp_dir }}/gitconfig_file"
|
||||
state: absent
|
||||
|
||||
- name: setup global config
|
||||
copy:
|
||||
src: gitconfig
|
||||
dest: ~/.gitconfig
|
7
tests/integration/targets/git_config_info/vars/main.yml
Normal file
7
tests/integration/targets/git_config_info/vars/main.yml
Normal file
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
# 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
|
||||
|
||||
git_version_supporting_includes: 1.7.10
|
||||
...
|
Loading…
Reference in a new issue