summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorScott Moser <smoser@brickies.net>2016-08-23 16:48:41 -0400
committerScott Moser <smoser@brickies.net>2016-08-23 16:48:41 -0400
commit7b925df28f84c824e9e4697723d879903a81e780 (patch)
tree2314e210f13cc5cc7bdc59971b9f4b657f755825
parentd0c794919d9a9bf176eb96e25e72836a65e841f1 (diff)
parenta551cb080388c2016bcf23981f99a4a6aa0fe198 (diff)
downloadvyos-cloud-init-7b925df28f84c824e9e4697723d879903a81e780.tar.gz
vyos-cloud-init-7b925df28f84c824e9e4697723d879903a81e780.zip
merge trunk at 0.7.7~bzr1208
-rw-r--r--ChangeLog3
-rw-r--r--cloudinit/config/cc_chef.py26
-rw-r--r--cloudinit/config/cc_lxd.py121
-rw-r--r--cloudinit/config/cc_phone_home.py7
-rw-r--r--cloudinit/config/cc_rh_subscription.py14
-rw-r--r--cloudinit/distros/rhel_util.py2
-rw-r--r--cloudinit/net/__init__.py3
-rw-r--r--cloudinit/sources/DataSourceCloudSigma.py2
-rw-r--r--cloudinit/sources/DataSourceNoCloud.py7
-rw-r--r--cloudinit/sources/DataSourceSmartOS.py2
-rw-r--r--doc/examples/cloud-config-chef.txt4
-rw-r--r--doc/examples/cloud-config-lxd.txt27
-rw-r--r--templates/chef_client.rb.tmpl2
-rw-r--r--tests/unittests/test_distros/test_resolv.py6
-rw-r--r--tests/unittests/test_handler/test_handler_chef.py65
-rw-r--r--tests/unittests/test_handler/test_handler_lxd.py59
-rw-r--r--tests/unittests/test_rh_subscription.py9
17 files changed, 319 insertions, 40 deletions
diff --git a/ChangeLog b/ChangeLog
index 9fb6e6d4..7bfd0c0a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -102,6 +102,9 @@
- disk_setup: correctly send --force to mkfs on block devices (LP: #1548772)
- chef: fix chef install from gems (LP: #1553345)
- systemd: do not specify After of obsolete syslog.target (LP: #1536964)
+ - centos: Ensure that resolve conf object is written as a str (LP: #1479988)
+ - chef: straighten out validation_cert and validation_key (LP: #1568940)
+ - phone_home: allow usage of fqdn (LP: #1566824) [Ollie Armstrong]
0.7.6:
- open 0.7.6
diff --git a/cloudinit/config/cc_chef.py b/cloudinit/config/cc_chef.py
index 28711a59..4c28be6a 100644
--- a/cloudinit/config/cc_chef.py
+++ b/cloudinit/config/cc_chef.py
@@ -38,8 +38,10 @@ It can be configured with the following option structure::
chef:
directories: (defaulting to /etc/chef, /var/log/chef, /var/lib/chef,
/var/cache/chef, /var/backups/chef, /var/run/chef)
- validation_key or validation_cert: (optional string to be written to
- /etc/chef/validation.pem)
+ validation_cert: (optional string to be written to file validation_key)
+ special value 'system' means set use existing file
+ validation_key: (optional the path for validation_cert. default
+ /etc/chef/validation.pem)
firstboot_path: (path to write run_list and initial_attributes keys that
should also be present in this configuration, defaults
to /etc/chef/firstboot.json)
@@ -64,6 +66,7 @@ It can be configured with the following option structure::
server_url:
show_time:
ssl_verify_mode:
+ validation_cert:
validation_key:
validation_name:
"""
@@ -105,6 +108,7 @@ CHEF_RB_TPL_DEFAULTS = {
# These are not symbols...
'log_location': '/var/log/chef/client.log',
'validation_key': CHEF_VALIDATION_PEM_PATH,
+ 'validation_cert': None,
'client_key': "/etc/chef/client.pem",
'json_attribs': CHEF_FB_PATH,
'file_cache_path': "/var/cache/chef",
@@ -201,13 +205,17 @@ def handle(name, cfg, cloud, log, _args):
for d in itertools.chain(chef_dirs, REQUIRED_CHEF_DIRS):
util.ensure_dir(d)
- # Set the validation key based on the presence of either 'validation_key'
- # or 'validation_cert'. In the case where both exist, 'validation_key'
- # takes precedence
- for key in ('validation_key', 'validation_cert'):
- if key in chef_cfg and chef_cfg[key]:
- util.write_file(CHEF_VALIDATION_PEM_PATH, chef_cfg[key])
- break
+ vkey_path = chef_cfg.get('validation_key', CHEF_VALIDATION_PEM_PATH)
+ vcert = chef_cfg.get('validation_cert')
+ # special value 'system' means do not overwrite the file
+ # but still render the template to contain 'validation_key'
+ if vcert:
+ if vcert != "system":
+ util.write_file(vkey_path, vcert)
+ elif not os.path.isfile(vkey_path):
+ log.warn("chef validation_cert provided as 'system', but "
+ "validation_key path '%s' does not exist.",
+ vkey_path)
# Create the chef config from template
template_fn = cloud.get_template_filename('chef_client.rb')
diff --git a/cloudinit/config/cc_lxd.py b/cloudinit/config/cc_lxd.py
index 63b8fb63..bf735648 100644
--- a/cloudinit/config/cc_lxd.py
+++ b/cloudinit/config/cc_lxd.py
@@ -30,6 +30,19 @@ Example config:
storage_create_loop: <size>
storage_pool: <name>
trust_password: <password>
+ bridge:
+ mode: <new, existing or none>
+ name: <name>
+ ipv4_address: <ip addr>
+ ipv4_netmask: <cidr>
+ ipv4_dhcp_first: <ip addr>
+ ipv4_dhcp_last: <ip addr>
+ ipv4_dhcp_leases: <size>
+ ipv4_nat: <bool>
+ ipv6_address: <ip addr>
+ ipv6_netmask: <cidr>
+ ipv6_nat: <bool>
+ domain: <domain>
"""
from cloudinit import util
@@ -46,22 +59,24 @@ def handle(name, cfg, cloud, log, args):
type(lxd_cfg))
return
+ # Grab the configuration
init_cfg = lxd_cfg.get('init')
if not isinstance(init_cfg, dict):
log.warn("lxd/init config must be a dictionary. found a '%s'",
type(init_cfg))
init_cfg = {}
- if not init_cfg:
- log.debug("no lxd/init config. disabled.")
- return
+ bridge_cfg = lxd_cfg.get('bridge')
+ if not isinstance(bridge_cfg, dict):
+ log.warn("lxd/bridge config must be a dictionary. found a '%s'",
+ type(bridge_cfg))
+ bridge_cfg = {}
+ # Install the needed packages
packages = []
- # Ensure lxd is installed
if not util.which("lxd"):
packages.append('lxd')
- # if using zfs, get the utils
if init_cfg.get("storage_backend") == "zfs" and not util.which('zfs'):
packages.append('zfs')
@@ -73,13 +88,89 @@ def handle(name, cfg, cloud, log, args):
return
# Set up lxd if init config is given
- init_keys = (
- 'network_address', 'network_port', 'storage_backend',
- 'storage_create_device', 'storage_create_loop',
- 'storage_pool', 'trust_password')
- cmd = ['lxd', 'init', '--auto']
- for k in init_keys:
- if init_cfg.get(k):
- cmd.extend(["--%s=%s" %
- (k.replace('_', '-'), str(init_cfg[k]))])
- util.subp(cmd)
+ if init_cfg:
+ init_keys = (
+ 'network_address', 'network_port', 'storage_backend',
+ 'storage_create_device', 'storage_create_loop',
+ 'storage_pool', 'trust_password')
+ cmd = ['lxd', 'init', '--auto']
+ for k in init_keys:
+ if init_cfg.get(k):
+ cmd.extend(["--%s=%s" %
+ (k.replace('_', '-'), str(init_cfg[k]))])
+ util.subp(cmd)
+
+ # Set up lxd-bridge if bridge config is given
+ dconf_comm = "debconf-communicate"
+ if bridge_cfg and util.which(dconf_comm):
+ debconf = bridge_to_debconf(bridge_cfg)
+
+ # Update debconf database
+ try:
+ log.debug("Setting lxd debconf via " + dconf_comm)
+ data = "\n".join(["set %s %s" % (k, v)
+ for k, v in debconf.items()]) + "\n"
+ util.subp(['debconf-communicate'], data)
+ except:
+ util.logexc(log, "Failed to run '%s' for lxd with" % dconf_comm)
+
+ # Remove the existing configuration file (forces re-generation)
+ util.del_file("/etc/default/lxd-bridge")
+
+ # Run reconfigure
+ log.debug("Running dpkg-reconfigure for lxd")
+ util.subp(['dpkg-reconfigure', 'lxd',
+ '--frontend=noninteractive'])
+ elif bridge_cfg:
+ raise RuntimeError(
+ "Unable to configure lxd bridge without %s." + dconf_comm)
+
+
+def bridge_to_debconf(bridge_cfg):
+ debconf = {}
+
+ if bridge_cfg.get("mode") == "none":
+ debconf["lxd/setup-bridge"] = "false"
+ debconf["lxd/bridge-name"] = ""
+
+ elif bridge_cfg.get("mode") == "existing":
+ debconf["lxd/setup-bridge"] = "false"
+ debconf["lxd/use-existing-bridge"] = "true"
+ debconf["lxd/bridge-name"] = bridge_cfg.get("name")
+
+ elif bridge_cfg.get("mode") == "new":
+ debconf["lxd/setup-bridge"] = "true"
+ if bridge_cfg.get("name"):
+ debconf["lxd/bridge-name"] = bridge_cfg.get("name")
+
+ if bridge_cfg.get("ipv4_address"):
+ debconf["lxd/bridge-ipv4"] = "true"
+ debconf["lxd/bridge-ipv4-address"] = \
+ bridge_cfg.get("ipv4_address")
+ debconf["lxd/bridge-ipv4-netmask"] = \
+ bridge_cfg.get("ipv4_netmask")
+ debconf["lxd/bridge-ipv4-dhcp-first"] = \
+ bridge_cfg.get("ipv4_dhcp_first")
+ debconf["lxd/bridge-ipv4-dhcp-last"] = \
+ bridge_cfg.get("ipv4_dhcp_last")
+ debconf["lxd/bridge-ipv4-dhcp-leases"] = \
+ bridge_cfg.get("ipv4_dhcp_leases")
+ debconf["lxd/bridge-ipv4-nat"] = \
+ bridge_cfg.get("ipv4_nat", "true")
+
+ if bridge_cfg.get("ipv6_address"):
+ debconf["lxd/bridge-ipv6"] = "true"
+ debconf["lxd/bridge-ipv6-address"] = \
+ bridge_cfg.get("ipv6_address")
+ debconf["lxd/bridge-ipv6-netmask"] = \
+ bridge_cfg.get("ipv6_netmask")
+ debconf["lxd/bridge-ipv6-nat"] = \
+ bridge_cfg.get("ipv6_nat", "false")
+
+ if bridge_cfg.get("domain"):
+ debconf["lxd/bridge-domain"] = bridge_cfg.get("domain")
+
+ else:
+ raise Exception("invalid bridge mode \"%s\"" % bridge_cfg.get("mode"))
+
+ return debconf
diff --git a/cloudinit/config/cc_phone_home.py b/cloudinit/config/cc_phone_home.py
index 18a7ddad..3dcc9459 100644
--- a/cloudinit/config/cc_phone_home.py
+++ b/cloudinit/config/cc_phone_home.py
@@ -30,7 +30,8 @@ POST_LIST_ALL = [
'pub_key_rsa',
'pub_key_ecdsa',
'instance_id',
- 'hostname'
+ 'hostname',
+ 'fdqn'
]
@@ -41,7 +42,8 @@ POST_LIST_ALL = [
#
# phone_home:
# url: http://my.foo.bar/$INSTANCE_ID/
-# post: [ pub_key_dsa, pub_key_rsa, pub_key_ecdsa, instance_id
+# post: [ pub_key_dsa, pub_key_rsa, pub_key_ecdsa, instance_id, hostname,
+# fqdn ]
#
def handle(name, cfg, cloud, log, args):
if len(args) != 0:
@@ -74,6 +76,7 @@ def handle(name, cfg, cloud, log, args):
all_keys = {}
all_keys['instance_id'] = cloud.get_instance_id()
all_keys['hostname'] = cloud.get_hostname()
+ all_keys['fqdn'] = cloud.get_hostname(fqdn=True)
pubkeys = {
'pub_key_dsa': '/etc/ssh/ssh_host_dsa_key.pub',
diff --git a/cloudinit/config/cc_rh_subscription.py b/cloudinit/config/cc_rh_subscription.py
index 6087c45c..3a113aea 100644
--- a/cloudinit/config/cc_rh_subscription.py
+++ b/cloudinit/config/cc_rh_subscription.py
@@ -19,10 +19,14 @@
from cloudinit import util
-def handle(_name, cfg, _cloud, log, _args):
+def handle(name, cfg, _cloud, log, _args):
sm = SubscriptionManager(cfg)
sm.log = log
- if not sm.is_registered:
+ if not sm.is_configured():
+ log.debug("%s: module not configured.", name)
+ return None
+
+ if not sm.is_registered():
try:
verify, verify_msg = sm._verify_keys()
if verify is not True:
@@ -95,7 +99,6 @@ class SubscriptionManager(object):
self.disable_repo = self.rhel_cfg.get('disable-repo')
self.servicelevel = self.rhel_cfg.get('service-level')
self.subman = ['subscription-manager']
- self.is_registered = self._is_registered()
def log_success(self, msg):
'''Simple wrapper for logging info messages. Useful for unittests'''
@@ -134,7 +137,7 @@ class SubscriptionManager(object):
return False, no_auto
return True, None
- def _is_registered(self):
+ def is_registered(self):
'''
Checks if the system is already registered and returns
True if so, else False
@@ -400,3 +403,6 @@ class SubscriptionManager(object):
self.log.debug("Disabled the following repos: %s" %
(", ".join(disable_list)).replace('--disable=', ''))
return True
+
+ def is_configured(self):
+ return bool((self.userid and self.password) or self.activation_key)
diff --git a/cloudinit/distros/rhel_util.py b/cloudinit/distros/rhel_util.py
index 84aad623..903d7793 100644
--- a/cloudinit/distros/rhel_util.py
+++ b/cloudinit/distros/rhel_util.py
@@ -86,4 +86,4 @@ def update_resolve_conf_file(fn, dns_servers, search_servers):
r_conf.add_search_domain(s)
except ValueError:
util.logexc(LOG, "Failed at adding search domain %s", s)
- util.write_file(fn, r_conf, 0o644)
+ util.write_file(fn, str(r_conf), 0o644)
diff --git a/cloudinit/net/__init__.py b/cloudinit/net/__init__.py
index 40929c6e..31110292 100644
--- a/cloudinit/net/__init__.py
+++ b/cloudinit/net/__init__.py
@@ -646,6 +646,9 @@ def generate_fallback_config():
connected = []
possibly_connected = []
for interface in potential_interfaces:
+ if os.path.exists(sys_dev_path(interface, "bridge")):
+ # skip any bridges
+ continue
try:
carrier = int(sys_netdev_info(interface, 'carrier'))
if carrier:
diff --git a/cloudinit/sources/DataSourceCloudSigma.py b/cloudinit/sources/DataSourceCloudSigma.py
index f8f94759..d7d4e844 100644
--- a/cloudinit/sources/DataSourceCloudSigma.py
+++ b/cloudinit/sources/DataSourceCloudSigma.py
@@ -56,7 +56,7 @@ class DataSourceCloudSigma(sources.DataSource):
LOG.debug("determining hypervisor product name via dmi data")
sys_product_name = util.read_dmi_data("system-product-name")
if not sys_product_name:
- LOG.warn("failed to get hypervisor product name via dmi data")
+ LOG.debug("system-product-name not available in dmi data")
return False
else:
LOG.debug("detected hypervisor as %s", sys_product_name)
diff --git a/cloudinit/sources/DataSourceNoCloud.py b/cloudinit/sources/DataSourceNoCloud.py
index c2fba4d2..74d0e5ec 100644
--- a/cloudinit/sources/DataSourceNoCloud.py
+++ b/cloudinit/sources/DataSourceNoCloud.py
@@ -216,8 +216,11 @@ class DataSourceNoCloud(sources.DataSource):
if not current:
return None
+ # LP: #1568150 need getattr in the case that an old class object
+ # has been loaded from a pickled file and now executing new source.
+ dirs = getattr(self, 'seed_dirs', [self.seed_dir])
quick_id = _quick_read_instance_id(cmdline_id=self.cmdline_id,
- dirs=self.seed_dirs)
+ dirs=dirs)
if not quick_id:
return None
return quick_id == current
@@ -238,6 +241,8 @@ def _quick_read_instance_id(cmdline_id, dirs=None):
return fill[iid_key]
for d in dirs:
+ if d is None:
+ continue
try:
data = util.pathprefix2dict(d, required=['meta-data'])
md = util.load_yaml(data['meta-data'])
diff --git a/cloudinit/sources/DataSourceSmartOS.py b/cloudinit/sources/DataSourceSmartOS.py
index 5edab152..6cbd8dfa 100644
--- a/cloudinit/sources/DataSourceSmartOS.py
+++ b/cloudinit/sources/DataSourceSmartOS.py
@@ -242,7 +242,7 @@ class DataSourceSmartOS(sources.DataSource):
# SDC KVM instances will provide dmi data, LX-brand does not
if self.smartos_type == 'kvm':
dmi_info = dmi_data()
- if dmi_info is False:
+ if dmi_info is None:
LOG.debug("No dmidata utility found")
return False
diff --git a/doc/examples/cloud-config-chef.txt b/doc/examples/cloud-config-chef.txt
index 4edad653..b886cba2 100644
--- a/doc/examples/cloud-config-chef.txt
+++ b/doc/examples/cloud-config-chef.txt
@@ -67,7 +67,9 @@ chef:
# Default validation name is chef-validator
validation_name: "yourorg-validator"
- validation_key: |
+ # if validation_cert's value is "system" then it is expected
+ # that the file already exists on the system.
+ validation_cert: |
-----BEGIN RSA PRIVATE KEY-----
YOUR-ORGS-VALIDATION-KEY-HERE
-----END RSA PRIVATE KEY-----
diff --git a/doc/examples/cloud-config-lxd.txt b/doc/examples/cloud-config-lxd.txt
index b9bb4aa5..e96f314b 100644
--- a/doc/examples/cloud-config-lxd.txt
+++ b/doc/examples/cloud-config-lxd.txt
@@ -12,6 +12,20 @@
# storage_create_loop: set up loop based storage with size in GB
# storage_pool: name of storage pool to use or create
# trust_password: password required to add new clients
+# bridge: dict of options for the lxd bridge
+# mode: one of "new", "existing" or "none". Defaults to "new"
+# name: the name of the bridge. Defaults to "lxdbr0"
+# ipv4_address: an IPv4 address (e.g. 10.0.8.1)
+# ipv4_netmask: a CIDR mask value (e.g. 24)
+# ipv4_dhcp_first: the first IP of the DHCP range (e.g. 10.0.8.2)
+# ipv4_dhcp_last: the last IP of the DHCP range (e.g. 10.0.8.254)
+# ipv4_dhcp_leases: the size of the DHCP pool (e.g. 250)
+# ipv4_nat: either "true" or "false"
+# ipv6_address: an IPv6 address (e.g. fd98:9e0:3744::1)
+# ipv6_netmask: a CIDR mask value (e.g. 64)
+# ipv6_nat: either "true" or "false"
+# domain: domain name to use for the bridge
+
lxd:
init:
@@ -20,6 +34,19 @@ lxd:
storage_backend: zfs
storage_pool: datapool
storage_create_loop: 10
+ bridge:
+ mode: new
+ name: lxdbr0
+ ipv4_address: 10.0.8.1
+ ipv4_netmask: 24
+ ipv4_dhcp_first: 10.0.8.2
+ ipv4_dhcp_last: 10.0.8.3
+ ipv4_dhcp_leases: 250
+ ipv4_nat: true
+ ipv6_address: fd98:9e0:3744::1
+ ipv6_netmask: 64
+ ipv6_nat: true
+ domain: lxd
# The simplist working configuration is
diff --git a/templates/chef_client.rb.tmpl b/templates/chef_client.rb.tmpl
index c4069d22..cbb6b15f 100644
--- a/templates/chef_client.rb.tmpl
+++ b/templates/chef_client.rb.tmpl
@@ -26,7 +26,7 @@ log_location "{{log_location}}"
{% if validation_name %}
validation_client_name "{{validation_name}}"
{% endif %}
-{% if validation_key %}
+{% if validation_cert %}
validation_key "{{validation_key}}"
{% endif %}
{% if client_key %}
diff --git a/tests/unittests/test_distros/test_resolv.py b/tests/unittests/test_distros/test_resolv.py
index faaf5b7f..9edeb6e7 100644
--- a/tests/unittests/test_distros/test_resolv.py
+++ b/tests/unittests/test_distros/test_resolv.py
@@ -1,6 +1,8 @@
from cloudinit.distros.parsers import resolv_conf
+from cloudinit.distros import rhel_util
import re
+import tempfile
from ..helpers import TestCase
@@ -19,6 +21,10 @@ class TestResolvHelper(TestCase):
rp_r = str(rp).strip()
self.assertEquals(BASE_RESOLVE, rp_r)
+ def test_write_works(self):
+ with tempfile.NamedTemporaryFile() as fh:
+ rhel_util.update_resolve_conf_file(fh.name, [], [])
+
def test_local_domain(self):
rp = resolv_conf.ResolvConf(BASE_RESOLVE)
self.assertEquals(None, rp.local_domain)
diff --git a/tests/unittests/test_handler/test_handler_chef.py b/tests/unittests/test_handler/test_handler_chef.py
index edad88cb..7763f23b 100644
--- a/tests/unittests/test_handler/test_handler_chef.py
+++ b/tests/unittests/test_handler/test_handler_chef.py
@@ -75,17 +75,28 @@ class TestChef(t_help.FilesystemMockingTestCase):
'chef': {
'server_url': 'localhost',
'validation_name': 'bob',
+ 'validation_key': "/etc/chef/vkey.pem",
+ 'validation_cert': "this is my cert",
},
}
cc_chef.handle('chef', cfg, self.fetch_cloud('ubuntu'), LOG, [])
for d in cc_chef.CHEF_DIRS:
self.assertTrue(os.path.isdir(d))
c = util.load_file(cc_chef.CHEF_RB_PATH)
+
+ # the content of these keys is not expected to be rendered to tmpl
+ unrendered_keys = ('validation_cert',)
for k, v in cfg['chef'].items():
+ if k in unrendered_keys:
+ continue
self.assertIn(v, c)
for k, v in cc_chef.CHEF_RB_TPL_DEFAULTS.items():
- if isinstance(v, six.string_types):
- self.assertIn(v, c)
+ if k in unrendered_keys:
+ continue
+ # the value from the cfg overrides that in the default
+ val = cfg['chef'].get(k, v)
+ if isinstance(val, six.string_types):
+ self.assertIn(val, c)
c = util.load_file(cc_chef.CHEF_FB_PATH)
self.assertEqual({}, json.loads(c))
@@ -131,3 +142,53 @@ class TestChef(t_help.FilesystemMockingTestCase):
c = util.load_file(cc_chef.CHEF_RB_PATH)
self.assertNotIn('json_attribs', c)
self.assertNotIn('Formatter.show_time', c)
+
+ @t_help.skipIf(not os.path.isfile(CLIENT_TEMPL),
+ CLIENT_TEMPL + " is not available")
+ def test_validation_cert_and_validation_key(self):
+ # test validation_cert content is written to validation_key path
+ tpl_file = util.load_file('templates/chef_client.rb.tmpl')
+ self.patchUtils(self.tmp)
+ self.patchOS(self.tmp)
+
+ util.write_file('/etc/cloud/templates/chef_client.rb.tmpl', tpl_file)
+ v_path = '/etc/chef/vkey.pem'
+ v_cert = 'this is my cert'
+ cfg = {
+ 'chef': {
+ 'server_url': 'localhost',
+ 'validation_name': 'bob',
+ 'validation_key': v_path,
+ 'validation_cert': v_cert
+ },
+ }
+ cc_chef.handle('chef', cfg, self.fetch_cloud('ubuntu'), LOG, [])
+ content = util.load_file(cc_chef.CHEF_RB_PATH)
+ self.assertIn(v_path, content)
+ util.load_file(v_path)
+ self.assertEqual(v_cert, util.load_file(v_path))
+
+ def test_validation_cert_with_system(self):
+ # test validation_cert content is not written over system file
+ tpl_file = util.load_file('templates/chef_client.rb.tmpl')
+ self.patchUtils(self.tmp)
+ self.patchOS(self.tmp)
+
+ v_path = '/etc/chef/vkey.pem'
+ v_cert = "system"
+ expected_cert = "this is the system file certificate"
+ cfg = {
+ 'chef': {
+ 'server_url': 'localhost',
+ 'validation_name': 'bob',
+ 'validation_key': v_path,
+ 'validation_cert': v_cert
+ },
+ }
+ util.write_file('/etc/cloud/templates/chef_client.rb.tmpl', tpl_file)
+ util.write_file(v_path, expected_cert)
+ cc_chef.handle('chef', cfg, self.fetch_cloud('ubuntu'), LOG, [])
+ content = util.load_file(cc_chef.CHEF_RB_PATH)
+ self.assertIn(v_path, content)
+ util.load_file(v_path)
+ self.assertEqual(expected_cert, util.load_file(v_path))
diff --git a/tests/unittests/test_handler/test_handler_lxd.py b/tests/unittests/test_handler/test_handler_lxd.py
index 7ffa2a53..5f61ba6a 100644
--- a/tests/unittests/test_handler/test_handler_lxd.py
+++ b/tests/unittests/test_handler/test_handler_lxd.py
@@ -73,3 +73,62 @@ class TestLxd(t_help.TestCase):
cc_lxd.handle('cc_lxd', {'package_update': True}, cc, LOG, [])
self.assertFalse(cc.distro.install_packages.called)
self.assertFalse(mock_util.subp.called)
+
+ def test_lxd_debconf_new_full(self):
+ data = {"mode": "new",
+ "name": "testbr0",
+ "ipv4_address": "10.0.8.1",
+ "ipv4_netmask": "24",
+ "ipv4_dhcp_first": "10.0.8.2",
+ "ipv4_dhcp_last": "10.0.8.254",
+ "ipv4_dhcp_leases": "250",
+ "ipv4_nat": "true",
+ "ipv6_address": "fd98:9e0:3744::1",
+ "ipv6_netmask": "64",
+ "ipv6_nat": "true",
+ "domain": "lxd"}
+ self.assertEquals(
+ cc_lxd.bridge_to_debconf(data),
+ {"lxd/setup-bridge": "true",
+ "lxd/bridge-name": "testbr0",
+ "lxd/bridge-ipv4": "true",
+ "lxd/bridge-ipv4-address": "10.0.8.1",
+ "lxd/bridge-ipv4-netmask": "24",
+ "lxd/bridge-ipv4-dhcp-first": "10.0.8.2",
+ "lxd/bridge-ipv4-dhcp-last": "10.0.8.254",
+ "lxd/bridge-ipv4-dhcp-leases": "250",
+ "lxd/bridge-ipv4-nat": "true",
+ "lxd/bridge-ipv6": "true",
+ "lxd/bridge-ipv6-address": "fd98:9e0:3744::1",
+ "lxd/bridge-ipv6-netmask": "64",
+ "lxd/bridge-ipv6-nat": "true",
+ "lxd/bridge-domain": "lxd"})
+
+ def test_lxd_debconf_new_partial(self):
+ data = {"mode": "new",
+ "ipv6_address": "fd98:9e0:3744::1",
+ "ipv6_netmask": "64",
+ "ipv6_nat": "true"}
+ self.assertEquals(
+ cc_lxd.bridge_to_debconf(data),
+ {"lxd/setup-bridge": "true",
+ "lxd/bridge-ipv6": "true",
+ "lxd/bridge-ipv6-address": "fd98:9e0:3744::1",
+ "lxd/bridge-ipv6-netmask": "64",
+ "lxd/bridge-ipv6-nat": "true"})
+
+ def test_lxd_debconf_existing(self):
+ data = {"mode": "existing",
+ "name": "testbr0"}
+ self.assertEquals(
+ cc_lxd.bridge_to_debconf(data),
+ {"lxd/setup-bridge": "false",
+ "lxd/use-existing-bridge": "true",
+ "lxd/bridge-name": "testbr0"})
+
+ def test_lxd_debconf_none(self):
+ data = {"mode": "none"}
+ self.assertEquals(
+ cc_lxd.bridge_to_debconf(data),
+ {"lxd/setup-bridge": "false",
+ "lxd/bridge-name": ""})
diff --git a/tests/unittests/test_rh_subscription.py b/tests/unittests/test_rh_subscription.py
index 38d5763a..8c586ad7 100644
--- a/tests/unittests/test_rh_subscription.py
+++ b/tests/unittests/test_rh_subscription.py
@@ -126,7 +126,8 @@ class TestBadInput(unittest.TestCase):
'enable-repo': 'not_a_list'
}}
config_badkey = {'rh_subscription':
- {'activation_key': 'abcdef1234',
+ {'activation-key': 'abcdef1234',
+ 'fookey': 'bar',
'org': '123',
}}
@@ -138,7 +139,11 @@ class TestBadInput(unittest.TestCase):
'''
Attempt to register without the password key/value
'''
- self.input_is_missing_data(self.config_no_password)
+ self.SM._sub_man_cli = mock.MagicMock(
+ side_effect=[util.ProcessExecutionError, (self.reg, 'bar')])
+ self.handle(self.name, self.config_no_password, self.cloud_init,
+ self.log, self.args)
+ self.assertEqual(self.SM._sub_man_cli.call_count, 0)
def test_no_org(self):
'''