1
# Copyright 2015-2016 Canonical Ltd.
3
# This file is part of the Apt layer for Juju.
5
# This program is free software: you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License version 3, as
7
# published by the Free Software Foundation.
9
# This program is distributed in the hope that it will be useful, but
10
# WITHOUT ANY WARRANTY; without even the implied warranties of
11
# MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
12
# PURPOSE. See the GNU General Public License for more details.
14
# You should have received a copy of the GNU General Public License
15
# along with this program. If not, see <http://www.gnu.org/licenses/>.
18
charms.reactive helpers for dealing with deb packages.
20
Add apt package sources using add_source(). Queue deb packages for
21
installation with install(). Configure and work with your software
22
once the apt.installed.{packagename} state is set.
24
from charmhelpers import fetch
25
from charmhelpers.core import hookenv
26
from charms import reactive
27
from charms.reactive import when, when_not
30
# Aliases for backwards compatibility
31
from charms.apt import add_source, queue_install, installed, purge
34
__all__ = ['add_source', 'update', 'queue_install', 'install_queued',
35
'installed', 'purge', 'ensure_package_status']
38
@when('apt.needs_update')
43
@when('apt.queued_installs')
44
@when_not('apt.needs_update')
46
charms.apt.install_queued()
49
@when_not('apt.queued_installs')
50
def ensure_package_status():
51
charms.apt.ensure_package_status()
54
def configure_sources():
55
"""Add user specified package sources from the service configuration.
57
See charmhelpers.fetch.configure_sources for details.
59
hookenv.log('Initializing Apt Layer')
60
config = hookenv.config()
62
# We don't have enums, so we need to validate this ourselves.
63
package_status = config.get('package_status')
64
if package_status not in ('hold', 'install'):
65
charms.apt.status_set('blocked',
66
'Unknown package_status {}'
67
''.format(package_status))
68
# Die before further hooks are run. This isn't very nice, but
69
# there is no other way to inform the operator that they have
70
# invalid configuration.
73
sources = config.get('install_sources')
74
keys = config.get('install_keys')
75
if reactive.helpers.data_changed('apt.configure_sources', (sources, keys)):
76
fetch.configure_sources(update=False,
77
sources_var='install_sources',
78
keys_var='install_keys')
79
reactive.set_state('apt.needs_update')
81
extra_packages = sorted(config.get('extra_packages', '').split())
83
queue_install(extra_packages)
86
# Per https://github.com/juju-solutions/charms.reactive/issues/33,
87
# this module may be imported multiple times so ensure the
88
# initialization hook is only registered once. I have to piggy back
89
# onto the namespace of a module imported before reactive discovery
91
if not hasattr(reactive, '_apt_registered'):
92
# We need to register this to run every hook, not just during install
93
# and config-changed, to protect against race conditions. If we don't
94
# do this, then the config in the hook environment may show updates
95
# to running hooks well before the config-changed hook has been invoked
96
# and the intialization provided an opertunity to be run.
97
hookenv.atstart(configure_sources)
98
reactive._apt_registered = True