~ibmcharmers/charms/trusty/layer-ibm-mobilefirst-server/devel

« back to all changes in this revision

Viewing changes to deps/layer/layer-basic/README.md

  • Committer: Suchitra Venugopal
  • Date: 2016-09-06 09:48:53 UTC
  • Revision ID: suchvenu@in.ibm.com-20160906094853-1n09myeisek096nm
IBM MobileFirst Server

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Overview
 
2
 
 
3
This is the base layer for all charms [built using layers][building].  It
 
4
provides all of the standard Juju hooks and runs the
 
5
[charms.reactive.main][charms.reactive] loop for them.  It also bootstraps the
 
6
[charm-helpers][] and [charms.reactive][] libraries and all of their
 
7
dependencies for use by the charm.
 
8
 
 
9
# Usage
 
10
 
 
11
To create a charm layer using this base layer, you need only include it in
 
12
a `layer.yaml` file:
 
13
 
 
14
```yaml
 
15
includes: ['layer:basic']
 
16
```
 
17
 
 
18
This will fetch this layer from [interfaces.juju.solutions][] and incorporate
 
19
it into your charm layer.  You can then add handlers under the `reactive/`
 
20
directory.  Note that **any** file under `reactive/` will be expected to
 
21
contain handlers, whether as Python decorated functions or [executables][non-python]
 
22
using the [external handler protocol][].
 
23
 
 
24
### Charm Dependencies
 
25
 
 
26
Each layer can include a `wheelhouse.txt` file with Python requirement lines.
 
27
For example, this layer's `wheelhouse.txt` includes:
 
28
 
 
29
```
 
30
pip>=7.0.0,<8.0.0
 
31
charmhelpers>=0.4.0,<1.0.0
 
32
charms.reactive>=0.1.0,<2.0.0
 
33
```
 
34
 
 
35
All of these dependencies from each layer will be fetched (and updated) at build
 
36
time and will be automatically installed by this base layer before any reactive
 
37
handlers are run.
 
38
 
 
39
Note that the `wheelhouse.txt` file is intended for **charm** dependencies only.
 
40
That is, for libraries that the charm code itself needs to do its job of deploying
 
41
and configuring the payload.  If the payload itself has Python dependencies, those
 
42
should be handled separately, by the charm.
 
43
 
 
44
See [PyPI][pypi charms.X] for packages under the `charms.` namespace which might
 
45
be useful for your charm.
 
46
 
 
47
### Layer Namespace
 
48
 
 
49
Each layer has a reserved section in the `charms.layer.` Python package namespace,
 
50
which it can populate by including a `lib/charms/layer/<layer-name>.py` file or
 
51
by placing files under `lib/charms/layer/<layer-name>/`.  (If the layer name
 
52
includes hyphens, replace them with underscores.)  These can be helpers that the
 
53
layer uses internally, or it can expose classes or functions to be used by other
 
54
layers to interact with that layer.
 
55
 
 
56
For example, a layer named `foo` could include a `lib/charms/layer/foo.py` file
 
57
with some helper functions that other layers could access using:
 
58
 
 
59
```python
 
60
from charms.layer.foo import my_helper
 
61
```
 
62
 
 
63
### Layer Options
 
64
 
 
65
Any layer can define options in its `layer.yaml`.  Those options can then be set
 
66
by other layers to change the behavior of your layer.  The options are defined
 
67
using [jsonschema][], which is the same way that [action paramters][] are defined.
 
68
 
 
69
For example, the `foo` layer could include the following option definitons:
 
70
 
 
71
```yaml
 
72
includes: ['layer:basic']
 
73
defines:  # define some options for this layer (the layer "foo")
 
74
  enable-bar:  # define an "enable-bar" option for this layer
 
75
    description: If true, enable support for "bar".
 
76
    type: boolean
 
77
    default: false
 
78
```
 
79
 
 
80
A layer using `foo` could then set it:
 
81
 
 
82
```yaml
 
83
includes: ['layer:foo']
 
84
options:
 
85
  foo:  # setting options for the "foo" layer
 
86
    enable-bar: true  # set the "enable-bar" option to true
 
87
```
 
88
 
 
89
The `foo` layer can then use the `charms.layer.options` helper to load the values
 
90
for the options that it defined.  For example:
 
91
 
 
92
```python
 
93
from charms import layer
 
94
 
 
95
@when('state')
 
96
def do_thing():
 
97
  layer_opts = layer.options('foo')  # load all of the options for the "foo" layer
 
98
  if layer_opts['enable-bar']:  # check the value of the "enable-bar" option
 
99
      hookenv.log("Bar is enabled")
 
100
```
 
101
 
 
102
You can also access layer options in other handlers, such as Bash, using
 
103
the command-line interface:
 
104
 
 
105
```bash
 
106
. charms.reactive.sh
 
107
 
 
108
@when 'state'
 
109
function do_thing() {
 
110
    if layer_option foo enable-bar; then
 
111
        juju-log "Bar is enabled"
 
112
        juju-log "bar-value is: $(layer_option foo bar-value)"
 
113
    fi
 
114
}
 
115
 
 
116
reactive_handler_main
 
117
```
 
118
 
 
119
Note that options of type `boolean` will set the exit code, while other types
 
120
will be printed out.
 
121
 
 
122
# Hooks
 
123
 
 
124
This layer provides hooks that other layers can react to using the decorators
 
125
of the [charms.reactive][] library:
 
126
 
 
127
  * `config-changed`
 
128
  * `install`
 
129
  * `leader-elected`
 
130
  * `leader-settings-changed`
 
131
  * `start`
 
132
  * `stop`
 
133
  * `upgrade-charm`
 
134
  * `update-status`
 
135
 
 
136
Other hooks are not implemented at this time. A new layer can implement storage
 
137
or relation hooks in their own layer by putting them in the `hooks` directory.
 
138
 
 
139
**Note:** Because `update-status` is invoked every 5 minutes, you should take
 
140
care to ensure that your reactive handlers only invoke expensive operations
 
141
when absolutely necessary.  It is recommended that you use helpers like
 
142
[`@only_once`][], [`@when_file_changed`][], and [`data_changed`][] to ensure
 
143
that handlers run only when necessary.
 
144
 
 
145
# Layer Configuration
 
146
 
 
147
This layer supports the following options, which can be set in `layer.yaml`:
 
148
 
 
149
  * **packages**  A list of system packages to be installed before the reactive
 
150
    handlers are invoked.
 
151
 
 
152
  * **use_venv**  If set to true, the charm dependencies from the various
 
153
    layers' `wheelhouse.txt` files will be installed in a Python virtualenv
 
154
    located at `$CHARM_DIR/../.venv`.  This keeps charm dependencies from
 
155
    conflicting with payload dependencies, but you must take care to preserve
 
156
    the environment and interpreter if using `execl` or `subprocess`.
 
157
 
 
158
  * **include_system_packages**  If set to true and using a venv, include
 
159
    the `--system-site-packages` options to make system Python libraries
 
160
    visible within the venv.
 
161
 
 
162
An example `layer.yaml` using these options might be:
 
163
 
 
164
```yaml
 
165
includes: ['layer:basic']
 
166
options:
 
167
  basic:
 
168
    packages: ['git']
 
169
    use_venv: true
 
170
    include_system_packages: true
 
171
```
 
172
 
 
173
 
 
174
# Reactive States
 
175
 
 
176
This layer will set the following states:
 
177
 
 
178
  * **`config.changed`**  Any config option has changed from its previous value.
 
179
    This state is cleared automatically at the end of each hook invocation.
 
180
 
 
181
  * **`config.changed.<option>`** A specific config option has changed.
 
182
    **`<option>`** will be replaced by the config option name from `config.yaml`.
 
183
    This state is cleared automatically at the end of each hook invocation.
 
184
 
 
185
  * **`config.set.<option>`** A specific config option has a True or non-empty
 
186
    value set.  **`<option>`** will be replaced by the config option name from
 
187
    `config.yaml`.  This state is cleared automatically at the end of each hook
 
188
    invocation.
 
189
 
 
190
  * **`config.default.<option>`** A specific config option is set to its
 
191
    default value.  **`<option>`** will be replaced by the config option name
 
192
    from `config.yaml`.  This state is cleared automatically at the end of
 
193
    each hook invocation.
 
194
 
 
195
An example using the config states would be:
 
196
 
 
197
```python
 
198
@when('config.changed.my-opt')
 
199
def my_opt_changed():
 
200
    update_config()
 
201
    restart_service()
 
202
```
 
203
 
 
204
 
 
205
# Actions
 
206
 
 
207
This layer currently does not define any actions.
 
208
 
 
209
 
 
210
[building]: https://jujucharms.com/docs/devel/authors-charm-building
 
211
[charm-helpers]: https://pythonhosted.org/charmhelpers/
 
212
[charms.reactive]: https://pythonhosted.org/charms.reactive/
 
213
[interfaces.juju.solutions]: http://interfaces.juju.solutions/
 
214
[non-python]: https://pythonhosted.org/charms.reactive/#non-python-reactive-handlers
 
215
[external handler protocol]: https://pythonhosted.org/charms.reactive/charms.reactive.bus.html#charms.reactive.bus.ExternalHandler
 
216
[jsonschema]: http://json-schema.org/
 
217
[action paramters]: https://jujucharms.com/docs/stable/authors-charm-actions
 
218
[pypi charms.X]: https://pypi.python.org/pypi?%3Aaction=search&term=charms.&submit=search
 
219
[`@only_once`]: https://pythonhosted.org/charms.reactive/charms.reactive.decorators.html#charms.reactive.decorators.only_once
 
220
[`@when_file_changed`]: https://pythonhosted.org/charms.reactive/charms.reactive.decorators.html#charms.reactive.decorators.when_file_changed
 
221
[`data_changed`]: https://pythonhosted.org/charms.reactive/charms.reactive.helpers.html#charms.reactive.helpers.data_changed