1
"""Charm Helpers saltstack - declare the state of your machines.
3
This helper enables you to declare your machine state, rather than
4
program it procedurally (and have to test each change to your procedures).
5
Your install hook can be as simple as:
8
from charmhelpers.contrib.saltstack import (
15
install_salt_support()
16
update_machine_state('machine_states/dependencies.yaml')
17
update_machine_state('machine_states/installed.yaml')
20
and won't need to change (nor will its tests) when you change the machine
23
It's using a python package called salt-minion which allows various formats for
24
specifying resources, such as:
48
The docs for all the different state definitions are at:
49
http://docs.saltstack.com/ref/states/all/
53
* Add test helpers which will ensure that machine state definitions
54
are functionally (but not necessarily logically) correct (ie. getting
55
salt to parse all state defs.
56
* Add a link to a public bootstrap charm example / blogpost.
57
* Find a way to obviate the need to use the grains['charm_dir'] syntax
60
# Copyright 2013 Canonical Ltd.
63
# Charm Helpers Developers <juju@lists.ubuntu.com>
68
import charmhelpers.core.host
69
import charmhelpers.core.hookenv
72
charm_dir = os.environ.get('CHARM_DIR', '')
73
salt_grains_path = '/etc/salt/grains'
76
def install_salt_support(from_ppa=True):
77
"""Installs the salt-minion helper for machine state.
79
By default the salt-minion package is installed from
80
the saltstack PPA. If from_ppa is False you must ensure
81
that the salt-minion package is available in the apt cache.
84
subprocess.check_call([
85
'/usr/bin/add-apt-repository',
89
subprocess.check_call(['/usr/bin/apt-get', 'update'])
90
# We install salt-common as salt-minion would run the salt-minion
92
charmhelpers.core.host.apt_install('salt-common')
95
def update_machine_state(state_path):
96
"""Update the machine state using the provided state declaration."""
97
juju_config_2_grains()
98
subprocess.check_call([
106
def juju_config_2_grains():
107
"""Insert the juju config as salt grains for use in state templates.
109
This includes any current relation-get data, and the charm
112
config = charmhelpers.core.hookenv.config()
114
# Add the charm_dir which we will need to refer to charm
115
# file resources etc.
116
config['charm_dir'] = charm_dir
117
config['local_unit'] = charmhelpers.core.hookenv.local_unit()
118
config.update(charmhelpers.core.hookenv.relation_get())
120
# Don't use non-standard tags for unicode which will not
121
# work when salt uses yaml.load_safe.
122
yaml.add_representer(unicode, lambda dumper,
123
value: dumper.represent_scalar(
124
u'tag:yaml.org,2002:str', value))
125
with open(salt_grains_path, "w+") as fp:
126
fp.write(config.yaml())