summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorScott Moser <smoser@brickies.net>2017-04-27 12:50:12 -0400
committerScott Moser <smoser@brickies.net>2017-04-27 12:50:12 -0400
commit8310484a880690529a4936615df596d467e51708 (patch)
tree886aeb1a6e3ca809e466ddbcacbe9741b56dafa0 /doc
parentaf63cf763946bca6163dc797195a3aeae975f8da (diff)
parent513e99e049eab4acea14e187f59d760adc755b40 (diff)
downloadvyos-cloud-init-8310484a880690529a4936615df596d467e51708.tar.gz
vyos-cloud-init-8310484a880690529a4936615df596d467e51708.zip
merge from 513e99e049ea at 0.7.9-113-g513e99e0
Diffstat (limited to 'doc')
-rw-r--r--doc/examples/cloud-config-chef.txt72
-rw-r--r--doc/examples/cloud-config-resolv-conf.txt4
-rw-r--r--doc/examples/cloud-config-update-apt.txt7
-rw-r--r--doc/merging.rst201
-rw-r--r--doc/rtd/topics/examples.rst30
-rw-r--r--doc/rtd/topics/merging.rst200
-rw-r--r--doc/rtd/topics/modules.rst1
7 files changed, 273 insertions, 242 deletions
diff --git a/doc/examples/cloud-config-chef.txt b/doc/examples/cloud-config-chef.txt
index 75d78a15..3cb62006 100644
--- a/doc/examples/cloud-config-chef.txt
+++ b/doc/examples/cloud-config-chef.txt
@@ -5,46 +5,50 @@
# Make sure that this file is valid yaml before starting instances.
# It should be passed as user-data when starting the instance.
#
-# This example assumes the instance is 12.04 (precise)
+# This example assumes the instance is 16.04 (xenial)
# The default is to install from packages.
-# Key from http://apt.opscode.com/packages@opscode.com.gpg.key
+# Key from https://packages.chef.io/chef.asc
apt:
- sources:
- - source: "deb http://apt.opscode.com/ $RELEASE-0.10 main"
- key: |
- -----BEGIN PGP PUBLIC KEY BLOCK-----
- Version: GnuPG v1.4.9 (GNU/Linux)
+ source1:
+ source: "deb http://packages.chef.io/repos/apt/stable $RELEASE main"
+ key: |
+ -----BEGIN PGP PUBLIC KEY BLOCK-----
+ Version: GnuPG v1.4.12 (Darwin)
+ Comment: GPGTools - http://gpgtools.org
- mQGiBEppC7QRBADfsOkZU6KZK+YmKw4wev5mjKJEkVGlus+NxW8wItX5sGa6kdUu
- twAyj7Yr92rF+ICFEP3gGU6+lGo0Nve7KxkN/1W7/m3G4zuk+ccIKmjp8KS3qn99
- dxy64vcji9jIllVa+XXOGIp0G8GEaj7mbkixL/bMeGfdMlv8Gf2XPpp9vwCgn/GC
- JKacfnw7MpLKUHOYSlb//JsEAJqao3ViNfav83jJKEkD8cf59Y8xKia5OpZqTK5W
- ShVnNWS3U5IVQk10ZDH97Qn/YrK387H4CyhLE9mxPXs/ul18ioiaars/q2MEKU2I
- XKfV21eMLO9LYd6Ny/Kqj8o5WQK2J6+NAhSwvthZcIEphcFignIuobP+B5wNFQpe
- DbKfA/0WvN2OwFeWRcmmd3Hz7nHTpcnSF+4QX6yHRF/5BgxkG6IqBIACQbzPn6Hm
- sMtm/SVf11izmDqSsQptCrOZILfLX/mE+YOl+CwWSHhl+YsFts1WOuh1EhQD26aO
- Z84HuHV5HFRWjDLw9LriltBVQcXbpfSrRP5bdr7Wh8vhqJTPjrQnT3BzY29kZSBQ
- YWNrYWdlcyA8cGFja2FnZXNAb3BzY29kZS5jb20+iGAEExECACAFAkppC7QCGwMG
- CwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRApQKupg++Caj8sAKCOXmdG36gWji/K
- +o+XtBfvdMnFYQCfTCEWxRy2BnzLoBBFCjDSK6sJqCu5Ag0ESmkLtBAIAIO2SwlR
- lU5i6gTOp42RHWW7/pmW78CwUqJnYqnXROrt3h9F9xrsGkH0Fh1FRtsnncgzIhvh
- DLQnRHnkXm0ws0jV0PF74ttoUT6BLAUsFi2SPP1zYNJ9H9fhhK/pjijtAcQwdgxu
- wwNJ5xCEscBZCjhSRXm0d30bK1o49Cow8ZIbHtnXVP41c9QWOzX/LaGZsKQZnaMx
- EzDk8dyyctR2f03vRSVyTFGgdpUcpbr9eTFVgikCa6ODEBv+0BnCH6yGTXwBid9g
- w0o1e/2DviKUWCC+AlAUOubLmOIGFBuI4UR+rux9affbHcLIOTiKQXv79lW3P7W8
- AAfniSQKfPWXrrcAAwUH/2XBqD4Uxhbs25HDUUiM/m6Gnlj6EsStg8n0nMggLhuN
- QmPfoNByMPUqvA7sULyfr6xCYzbzRNxABHSpf85FzGQ29RF4xsA4vOOU8RDIYQ9X
- Q8NqqR6pydprRFqWe47hsAN7BoYuhWqTtOLSBmnAnzTR5pURoqcquWYiiEavZixJ
- 3ZRAq/HMGioJEtMFrvsZjGXuzef7f0ytfR1zYeLVWnL9Bd32CueBlI7dhYwkFe+V
- Ep5jWOCj02C1wHcwt+uIRDJV6TdtbIiBYAdOMPk15+VBdweBXwMuYXr76+A7VeDL
- zIhi7tKFo6WiwjKZq0dzctsJJjtIfr4K4vbiD9Ojg1iISQQYEQIACQUCSmkLtAIb
- DAAKCRApQKupg++CauISAJ9CxYPOKhOxalBnVTLeNUkAHGg2gACeIsbobtaD4ZHG
- 0GLl8EkfA8uhluM=
- =zKAm
- -----END PGP PUBLIC KEY BLOCK-----
+ mQGiBEppC7QRBADfsOkZU6KZK+YmKw4wev5mjKJEkVGlus+NxW8wItX5sGa6kdUu
+ twAyj7Yr92rF+ICFEP3gGU6+lGo0Nve7KxkN/1W7/m3G4zuk+ccIKmjp8KS3qn99
+ dxy64vcji9jIllVa+XXOGIp0G8GEaj7mbkixL/bMeGfdMlv8Gf2XPpp9vwCgn/GC
+ JKacfnw7MpLKUHOYSlb//JsEAJqao3ViNfav83jJKEkD8cf59Y8xKia5OpZqTK5W
+ ShVnNWS3U5IVQk10ZDH97Qn/YrK387H4CyhLE9mxPXs/ul18ioiaars/q2MEKU2I
+ XKfV21eMLO9LYd6Ny/Kqj8o5WQK2J6+NAhSwvthZcIEphcFignIuobP+B5wNFQpe
+ DbKfA/0WvN2OwFeWRcmmd3Hz7nHTpcnSF+4QX6yHRF/5BgxkG6IqBIACQbzPn6Hm
+ sMtm/SVf11izmDqSsQptCrOZILfLX/mE+YOl+CwWSHhl+YsFts1WOuh1EhQD26aO
+ Z84HuHV5HFRWjDLw9LriltBVQcXbpfSrRP5bdr7Wh8vhqJTPjrQnT3BzY29kZSBQ
+ YWNrYWdlcyA8cGFja2FnZXNAb3BzY29kZS5jb20+iGAEExECACAFAkppC7QCGwMG
+ CwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRApQKupg++Caj8sAKCOXmdG36gWji/K
+ +o+XtBfvdMnFYQCfTCEWxRy2BnzLoBBFCjDSK6sJqCu0IENIRUYgUGFja2FnZXMg
+ PHBhY2thZ2VzQGNoZWYuaW8+iGIEExECACIFAlQwYFECGwMGCwkIBwMCBhUIAgkK
+ CwQWAgMBAh4BAheAAAoJEClAq6mD74JqX94An26z99XOHWpLN8ahzm7cp13t4Xid
+ AJ9wVcgoUBzvgg91lKfv/34cmemZn7kCDQRKaQu0EAgAg7ZLCVGVTmLqBM6njZEd
+ Zbv+mZbvwLBSomdiqddE6u3eH0X3GuwaQfQWHUVG2yedyDMiG+EMtCdEeeRebTCz
+ SNXQ8Xvi22hRPoEsBSwWLZI8/XNg0n0f1+GEr+mOKO0BxDB2DG7DA0nnEISxwFkK
+ OFJFebR3fRsrWjj0KjDxkhse2ddU/jVz1BY7Nf8toZmwpBmdozETMOTx3LJy1HZ/
+ Te9FJXJMUaB2lRyluv15MVWCKQJro4MQG/7QGcIfrIZNfAGJ32DDSjV7/YO+IpRY
+ IL4CUBQ65suY4gYUG4jhRH6u7H1p99sdwsg5OIpBe/v2Vbc/tbwAB+eJJAp89Zeu
+ twADBQf/ZcGoPhTGFuzbkcNRSIz+boaeWPoSxK2DyfScyCAuG41CY9+g0HIw9Sq8
+ DuxQvJ+vrEJjNvNE3EAEdKl/zkXMZDb1EXjGwDi845TxEMhhD1dDw2qpHqnJ2mtE
+ WpZ7juGwA3sGhi6FapO04tIGacCfNNHmlRGipyq5ZiKIRq9mLEndlECr8cwaKgkS
+ 0wWu+xmMZe7N5/t/TK19HXNh4tVacv0F3fYK54GUjt2FjCQV75USnmNY4KPTYLXA
+ dzC364hEMlXpN21siIFgB04w+TXn5UF3B4FfAy5hevvr4DtV4MvMiGLu0oWjpaLC
+ MpmrR3Ny2wkmO0h+vgri9uIP06ODWIhJBBgRAgAJBQJKaQu0AhsMAAoJEClAq6mD
+ 74Jq4hIAoJ5KrYS8kCwj26SAGzglwggpvt3CAJ0bekyky56vNqoegB+y4PQVDv4K
+ zA==
+ =IxPr
+ -----END PGP PUBLIC KEY BLOCK-----
chef:
diff --git a/doc/examples/cloud-config-resolv-conf.txt b/doc/examples/cloud-config-resolv-conf.txt
index 37ffc91a..c4843f54 100644
--- a/doc/examples/cloud-config-resolv-conf.txt
+++ b/doc/examples/cloud-config-resolv-conf.txt
@@ -5,9 +5,9 @@
#
# Ensure that your yaml is valid and pass this as user-data when starting
# the instance. Also be sure that your cloud.cfg file includes this
-# configuration module in the appropirate section.
+# configuration module in the appropriate section.
#
-manage-resolv-conf: true
+manage_resolv_conf: true
resolv_conf:
nameservers: ['8.8.4.4', '8.8.8.8']
diff --git a/doc/examples/cloud-config-update-apt.txt b/doc/examples/cloud-config-update-apt.txt
index a83ce3f7..647241ca 100644
--- a/doc/examples/cloud-config-update-apt.txt
+++ b/doc/examples/cloud-config-update-apt.txt
@@ -1,7 +1,8 @@
#cloud-config
-# Update apt database on first boot
-# (ie run apt-get update)
+# Update apt database on first boot (run 'apt-get update').
+# Note, if packages are given, or package_upgrade is true, then
+# update will be done independent of this setting.
#
-# Default: true
+# Default: false
# Aliases: apt_update
package_update: false
diff --git a/doc/merging.rst b/doc/merging.rst
deleted file mode 100644
index bf49b909..00000000
--- a/doc/merging.rst
+++ /dev/null
@@ -1,201 +0,0 @@
-Overview
-========
-
-This was implemented because it has been a common feature request that there be
-a way to specify how cloud-config yaml "dictionaries" provided as user-data are
-merged together when there are multiple yamls to merge together (say when
-performing an #include).
-
-Since previously the merging algorithm was very simple and would only overwrite
-and not append lists, or strings, and so on it was decided to create a new and
-improved way to merge dictionaries (and there contained objects) together in a
-way that is customizable, thus allowing for users who provide cloud-config
-user-data to determine exactly how there objects will be merged.
-
-For example.
-
-.. code-block:: yaml
-
- #cloud-config (1)
- run_cmd:
- - bash1
- - bash2
-
- #cloud-config (2)
- run_cmd:
- - bash3
- - bash4
-
-The previous way of merging the following 2 objects would result in a final
-cloud-config object that contains the following.
-
-.. code-block:: yaml
-
- #cloud-config (merged)
- run_cmd:
- - bash3
- - bash4
-
-Typically this is not what users want, instead they would likely prefer:
-
-.. code-block:: yaml
-
- #cloud-config (merged)
- run_cmd:
- - bash1
- - bash2
- - bash3
- - bash4
-
-This way makes it easier to combine the various cloud-config objects you have
-into a more useful list, thus reducing duplication that would have had to
-occur in the previous method to accomplish the same result.
-
-Customizability
-===============
-
-Since the above merging algorithm may not always be the desired merging
-algorithm (like how the previous merging algorithm was not always the preferred
-one) the concept of customizing how merging can be done was introduced through
-a new concept call 'merge classes'.
-
-A merge class is a class defintion which provides functions that can be used
-to merge a given type with another given type.
-
-An example of one of these merging classes is the following:
-
-.. code-block:: python
-
- class Merger(object):
- def __init__(self, merger, opts):
- self._merger = merger
- self._overwrite = 'overwrite' in opts
-
- # This merging algorithm will attempt to merge with
- # another dictionary, on encountering any other type of object
- # it will not merge with said object, but will instead return
- # the original value
- #
- # On encountering a dictionary, it will create a new dictionary
- # composed of the original and the one to merge with, if 'overwrite'
- # is enabled then keys that exist in the original will be overwritten
- # by keys in the one to merge with (and associated values). Otherwise
- # if not in overwrite mode the 2 conflicting keys themselves will
- # be merged.
- def _on_dict(self, value, merge_with):
- if not isinstance(merge_with, (dict)):
- return value
- merged = dict(value)
- for (k, v) in merge_with.items():
- if k in merged:
- if not self._overwrite:
- merged[k] = self._merger.merge(merged[k], v)
- else:
- merged[k] = v
- else:
- merged[k] = v
- return merged
-
-As you can see there is a '_on_dict' method here that will be given a source
-value and a value to merge with. The result will be the merged object. This
-code itself is called by another merging class which 'directs' the merging to
-happen by analyzing the types of the objects to merge and attempting to find a
-know object that will merge that type. I will avoid pasting that here, but it
-can be found in the `mergers/__init__.py` file (see `LookupMerger` and
-`UnknownMerger`).
-
-So following the typical cloud-init way of allowing source code to be
-downloaded and used dynamically, it is possible for users to inject there own
-merging files to handle specific types of merging as they choose (the basic
-ones included will handle lists, dicts, and strings). Note how each merge can
-have options associated with it which affect how the merging is performed, for
-example a dictionary merger can be told to overwrite instead of attempt to
-merge, or a string merger can be told to append strings instead of discarding
-other strings to merge with.
-
-How to activate
-===============
-
-There are a few ways to activate the merging algorithms, and to customize them
-for your own usage.
-
-1. The first way involves the usage of MIME messages in cloud-init to specify
- multipart documents (this is one way in which multiple cloud-config is
- joined together into a single cloud-config). Two new headers are looked
- for, both of which can define the way merging is done (the first header to
- exist wins). These new headers (in lookup order) are 'Merge-Type' and
- 'X-Merge-Type'. The value should be a string which will satisfy the new
- merging format defintion (see below for this format).
-
-2. The second way is actually specifying the merge-type in the body of the
- cloud-config dictionary. There are 2 ways to specify this, either as a
- string or as a dictionary (see format below). The keys that are looked up
- for this definition are the following (in order), 'merge_how',
- 'merge_type'.
-
-String format
--------------
-
-The string format that is expected is the following.
-
-::
-
- classname1(option1,option2)+classname2(option3,option4)....
-
-The class name there will be connected to class names used when looking for the
-class that can be used to merge and options provided will be given to the class
-on construction of that class.
-
-For example, the default string that is used when none is provided is the
-following:
-
-::
-
- list()+dict()+str()
-
-Dictionary format
------------------
-
-In cases where a dictionary can be used to specify the same information as the
-string format (ie option #2 of above) it can be used, for example.
-
-.. code-block:: python
-
- {'merge_how': [{'name': 'list', 'settings': ['extend']},
- {'name': 'dict', 'settings': []},
- {'name': 'str', 'settings': ['append']}]}
-
-This would be the equivalent format for default string format but in dictionary
-form instead of string form.
-
-Specifying multiple types and its effect
-========================================
-
-Now you may be asking yourself, if I specify a merge-type header or dictionary
-for every cloud-config that I provide, what exactly happens?
-
-The answer is that when merging, a stack of 'merging classes' is kept, the
-first one on that stack is the default merging classes, this set of mergers
-will be used when the first cloud-config is merged with the initial empty
-cloud-config dictionary. If the cloud-config that was just merged provided a
-set of merging classes (via the above formats) then those merging classes will
-be pushed onto the stack. Now if there is a second cloud-config to be merged
-then the merging classes from the cloud-config before the first will be used
-(not the default) and so on. This way a cloud-config can decide how it will
-merge with a cloud-config dictionary coming after it.
-
-Other uses
-==========
-
-In addition to being used for merging user-data sections, the default merging
-algorithm for merging 'conf.d' yaml files (which form an initial yaml config
-for cloud-init) was also changed to use this mechanism so its full
-benefits (and customization) can also be used there as well. Other places that
-used the previous merging are also, similarly, now extensible (metadata
-merging, for example).
-
-Note, however, that merge algorithms are not used *across* types of
-configuration. As was the case before merging was implemented,
-user-data will overwrite conf.d configuration without merging.
-
-.. vi: textwidth=78
diff --git a/doc/rtd/topics/examples.rst b/doc/rtd/topics/examples.rst
index a110721c..c30d2263 100644
--- a/doc/rtd/topics/examples.rst
+++ b/doc/rtd/topics/examples.rst
@@ -93,6 +93,13 @@ Install arbitrary packages
:language: yaml
:linenos:
+Update apt database on first boot
+=================================
+
+.. literalinclude:: ../../examples/cloud-config-update-apt.txt
+ :language: yaml
+ :linenos:
+
Run apt or yum upgrade
======================
@@ -149,6 +156,27 @@ Register RedHat Subscription
:language: yaml
:linenos:
-.. _chef: http://www.opscode.com/chef/
+Configure data sources
+======================
+
+.. literalinclude:: ../../examples/cloud-config-datasources.txt
+ :language: yaml
+ :linenos:
+
+Create partitions and filesystems
+=================================
+
+.. literalinclude:: ../../examples/cloud-config-disk-setup.txt
+ :language: yaml
+ :linenos:
+
+Grow partitions
+===============
+
+.. literalinclude:: ../../examples/cloud-config-growpart.txt
+ :language: yaml
+ :linenos:
+
+.. _chef: http://www.chef.io/chef/
.. _puppet: http://puppetlabs.com/
.. vi: textwidth=78
diff --git a/doc/rtd/topics/merging.rst b/doc/rtd/topics/merging.rst
index eca118f5..2f927a47 100644
--- a/doc/rtd/topics/merging.rst
+++ b/doc/rtd/topics/merging.rst
@@ -2,5 +2,203 @@
Merging User-Data Sections
**************************
-.. include:: ../../merging.rst
+Overview
+========
+
+This was implemented because it has been a common feature request that there be
+a way to specify how cloud-config yaml "dictionaries" provided as user-data are
+merged together when there are multiple yamls to merge together (say when
+performing an #include).
+
+Since previously the merging algorithm was very simple and would only overwrite
+and not append lists, or strings, and so on it was decided to create a new and
+improved way to merge dictionaries (and their contained objects) together in a
+way that is customizable, thus allowing for users who provide cloud-config
+user-data to determine exactly how their objects will be merged.
+
+For example.
+
+.. code-block:: yaml
+
+ #cloud-config (1)
+ run_cmd:
+ - bash1
+ - bash2
+
+ #cloud-config (2)
+ run_cmd:
+ - bash3
+ - bash4
+
+The previous way of merging the two objects above would result in a final
+cloud-config object that contains the following.
+
+.. code-block:: yaml
+
+ #cloud-config (merged)
+ run_cmd:
+ - bash3
+ - bash4
+
+Typically this is not what users want; instead they would likely prefer:
+
+.. code-block:: yaml
+
+ #cloud-config (merged)
+ run_cmd:
+ - bash1
+ - bash2
+ - bash3
+ - bash4
+
+This way makes it easier to combine the various cloud-config objects you have
+into a more useful list, thus reducing duplication necessary to accomplish the
+same result with the previous method.
+
+Customizability
+===============
+
+Because the above merging algorithm may not always be desired (just as the
+previous merging algorithm was not always the preferred one), the concept of
+customized merging was introduced through 'merge classes'.
+
+A merge class is a class definition which provides functions that can be used
+to merge a given type with another given type.
+
+An example of one of these merging classes is the following:
+
+.. code-block:: python
+
+ class Merger(object):
+ def __init__(self, merger, opts):
+ self._merger = merger
+ self._overwrite = 'overwrite' in opts
+
+ # This merging algorithm will attempt to merge with
+ # another dictionary, on encountering any other type of object
+ # it will not merge with said object, but will instead return
+ # the original value
+ #
+ # On encountering a dictionary, it will create a new dictionary
+ # composed of the original and the one to merge with, if 'overwrite'
+ # is enabled then keys that exist in the original will be overwritten
+ # by keys in the one to merge with (and associated values). Otherwise
+ # if not in overwrite mode the 2 conflicting keys themselves will
+ # be merged.
+ def _on_dict(self, value, merge_with):
+ if not isinstance(merge_with, (dict)):
+ return value
+ merged = dict(value)
+ for (k, v) in merge_with.items():
+ if k in merged:
+ if not self._overwrite:
+ merged[k] = self._merger.merge(merged[k], v)
+ else:
+ merged[k] = v
+ else:
+ merged[k] = v
+ return merged
+
+As you can see there is a '_on_dict' method here that will be given a source
+value and a value to merge with. The result will be the merged object. This
+code itself is called by another merging class which 'directs' the merging to
+happen by analyzing the types of the objects to merge and attempting to find a
+know object that will merge that type. I will avoid pasting that here, but it
+can be found in the `mergers/__init__.py` file (see `LookupMerger` and
+`UnknownMerger`).
+
+So following the typical cloud-init way of allowing source code to be
+downloaded and used dynamically, it is possible for users to inject there own
+merging files to handle specific types of merging as they choose (the basic
+ones included will handle lists, dicts, and strings). Note how each merge can
+have options associated with it which affect how the merging is performed, for
+example a dictionary merger can be told to overwrite instead of attempt to
+merge, or a string merger can be told to append strings instead of discarding
+other strings to merge with.
+
+How to activate
+===============
+
+There are a few ways to activate the merging algorithms, and to customize them
+for your own usage.
+
+1. The first way involves the usage of MIME messages in cloud-init to specify
+ multipart documents (this is one way in which multiple cloud-config is
+ joined together into a single cloud-config). Two new headers are looked
+ for, both of which can define the way merging is done (the first header to
+ exist wins). These new headers (in lookup order) are 'Merge-Type' and
+ 'X-Merge-Type'. The value should be a string which will satisfy the new
+ merging format defintion (see below for this format).
+
+2. The second way is actually specifying the merge-type in the body of the
+ cloud-config dictionary. There are 2 ways to specify this, either as a
+ string or as a dictionary (see format below). The keys that are looked up
+ for this definition are the following (in order), 'merge_how',
+ 'merge_type'.
+
+String format
+-------------
+
+The string format that is expected is the following.
+
+::
+
+ classname1(option1,option2)+classname2(option3,option4)....
+
+The class name there will be connected to class names used when looking for the
+class that can be used to merge and options provided will be given to the class
+on construction of that class.
+
+For example, the default string that is used when none is provided is the
+following:
+
+::
+
+ list()+dict()+str()
+
+Dictionary format
+-----------------
+
+A dictionary can be used when it specifies the same information as the
+string format (i.e. the second option above), for example:
+
+.. code-block:: python
+
+ {'merge_how': [{'name': 'list', 'settings': ['extend']},
+ {'name': 'dict', 'settings': []},
+ {'name': 'str', 'settings': ['append']}]}
+
+This would be the equivalent format for default string format but in dictionary
+form instead of string form.
+
+Specifying multiple types and its effect
+========================================
+
+Now you may be asking yourself, if I specify a merge-type header or dictionary
+for every cloud-config that I provide, what exactly happens?
+
+The answer is that when merging, a stack of 'merging classes' is kept, the
+first one on that stack is the default merging classes, this set of mergers
+will be used when the first cloud-config is merged with the initial empty
+cloud-config dictionary. If the cloud-config that was just merged provided a
+set of merging classes (via the above formats) then those merging classes will
+be pushed onto the stack. Now if there is a second cloud-config to be merged
+then the merging classes from the cloud-config before the first will be used
+(not the default) and so on. This way a cloud-config can decide how it will
+merge with a cloud-config dictionary coming after it.
+
+Other uses
+==========
+
+In addition to being used for merging user-data sections, the default merging
+algorithm for merging 'conf.d' yaml files (which form an initial yaml config
+for cloud-init) was also changed to use this mechanism so its full
+benefits (and customization) can also be used there as well. Other places that
+used the previous merging are also, similarly, now extensible (metadata
+merging, for example).
+
+Note, however, that merge algorithms are not used *across* types of
+configuration. As was the case before merging was implemented,
+user-data will overwrite conf.d configuration without merging.
+
.. vi: textwidth=78
diff --git a/doc/rtd/topics/modules.rst b/doc/rtd/topics/modules.rst
index a3ead4f1..c963c09a 100644
--- a/doc/rtd/topics/modules.rst
+++ b/doc/rtd/topics/modules.rst
@@ -44,6 +44,7 @@ Modules
.. automodule:: cloudinit.config.cc_set_hostname
.. automodule:: cloudinit.config.cc_set_passwords
.. automodule:: cloudinit.config.cc_snappy
+.. automodule:: cloudinit.config.cc_snap_config
.. automodule:: cloudinit.config.cc_spacewalk
.. automodule:: cloudinit.config.cc_ssh
.. automodule:: cloudinit.config.cc_ssh_authkey_fingerprints