summaryrefslogtreecommitdiff
path: root/doc/rtd/topics/format.rst
blob: a4b772a24833c4fe5470129edd2ab064d4e044cf (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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
.. _user_data_formats:

*****************
User-Data Formats
*****************

User data that will be acted upon by cloud-init must be in one of the following
types.

Cloud Config Data
=================

Cloud-config is the simplest way to accomplish some things via user-data. Using
cloud-config syntax, the user can specify certain things in a human friendly
format.

These things include:

- apt upgrade should be run on first boot
- a different apt mirror should be used
- additional apt sources should be added
- certain SSH keys should be imported
- *and many more...*

.. note::
   This file must be valid YAML syntax.

See the :ref:`yaml_examples` section for a commented set of examples of
supported cloud config formats.

Begins with: ``#cloud-config`` or ``Content-Type: text/cloud-config`` when
using a MIME archive.

.. note::
   New in cloud-init v. 18.4: Cloud config data can also render cloud instance
   metadata variables using jinja templating. See
   :ref:`instance_metadata` for more information.

User-Data Script
================

Typically used by those who just want to execute a shell script.

Begins with: ``#!`` or ``Content-Type: text/x-shellscript`` when using a MIME
archive.

.. note::
   New in cloud-init v. 18.4: User-data scripts can also render cloud instance
   metadata variables using jinja templating. See
   :ref:`instance_metadata` for more information.

Example
-------

.. code-block:: shell-session

  $ cat myscript.sh

  #!/bin/sh
  echo "Hello World.  The time is now $(date -R)!" | tee /root/output.txt

  $ euca-run-instances --key mykey --user-data-file myscript.sh ami-a07d95c9

Kernel Command Line
===================

When using the :ref:`datasource_nocloud` datasource, users can pass user data
via the kernel command line parameters. See the :ref:`datasource_nocloud`
datasource documentation for more details.

Gzip Compressed Content
=======================

Content found to be gzip compressed will be uncompressed.
The uncompressed data will then be used as if it were not compressed.
This is typically useful because user-data is limited to ~16384 [#]_ bytes.

Mime Multi Part Archive
=======================

This list of rules is applied to each part of this multi-part file.
Using a mime-multi part file, the user can specify more than one type of data.

For example, both a user data script and a cloud-config type could be
specified.

Supported content-types are listed from the cloud-init subcommand make-mime:

.. code-block:: shell-session

    $ cloud-init devel make-mime --list-types
    cloud-boothook
    cloud-config
    cloud-config-archive
    cloud-config-jsonp
    jinja2
    part-handler
    x-include-once-url
    x-include-url
    x-shellscript
    x-shellscript-per-boot
    x-shellscript-per-instance
    x-shellscript-per-once

Helper subcommand to generate mime messages
-------------------------------------------

The cloud-init subcommand can generate MIME multi-part files: `make-mime`_.

``make-mime`` subcommand takes pairs of (filename, "text/" mime subtype)
separated by a colon (e.g. ``config.yaml:cloud-config``) and emits a MIME
multipart message to stdout.

Examples
--------
Create userdata containing both a cloud-config (``config.yaml``)
and a shell script (``script.sh``)

.. code-block:: shell-session

    $ cloud-init devel make-mime -a config.yaml:cloud-config -a script.sh:x-shellscript > userdata

Create userdata containing 3 shell scripts:

- ``always.sh`` - Run every boot
- ``instance.sh`` - Run once per instance
- ``once.sh`` - Run once

.. code-block:: shell-session

    $ cloud-init devel make-mime -a always.sh:x-shellscript-per-boot -a instance.sh:x-shellscript-per-instance -a once.sh:x-shellscript-per-once

.. _make-mime: https://github.com/canonical/cloud-init/blob/main/cloudinit/cmd/devel/make_mime.py

Include File
============

This content is a ``include`` file.

The file contains a list of urls, one per line. Each of the URLs will be read,
and their content will be passed through this same set of rules. I.e., the
content read from the URL can be gzipped, mime-multi-part, or plain text. If
an error occurs reading a file the remaining files will not be read.

Begins with: ``#include`` or ``Content-Type: text/x-include-url``  when using
a MIME archive.

Cloud Boothook
==============

This content is ``boothook`` data. It is stored in a file under
``/var/lib/cloud`` and then executed immediately. This is the earliest ``hook``
available. Note, that there is no mechanism provided for running only once. The
boothook must take care of this itself.

It is provided with the instance id in the environment variable
``INSTANCE_ID``. This could be made use of to provide a 'once-per-instance'
type of functionality.

Begins with: ``#cloud-boothook`` or ``Content-Type: text/cloud-boothook`` when
using a MIME archive.

Part Handler
============

This is a ``part-handler``: It contains custom code for either supporting new
mime-types in multi-part user data, or overriding the existing handlers for
supported mime-types.  It will be written to a file in ``/var/lib/cloud/data``
based on its filename (which is generated).

This must be python code that contains a ``list_types`` function and a
``handle_part`` function. Once the section is read the ``list_types`` method
will be called. It must return a list of mime-types that this part-handler
handles.  Because mime parts are processed in order, a ``part-handler`` part
must precede any parts with mime-types it is expected to handle in the same
user data.

The ``handle_part`` function must be defined like:

.. code-block:: python

    def handle_part(data, ctype, filename, payload):
      # data = the cloudinit object
      # ctype = "__begin__", "__end__", or the mime-type of the part that is being handled.
      # filename = the filename of the part (or a generated filename if none is present in mime data)
      # payload = the parts' content

Cloud-init will then call the ``handle_part`` function once before it handles
any parts, once per part received, and once after all parts have been handled.
The ``'__begin__'`` and ``'__end__'`` sentinels allow the part handler to do
initialization or teardown before or after receiving any parts.

Begins with: ``#part-handler`` or ``Content-Type: text/part-handler`` when
using a MIME archive.

Example
-------

.. literalinclude:: ../../examples/part-handler.txt
   :language: python
   :linenos:

Also this `blog`_ post offers another example for more advanced usage.

Disabling User-Data
===================

Cloud-init can be configured to ignore any user-data provided to instance.
This allows custom images to prevent users from accidentally breaking closed
appliances. Setting ``allow_userdata: false`` in the configuration will disable
cloud-init from processing user-data.

.. [#] See your cloud provider for applicable user-data size limitations...
.. _blog: http://foss-boss.blogspot.com/2011/01/advanced-cloud-init-custom-handlers.html