1#!/usr/local/bin/python3.8
2# -*- coding: utf-8 -*-
3
4# Copyright: (c) 2018, Mikhail Gordeev
5
6# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
7
8from __future__ import absolute_import, division, print_function
9__metaclass__ = type
10
11DOCUMENTATION = '''
12---
13module: apt_repo
14short_description: Manage APT repositories via apt-repo
15description:
16  - Manages APT repositories using apt-repo tool.
17  - See U(https://www.altlinux.org/Apt-repo) for details about apt-repo
18notes:
19    - This module works on ALT based distros.
20    - Does NOT support checkmode, due to a limitation in apt-repo tool.
21options:
22  repo:
23    description:
24      - Name of the repository to add or remove.
25    required: true
26    type: str
27  state:
28    description:
29      - Indicates the desired repository state.
30    choices: [ absent, present ]
31    default: present
32    type: str
33  remove_others:
34    description:
35      - Remove other then added repositories
36      - Used if I(state=present)
37    type: bool
38    default: no
39  update:
40    description:
41      - Update the package database after changing repositories.
42    type: bool
43    default: no
44author:
45- Mikhail Gordeev (@obirvalger)
46'''
47
48EXAMPLES = '''
49- name: Remove all repositories
50  community.general.apt_repo:
51    repo: all
52    state: absent
53
54- name: Add repository `Sisysphus` and remove other repositories
55  community.general.apt_repo:
56    repo: Sisysphus
57    state: present
58    remove_others: yes
59
60- name: Add local repository `/space/ALT/Sisyphus` and update package cache
61  community.general.apt_repo:
62    repo: copy:///space/ALT/Sisyphus
63    state: present
64    update: yes
65'''
66
67RETURN = ''' # '''
68
69import os
70
71from ansible.module_utils.basic import AnsibleModule
72
73APT_REPO_PATH = "/usr/bin/apt-repo"
74
75
76def apt_repo(module, *args):
77    """run apt-repo with args and return its output"""
78    # make args list to use in concatenation
79    args = list(args)
80    rc, out, err = module.run_command([APT_REPO_PATH] + args)
81
82    if rc != 0:
83        module.fail_json(msg="'%s' failed: %s" % (' '.join(['apt-repo'] + args), err))
84
85    return out
86
87
88def add_repo(module, repo):
89    """add a repository"""
90    apt_repo(module, 'add', repo)
91
92
93def rm_repo(module, repo):
94    """remove a repository"""
95    apt_repo(module, 'rm', repo)
96
97
98def set_repo(module, repo):
99    """add a repository and remove other repositories"""
100    # first add to validate repository
101    apt_repo(module, 'add', repo)
102    apt_repo(module, 'rm', 'all')
103    apt_repo(module, 'add', repo)
104
105
106def update(module):
107    """update package cache"""
108    apt_repo(module, 'update')
109
110
111def main():
112    module = AnsibleModule(
113        argument_spec=dict(
114            repo=dict(type='str', required=True),
115            state=dict(type='str', default='present', choices=['absent', 'present']),
116            remove_others=dict(type='bool', default=False),
117            update=dict(type='bool', default=False),
118        ),
119    )
120
121    if not os.path.exists(APT_REPO_PATH):
122        module.fail_json(msg='cannot find /usr/bin/apt-repo')
123
124    params = module.params
125    repo = params['repo']
126    state = params['state']
127    old_repositories = apt_repo(module)
128
129    if state == 'present':
130        if params['remove_others']:
131            set_repo(module, repo)
132        else:
133            add_repo(module, repo)
134    elif state == 'absent':
135        rm_repo(module, repo)
136
137    if params['update']:
138        update(module)
139
140    new_repositories = apt_repo(module)
141    changed = old_repositories != new_repositories
142    module.exit_json(changed=changed, repo=repo, state=state)
143
144
145if __name__ == '__main__':
146    main()
147