autoinstall: Allow "autoinstall" as top-level key
This commit is contained in:
parent
a25f2e03c1
commit
ba3dbb52ef
|
@ -673,9 +673,28 @@ class SubiquityServer(Application):
|
||||||
with open(cfg_path) as fp:
|
with open(cfg_path) as fp:
|
||||||
config: dict[str, Any] = yaml.safe_load(fp)
|
config: dict[str, Any] = yaml.safe_load(fp)
|
||||||
|
|
||||||
autoinstall_config: dict[str, Any] = dict()
|
autoinstall_config: dict[str, Any]
|
||||||
|
|
||||||
autoinstall_config = config
|
# Support "autoinstall" as a top-level key
|
||||||
|
if "autoinstall" in config:
|
||||||
|
autoinstall_config = config.pop("autoinstall")
|
||||||
|
|
||||||
|
# but the only top level key
|
||||||
|
if len(config) != 0:
|
||||||
|
self.interactive = bool(autoinstall_config.get("interactive-sections"))
|
||||||
|
msg: str = (
|
||||||
|
"autoinstall.yaml is not a valid cloud config datasource.\n"
|
||||||
|
"No other keys may be present alongside 'autoinstall' at "
|
||||||
|
"the top level."
|
||||||
|
)
|
||||||
|
context.error(msg)
|
||||||
|
raise AutoinstallValidationError(
|
||||||
|
owner="top-level keys",
|
||||||
|
details="autoinstall.yaml is not a valid cloud config datasource",
|
||||||
|
)
|
||||||
|
|
||||||
|
else:
|
||||||
|
autoinstall_config = config
|
||||||
|
|
||||||
return autoinstall_config
|
return autoinstall_config
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ from typing import Any
|
||||||
from unittest.mock import AsyncMock, Mock, patch
|
from unittest.mock import AsyncMock, Mock, patch
|
||||||
|
|
||||||
import jsonschema
|
import jsonschema
|
||||||
|
import yaml
|
||||||
from jsonschema.validators import validator_for
|
from jsonschema.validators import validator_for
|
||||||
|
|
||||||
from subiquity.cloudinit import CloudInitSchemaValidationError
|
from subiquity.cloudinit import CloudInitSchemaValidationError
|
||||||
|
@ -156,6 +157,7 @@ early-commands: ["{cmd}"]
|
||||||
|
|
||||||
class TestAutoinstallValidation(SubiTestCase):
|
class TestAutoinstallValidation(SubiTestCase):
|
||||||
async def asyncSetUp(self):
|
async def asyncSetUp(self):
|
||||||
|
self.tempdir = self.tmp_dir()
|
||||||
opts = Mock()
|
opts = Mock()
|
||||||
opts.dry_run = True
|
opts.dry_run = True
|
||||||
opts.output_base = self.tmp_dir()
|
opts.output_base = self.tmp_dir()
|
||||||
|
@ -171,6 +173,15 @@ class TestAutoinstallValidation(SubiTestCase):
|
||||||
}
|
}
|
||||||
self.server.make_apport_report = Mock()
|
self.server.make_apport_report = Mock()
|
||||||
|
|
||||||
|
def path(self, relative_path):
|
||||||
|
return self.tmp_path(relative_path, dir=self.tempdir)
|
||||||
|
|
||||||
|
def create(self, path, contents):
|
||||||
|
path = self.path(path)
|
||||||
|
with open(path, "w") as fp:
|
||||||
|
fp.write(contents)
|
||||||
|
return path
|
||||||
|
|
||||||
# Pseudo Load Controllers to avoid patching the loading logic for each
|
# Pseudo Load Controllers to avoid patching the loading logic for each
|
||||||
# controller when we still want access to class attributes
|
# controller when we still want access to class attributes
|
||||||
def pseudo_load_controllers(self):
|
def pseudo_load_controllers(self):
|
||||||
|
@ -445,6 +456,44 @@ class TestAutoinstallValidation(SubiTestCase):
|
||||||
|
|
||||||
self.assertEqual(cfg, expected)
|
self.assertEqual(cfg, expected)
|
||||||
|
|
||||||
|
async def test_autoinstall_validation__top_level_autoinstall(self):
|
||||||
|
"""Test allow autoinstall as top-level key"""
|
||||||
|
|
||||||
|
new_style = {
|
||||||
|
"autoinstall": {
|
||||||
|
"version": 1,
|
||||||
|
"interactive-sections": ["identity"],
|
||||||
|
"apt": "...",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
old_style = new_style["autoinstall"]
|
||||||
|
|
||||||
|
# Read new style correctly
|
||||||
|
path = self.create("autoinstall.yaml", yaml.dump(new_style))
|
||||||
|
self.assertEqual(self.server._read_config(cfg_path=path), old_style)
|
||||||
|
|
||||||
|
# No changes to old style
|
||||||
|
path = self.create("autoinstall.yaml", yaml.dump(old_style))
|
||||||
|
self.assertEqual(self.server._read_config(cfg_path=path), old_style)
|
||||||
|
|
||||||
|
async def test_autoinstall_validation__not_cloudinit_datasource(self):
|
||||||
|
"""Test no cloud init datasources in new style autoinstall"""
|
||||||
|
|
||||||
|
new_style = {
|
||||||
|
"autoinstall": {
|
||||||
|
"version": 1,
|
||||||
|
"interactive-sections": ["identity"],
|
||||||
|
"apt": "...",
|
||||||
|
},
|
||||||
|
"cloudinit-data": "I am data",
|
||||||
|
}
|
||||||
|
|
||||||
|
with self.assertRaises(AutoinstallValidationError) as ctx:
|
||||||
|
path = self.create("autoinstall.yaml", yaml.dump(new_style))
|
||||||
|
self.server._read_config(cfg_path=path)
|
||||||
|
|
||||||
|
self.assertEqual("top-level keys", ctx.exception.owner)
|
||||||
|
|
||||||
|
|
||||||
class TestMetaController(SubiTestCase):
|
class TestMetaController(SubiTestCase):
|
||||||
async def test_interactive_sections_not_present(self):
|
async def test_interactive_sections_not_present(self):
|
||||||
|
|
Loading…
Reference in New Issue