diff --git a/plugins/module_utils/pvecm.py b/plugins/module_utils/pvecm.py new file mode 100644 index 0000000..8400569 --- /dev/null +++ b/plugins/module_utils/pvecm.py @@ -0,0 +1,60 @@ +#!/usr/bin/python +from __future__ import annotations + +from ansible.module_utils.common.arg_spec import ArgumentSpecValidator +import sys + +class PVECM: + def __init__(self, command, module): + self.command = command + self.module = module + + def argument_spec(self): + argument_spec = dict() + + + + @staticmethod + def arg_spec_link(): + link_args = dict() + + for n in range(8): + link_args[f'link{n}'] = dict(type='dict', required=False, default=None, options=dict( + address=dict(type='str', required=False, default=None), + priority=dict(type='int', required=False, default=None), + )) + + return link_args + +def add (module, **parameters): + link_options = dict( + address = dict(type='str', required=False, default=None), + priority = dict(type='int', required=False, default=None), + ) + argument_spec = dict( + hostname=dict(type='str', required=True), + fingerprint=dict(type='str', required=False, default=None), + force=dict(type='bool', required=False, default=False), + link0=dict(type='dict', required=False, default=None, options=link_options), + link1=dict(type='dict', required=False, default=None, options=link_options), + link2=dict(type='dict', required=False, default=None, options=link_options), + link3=dict(type='dict', required=False, default=None, options=link_options), + link4=dict(type='dict', required=False, default=None, options=link_options), + link5=dict(type='dict', required=False, default=None, options=link_options), + link6=dict(type='dict', required=False, default=None, options=link_options), + link7=dict(type='dict', required=False, default=None, options=link_options), + nodeid=dict(type='int', required=False, default=None), + use_ssh=dict(type='bool', required=False, default=False), + votes=dict(type='int', required=False, default=None), + ) + + validator = ArgumentSpecValidator(argument_spec) + result = validator.validate(parameters) + + if result.error_messages: + sys.exit("Validation failed: {0}".format(", ".join(result.error_messages))) + + valid_params = result.validated_parameters + +def status(module): + return module.run_command(['pvecm', 'status']) \ No newline at end of file diff --git a/plugins/modules/proxmox_cluster.py b/plugins/modules/proxmox_cluster.py new file mode 100755 index 0000000..843f0c9 --- /dev/null +++ b/plugins/modules/proxmox_cluster.py @@ -0,0 +1,22 @@ +#!/usr/bin/python + +from ansible.module_utils.basic import AnsibleModule +import ansible_collections.aybarsm.linux.plugins.module_utils.pvecm as pvecm + +def main(): + module = AnsibleModule( + argument_spec = dict( + command=dict(type='str', required=True, choices=['add', 'status']), + ), + supports_check_mode=False + ) + + rc, out, err = pvecm.status(module) + + result = {"changed": False} + result['response'] = {'stdout': out, 'stderr': err, 'rc': rc} + + module.exit_json(**result) + +if __name__ == '__main__': + main() diff --git a/plugins/modules/pvesh.py b/plugins/modules/pvesh.py new file mode 100755 index 0000000..b67e798 --- /dev/null +++ b/plugins/modules/pvesh.py @@ -0,0 +1,28 @@ +#!/usr/bin/python + +from ansible.module_utils.basic import AnsibleModule +# import ansible_collections.aybarsm.linux.plugins.module_utils.pvecm as pvecm + +def main(): + module = AnsibleModule( + argument_spec = dict( + command=dict(type='str', required=True, choices=['create', 'delete', 'get', 'ls', 'set']), + path=dict(type='str', required=True), + noproxy=dict(type='bool', required=False, default=False), + human_readable=dict(type='bool', required=False, default=False), + noborder=dict(type='bool', required=False, default=False), + noheader=dict(type='bool', required=False, default=False), + output_format=dict(type='str', required=False, default='json', choices=['json', 'json-pretty', 'text', 'yaml']), + ), + supports_check_mode=False + ) + + # rc, out, err = pvecm.status(module) + + result = {"changed": False} + result['response'] = locals() + + module.exit_json(**result) + +if __name__ == '__main__': + main() diff --git a/plugins/modules/pvesh_get.py b/plugins/modules/pvesh_get.py new file mode 100755 index 0000000..84f8895 --- /dev/null +++ b/plugins/modules/pvesh_get.py @@ -0,0 +1,28 @@ +#!/usr/bin/python + +from ansible.module_utils.basic import AnsibleModule +# import ansible_collections.aybarsm.linux.plugins.module_utils.pvecm as pvecm + +def main(): + module = AnsibleModule( + argument_spec = dict( + path=dict(type='path', required=True), + options=dict(type='dict', required=False), + noproxy=dict(type='bool', required=False, default=False), + human_readable=dict(type='bool', required=False, default=False), + noborder=dict(type='bool', required=False, default=False), + noheader=dict(type='bool', required=False, default=False), + output_format=dict(type='str', required=False, default='json', choices=['json', 'json-pretty', 'text', 'yaml']), + ), + supports_check_mode=True + ) + + # rc, out, err = pvecm.status(module) + + result = {"changed": False} + result['response'] = module.params + + module.exit_json(**result) + +if __name__ == '__main__': + main() diff --git a/roles/auth/defaults/main.yml b/roles/auth/defaults/main.yml index f1b976b..bc9f160 100644 --- a/roles/auth/defaults/main.yml +++ b/roles/auth/defaults/main.yml @@ -21,9 +21,9 @@ auth__ssh_changes_strategy: module: service immediate: true smart: true - name: 'ssh.service' + name: ssh.service enabled: true - state: started + state: restarted # Set  auth__sshd_validate variable to validate the ssh daemon config # auth__sshd_validate: "/usr/sbin/sshd -t -f %s" auth__sshd_config_dir: "{{ auth__ssh_dir }}/sshd_config.d" @@ -47,5 +47,3 @@ auth__sudoers_template: etc/sudoers.d/50-ansible.j2 auth__default: [] auth__group: [] auth__host: [] - -auth__all: "{{ auth__host + auth__group + auth__default }}" \ No newline at end of file diff --git a/roles/auth/tasks/authorized_keys.yml b/roles/auth/tasks/authorized_keys.yml index ce60e91..291a93b 100644 --- a/roles/auth/tasks/authorized_keys.yml +++ b/roles/auth/tasks/authorized_keys.yml @@ -1,11 +1,21 @@ --- +- name: Set fact for ssh key distribution to authorized keys, if any + set_fact: + auth__authorized_keys_all: "{{ (auth__authorized_keys_all | default([])) + ssh_keys_distribute }}" + vars: + distribute_query: "*.auth__users_apply.results[*] | [] | [?contains(not_null(item.distribute_ssh_key,``),`{{ inventory_hostname }}`)].{user: name, key: ssh_public_key}" + ssh_keys_distribute: "{{ dict(hostvars) | + aybarsm.helper.only_with(ansible_play_batch | difference([inventory_hostname])) | + community.general.json_query(distribute_query) | default([]) }}" + register: auth__users__ssh_key_distribution + when: ssh_keys_distribute | length > 0 + - name: Retrieve passwd database in check mode for authorized keys become: true ansible.builtin.getent: database: passwd register: auth__authorized_keys_test_user_existence when: - - auth__authorized_keys_all | type_debug == 'list' - auth__authorized_keys_all | length > 0 - ansible_check_mode | bool @@ -25,6 +35,5 @@ loop: "{{ auth__authorized_keys_all }}" register: auth__authorized_keys_apply when: - - auth__authorized_keys_all | type_debug == 'list' - auth__authorized_keys_all | length > 0 - not ansible_check_mode | bool or (ansible_check_mode and (item.user in ansible_facts['getent_passwd'] or item.path is defined)) diff --git a/roles/auth/tasks/main.yml b/roles/auth/tasks/main.yml index 5ca4de8..a3f8371 100644 --- a/roles/auth/tasks/main.yml +++ b/roles/auth/tasks/main.yml @@ -1,7 +1,7 @@ --- -# Require for configuration management - name: Load aybarsm ansible role main variables ansible.builtin.include_vars: ../ansible/vars/main.yml + when: __ansible__config is undefined - name: Include groups tasks ansible.builtin.include_tasks: diff --git a/roles/auth/tasks/ssh.yml b/roles/auth/tasks/ssh.yml index 655a413..c8fdb78 100644 --- a/roles/auth/tasks/ssh.yml +++ b/roles/auth/tasks/ssh.yml @@ -27,6 +27,37 @@ - auth__ssh_config_all | type_debug == 'list' - auth__ssh_config_all | length > 0 +- name: Apply ssh client configuration via community.general.ssh_config module + become: true + community.general.ssh_config: + add_keys_to_agent: "{{ item.add_keys_to_agent | default(omit) | bool }}" + controlmaster: "{{ item.controlmaster | default(omit) }}" + controlpath: "{{ item.controlpath | default(omit) }}" + controlpersist: "{{ item.controlpersist | default(omit) }}" + forward_agent: "{{ item.forward_agent | default(omit) | bool }}" + group: "{{ item.group | default(omit) }}" + host: "{{ item.host }}" + host_key_algorithms: "{{ item.host_key_algorithms | default(omit) }}" + hostname: "{{ item.hostname | default(omit) }}" + identities_only: "{{ item.identities_only | default(omit) | bool }}" + identity_file: "{{ item.identity_file | default(omit) }}" + port: "{{ item.port | default(omit) }}" + proxycommand: "{{ item.proxycommand | default(omit) }}" + proxyjump: "{{ item.proxyjump | default(omit) }}" + remote_user: "{{ item.remote_user | default(omit) }}" + ssh_config_file: "{{ item.ssh_config_file | default(omit) }}" + state: "{{ item.state | default(omit) }}" + strict_host_key_checking: "{{ item.strict_host_key_checking | default(omit) }}" + user: "{{ item.user | default(omit) }}" + user_known_hosts_file: "{{ item.user_known_hosts_file | default(omit) }}" + loop: "{{ auth__ssh_config_module_all }}" + register: auth__ssh_config_module_apply + notify: "auth__ssh_apply_changes" + when: + - auth__manage_ssh_config | default(false) | bool + - auth__ssh_config_module_all | type_debug == 'list' + - auth__ssh_config_module_all | length > 0 + - name: Run smart sshd configuration changes ansible.builtin.command: cmd: /usr/bin/true @@ -34,6 +65,7 @@ notify: "auth__ssh_apply_changes" when: - auth__sshd_validate is defined + - auth__sshd_validate - auth__sshd_config_apply is not change - auth__ssh_config_apply is not change - auth__ssh_changes_strategy.smart | default(false) | bool diff --git a/roles/auth/tasks/users.yml b/roles/auth/tasks/users.yml index 2caab97..dd578b1 100644 --- a/roles/auth/tasks/users.yml +++ b/roles/auth/tasks/users.yml @@ -44,4 +44,3 @@ when: - auth__users_all | type_debug == 'list' - auth__users_all | length > 0 - \ No newline at end of file diff --git a/roles/auth/vars/main.yml b/roles/auth/vars/main.yml index e48516c..e22c0cd 100644 --- a/roles/auth/vars/main.yml +++ b/roles/auth/vars/main.yml @@ -1,4 +1,6 @@ --- +auth__all: "{{ auth__host + auth__group + auth__default + (auth__external | default([])) }}" + __auth__config: authorized_keys: selectattr: @@ -35,6 +37,12 @@ __auth__config: - ['type', 'equalto', 'ssh_config'] - ['name', 'defined'] - ['value', 'defined'] + ssh_config_module: + selectattr: + - when: + - ['type', 'defined'] + - ['type', 'equalto', 'ssh_config_module'] + - ['host', 'defined'] sudoers_file: selectattr: - when: @@ -47,7 +55,7 @@ __auth__config: - ['type', 'defined'] - ['type', 'equalto', 'sudoers_module'] - ['name', 'defined'] - + auth__groups_all: "{{ auth__all | aybarsm.helper.selectattr(__auth__config.groups.selectattr) | aybarsm.helper.unique_recursive(__ansible__config.modules.ansible_builtin_group.uniques) | @@ -66,12 +74,17 @@ auth__authorized_keys_all: "{{ auth__all | auth__sshd_config_all: "{{ auth__all | aybarsm.helper.selectattr(__auth__config.sshd_config.selectattr) | - aybarsm.helper.unique_recursive('name', 'children') | + aybarsm.helper.unique_combinations([['name', 'value']]) | default([]) }}" auth__ssh_config_all: "{{ auth__all | aybarsm.helper.selectattr(__auth__config.ssh_config.selectattr) | - aybarsm.helper.unique_recursive('name', 'children') | + aybarsm.helper.unique_combinations([['name', 'value']]) | + default([]) }}" + +auth__ssh_config_module_all: "{{ auth__all | + aybarsm.helper.selectattr(__auth__config.ssh_config_module.selectattr) | + aybarsm.helper.unique_recursive('host') | default([]) }}" auth__sudoers_file_all: "{{ auth__all | diff --git a/roles/grub/tasks/main.yml b/roles/grub/tasks/main.yml index 4a420ea..aa62c9c 100644 --- a/roles/grub/tasks/main.yml +++ b/roles/grub/tasks/main.yml @@ -2,6 +2,7 @@ # Required for configuration management - name: Load aybarsm ansible role main variables ansible.builtin.include_vars: ../ansible/vars/main.yml + when: __ansible__config is undefined - name: Include grub tasks ansible.builtin.include_tasks: diff --git a/roles/network/tasks/main.yml b/roles/network/tasks/main.yml index 9a4f20e..79898ea 100644 --- a/roles/network/tasks/main.yml +++ b/roles/network/tasks/main.yml @@ -2,6 +2,7 @@ # Required for configuration management - name: Load aybarsm ansible role main variables ansible.builtin.include_vars: ../ansible/vars/main.yml + when: __ansible__config is undefined - name: Include systemd network tasks ansible.builtin.include_tasks: diff --git a/roles/network/tasks/systemd.yml b/roles/network/tasks/systemd.yml index f4d91e8..1698768 100644 --- a/roles/network/tasks/systemd.yml +++ b/roles/network/tasks/systemd.yml @@ -14,7 +14,7 @@ path: "{{ item }}" state: absent loop: "{{ network__systemd_find_cleanup_files.files | map(attribute='path') }}" - register: systemd__network_cleanup_files + register: network__systemd_cleanup_files notify: network__systemd_apply_changes when: - network__systemd_cleanup | default(false) | bool @@ -28,7 +28,7 @@ backup: "{{ network__systemd_backup | default(omit) | bool }}" mode: "0644" loop: "{{ network__systemd_all }}" - register: systemd__network_deploy + register: network__systemd_deploy notify: network__systemd_apply_changes when: - network__systemd_all | type_debug == 'list' diff --git a/roles/network/vars/main.yml b/roles/network/vars/main.yml index 345a216..56ca2dc 100644 --- a/roles/network/vars/main.yml +++ b/roles/network/vars/main.yml @@ -4,7 +4,7 @@ __network_systemd_available_change_modules: ['systemd_service'] # REVIEW: There is room for optimisation __network__systemd_configs: >- {%- set __configs_prepared = [] -%} - {%- for config in [network__default, network__group, network__host] -%} + {%- for config in [network__default, network__group, network__host] if config -%} {%- set __configs_prepared = __configs_prepared.append(config | selectattr('type', 'defined') | selectattr('type', 'equalto', 'systemd') | selectattr('name', 'defined') | selectattr('name', 'search', '\\.(network|link|netdev)$') | selectattr('children', 'defined')) -%} {%- endfor -%} @@ -34,7 +34,7 @@ __network_interfaces_available_change_modules: ['service', 'systemd_service', 'c # REVIEW: There is room for optimisation __network__interfaces_configs: >- {%- set __configs_prepared = [] -%} - {%- for config in [network__default, network__group, network__host] -%} + {%- for config in [network__default, network__group, network__host] if config -%} {%- set __configs_prepared = __configs_prepared.append(config | selectattr('type', 'defined') | selectattr('type', 'equalto', 'interface') | selectattr('name', 'defined')) -%} {%- endfor -%} {{ __configs_prepared }} diff --git a/roles/package_manager/tasks/main.yml b/roles/package_manager/tasks/main.yml index 249aa7c..546edf3 100644 --- a/roles/package_manager/tasks/main.yml +++ b/roles/package_manager/tasks/main.yml @@ -1,4 +1,8 @@ --- +- name: Load aybarsm ansible role main variables + ansible.builtin.include_vars: ../ansible/vars/main.yml + when: __ansible__config is undefined + - name: Load OS family related variables ansible.builtin.include_vars: "{{ ansible_os_family | lower }}.yml" diff --git a/roles/proxmox/defaults/main.yml b/roles/proxmox/defaults/main.yml index 2bd35b3..708334e 100644 --- a/roles/proxmox/defaults/main.yml +++ b/roles/proxmox/defaults/main.yml @@ -1,5 +1,18 @@ proxmox__role_enabled: false +proxmox__manage_cluster: false +proxmox__manage_cluster_ssh_config: false + +proxmox__cluster_name: '' +# For inventory specs, consult https://docs.ansible.com/ansible/latest/inventory_guide/intro_patterns.html for more information +# i.e. proxmox__cluster_inventory: 'proxmox:&atlanta' +proxmox__cluster_inventory: '' +# Ip addresses for the cluster links (will be automatically prioritized regarding the posisiton in the list) +proxmox__cluster_links: [] +# If set to any integer higher than 0, cluster links will be prioritized automatically regarding the step. +# i.e. proxmox__cluster_links: ['10.0.0.2', 'fd00::2'] and proxmox__cluster_links_auto_priority_step: 10 will be prioritized as 10.0.0.2 = 20 and fd00::2 = 10 +proxmox__cluster_links_auto_priority_step: 0 + proxmox__repo_url_enterprise: https://enterprise.proxmox.com/debian proxmox__repo_url_no_subscription: http://download.proxmox.com/debian @@ -26,7 +39,6 @@ proxmox__host: {} # type: no-subscription # version: latest # # ------------------------------------------------ -# proxmox__group: # proxmox__host: # purposes: # pve: diff --git a/roles/proxmox/tasks/main.yml b/roles/proxmox/tasks/main.yml index 790eec9..0e18fa7 100644 --- a/roles/proxmox/tasks/main.yml +++ b/roles/proxmox/tasks/main.yml @@ -1,16 +1,20 @@ --- -- name: Proxmox Query - become: true - proxmox_query: - query: storage - register: proxmox__query_storage -- name: Debug - ansible.builtin.debug: - msg: - proxmox__query_storage: "{{ proxmox__query_storage }}" - # role_path: "{{ role_path }}" - # purpose_package_setup: "{{ lookup('template', proxmox__purpose_package_setup_template) }}" - delegate_to: localhost +- name: Load aybarsm ansible role main variables + ansible.builtin.include_vars: ../ansible/vars/main.yml + when: __ansible__config is undefined + +# - name: Proxmox Query +# become: true +# proxmox_query: +# query: storage +# register: proxmox__query_storage +# - name: Debug +# ansible.builtin.debug: +# msg: +# proxmox__query_storage: "{{ proxmox__query_storage }}" +# # role_path: "{{ role_path }}" +# # purpose_package_setup: "{{ lookup('template', proxmox__purpose_package_setup_template) }}" +# delegate_to: localhost # - name: Import aybarsm linux ansible role # ansible.builtin.import_role: # name: aybarsm.linux.ansible diff --git a/roles/proxmox/tasks/ssh_config.yml b/roles/proxmox/tasks/ssh_config.yml new file mode 100644 index 0000000..4a67df0 --- /dev/null +++ b/roles/proxmox/tasks/ssh_config.yml @@ -0,0 +1,6 @@ +--- +- name: Create SSH directory for root + ansible.builtin.file: + path: /root/.ssh/ + state: directory + mode: 0700 diff --git a/roles/proxmox/vars/main.yml b/roles/proxmox/vars/main.yml index ac7f7d0..e099ac7 100644 --- a/roles/proxmox/vars/main.yml +++ b/roles/proxmox/vars/main.yml @@ -3,44 +3,49 @@ proxmox__all: "{{ proxmox__default | combine(proxmox__group, proxmox__host, recursive=true, list_merge='replace') }}" __proxmox__purpose_packages: >- - {%- set proxmox_repos = [] -%} - {%- set proxmox_packages = [] -%} - {%- set purpose_packages = [] -%} - {%- if proxmox__manage_purpose_package_setup is defined and proxmox__manage_purpose_package_setup and proxmox__all.purposes is defined -%} - {%- for purpose in proxmox__purpose_names -%} - {%- for purpose_type in proxmox__purpose_types -%} - {%- set host_config = proxmox__all.purposes[purpose] if purpose in proxmox__all.purposes else none -%} - {%- set is_host_purpose = true if host_config else false -%} - {%- set is_host_purpose_type = true if host_config and host_config.type is defined and host_config.type == purpose_type else false -%} - {%- set host_purpose_version = host_config.version if host_config and host_config.version is defined else none -%} - {%- set purpose_repo_state = 'present' if is_host_purpose and is_host_purpose_type else 'absent' -%} - {%- set purpose_repo = proxmox__repo_url_enterprise if purpose_type == 'enterprise' else proxmox__repo_url_no_subscription -%} - {%- if purpose in ['pve', 'pbs', 'pmg'] -%} - {%- set proxmox_repos = proxmox_repos.append({ - 'type': 'repo', - 'repo': 'deb ' + purpose_repo + '/' + purpose + ' ' + ansible_distribution_release + ' ' + purpose + '-' + purpose_type, - 'filename': purpose + '-' + purpose_type, - 'state': purpose_repo_state - }) -%} - {%- if host_purpose_version and proxmox__purpose_packages[purpose] is defined and not purpose in purpose_packages -%} - {%- set purpose_packages = purpose_packages.append(purpose) -%} - {%- set package_name = proxmox__purpose_packages[purpose] if host_purpose_version == 'latest' else proxmox__purpose_packages[purpose] + '=' + host_purpose_version -%} - {%- set package_state = 'latest' if host_purpose_version == 'latest' else 'present' -%} - {%- set proxmox_packages = proxmox_packages.append({ - 'type': 'package', - 'name': package_name, - 'state': package_state - }) -%} - {%- endif -%} - {%- elif purpose.startswith('ceph-') or purpose.startswith('ceph_') -%} - {%- set proxmox_repos = proxmox_repos.append({ - 'type': 'repo', - 'repo': 'deb ' + purpose_repo + '/' + (purpose | replace('_', '-')) + ' ' + ansible_distribution_release + ' ' + purpose_type, - 'filename': 'ceph', - 'state': purpose_repo_state - }) -%} - {%- endif -%} - {%- endfor -%} - {%- endfor -%} - {%- endif -%} - {{ proxmox_repos + proxmox_packages }} \ No newline at end of file + {%- set proxmox_repos = [] -%} + {%- set proxmox_packages = [] -%} + {%- set purpose_packages = [] -%} + {%- if proxmox__manage_purpose_package_setup is defined and proxmox__manage_purpose_package_setup and proxmox__all.purposes is defined -%} + {%- for purpose in proxmox__purpose_names -%} + {%- for purpose_type in proxmox__purpose_types -%} + {%- set host_config = proxmox__all.purposes[purpose] if purpose in proxmox__all.purposes else none -%} + {%- set is_host_purpose = true if host_config else false -%} + {%- set is_host_purpose_type = true if host_config and host_config.type is defined and host_config.type == purpose_type else false -%} + {%- set host_purpose_version = host_config.version if host_config and host_config.version is defined else none -%} + {%- set purpose_repo_state = 'present' if is_host_purpose and is_host_purpose_type else 'absent' -%} + {%- set purpose_repo = proxmox__repo_url_enterprise if purpose_type == 'enterprise' else proxmox__repo_url_no_subscription -%} + {%- if purpose in ['pve', 'pbs', 'pmg'] -%} + {%- set proxmox_repos = proxmox_repos.append({ + 'type': 'repo', + 'repo': 'deb ' + purpose_repo + '/' + purpose + ' ' + ansible_distribution_release + ' ' + purpose + '-' + purpose_type, + 'filename': purpose + '-' + purpose_type, + 'state': purpose_repo_state + }) -%} + {%- if host_purpose_version and proxmox__purpose_packages[purpose] is defined and not purpose in purpose_packages -%} + {%- set purpose_packages = purpose_packages.append(purpose) -%} + {%- set package_name = proxmox__purpose_packages[purpose] if host_purpose_version == 'latest' else proxmox__purpose_packages[purpose] + '=' + host_purpose_version -%} + {%- set package_state = 'latest' if host_purpose_version == 'latest' else 'present' -%} + {%- set proxmox_packages = proxmox_packages.append({ + 'type': 'package', + 'name': package_name, + 'state': package_state + }) -%} + {%- endif -%} + {%- elif purpose.startswith('ceph-') or purpose.startswith('ceph_') -%} + {%- set proxmox_repos = proxmox_repos.append({ + 'type': 'repo', + 'repo': 'deb ' + purpose_repo + '/' + (purpose | replace('_', '-')) + ' ' + ansible_distribution_release + ' ' + purpose_type, + 'filename': 'ceph', + 'state': purpose_repo_state + }) -%} + {%- endif -%} + {%- endfor -%} + {%- endfor -%} + {%- endif -%} + {{ proxmox_repos + proxmox_packages }} + +__proxmox_cluster_links: >- + {%- set proxmox_links = [] -%} + {%- if proxmox__manage_purpose_package_setup is defined and proxmox__manage_purpose_package_setup and proxmox__all.purposes is defined -%} + {%- endif -%} \ No newline at end of file