From a5727fe1477c9cc4288d1ac41f70bd1ab7d7928a Mon Sep 17 00:00:00 2001
From: Ben Howard <ben.howard@canonical.com>
Date: Wed, 8 Jan 2014 17:16:24 -0700
Subject: Significant re-working of the userdata handling and introduction of
 vendordata.

Vendordata is a datasource provided userdata-like blob that is parsed
similiarly to userdata, execept at the user's pleasure.


cloudinit/config/cc_scripts_vendor.py: added vendor script cloud config

cloudinit/config/cc_vendor_scripts_per_boot.py: added vendor per boot
    cloud config

cloudinit/config/cc_vendor_scripts_per_instance.py: added vendor per
    instance vendor cloud config

cloudinit/config/cc_vendor_scripts_per_once.py: added per once vendor
    cloud config script

doc/examples/cloud-config-vendor-data.txt: documentation of vendor-data
    examples

doc/vendordata.txt: documentation of vendordata for vendors

(RENAMED) tests/unittests/test_userdata.py => tests/unittests/test_userdata.py
      TO: tests/unittests/test_userdata.py => tests/unittests/test_data.py:
    userdata test cases are not expanded to confirm superiority over vendor
    data.

bin/cloud-init: change instances of 'consume_userdata' to 'consume_data'

cloudinit/handlers/cloud_config.py: Added vendor script handling to default
    cloud-config modules

cloudinit/handlers/shell_script.py: Added ability to change the path key to
    support vendor provided 'vendor-scripts'. Defaults to 'script'.

cloudinit/helpers.py:
    - Changed ConfigMerger to include handling of vendordata.
    - Changed helpers to include paths for vendordata.

cloudinit/sources/__init__.py: Added functions for helping vendordata
    - get_vendordata_raw(): returns vendordata unprocessed
    - get_vendordata(): returns vendordata through userdata processor
    - has_vendordata(): indicator if vendordata is present
    - consume_vendordata(): datasource directive for indicating explict
        user approval of vendordata consumption. Defaults to 'false'

cloudinit/stages.py: Re-jiggered for handling of vendordata
    - _initial_subdirs(): added vendor script definition
    - update(): added self._store_vendordata()
    - [ADDED] _store_vendordata(): store vendordata
    - _get_default_handlers(): modified to allow for filtering
        which handlers will run against vendordata
    - [ADDED] _do_handlers(): moved logic from consume_userdata
        to _do_handlers(). This allows _consume_vendordata() and
        _consume_userdata() to use the same code path.
    - [RENAMED] consume_userdata() to _consume_userdata()
    - [ADDED] _consume_vendordata() for handling vendordata
        - run after userdata to get user cloud-config
        - uses ConfigMerger to get the configuration from the
            instance perspective about whether or not to use
            vendordata
    - [ADDED] consume_data() to call _consume_{user,vendor}data

cloudinit/util.py:
    - [ADDED] get_nested_option_as_list() used by cc_vendor* for
        getting a nested value from a dict and returned as a list
    - runparts(): added 'exe_prefix' for running exe with a prefix,
        used by cc_vendor*

config/cloud.cfg: Added vendor script execution as default

tests/unittests/test_runs/test_merge_run.py: changed consume_userdata() to
    consume_data()

tests/unittests/test_runs/test_simple_run.py: changed consume_userdata() to
    consume_data()
---
 cloudinit/sources/__init__.py | 28 ++++++++++++++++++++++++++--
 1 file changed, 26 insertions(+), 2 deletions(-)

(limited to 'cloudinit/sources')

diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py
index 7dc1fbde..a7c7993f 100644
--- a/cloudinit/sources/__init__.py
+++ b/cloudinit/sources/__init__.py
@@ -53,6 +53,8 @@ class DataSource(object):
         self.userdata = None
         self.metadata = None
         self.userdata_raw = None
+        self.vendordata = None
+        self.vendordata_raw = None
 
         # find the datasource config name.
         # remove 'DataSource' from classname on front, and remove 'Net' on end.
@@ -77,9 +79,28 @@ class DataSource(object):
         if self.userdata is None:
             self.userdata = self.ud_proc.process(self.get_userdata_raw())
         if apply_filter:
-            return self._filter_userdata(self.userdata)
+            return self._filter_xdata(self.userdata)
         return self.userdata
 
+    def get_vendordata(self, apply_filter=False):
+        if self.vendordata is None:
+            self.vendordata = self.ud_proc.process(self.get_vendordata_raw())
+        if apply_filter:
+            return self._filter_xdata(self.vendordata)
+        return self.vendordata
+
+    def has_vendordata(self):
+        if self.vendordata_raw is not None:
+            return True
+        return False
+
+    def consume_vendordata(self):
+        """
+        The datasource may allow for consumption of vendordata, but only
+        when the datasource has allowed it. The default is false.
+        """
+        return False
+
     @property
     def launch_index(self):
         if not self.metadata:
@@ -88,7 +109,7 @@ class DataSource(object):
             return self.metadata['launch-index']
         return None
 
-    def _filter_userdata(self, processed_ud):
+    def _filter_xdata(self, processed_ud):
         filters = [
             launch_index.Filter(util.safe_int(self.launch_index)),
         ]
@@ -104,6 +125,9 @@ class DataSource(object):
     def get_userdata_raw(self):
         return self.userdata_raw
 
+    def get_vendordata_raw(self):
+        return self.vendordata_raw
+
     # the data sources' config_obj is a cloud-config formated
     # object that came to it from ways other than cloud-config
     # because cloud-config content would be handled elsewhere
-- 
cgit v1.2.3


From 9874d0590dba4a67ff7268a6a1d22207088e1a13 Mon Sep 17 00:00:00 2001
From: Ben Howard <ben.howard@canonical.com>
Date: Thu, 9 Jan 2014 08:31:52 -0700
Subject: Added vendordata to SmartOS

---
 cloudinit/sources/DataSourceSmartOS.py | 2 ++
 1 file changed, 2 insertions(+)

(limited to 'cloudinit/sources')

diff --git a/cloudinit/sources/DataSourceSmartOS.py b/cloudinit/sources/DataSourceSmartOS.py
index 551b20c4..ccfee931 100644
--- a/cloudinit/sources/DataSourceSmartOS.py
+++ b/cloudinit/sources/DataSourceSmartOS.py
@@ -47,6 +47,7 @@ SMARTOS_ATTRIB_MAP = {
     'iptables_disable': ('iptables_disable', True),
     'motd_sys_info': ('motd_sys_info', True),
     'availability_zone': ('datacenter_name', True),
+    'vendordata': ('sdc:operator-script', False),
 }
 
 DS_NAME = 'SmartOS'
@@ -154,6 +155,7 @@ class DataSourceSmartOS(sources.DataSource):
 
         self.metadata = util.mergemanydict([md, self.metadata])
         self.userdata_raw = ud
+        self.vendordata_raw = vendordata
         return True
 
     def device_name_to_device(self, name):
-- 
cgit v1.2.3


From 8a952c7c7797e2a1dfcd2be1c3a983de767de04e Mon Sep 17 00:00:00 2001
From: Scott Moser <smoser@ubuntu.com>
Date: Thu, 16 Jan 2014 16:54:23 -0500
Subject: DataSource: remove has_vendordata and consume_vendordata, drop
 filters

remove apply_filter from get_vendordata.  I can't think of a good
reason to filter vendor-data per instance-id.

remove has_vendordata and consume_vendordata.
has vendordata is always "true", whether or not there is something
to operate is determined by:
 if ds.vendordata_raw()

consume_vendordata is based on config entirely.
---
 cloudinit/sources/__init__.py | 16 +---------------
 1 file changed, 1 insertion(+), 15 deletions(-)

(limited to 'cloudinit/sources')

diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py
index a7c7993f..7e11c1ca 100644
--- a/cloudinit/sources/__init__.py
+++ b/cloudinit/sources/__init__.py
@@ -82,25 +82,11 @@ class DataSource(object):
             return self._filter_xdata(self.userdata)
         return self.userdata
 
-    def get_vendordata(self, apply_filter=False):
+    def get_vendordata(self)
         if self.vendordata is None:
             self.vendordata = self.ud_proc.process(self.get_vendordata_raw())
-        if apply_filter:
-            return self._filter_xdata(self.vendordata)
         return self.vendordata
 
-    def has_vendordata(self):
-        if self.vendordata_raw is not None:
-            return True
-        return False
-
-    def consume_vendordata(self):
-        """
-        The datasource may allow for consumption of vendordata, but only
-        when the datasource has allowed it. The default is false.
-        """
-        return False
-
     @property
     def launch_index(self):
         if not self.metadata:
-- 
cgit v1.2.3


From b94c9790e055960fccf3b159d86db85ef37fb34f Mon Sep 17 00:00:00 2001
From: Ben Howard <ben.howard@canonical.com>
Date: Thu, 16 Jan 2014 16:32:57 -0700
Subject: Fixed typos

---
 cloudinit/sources/DataSourceSmartOS.py | 2 +-
 cloudinit/sources/__init__.py          | 2 +-
 cloudinit/stages.py                    | 4 ++--
 3 files changed, 4 insertions(+), 4 deletions(-)

(limited to 'cloudinit/sources')

diff --git a/cloudinit/sources/DataSourceSmartOS.py b/cloudinit/sources/DataSourceSmartOS.py
index ccfee931..6593ce6e 100644
--- a/cloudinit/sources/DataSourceSmartOS.py
+++ b/cloudinit/sources/DataSourceSmartOS.py
@@ -155,7 +155,7 @@ class DataSourceSmartOS(sources.DataSource):
 
         self.metadata = util.mergemanydict([md, self.metadata])
         self.userdata_raw = ud
-        self.vendordata_raw = vendordata
+        self.vendordata_raw = md['vendordata']
         return True
 
     def device_name_to_device(self, name):
diff --git a/cloudinit/sources/__init__.py b/cloudinit/sources/__init__.py
index 7e11c1ca..4b3bf62f 100644
--- a/cloudinit/sources/__init__.py
+++ b/cloudinit/sources/__init__.py
@@ -82,7 +82,7 @@ class DataSource(object):
             return self._filter_xdata(self.userdata)
         return self.userdata
 
-    def get_vendordata(self)
+    def get_vendordata(self):
         if self.vendordata is None:
             self.vendordata = self.ud_proc.process(self.get_vendordata_raw())
         return self.vendordata
diff --git a/cloudinit/stages.py b/cloudinit/stages.py
index 19fbe706..5dced998 100644
--- a/cloudinit/stages.py
+++ b/cloudinit/stages.py
@@ -514,8 +514,8 @@ class Init(object):
             LOG.debug("vendordata consumption is disabled.")
             return
 
-        enabled = vdc.get('enabled')
-        no_handlers = vdc.get('disabled_handlers', None)
+        enabled = vdcfg.get('enabled')
+        no_handlers = vdcfg.get('disabled_handlers', None)
 
         LOG.debug("vendor data will be consumed. disabled_handlers=%s",
                   no_handlers)
-- 
cgit v1.2.3