aboutsummaryrefslogtreecommitdiffstats
path: root/library/apk
blob: d40a84ccb5932201158fe1ee5a1aec3aca2ec512 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/python -tt
# -*- coding: utf-8 -*-

# (c) Bartłomiej Piotrowski <bpiotrowski@alpinelinux.org>
#
# This module is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this software.  If not, see <http://www.gnu.org/licenses/>.


DOCUMENTATION = '''
---
module: apk
short_description: Package manager for Alpine Linux
description:
    - Manages Alpine Linux packages (*.apk)
author: Bartłomiej Piotrowski

options:
    pkg:
        description:
            - A package name or package specifier with version
        required: true
        default: null

    state:
        description:
            - Indicates the desired package state
        required: false
        default: "no"
        choices: [ "absent", "latest", "present" , "purge" ]

    update:
        description:
            - Update the package database before the operation
        required: false
        default: "no"
        choices: [ "yes", "no" ]

    force:
        description:
            - Do what was asked even if it looks dangerous
        required: false
        default: "no"
        choices: [ "yes", "no" ]

notes: []
examples:
    - code: "apk: pkg=foo"
      description: Install package foo
    - code: "apk: pkg=foo state=purge"
      description: Remove package foo and delete modified configuration files
    - code: "apk: pkg=foo state=latest"
      description: Update package foo to newest available version
'''

import json
import shlex
import os
import sys

def update(module):
    rc = os.system("apk -q update")

    if rc != 0:
        module.fail_json(msg="failed to update package database")

def remove(module, pkgs, opts):
    removed = 0

    for pkg in pkgs:
        rc = os.system("apk -q del %s %s" % (opts, pkg))

        if rc == 0:
            removed += 1
        else:
            module.fail_json(msg="failed to remove %s" % pkg)

    if removed > 0:
        module.exit_json(changed=True, msg="removed %s package(s) (or already absent)" % removed)
    module.exit_json(changed=False, msg="failed to remove specified packages")

def install(module, pkgs, opts):
    installed = 0

    for pkg in pkgs:
        rc = os.system("apk -q add %s %s" % (opts, pkg))

        if rc == 0:
            installed += 1
        else:
            module.fail_json(msg="failed to install %s" % pkg)

    if installed >= 1:
        module.exit_json(changed=True, msg="installed %s package(s) (or already present)" % installed)
    module.exit_json(changed=False, msg="failed to install specified packages")

def main():
    module = AnsibleModule(
            argument_spec   = dict(
                pkg         = dict(aliases=["name"], required=False),
                state       = dict(default="present", choices=["absent","latest","present","purge"]),
                update      = dict(default="no", type="bool"),
                force       = dict(default="no", type="bool")))

    if not os.path.exists("/sbin/apk"):
        module.fail_json(msg="unable to find apk executable")

    p = module.params

    if p["update"]:
        update(module)

    pkgs = p["pkg"].split(",")

    opts = ''
    if p["force"]:
        opts += " --force"
    if p["state"] == "latest":
        opts += " --upgrade"
    if p["state"] == "purge":
        opts += " --purge"

    if p["state"] in [ "present", "latest" ]:
        install(module, pkgs, opts)
    else:
        remove(module, pkgs, opts)

#<<INCLUDE_ANSIBLE_MODULE_COMMON>>
main()