Merge lp:~raharper/curtin/trunk.apt-config-validate into lp:~curtin-dev/curtin/trunk

Proposed by Ryan Harper
Status: Work in progress
Proposed branch: lp:~raharper/curtin/trunk.apt-config-validate
Merge into: lp:~curtin-dev/curtin/trunk
Diff against target: 125 lines (+54/-7)
2 files modified
curtin/commands/apt_config.py (+25/-7)
tests/unittests/test_apt_source.py (+29/-0)
To merge this branch: bzr merge lp:~raharper/curtin/trunk.apt-config-validate
Reviewer Review Type Date Requested Status
Server Team CI bot continuous-integration Approve
curtin developers Pending
Review via email: mp+303267@code.launchpad.net

Description of the change

curtin.apt-config: Add some type checking for common input mistakes

The curtin apt-config format requires some specific types. Assert those
types while processing and raise exceptions if found.

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Scott Moser (smoser) wrote :

some comments, generally agree with the idea.

Revision history for this message
Ryan Harper (raharper) wrote :
Download full text (5.7 KiB)

On Thu, Aug 18, 2016 at 9:18 AM, Scott Moser <email address hidden> wrote:

> some comments, generally agree with the idea.
>
> Diff comments:
>
> > === modified file 'curtin/commands/apt_config.py'
> > --- curtin/commands/apt_config.py 2016-08-04 16:53:56 +0000
> > +++ curtin/commands/apt_config.py 2016-08-18 13:48:54 +0000
> > @@ -457,14 +459,21 @@
> > """out of a list of potential mirror configurations select
> > and return the one matching the architecture (or default)"""
> > # select the mirror specification (if-any)
> > - mirror_cfg_list = cfg.get(mirrortype, None)
> > - if mirror_cfg_list is None:
> > - return None
> > + mirror_cfg_list = cfg.get(mirrortype, [])
> > + if not isinstance(mirror_cfg_list, list):
> > + raise ValueError(
> > + ('apt[\'%s\'] mirror value must be a list' % mirrortype))
> >
> > # select the specification matching the target arch
> > default = None
> > for mirror_cfg_elem in mirror_cfg_list:
> > - arches = mirror_cfg_elem.get("arches")
> > + if not isinstance(mirror_cfg_elem, dict):
> > + LOG.debug('Skipping invalid mirror element: %s',
> mirror_cfg_elem)
>
> why do we raise ValueError if arches is not a list below, but just log
> debug here? Ie, why is one invalid thing a debug log and the other a
> valueerror.
>

it should raise as well.

>
> > + continue
> > + arches = mirror_cfg_elem.get("arches", {})
> > + if not isinstance(arches, list):
> > + raise ValueError(
> > + ("apt mirror 'arches' value must be a list: [%s]" %
> arches))
> > if arch in arches:
> > return mirror_cfg_elem
> > if "default" in arches:
> > @@ -488,6 +497,10 @@
> > # list of mirrors to try to resolve
> > mirror = search_for_mirror(mcfg.get("search", None))
> >
> > + if not isinstance(mirror, str):
> > + raise ValueError("apt mirror 'uri' value must be a string:
> [%s]" %
>
> this i think fits on one line.
>

OK

>
> > + mirror)
> > +
> > return mirror
> >
> >
> > @@ -564,8 +582,8 @@
> > apt_cfg = cfg.get("apt")
> > # if no apt config section is available, do nothing
> > if apt_cfg is not None:
> > - LOG.debug("Handling apt to target %s with config %s",
> > - target, apt_cfg)
> > + LOG.info("Configuring apt in target %s with config %s",
>
> you can probably join this line break and be < 80 chars.
>

OK

>
> > + target, apt_cfg)
> > try:
> > with util.ChrootableTarget(target, sys_resolvconf=True):
> > handle_apt(apt_cfg, target)
> >
> > === modified file 'tests/unittests/test_apt_source.py'
> > --- tests/unittests/test_apt_source.py 2016-08-05 23:32:42 +0000
> > +++ tests/unittests/test_apt_source.py 2016-08-18 13:48:54 +0000
> > @@ -569,6 +569,29 @@
> > self.assertEqual(mirrors['SECURITY'],
> > smir)
> >
> > + def test_mirror_not_list(self):
> > + """test_mirror_not_list - Test for exception on invalid mirror
> cfg"""
> > + pmir = "htt...

Read more...

Revision history for this message
Scott Moser (smoser) wrote :

one other comment

Revision history for this message
Ryan Harper (raharper) wrote :

Currently when you run curtin apt-config, you see *nothing*. I don't think
that's right.

w.r.t the output format, I'm happy to change the message (and demote the
dict dump to debug).

On Thu, Aug 18, 2016 at 10:00 AM, Scott Moser <email address hidden> wrote:

> one other comment
>
> Diff comments:
>
> > === modified file 'curtin/commands/apt_config.py'
> > --- curtin/commands/apt_config.py 2016-08-04 16:53:56 +0000
> > +++ curtin/commands/apt_config.py 2016-08-18 13:48:54 +0000
> > @@ -564,8 +582,8 @@
> > apt_cfg = cfg.get("apt")
> > # if no apt config section is available, do nothing
> > if apt_cfg is not None:
> > - LOG.debug("Handling apt to target %s with config %s",
> > - target, apt_cfg)
> > + LOG.info("Configuring apt in target %s with config %s",
>
> other thing... LOG.info seems loud to me for something that is going to
> dump a string representation of a large dictionary.
> we dont have really good policy in place at all anywhere, but "info" to me
> seems like something that is reasonably shown to a user, and string
> formated dictionaries dumped to users dont' seem reasonable to me.
>
> this is why i almost always use DEBUG.
>
> > + target, apt_cfg)
> > try:
> > with util.ChrootableTarget(target, sys_resolvconf=True):
> > handle_apt(apt_cfg, target)
>
>
> --
> https://code.launchpad.net/~raharper/curtin/trunk.apt-
> config-validate/+merge/303267
> You are the owner of lp:~raharper/curtin/trunk.apt-config-validate.
>

Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)
Revision history for this message
Server Team CI bot (server-team-bot) wrote :
review: Approve (continuous-integration)

Unmerged revisions

419. By Ryan Harper

fix formatting

418. By Ryan Harper

curtin.apt_config: configure log for subcommand usage

417. By Ryan Harper

curtin.apt-config: Add some type checking for common input mistakes

The curtin apt-config format requires some specific types. Assert those
types while processing and raise exceptions if found.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'curtin/commands/apt_config.py'
2--- curtin/commands/apt_config.py 2016-08-04 16:53:56 +0000
3+++ curtin/commands/apt_config.py 2016-08-18 13:48:54 +0000
4@@ -26,11 +26,13 @@
5 import sys
6 import yaml
7
8-from curtin.log import LOG
9+from .. import log
10 from curtin import (config, util, gpg)
11
12 from . import populate_one_subcmd
13
14+LOG = log.LOG
15+
16 # this will match 'XXX:YYY' (ie, 'cloud-archive:foo' or 'ppa:bar')
17 ADD_APT_REPO_MATCH = r"^[\w-]+:\w"
18
19@@ -457,14 +459,21 @@
20 """out of a list of potential mirror configurations select
21 and return the one matching the architecture (or default)"""
22 # select the mirror specification (if-any)
23- mirror_cfg_list = cfg.get(mirrortype, None)
24- if mirror_cfg_list is None:
25- return None
26+ mirror_cfg_list = cfg.get(mirrortype, [])
27+ if not isinstance(mirror_cfg_list, list):
28+ raise ValueError(
29+ ('apt[\'%s\'] mirror value must be a list' % mirrortype))
30
31 # select the specification matching the target arch
32 default = None
33 for mirror_cfg_elem in mirror_cfg_list:
34- arches = mirror_cfg_elem.get("arches")
35+ if not isinstance(mirror_cfg_elem, dict):
36+ LOG.debug('Skipping invalid mirror element: %s', mirror_cfg_elem)
37+ continue
38+ arches = mirror_cfg_elem.get("arches", {})
39+ if not isinstance(arches, list):
40+ raise ValueError(
41+ ("apt mirror 'arches' value must be a list: [%s]" % arches))
42 if arch in arches:
43 return mirror_cfg_elem
44 if "default" in arches:
45@@ -488,6 +497,10 @@
46 # list of mirrors to try to resolve
47 mirror = search_for_mirror(mcfg.get("search", None))
48
49+ if not isinstance(mirror, str):
50+ raise ValueError("apt mirror 'uri' value must be a string: [%s]" %
51+ mirror)
52+
53 return mirror
54
55
56@@ -550,6 +563,11 @@
57 """
58 cfg = config.load_command_config(args, {})
59
60+ log.basicConfig(stream=args.log_file, verbosity=1)
61+
62+ if not isinstance(cfg, dict):
63+ raise TypeError("apt config is not a dict.")
64+
65 if args.target is not None:
66 target = args.target
67 else:
68@@ -564,8 +582,8 @@
69 apt_cfg = cfg.get("apt")
70 # if no apt config section is available, do nothing
71 if apt_cfg is not None:
72- LOG.debug("Handling apt to target %s with config %s",
73- target, apt_cfg)
74+ LOG.info("Configuring apt in target %s with config %s",
75+ target, apt_cfg)
76 try:
77 with util.ChrootableTarget(target, sys_resolvconf=True):
78 handle_apt(apt_cfg, target)
79
80=== modified file 'tests/unittests/test_apt_source.py'
81--- tests/unittests/test_apt_source.py 2016-08-05 23:32:42 +0000
82+++ tests/unittests/test_apt_source.py 2016-08-18 13:48:54 +0000
83@@ -569,6 +569,29 @@
84 self.assertEqual(mirrors['SECURITY'],
85 smir)
86
87+ def test_mirror_not_list(self):
88+ """test_mirror_not_list - Test for exception on invalid mirror cfg"""
89+ pmir = "http://us.archive.ubuntu.com/ubuntu/"
90+ smir = "http://security.ubuntu.com/ubuntu/"
91+ cfg_not_list = {"primary": {"arches": ["default"],
92+ "uri": pmir},
93+ "security": {"arches": ["default"],
94+ "uri": smir}}
95+
96+ with self.assertRaises(ValueError):
97+ apt_config.find_apt_mirror_info(cfg_not_list, 'amd64')
98+
99+ def test_mirror_not_list_of_dicts(self):
100+ """test_mirror_arches_type - Test for exception on invld mirror cfg"""
101+ pmir = "http://us.archive.ubuntu.com/ubuntu/"
102+ smir = "http://security.ubuntu.com/ubuntu/"
103+ cfg_not_list = {"primary": [{"arches": "default",
104+ "uri": pmir}],
105+ "security": {"arches": "default",
106+ "uri": smir}}
107+ with self.assertRaises(ValueError):
108+ apt_config.find_apt_mirror_info(cfg_not_list, 'amd64')
109+
110 def test_mirror_default(self):
111 """test_mirror_default - Test without defining a mirror"""
112 arch = util.get_architecture()
113@@ -584,6 +607,12 @@
114 self.assertEqual(mirrors['SECURITY'],
115 smir)
116
117+ def test_mirror_uri_not_none_not_string(self):
118+ cfg = {"primary": [{"arches": "default", "uri": {'foobar': 1}}],
119+ "security": {"arches": "default", "uri": ["None"]}}
120+ with self.assertRaises(ValueError):
121+ apt_config.get_mirror(cfg, "primary", 'amd64')
122+
123 def test_mirror_arches(self):
124 """test_mirror_arches - Test arches selection of mirror"""
125 pmir = "http://my-primary.ubuntu.com/ubuntu/"

Subscribers

People subscribed via source and target branches