change 'configs' to 'config', and namespace input to 'snappy config'
the input to 'snappy config <packagename>' is expected to have config: <packagename>: content: So here we pad that input correctly. Note, that a .config file on disk is not modified. Also, we change 'configs' to just be 'config', to be possibly compatible with the a future 'snappy config /' that dumped: config: pkg1: data1 pkg2: data2
This commit is contained in:
parent
b2c0b0028f
commit
eacf44e17d
@ -8,9 +8,11 @@ Example config:
|
|||||||
system_snappy: auto
|
system_snappy: auto
|
||||||
ssh_enabled: False
|
ssh_enabled: False
|
||||||
packages: [etcd, pkg2]
|
packages: [etcd, pkg2]
|
||||||
configs:
|
config:
|
||||||
pkgname: pkgname-config-blob
|
pkgname:
|
||||||
pkg2: config-blob
|
key2: value2
|
||||||
|
pkg2:
|
||||||
|
key1: value1
|
||||||
packages_dir: '/writable/user-data/cloud-init/snaps'
|
packages_dir: '/writable/user-data/cloud-init/snaps'
|
||||||
|
|
||||||
- ssh_enabled:
|
- ssh_enabled:
|
||||||
@ -31,7 +33,7 @@ Example config:
|
|||||||
<packages_dir>/foo.snap
|
<packages_dir>/foo.snap
|
||||||
snappy install <packages_dir>/bar.snap
|
snappy install <packages_dir>/bar.snap
|
||||||
|
|
||||||
Note, that if provided a 'configs' entry for 'ubuntu-core', then
|
Note, that if provided a 'config' entry for 'ubuntu-core', then
|
||||||
cloud-init will invoke: snappy config ubuntu-core <config>
|
cloud-init will invoke: snappy config ubuntu-core <config>
|
||||||
Allowing you to configure ubuntu-core in this way.
|
Allowing you to configure ubuntu-core in this way.
|
||||||
"""
|
"""
|
||||||
@ -56,7 +58,7 @@ BUILTIN_CFG = {
|
|||||||
'packages_dir': '/writable/user-data/cloud-init/snaps',
|
'packages_dir': '/writable/user-data/cloud-init/snaps',
|
||||||
'ssh_enabled': False,
|
'ssh_enabled': False,
|
||||||
'system_snappy': "auto",
|
'system_snappy': "auto",
|
||||||
'configs': {},
|
'config': {},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -119,15 +121,14 @@ def render_snap_op(op, name, path=None, cfgfile=None, config=None):
|
|||||||
try:
|
try:
|
||||||
cfg_tmpf = None
|
cfg_tmpf = None
|
||||||
if config is not None:
|
if config is not None:
|
||||||
if isinstance(config, six.binary_type):
|
# input to 'snappy config packagename' must have nested data. odd.
|
||||||
cfg_bytes = config
|
# config:
|
||||||
elif isinstance(config, six.text_type):
|
# packagename:
|
||||||
cfg_bytes = config.encode()
|
# config
|
||||||
else:
|
# Note, however, we do not touch config files on disk.
|
||||||
cfg_bytes = util.yaml_dumps(config).encode()
|
nested_cfg = {'config': {name: config}}
|
||||||
|
|
||||||
(fd, cfg_tmpf) = tempfile.mkstemp()
|
(fd, cfg_tmpf) = tempfile.mkstemp()
|
||||||
os.write(fd, cfg_bytes)
|
os.write(fd, util.yaml_dumps(nested_cfg).encode())
|
||||||
os.close(fd)
|
os.close(fd)
|
||||||
cfgfile = cfg_tmpf
|
cfgfile = cfg_tmpf
|
||||||
|
|
||||||
@ -218,7 +219,7 @@ def handle(name, cfg, cloud, log, args):
|
|||||||
return
|
return
|
||||||
|
|
||||||
pkg_ops = get_package_ops(packages=mycfg['packages'],
|
pkg_ops = get_package_ops(packages=mycfg['packages'],
|
||||||
configs=mycfg['configs'],
|
configs=mycfg['config'],
|
||||||
fspath=mycfg['packages_dir'])
|
fspath=mycfg['packages_dir'])
|
||||||
|
|
||||||
set_snappy_command()
|
set_snappy_command()
|
||||||
|
@ -6,6 +6,9 @@ from .. import helpers as t_help
|
|||||||
import os
|
import os
|
||||||
import shutil
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
ALLOWED = (dict, list, int, str)
|
||||||
|
|
||||||
|
|
||||||
class TestInstallPackages(t_help.TestCase):
|
class TestInstallPackages(t_help.TestCase):
|
||||||
@ -44,7 +47,7 @@ class TestInstallPackages(t_help.TestCase):
|
|||||||
config = kwargs.get('data', '')
|
config = kwargs.get('data', '')
|
||||||
else:
|
else:
|
||||||
with open(args[3], "rb") as fp:
|
with open(args[3], "rb") as fp:
|
||||||
config = fp.read()
|
config = yaml.safe_load(fp.read())
|
||||||
self.snapcmds.append(['config', args[2], config])
|
self.snapcmds.append(['config', args[2], config])
|
||||||
elif args[0:2] == ['snappy', 'install']:
|
elif args[0:2] == ['snappy', 'install']:
|
||||||
config = None
|
config = None
|
||||||
@ -56,7 +59,7 @@ class TestInstallPackages(t_help.TestCase):
|
|||||||
config = kwargs.get('data', '')
|
config = kwargs.get('data', '')
|
||||||
elif cfgfile:
|
elif cfgfile:
|
||||||
with open(cfgfile, "rb") as fp:
|
with open(cfgfile, "rb") as fp:
|
||||||
config = fp.read()
|
config = yaml.safe_load(fp.read())
|
||||||
elif not pkg and not arg.startswith("-"):
|
elif not pkg and not arg.startswith("-"):
|
||||||
pkg = arg
|
pkg = arg
|
||||||
self.snapcmds.append(['install', pkg, config])
|
self.snapcmds.append(['install', pkg, config])
|
||||||
@ -126,7 +129,7 @@ class TestInstallPackages(t_help.TestCase):
|
|||||||
path='snapf1.snap', cfgfile='snapf1.config')
|
path='snapf1.snap', cfgfile='snapf1.config')
|
||||||
render_snap_op(**op)
|
render_snap_op(**op)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.snapcmds, [['install', op['path'], b'snapf1cfg']])
|
self.snapcmds, [['install', op['path'], 'snapf1cfg']])
|
||||||
|
|
||||||
def test_render_op_snap(self):
|
def test_render_op_snap(self):
|
||||||
op = makeop('install', 'snapf1')
|
op = makeop('install', 'snapf1')
|
||||||
@ -135,49 +138,77 @@ class TestInstallPackages(t_help.TestCase):
|
|||||||
self.snapcmds, [['install', 'snapf1', None]])
|
self.snapcmds, [['install', 'snapf1', None]])
|
||||||
|
|
||||||
def test_render_op_snap_config(self):
|
def test_render_op_snap_config(self):
|
||||||
op = makeop('install', 'snapf1', config=b'myconfig')
|
mycfg = {'key1': 'value1'}
|
||||||
|
name = "snapf1"
|
||||||
|
op = makeop('install', name, config=mycfg)
|
||||||
render_snap_op(**op)
|
render_snap_op(**op)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.snapcmds, [['install', 'snapf1', b'myconfig']])
|
self.snapcmds, [['install', name, {'config': {name: mycfg}}]])
|
||||||
|
|
||||||
def test_render_op_config_bytes(self):
|
def test_render_op_config_bytes(self):
|
||||||
op = makeop('config', 'snapf1', config=b'myconfig')
|
name = "snapf1"
|
||||||
|
mycfg = b'myconfig'
|
||||||
|
op = makeop('config', name, config=mycfg)
|
||||||
render_snap_op(**op)
|
render_snap_op(**op)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.snapcmds, [['config', 'snapf1', b'myconfig']])
|
self.snapcmds, [['config', 'snapf1', {'config': {name: mycfg}}]])
|
||||||
|
|
||||||
def test_render_op_config_string(self):
|
def test_render_op_config_string(self):
|
||||||
|
name = 'snapf1'
|
||||||
mycfg = 'myconfig: foo\nhisconfig: bar\n'
|
mycfg = 'myconfig: foo\nhisconfig: bar\n'
|
||||||
op = makeop('config', 'snapf1', config=mycfg)
|
op = makeop('config', name, config=mycfg)
|
||||||
render_snap_op(**op)
|
render_snap_op(**op)
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
self.snapcmds, [['config', 'snapf1', mycfg.encode()]])
|
self.snapcmds, [['config', 'snapf1', {'config': {name: mycfg}}]])
|
||||||
|
|
||||||
def test_render_op_config_dict(self):
|
def test_render_op_config_dict(self):
|
||||||
# config entry for package can be a dict, not a string blob
|
# config entry for package can be a dict, not a string blob
|
||||||
mycfg = {'foo': 'bar'}
|
mycfg = {'foo': 'bar'}
|
||||||
op = makeop('config', 'snapf1', config=mycfg)
|
name = 'snapf1'
|
||||||
|
op = makeop('config', name, config=mycfg)
|
||||||
render_snap_op(**op)
|
render_snap_op(**op)
|
||||||
# snapcmds is a list of 3-entry lists. data_found will be the
|
# snapcmds is a list of 3-entry lists. data_found will be the
|
||||||
# blob of data in the file in 'snappy install --config=<file>'
|
# blob of data in the file in 'snappy install --config=<file>'
|
||||||
data_found = self.snapcmds[0][2]
|
data_found = self.snapcmds[0][2]
|
||||||
self.assertEqual(mycfg, util.load_yaml(data_found))
|
self.assertEqual(mycfg, data_found['config'][name])
|
||||||
|
|
||||||
def test_render_op_config_list(self):
|
def test_render_op_config_list(self):
|
||||||
# config entry for package can be a list, not a string blob
|
# config entry for package can be a list, not a string blob
|
||||||
mycfg = ['foo', 'bar', 'wark', {'f1': 'b1'}]
|
mycfg = ['foo', 'bar', 'wark', {'f1': 'b1'}]
|
||||||
op = makeop('config', 'snapf1', config=mycfg)
|
name = "snapf1"
|
||||||
|
op = makeop('config', name, config=mycfg)
|
||||||
render_snap_op(**op)
|
render_snap_op(**op)
|
||||||
data_found = self.snapcmds[0][2]
|
data_found = self.snapcmds[0][2]
|
||||||
self.assertEqual(mycfg, util.load_yaml(data_found, allowed=(list,)))
|
self.assertEqual(mycfg, data_found['config'][name])
|
||||||
|
|
||||||
def test_render_op_config_int(self):
|
def test_render_op_config_int(self):
|
||||||
# config entry for package can be a list, not a string blob
|
# config entry for package can be a list, not a string blob
|
||||||
mycfg = 1
|
mycfg = 1
|
||||||
op = makeop('config', 'snapf1', config=mycfg)
|
name = 'snapf1'
|
||||||
|
op = makeop('config', name, config=mycfg)
|
||||||
render_snap_op(**op)
|
render_snap_op(**op)
|
||||||
data_found = self.snapcmds[0][2]
|
data_found = self.snapcmds[0][2]
|
||||||
self.assertEqual(mycfg, util.load_yaml(data_found, allowed=(int,)))
|
self.assertEqual(mycfg, data_found['config'][name])
|
||||||
|
|
||||||
|
def test_render_does_not_pad_cfgfile(self):
|
||||||
|
# package_ops with cfgfile should not modify --file= content.
|
||||||
|
mydata = "foo1: bar1\nk: [l1, l2, l3]\n"
|
||||||
|
self.populate_tmp(
|
||||||
|
{"snapf1.snap": b"foo1", "snapf1.config": mydata.encode()})
|
||||||
|
ret = get_package_ops(
|
||||||
|
packages=[], configs={}, installed=[], fspath=self.tmp)
|
||||||
|
self.assertEqual(
|
||||||
|
ret,
|
||||||
|
[makeop_tmpd(self.tmp, 'install', 'snapf1', path="snapf1.snap",
|
||||||
|
cfgfile="snapf1.config")])
|
||||||
|
|
||||||
|
# now the op was ok, but test that render didn't mess it up.
|
||||||
|
render_snap_op(**ret[0])
|
||||||
|
data_found = self.snapcmds[0][2]
|
||||||
|
# the data found gets loaded in the snapcmd interpretation
|
||||||
|
# so this comparison is a bit lossy, but input to snappy config
|
||||||
|
# is expected to be yaml loadable, so it should be OK.
|
||||||
|
self.assertEqual(yaml.safe_load(mydata), data_found)
|
||||||
|
|
||||||
|
|
||||||
def makeop_tmpd(tmpd, op, name, config=None, path=None, cfgfile=None):
|
def makeop_tmpd(tmpd, op, name, config=None, path=None, cfgfile=None):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user