Custom Part Handler¶
This must be Python code that contains a list_types
function and a
handle_part
function.
The list_types
function takes no arguments and must return a list
of content types that this
part handler handles. These can include custom content types or built-in
content types that this handler will override.
The handle_part
function takes 4 arguments and returns nothing. See the
example for how exactly each argument is used.
To use this part handler, it must be included in a MIME multipart file as part of the user data. Since MIME parts are processed in order, a part handler part must precede any parts with mime-types that it is expected to handle in the same user data.
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. These additional calls allow for initialisation or teardown before
or after receiving any parts.
Example¶
1#part-handler
2
3"""This is a trivial example part-handler that creates a file with the path
4specified in the payload. It performs no input checking or error handling.
5
6To use it, first save the file you are currently viewing into your current
7working directory. Then run the following:
8```
9$ echo '/var/tmp/my_path' > part
10$ cloud-init devel make-mime -a part-handler.py:part-handler -a part:x-my-path --force > user-data
11```
12
13This will create a mime file with the contents of 'part' and the
14part-handler. You can now pass 'user-data' to your cloud of choice.
15
16When run, cloud-init will have created an empty file at /var/tmp/my_path.
17"""
18
19import pathlib
20from typing import Any
21
22from cloudinit.cloud import Cloud
23
24
25def list_types():
26 """Return a list of mime-types that are handled by this module."""
27 return ["text/x-my-path"]
28
29
30def handle_part(data: Cloud, ctype: str, filename: str, payload: Any):
31 """Handle a part with the given mime-type.
32
33 This function will get called multiple times. The first time is
34 to allow any initial setup needed to handle parts. It will then get
35 called once for each part matching the mime-type returned by `list_types`.
36 Finally, it will get called one last time to allow for any final
37 teardown.
38
39 :data: A `Cloud` instance. This will be the same instance for each call
40 to handle_part.
41 :ctype: '__begin__', '__end__', or the mime-type
42 (for this example 'text/x-my-path') of the part
43 :filename: The filename for the part as defined in the MIME archive,
44 or dynamically generated part if no filename is given
45 :payload: The content of the part. This will be
46 `None` when `ctype` is '__begin__' or '__end__'.
47 """
48 if ctype == "__begin__":
49 # Any custom setup needed before handling payloads
50 return
51
52 if ctype == "__end__":
53 # Any custom teardown needed after handling payloads can happen here
54 return
55
56 # If we've made it here, we're dealing with a real payload, so handle
57 # it appropriately
58 pathlib.Path(payload.strip()).touch()