Skip to content

Commit ea095cd

Browse files
committed
fixes #3
1 parent 7c773c4 commit ea095cd

File tree

3 files changed

+80
-110
lines changed

3 files changed

+80
-110
lines changed

fastcloudinit/core.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66

77
# %% ../nbs/00_core.ipynb
88
from fastcore.utils import *
9-
import fastcore.xtras, yaml
109
from textwrap import dedent
10+
from jsonschema import validate
11+
from httpx import get as xget
12+
13+
import fastcore.xtras, yaml, json
1114

1215
# %% ../nbs/00_core.ipynb
1316
def ufw(logging="off", def_incoming="deny", def_outgoing="allow", internal=None, **allows):
@@ -88,12 +91,13 @@ def runcmd(cmds):
8891
return dict(runcmd=cmds)
8992

9093
# %% ../nbs/00_core.ipynb
91-
def cloud_init_base(hostname, packages=None, **kw):
94+
def cloud_init_base(hostname, packages=None, check=True, **kw):
9295
cfg = dict(
9396
hostname=hostname, preserve_hostname=False,
9497
packages=listify(packages), package_update=True, package_upgrade=True,
9598
disable_root=True, ssh_pwauth=False, **kw
9699
)
100+
if check: cc_validate(cfg)
97101
return "#cloud-config\n" + yaml.safe_dump(cfg, sort_keys=False, width=1_000_000)
98102

99103
# %% ../nbs/00_core.ipynb

nbs/00_core.ipynb

Lines changed: 73 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,22 @@
2828
"source": [
2929
"#| export\n",
3030
"from fastcore.utils import *\n",
31-
"import fastcore.xtras, yaml\n",
32-
"from textwrap import dedent"
31+
"from textwrap import dedent\n",
32+
"from jsonschema import validate\n",
33+
"from httpx import get as xget\n",
34+
"\n",
35+
"import fastcore.xtras, yaml, json"
36+
]
37+
},
38+
{
39+
"cell_type": "code",
40+
"execution_count": null,
41+
"id": "aa8f2efa",
42+
"metadata": {},
43+
"outputs": [],
44+
"source": [
45+
"from fastcore.test import test_eq,test_fail\n",
46+
"from jsonschema import ValidationError"
3347
]
3448
},
3549
{
@@ -315,6 +329,59 @@
315329
" return dict(runcmd=cmds)"
316330
]
317331
},
332+
{
333+
"cell_type": "code",
334+
"execution_count": null,
335+
"id": "0f608fa1",
336+
"metadata": {},
337+
"outputs": [],
338+
"source": [
339+
"def cc_validate(d):\n",
340+
" vsc = xget('https://raw.githubusercontent.com/canonical/cloud-init/main/cloudinit/config/schemas/versions.schema.cloud-config.json').text\n",
341+
" validate(d, schema=json.loads(vsc))"
342+
]
343+
},
344+
{
345+
"cell_type": "code",
346+
"execution_count": null,
347+
"id": "0646d7af",
348+
"metadata": {},
349+
"outputs": [],
350+
"source": [
351+
"samp = '''#cloud-config\n",
352+
"hostname: example-host\n",
353+
"fqdn: example-host.example.com\n",
354+
"# User setup configuration\n",
355+
"users:\n",
356+
" - name: exampleuser\n",
357+
" gecos: Example User\n",
358+
" sudo: ['ALL=(ALL) NOPASSWD:ALL']'''\n",
359+
"cc_validate(yaml.safe_load(samp))"
360+
]
361+
},
362+
{
363+
"cell_type": "markdown",
364+
"id": "ea5aa012",
365+
"metadata": {},
366+
"source": [
367+
"This example has an intentional key error (\"hostna\" instead of \"hostname\"):"
368+
]
369+
},
370+
{
371+
"cell_type": "code",
372+
"execution_count": null,
373+
"id": "a8d9e3fd",
374+
"metadata": {},
375+
"outputs": [],
376+
"source": [
377+
"samp = '''#cloud-config\n",
378+
"hostna: example-host\n",
379+
"fqdn: example-host.example.com'''\n",
380+
"try: cc_validate(yaml.safe_load(samp))\n",
381+
"except ValidationError: pass\n",
382+
"else: raise Exception('Expected validation error')"
383+
]
384+
},
318385
{
319386
"cell_type": "code",
320387
"execution_count": null,
@@ -323,12 +390,13 @@
323390
"outputs": [],
324391
"source": [
325392
"#| export\n",
326-
"def cloud_init_base(hostname, packages=None, **kw):\n",
393+
"def cloud_init_base(hostname, packages=None, check=True, **kw):\n",
327394
" cfg = dict(\n",
328395
" hostname=hostname, preserve_hostname=False,\n",
329396
" packages=listify(packages), package_update=True, package_upgrade=True,\n",
330397
" disable_root=True, ssh_pwauth=False, **kw\n",
331398
" )\n",
399+
" if check: cc_validate(cfg)\n",
332400
" return \"#cloud-config\\n\" + yaml.safe_dump(cfg, sort_keys=False, width=1_000_000)"
333401
]
334402
},
@@ -368,109 +436,7 @@
368436
"text": [
369437
"#cloud-config\n",
370438
"hostname: myhost\n",
371-
"preserve_hostname: false\n",
372-
"packages:\n",
373-
"- unattended-upgrades\n",
374-
"- vim-nox\n",
375-
"- python3\n",
376-
"- rsync\n",
377-
"- ubuntu-drivers-common\n",
378-
"- python3-pip\n",
379-
"- ack\n",
380-
"- lsyncd\n",
381-
"- wget\n",
382-
"- bzip2\n",
383-
"- ca-certificates\n",
384-
"- git\n",
385-
"- build-essential\n",
386-
"- software-properties-common\n",
387-
"- curl\n",
388-
"- grep\n",
389-
"- sed\n",
390-
"- dpkg\n",
391-
"- tmux\n",
392-
"- less\n",
393-
"- htop\n",
394-
"- openssh-client\n",
395-
"- python-is-python3\n",
396-
"- python3-dev\n",
397-
"- cron\n",
398-
"- gnupg\n",
399-
"- docker-ce\n",
400-
"- docker-ce-cli\n",
401-
"- containerd.io\n",
402-
"- docker-buildx-plugin\n",
403-
"- docker-compose-plugin\n",
404-
"package_update: true\n",
405-
"package_upgrade: true\n",
406-
"disable_root: true\n",
407-
"ssh_pwauth: false\n",
408-
"users:\n",
409-
"- name: jph\n",
410-
" groups:\n",
411-
" - docker\n",
412-
" - sudo\n",
413-
" shell: /bin/bash\n",
414-
" sudo:\n",
415-
" - ALL=(ALL) NOPASSWD:ALL\n",
416-
" ssh_authorized_keys:\n",
417-
" - mykey\n",
418-
"runcmd:\n",
419-
"- ufw default deny incoming\n",
420-
"- ufw default allow outgoing\n",
421-
"- ufw logging off\n",
422-
"- ufw allow 22/tcp\n",
423-
"- ufw allow in on enp7s0\n",
424-
"- ufw --force enable\n",
425-
"apt:\n",
426-
" conf: 'APT::Periodic::Update-Package-Lists \"1\";\n",
427-
"\n",
428-
" APT::Periodic::Download-Upgradeable-Packages \"1\";\n",
429-
"\n",
430-
" APT::Periodic::AutocleanInterval \"7\";\n",
431-
"\n",
432-
" APT::Periodic::Unattended-Upgrade \"0\";\n",
433-
"\n",
434-
" Unattended-Upgrade::Automatic-Reboot \"false\";\n",
435-
"\n",
436-
" '\n",
437-
" sources:\n",
438-
" docker:\n",
439-
" source: deb [signed-by=$KEY_FILE] https://download.docker.com/linux/ubuntu $RELEASE stable\n",
440-
" keyid: 9DC858229FC7DD38854AE2D88D81803C0EBFCD88\n",
441-
" keyserver: https://download.docker.com/linux/ubuntu/gpg\n",
442-
"write_files:\n",
443-
"- path: /etc/logrotate.d/00-cloud-init-global\n",
444-
" owner: root:root\n",
445-
" permissions: '0644'\n",
446-
" content: \"/var/log/*.log {\\n weekly\\n rotate 7\\n compress\\n su root adm\\n create\\n missingok\\n}\\n\"\n",
447-
"- path: /etc/systemd/system/systemd-journald.service.d/override.conf\n",
448-
" owner: root:root\n",
449-
" permissions: '0644'\n",
450-
" content: '[Journal]\n",
451-
"\n",
452-
" SystemMaxUse=250M\n",
453-
"\n",
454-
" '\n",
455-
"mounts:\n",
456-
"- - mydevice\n",
457-
" - /data\n",
458-
" - ext4\n",
459-
" - defaults,nofail\n",
460-
" - '0'\n",
461-
" - '0'\n",
462-
"phone_home:\n",
463-
" url: https://ping.me\n",
464-
" post:\n",
465-
" - instance_id\n",
466-
" - hostname\n",
467-
" tries: 5\n",
468-
"power_state:\n",
469-
" mode: reboot\n",
470-
" message: Rebooting\n",
471-
" timeout: 1\n",
472-
" condition: true\n",
473-
"\n"
439+
"preserve_hostname: \n"
474440
]
475441
}
476442
],
@@ -486,7 +452,7 @@
486452
"\n",
487453
"res = cloud_init_config('myhost', 'jph', 'mykey', 'j@answer.ai', dropins=dropins, groups=\"docker\", internal=\"enp7s0\",\n",
488454
" devices=devices, ping_host='https://ping.me', packages=packages, docker=dsource)\n",
489-
"print(res)"
455+
"print(res[:50])"
490456
]
491457
},
492458
{

settings.ini

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ keywords = nbdev jupyter notebook python
2828
language = English
2929
status = 3
3030
user = AnswerDotAI
31-
requirements = fastcore PyYAML
31+
requirements = fastcore PyYAML httpx jsonschema
3232
readme_nb = index.ipynb
3333
allowed_metadata_keys =
3434
allowed_cell_metadata_keys =

0 commit comments

Comments
 (0)