Merge ~chad.smith/cloud-init:bug/drop-deprecated-snap-modules into cloud-init:master
- Git
- lp:~chad.smith/cloud-init
- bug/drop-deprecated-snap-modules
- Merge into master
Status: | Rejected |
---|---|
Rejected by: | Chad Smith |
Proposed branch: | ~chad.smith/cloud-init:bug/drop-deprecated-snap-modules |
Merge into: | cloud-init:master |
Diff against target: |
1201 lines (+0/-609) 3 files modified
dev/null (+0/-601) doc/rtd/topics/modules.rst (+0/-2) tests/cloud_tests/testcases/modules/TODO.md (+0/-6) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ryan Harper | Needs Information | ||
Server Team CI bot | continuous-integration | Needs Fixing | |
Review via email: mp+362691@code.launchpad.net |
Commit message
snap_config/snappy: Drop deprecated cloud-config modules
Both snap_config and snappy modules have been deprecated in 18.3.
We should have dropped deprecated modules in that timeframe as the
functionality is replaced by the snap module and a commands element.
Cloud-config that used to provided snappy assertions and configuration
can now instead use the top-level snap: and assertions or commands.
Detailed docs here:
https:/
LP: #1814296
Description of the change
Server Team CI bot (server-team-bot) wrote : | # |
Ryan Harper (raharper) wrote : | # |
Hrm, what should we do on upgrade?
Chad Smith (chad.smith) wrote : | # |
Unmerged commits
- a2d9c10... by Chad Smith
-
snap_config/snappy: Drop deprecated cloud-config modules
Both snap_config and snappy modules have been deprecated in 18.3.
We should have dropped deprecated modules in that timeframe as the
functionality is replaced by the snap module and a commands element.Cloud-config that used to provided snappy assertions and configuration
can now instead use the top-level snap: and assertions or commands.Detailed docs here:
https://cloudinit. readthedocs. io/en/latest/ topics/ modules. html#snap LP: #1814296
Preview Diff
1 | diff --git a/cloudinit/config/cc_snap_config.py b/cloudinit/config/cc_snap_config.py |
2 | deleted file mode 100644 |
3 | index afe297e..0000000 |
4 | --- a/cloudinit/config/cc_snap_config.py |
5 | +++ /dev/null |
6 | @@ -1,184 +0,0 @@ |
7 | -# Copyright (C) 2016 Canonical Ltd. |
8 | -# |
9 | -# Author: Ryan Harper <ryan.harper@canonical.com> |
10 | -# |
11 | -# This file is part of cloud-init. See LICENSE file for license information. |
12 | - |
13 | -# RELEASE_BLOCKER: Remove this deprecated module in 18.3 |
14 | -""" |
15 | -Snap Config |
16 | ------------ |
17 | -**Summary:** snap_config modules allows configuration of snapd. |
18 | - |
19 | -**Deprecated**: Use :ref:`snap` module instead. This module will not exist |
20 | -in cloud-init 18.3. |
21 | - |
22 | -This module uses the same ``snappy`` namespace for configuration but |
23 | -acts only only a subset of the configuration. |
24 | - |
25 | -If ``assertions`` is set and the user has included a list of assertions |
26 | -then cloud-init will collect the assertions into a single assertion file |
27 | -and invoke ``snap ack <path to file with assertions>`` which will attempt |
28 | -to load the provided assertions into the snapd assertion database. |
29 | - |
30 | -If ``email`` is set, this value is used to create an authorized user for |
31 | -contacting and installing snaps from the Ubuntu Store. This is done by |
32 | -calling ``snap create-user`` command. |
33 | - |
34 | -If ``known`` is set to True, then it is expected the user also included |
35 | -an assertion of type ``system-user``. When ``snap create-user`` is called |
36 | -cloud-init will append '--known' flag which instructs snapd to look for |
37 | -a system-user assertion with the details. If ``known`` is not set, then |
38 | -``snap create-user`` will contact the Ubuntu SSO for validating and importing |
39 | -a system-user for the instance. |
40 | - |
41 | -.. note:: |
42 | - If the system is already managed, then cloud-init will not attempt to |
43 | - create a system-user. |
44 | - |
45 | -**Internal name:** ``cc_snap_config`` |
46 | - |
47 | -**Module frequency:** per instance |
48 | - |
49 | -**Supported distros:** any with 'snapd' available |
50 | - |
51 | -**Config keys**:: |
52 | - |
53 | - #cloud-config |
54 | - snappy: |
55 | - assertions: |
56 | - - | |
57 | - <assertion 1> |
58 | - - | |
59 | - <assertion 2> |
60 | - email: user@user.org |
61 | - known: true |
62 | - |
63 | -""" |
64 | - |
65 | -from cloudinit import log as logging |
66 | -from cloudinit.settings import PER_INSTANCE |
67 | -from cloudinit import util |
68 | - |
69 | -LOG = logging.getLogger(__name__) |
70 | - |
71 | -frequency = PER_INSTANCE |
72 | -SNAPPY_CMD = "snap" |
73 | -ASSERTIONS_FILE = "/var/lib/cloud/instance/snapd.assertions" |
74 | - |
75 | - |
76 | -""" |
77 | -snappy: |
78 | - assertions: |
79 | - - | |
80 | - <snap assertion 1> |
81 | - - | |
82 | - <snap assertion 2> |
83 | - email: foo@foo.io |
84 | - known: true |
85 | -""" |
86 | - |
87 | - |
88 | -def add_assertions(assertions=None): |
89 | - """Import list of assertions. |
90 | - |
91 | - Import assertions by concatenating each assertion into a |
92 | - string separated by a '\n'. Write this string to a instance file and |
93 | - then invoke `snap ack /path/to/file` and check for errors. |
94 | - If snap exits 0, then all assertions are imported. |
95 | - """ |
96 | - if not assertions: |
97 | - assertions = [] |
98 | - |
99 | - if not isinstance(assertions, list): |
100 | - raise ValueError( |
101 | - 'assertion parameter was not a list: {assertions}'.format( |
102 | - assertions=assertions)) |
103 | - |
104 | - snap_cmd = [SNAPPY_CMD, 'ack'] |
105 | - combined = "\n".join(assertions) |
106 | - if len(combined) == 0: |
107 | - raise ValueError("Assertion list is empty") |
108 | - |
109 | - for asrt in assertions: |
110 | - LOG.debug('Acking: %s', asrt.split('\n')[0:2]) |
111 | - |
112 | - util.write_file(ASSERTIONS_FILE, combined.encode('utf-8')) |
113 | - util.subp(snap_cmd + [ASSERTIONS_FILE], capture=True) |
114 | - |
115 | - |
116 | -def add_snap_user(cfg=None): |
117 | - """Add a snap system-user if provided with email under snappy config. |
118 | - |
119 | - - Check that system is not already managed. |
120 | - - Check that if using a system-user assertion, that it's |
121 | - imported into snapd. |
122 | - |
123 | - Returns a dictionary to be passed to Distro.create_user |
124 | - """ |
125 | - |
126 | - if not cfg: |
127 | - cfg = {} |
128 | - |
129 | - if not isinstance(cfg, dict): |
130 | - raise ValueError( |
131 | - 'configuration parameter was not a dict: {cfg}'.format(cfg=cfg)) |
132 | - |
133 | - snapuser = cfg.get('email', None) |
134 | - if not snapuser: |
135 | - return |
136 | - |
137 | - usercfg = { |
138 | - 'snapuser': snapuser, |
139 | - 'known': cfg.get('known', False), |
140 | - } |
141 | - |
142 | - # query if we're already registered |
143 | - out, _ = util.subp([SNAPPY_CMD, 'managed'], capture=True) |
144 | - if out.strip() == "true": |
145 | - LOG.warning('This device is already managed. ' |
146 | - 'Skipping system-user creation') |
147 | - return |
148 | - |
149 | - if usercfg.get('known'): |
150 | - # Check that we imported a system-user assertion |
151 | - out, _ = util.subp([SNAPPY_CMD, 'known', 'system-user'], |
152 | - capture=True) |
153 | - if len(out) == 0: |
154 | - LOG.error('Missing "system-user" assertion. ' |
155 | - 'Check "snappy" user-data assertions.') |
156 | - return |
157 | - |
158 | - return usercfg |
159 | - |
160 | - |
161 | -def handle(name, cfg, cloud, log, args): |
162 | - cfgin = cfg.get('snappy') |
163 | - if not cfgin: |
164 | - LOG.debug('No snappy config provided, skipping') |
165 | - return |
166 | - |
167 | - log.warning( |
168 | - 'DEPRECATION: snap_config module will be dropped in 18.3 release.' |
169 | - ' Use snap module instead') |
170 | - if not(util.system_is_snappy()): |
171 | - LOG.debug("%s: system not snappy", name) |
172 | - return |
173 | - |
174 | - assertions = cfgin.get('assertions', []) |
175 | - if len(assertions) > 0: |
176 | - LOG.debug('Importing user-provided snap assertions') |
177 | - add_assertions(assertions) |
178 | - |
179 | - # Create a snap user if requested. |
180 | - # Snap systems contact the store with a user's email |
181 | - # and extract information needed to create a local user. |
182 | - # A user may provide a 'system-user' assertion which includes |
183 | - # the required information. Using such an assertion to create |
184 | - # a local user requires specifying 'known: true' in the supplied |
185 | - # user-data. |
186 | - usercfg = add_snap_user(cfg=cfgin) |
187 | - if usercfg: |
188 | - cloud.distro.create_user(usercfg.get('snapuser'), **usercfg) |
189 | - |
190 | -# vi: ts=4 expandtab |
191 | diff --git a/cloudinit/config/cc_snappy.py b/cloudinit/config/cc_snappy.py |
192 | deleted file mode 100644 |
193 | index 15bee2d..0000000 |
194 | --- a/cloudinit/config/cc_snappy.py |
195 | +++ /dev/null |
196 | @@ -1,321 +0,0 @@ |
197 | -# This file is part of cloud-init. See LICENSE file for license information. |
198 | - |
199 | -# RELEASE_BLOCKER: Remove this deprecated module in 18.3 |
200 | -""" |
201 | -Snappy |
202 | ------- |
203 | -**Summary:** snappy modules allows configuration of snappy. |
204 | - |
205 | -**Deprecated**: Use :ref:`snap` module instead. This module will not exist |
206 | -in cloud-init 18.3. |
207 | - |
208 | -The below example config config would install ``etcd``, and then install |
209 | -``pkg2.smoser`` with a ``<config-file>`` argument where ``config-file`` has |
210 | -``config-blob`` inside it. If ``pkgname`` is installed already, then |
211 | -``snappy config pkgname <file>`` |
212 | -will be called where ``file`` has ``pkgname-config-blob`` as its content. |
213 | - |
214 | -Entries in ``config`` can be namespaced or non-namespaced for a package. |
215 | -In either case, the config provided to snappy command is non-namespaced. |
216 | -The package name is provided as it appears. |
217 | - |
218 | -If ``packages_dir`` has files in it that end in ``.snap``, then they are |
219 | -installed. Given 3 files: |
220 | - |
221 | - - <packages_dir>/foo.snap |
222 | - - <packages_dir>/foo.config |
223 | - - <packages_dir>/bar.snap |
224 | - |
225 | -cloud-init will invoke: |
226 | - |
227 | - - snappy install <packages_dir>/foo.snap <packages_dir>/foo.config |
228 | - - snappy install <packages_dir>/bar.snap |
229 | - |
230 | -.. note:: |
231 | - that if provided a ``config`` entry for ``ubuntu-core``, then |
232 | - cloud-init will invoke: snappy config ubuntu-core <config> |
233 | - Allowing you to configure ubuntu-core in this way. |
234 | - |
235 | -The ``ssh_enabled`` key controls the system's ssh service. The default value |
236 | -is ``auto``. Options are: |
237 | - |
238 | - - **True:** enable ssh service |
239 | - - **False:** disable ssh service |
240 | - - **auto:** enable ssh service if either ssh keys have been provided |
241 | - or user has requested password authentication (ssh_pwauth). |
242 | - |
243 | -**Internal name:** ``cc_snappy`` |
244 | - |
245 | -**Module frequency:** per instance |
246 | - |
247 | -**Supported distros:** ubuntu |
248 | - |
249 | -**Config keys**:: |
250 | - |
251 | - #cloud-config |
252 | - snappy: |
253 | - system_snappy: auto |
254 | - ssh_enabled: auto |
255 | - packages: [etcd, pkg2.smoser] |
256 | - config: |
257 | - pkgname: |
258 | - key2: value2 |
259 | - pkg2: |
260 | - key1: value1 |
261 | - packages_dir: '/writable/user-data/cloud-init/snaps' |
262 | -""" |
263 | - |
264 | -from cloudinit import log as logging |
265 | -from cloudinit.settings import PER_INSTANCE |
266 | -from cloudinit import temp_utils |
267 | -from cloudinit import util |
268 | - |
269 | -import glob |
270 | -import os |
271 | - |
272 | -LOG = logging.getLogger(__name__) |
273 | - |
274 | -frequency = PER_INSTANCE |
275 | -SNAPPY_CMD = "snappy" |
276 | -NAMESPACE_DELIM = '.' |
277 | - |
278 | -BUILTIN_CFG = { |
279 | - 'packages': [], |
280 | - 'packages_dir': '/writable/user-data/cloud-init/snaps', |
281 | - 'ssh_enabled': "auto", |
282 | - 'system_snappy': "auto", |
283 | - 'config': {}, |
284 | -} |
285 | - |
286 | -distros = ['ubuntu'] |
287 | - |
288 | - |
289 | -def parse_filename(fname): |
290 | - fname = os.path.basename(fname) |
291 | - fname_noext = fname.rpartition(".")[0] |
292 | - name = fname_noext.partition("_")[0] |
293 | - shortname = name.partition(".")[0] |
294 | - return(name, shortname, fname_noext) |
295 | - |
296 | - |
297 | -def get_fs_package_ops(fspath): |
298 | - if not fspath: |
299 | - return [] |
300 | - ops = [] |
301 | - for snapfile in sorted(glob.glob(os.path.sep.join([fspath, '*.snap']))): |
302 | - (name, shortname, fname_noext) = parse_filename(snapfile) |
303 | - cfg = None |
304 | - for cand in (fname_noext, name, shortname): |
305 | - fpcand = os.path.sep.join([fspath, cand]) + ".config" |
306 | - if os.path.isfile(fpcand): |
307 | - cfg = fpcand |
308 | - break |
309 | - ops.append(makeop('install', name, config=None, |
310 | - path=snapfile, cfgfile=cfg)) |
311 | - return ops |
312 | - |
313 | - |
314 | -def makeop(op, name, config=None, path=None, cfgfile=None): |
315 | - return({'op': op, 'name': name, 'config': config, 'path': path, |
316 | - 'cfgfile': cfgfile}) |
317 | - |
318 | - |
319 | -def get_package_config(configs, name): |
320 | - # load the package's config from the configs dict. |
321 | - # prefer full-name entry (config-example.canonical) |
322 | - # over short name entry (config-example) |
323 | - if name in configs: |
324 | - return configs[name] |
325 | - return configs.get(name.partition(NAMESPACE_DELIM)[0]) |
326 | - |
327 | - |
328 | -def get_package_ops(packages, configs, installed=None, fspath=None): |
329 | - # get the install an config operations that should be done |
330 | - if installed is None: |
331 | - installed = read_installed_packages() |
332 | - short_installed = [p.partition(NAMESPACE_DELIM)[0] for p in installed] |
333 | - |
334 | - if not packages: |
335 | - packages = [] |
336 | - if not configs: |
337 | - configs = {} |
338 | - |
339 | - ops = [] |
340 | - ops += get_fs_package_ops(fspath) |
341 | - |
342 | - for name in packages: |
343 | - ops.append(makeop('install', name, get_package_config(configs, name))) |
344 | - |
345 | - to_install = [f['name'] for f in ops] |
346 | - short_to_install = [f['name'].partition(NAMESPACE_DELIM)[0] for f in ops] |
347 | - |
348 | - for name in configs: |
349 | - if name in to_install: |
350 | - continue |
351 | - shortname = name.partition(NAMESPACE_DELIM)[0] |
352 | - if shortname in short_to_install: |
353 | - continue |
354 | - if name in installed or shortname in short_installed: |
355 | - ops.append(makeop('config', name, |
356 | - config=get_package_config(configs, name))) |
357 | - |
358 | - # prefer config entries to filepath entries |
359 | - for op in ops: |
360 | - if op['op'] != 'install' or not op['cfgfile']: |
361 | - continue |
362 | - name = op['name'] |
363 | - fromcfg = get_package_config(configs, op['name']) |
364 | - if fromcfg: |
365 | - LOG.debug("preferring configs[%(name)s] over '%(cfgfile)s'", op) |
366 | - op['cfgfile'] = None |
367 | - op['config'] = fromcfg |
368 | - |
369 | - return ops |
370 | - |
371 | - |
372 | -def render_snap_op(op, name, path=None, cfgfile=None, config=None): |
373 | - if op not in ('install', 'config'): |
374 | - raise ValueError("cannot render op '%s'" % op) |
375 | - |
376 | - shortname = name.partition(NAMESPACE_DELIM)[0] |
377 | - try: |
378 | - cfg_tmpf = None |
379 | - if config is not None: |
380 | - # input to 'snappy config packagename' must have nested data. odd. |
381 | - # config: |
382 | - # packagename: |
383 | - # config |
384 | - # Note, however, we do not touch config files on disk. |
385 | - nested_cfg = {'config': {shortname: config}} |
386 | - (fd, cfg_tmpf) = temp_utils.mkstemp() |
387 | - os.write(fd, util.yaml_dumps(nested_cfg).encode()) |
388 | - os.close(fd) |
389 | - cfgfile = cfg_tmpf |
390 | - |
391 | - cmd = [SNAPPY_CMD, op] |
392 | - if op == 'install': |
393 | - if path: |
394 | - cmd.append("--allow-unauthenticated") |
395 | - cmd.append(path) |
396 | - else: |
397 | - cmd.append(name) |
398 | - if cfgfile: |
399 | - cmd.append(cfgfile) |
400 | - elif op == 'config': |
401 | - cmd += [name, cfgfile] |
402 | - |
403 | - util.subp(cmd) |
404 | - |
405 | - finally: |
406 | - if cfg_tmpf: |
407 | - os.unlink(cfg_tmpf) |
408 | - |
409 | - |
410 | -def read_installed_packages(): |
411 | - ret = [] |
412 | - for (name, _date, _version, dev) in read_pkg_data(): |
413 | - if dev: |
414 | - ret.append(NAMESPACE_DELIM.join([name, dev])) |
415 | - else: |
416 | - ret.append(name) |
417 | - return ret |
418 | - |
419 | - |
420 | -def read_pkg_data(): |
421 | - out, _err = util.subp([SNAPPY_CMD, "list"]) |
422 | - pkg_data = [] |
423 | - for line in out.splitlines()[1:]: |
424 | - toks = line.split(sep=None, maxsplit=3) |
425 | - if len(toks) == 3: |
426 | - (name, date, version) = toks |
427 | - dev = None |
428 | - else: |
429 | - (name, date, version, dev) = toks |
430 | - pkg_data.append((name, date, version, dev,)) |
431 | - return pkg_data |
432 | - |
433 | - |
434 | -def disable_enable_ssh(enabled): |
435 | - LOG.debug("setting enablement of ssh to: %s", enabled) |
436 | - # do something here that would enable or disable |
437 | - not_to_be_run = "/etc/ssh/sshd_not_to_be_run" |
438 | - if enabled: |
439 | - util.del_file(not_to_be_run) |
440 | - # this is an indempotent operation |
441 | - util.subp(["systemctl", "start", "ssh"]) |
442 | - else: |
443 | - # this is an indempotent operation |
444 | - util.subp(["systemctl", "stop", "ssh"]) |
445 | - util.write_file(not_to_be_run, "cloud-init\n") |
446 | - |
447 | - |
448 | -def set_snappy_command(): |
449 | - global SNAPPY_CMD |
450 | - if util.which("snappy-go"): |
451 | - SNAPPY_CMD = "snappy-go" |
452 | - elif util.which("snappy"): |
453 | - SNAPPY_CMD = "snappy" |
454 | - else: |
455 | - SNAPPY_CMD = "snap" |
456 | - LOG.debug("snappy command is '%s'", SNAPPY_CMD) |
457 | - |
458 | - |
459 | -def handle(name, cfg, cloud, log, args): |
460 | - cfgin = cfg.get('snappy') |
461 | - if not cfgin: |
462 | - cfgin = {} |
463 | - mycfg = util.mergemanydict([cfgin, BUILTIN_CFG]) |
464 | - |
465 | - sys_snappy = str(mycfg.get("system_snappy", "auto")) |
466 | - if util.is_false(sys_snappy): |
467 | - LOG.debug("%s: System is not snappy. disabling", name) |
468 | - return |
469 | - |
470 | - if sys_snappy.lower() == "auto" and not(util.system_is_snappy()): |
471 | - LOG.debug("%s: 'auto' mode, and system not snappy", name) |
472 | - return |
473 | - |
474 | - log.warning( |
475 | - 'DEPRECATION: snappy module will be dropped in 18.3 release.' |
476 | - ' Use snap module instead') |
477 | - |
478 | - set_snappy_command() |
479 | - |
480 | - pkg_ops = get_package_ops(packages=mycfg['packages'], |
481 | - configs=mycfg['config'], |
482 | - fspath=mycfg['packages_dir']) |
483 | - |
484 | - fails = [] |
485 | - for pkg_op in pkg_ops: |
486 | - try: |
487 | - render_snap_op(**pkg_op) |
488 | - except Exception as e: |
489 | - fails.append((pkg_op, e,)) |
490 | - LOG.warning("'%s' failed for '%s': %s", |
491 | - pkg_op['op'], pkg_op['name'], e) |
492 | - |
493 | - # Default to disabling SSH |
494 | - ssh_enabled = mycfg.get('ssh_enabled', "auto") |
495 | - |
496 | - # If the user has not explicitly enabled or disabled SSH, then enable it |
497 | - # when password SSH authentication is requested or there are SSH keys |
498 | - if ssh_enabled == "auto": |
499 | - user_ssh_keys = cloud.get_public_ssh_keys() or None |
500 | - password_auth_enabled = cfg.get('ssh_pwauth', False) |
501 | - if user_ssh_keys: |
502 | - LOG.debug("Enabling SSH, ssh keys found in datasource") |
503 | - ssh_enabled = True |
504 | - elif cfg.get('ssh_authorized_keys'): |
505 | - LOG.debug("Enabling SSH, ssh keys found in config") |
506 | - elif password_auth_enabled: |
507 | - LOG.debug("Enabling SSH, password authentication requested") |
508 | - ssh_enabled = True |
509 | - elif ssh_enabled not in (True, False): |
510 | - LOG.warning("Unknown value '%s' in ssh_enabled", ssh_enabled) |
511 | - |
512 | - disable_enable_ssh(ssh_enabled) |
513 | - |
514 | - if fails: |
515 | - raise Exception("failed to install/configure snaps") |
516 | - |
517 | -# vi: ts=4 expandtab |
518 | diff --git a/doc/rtd/topics/modules.rst b/doc/rtd/topics/modules.rst |
519 | index d9720f6..d4dce24 100644 |
520 | --- a/doc/rtd/topics/modules.rst |
521 | +++ b/doc/rtd/topics/modules.rst |
522 | @@ -46,8 +46,6 @@ Modules |
523 | .. automodule:: cloudinit.config.cc_set_hostname |
524 | .. automodule:: cloudinit.config.cc_set_passwords |
525 | .. automodule:: cloudinit.config.cc_snap |
526 | -.. automodule:: cloudinit.config.cc_snappy |
527 | -.. automodule:: cloudinit.config.cc_snap_config |
528 | .. automodule:: cloudinit.config.cc_spacewalk |
529 | .. automodule:: cloudinit.config.cc_ssh |
530 | .. automodule:: cloudinit.config.cc_ssh_authkey_fingerprints |
531 | diff --git a/tests/cloud_tests/testcases/modules/TODO.md b/tests/cloud_tests/testcases/modules/TODO.md |
532 | index 0b933b3..2a63609 100644 |
533 | --- a/tests/cloud_tests/testcases/modules/TODO.md |
534 | +++ b/tests/cloud_tests/testcases/modules/TODO.md |
535 | @@ -78,12 +78,6 @@ Not applicable to write a test for this as it specifies when something should be |
536 | ## scripts vendor |
537 | Not applicable to write a test for this as it specifies when something should be run. |
538 | |
539 | -## snappy |
540 | -2016-11-17: Need test to install snaps from store |
541 | - |
542 | -## snap-config |
543 | -2016-11-17: Need to investigate |
544 | - |
545 | ## spacewalk |
546 | |
547 | ## ssh authkey fingerprints |
548 | diff --git a/tests/cloud_tests/testcases/modules/snappy.py b/tests/cloud_tests/testcases/modules/snappy.py |
549 | deleted file mode 100644 |
550 | index 7d17fc5..0000000 |
551 | --- a/tests/cloud_tests/testcases/modules/snappy.py |
552 | +++ /dev/null |
553 | @@ -1,17 +0,0 @@ |
554 | -# This file is part of cloud-init. See LICENSE file for license information. |
555 | - |
556 | -"""cloud-init Integration Test Verify Script""" |
557 | -from tests.cloud_tests.testcases import base |
558 | - |
559 | - |
560 | -class TestSnappy(base.CloudTestCase): |
561 | - """Test snappy module""" |
562 | - |
563 | - expected_warnings = ('DEPRECATION',) |
564 | - |
565 | - def test_snappy_version(self): |
566 | - """Test snappy version output""" |
567 | - out = self.get_data_file('snapd') |
568 | - self.assertIn('Status: install ok installed', out) |
569 | - |
570 | -# vi: ts=4 expandtab |
571 | diff --git a/tests/cloud_tests/testcases/modules/snappy.yaml b/tests/cloud_tests/testcases/modules/snappy.yaml |
572 | deleted file mode 100644 |
573 | index 8ac322a..0000000 |
574 | --- a/tests/cloud_tests/testcases/modules/snappy.yaml |
575 | +++ /dev/null |
576 | @@ -1,18 +0,0 @@ |
577 | -# |
578 | -# Install snappy |
579 | -# |
580 | -# Aug 17, 2018: Disabled due to requiring a proxy for testing |
581 | -# tests do not handle the proxy well at this time. |
582 | -enabled: False |
583 | -required_features: |
584 | - - snap |
585 | -cloud_config: | |
586 | - #cloud-config |
587 | - snappy: |
588 | - system_snappy: auto |
589 | -collect_scripts: |
590 | - snapd: | |
591 | - #!/bin/bash |
592 | - dpkg -s snapd |
593 | - |
594 | -# vi: ts=4 expandtab |
595 | diff --git a/tests/unittests/test_handler/test_handler_snappy.py b/tests/unittests/test_handler/test_handler_snappy.py |
596 | deleted file mode 100644 |
597 | index 76b79c2..0000000 |
598 | --- a/tests/unittests/test_handler/test_handler_snappy.py |
599 | +++ /dev/null |
600 | @@ -1,601 +0,0 @@ |
601 | -# This file is part of cloud-init. See LICENSE file for license information. |
602 | - |
603 | -from cloudinit.config.cc_snappy import ( |
604 | - makeop, get_package_ops, render_snap_op) |
605 | -from cloudinit.config.cc_snap_config import ( |
606 | - add_assertions, add_snap_user, ASSERTIONS_FILE) |
607 | -from cloudinit import (distros, helpers, cloud, util) |
608 | -from cloudinit.config.cc_snap_config import handle as snap_handle |
609 | -from cloudinit.sources import DataSourceNone |
610 | -from cloudinit.tests.helpers import FilesystemMockingTestCase, mock |
611 | - |
612 | -from cloudinit.tests import helpers as t_help |
613 | - |
614 | -import logging |
615 | -import os |
616 | -import shutil |
617 | -import tempfile |
618 | -import textwrap |
619 | -import yaml |
620 | - |
621 | -LOG = logging.getLogger(__name__) |
622 | -ALLOWED = (dict, list, int, str) |
623 | - |
624 | - |
625 | -class TestInstallPackages(t_help.TestCase): |
626 | - def setUp(self): |
627 | - super(TestInstallPackages, self).setUp() |
628 | - self.unapply = [] |
629 | - |
630 | - # by default 'which' has nothing in its path |
631 | - self.apply_patches([(util, 'subp', self._subp)]) |
632 | - self.subp_called = [] |
633 | - self.snapcmds = [] |
634 | - self.tmp = tempfile.mkdtemp(prefix="TestInstallPackages") |
635 | - |
636 | - def tearDown(self): |
637 | - apply_patches([i for i in reversed(self.unapply)]) |
638 | - shutil.rmtree(self.tmp) |
639 | - |
640 | - def apply_patches(self, patches): |
641 | - ret = apply_patches(patches) |
642 | - self.unapply += ret |
643 | - |
644 | - def populate_tmp(self, files): |
645 | - return t_help.populate_dir(self.tmp, files) |
646 | - |
647 | - def _subp(self, *args, **kwargs): |
648 | - # supports subp calling with cmd as args or kwargs |
649 | - if 'args' not in kwargs: |
650 | - kwargs['args'] = args[0] |
651 | - self.subp_called.append(kwargs) |
652 | - args = kwargs['args'] |
653 | - # here we basically parse the snappy command invoked |
654 | - # and append to snapcmds a list of (mode, pkg, config) |
655 | - if args[0:2] == ['snappy', 'config']: |
656 | - if args[3] == "-": |
657 | - config = kwargs.get('data', '') |
658 | - else: |
659 | - with open(args[3], "rb") as fp: |
660 | - config = yaml.safe_load(fp.read()) |
661 | - self.snapcmds.append(['config', args[2], config]) |
662 | - elif args[0:2] == ['snappy', 'install']: |
663 | - config = None |
664 | - pkg = None |
665 | - for arg in args[2:]: |
666 | - if arg.startswith("-"): |
667 | - continue |
668 | - if not pkg: |
669 | - pkg = arg |
670 | - elif not config: |
671 | - cfgfile = arg |
672 | - if cfgfile == "-": |
673 | - config = kwargs.get('data', '') |
674 | - elif cfgfile: |
675 | - with open(cfgfile, "rb") as fp: |
676 | - config = yaml.safe_load(fp.read()) |
677 | - self.snapcmds.append(['install', pkg, config]) |
678 | - |
679 | - def test_package_ops_1(self): |
680 | - ret = get_package_ops( |
681 | - packages=['pkg1', 'pkg2', 'pkg3'], |
682 | - configs={'pkg2': b'mycfg2'}, installed=[]) |
683 | - self.assertEqual( |
684 | - ret, [makeop('install', 'pkg1', None, None), |
685 | - makeop('install', 'pkg2', b'mycfg2', None), |
686 | - makeop('install', 'pkg3', None, None)]) |
687 | - |
688 | - def test_package_ops_config_only(self): |
689 | - ret = get_package_ops( |
690 | - packages=None, |
691 | - configs={'pkg2': b'mycfg2'}, installed=['pkg1', 'pkg2']) |
692 | - self.assertEqual( |
693 | - ret, [makeop('config', 'pkg2', b'mycfg2')]) |
694 | - |
695 | - def test_package_ops_install_and_config(self): |
696 | - ret = get_package_ops( |
697 | - packages=['pkg3', 'pkg2'], |
698 | - configs={'pkg2': b'mycfg2', 'xinstalled': b'xcfg'}, |
699 | - installed=['xinstalled']) |
700 | - self.assertEqual( |
701 | - ret, [makeop('install', 'pkg3'), |
702 | - makeop('install', 'pkg2', b'mycfg2'), |
703 | - makeop('config', 'xinstalled', b'xcfg')]) |
704 | - |
705 | - def test_package_ops_install_long_config_short(self): |
706 | - # a package can be installed by full name, but have config by short |
707 | - cfg = {'k1': 'k2'} |
708 | - ret = get_package_ops( |
709 | - packages=['config-example.canonical'], |
710 | - configs={'config-example': cfg}, installed=[]) |
711 | - self.assertEqual( |
712 | - ret, [makeop('install', 'config-example.canonical', cfg)]) |
713 | - |
714 | - def test_package_ops_with_file(self): |
715 | - self.populate_tmp( |
716 | - {"snapf1.snap": b"foo1", "snapf1.config": b"snapf1cfg", |
717 | - "snapf2.snap": b"foo2", "foo.bar": "ignored"}) |
718 | - ret = get_package_ops( |
719 | - packages=['pkg1'], configs={}, installed=[], fspath=self.tmp) |
720 | - self.assertEqual( |
721 | - ret, |
722 | - [makeop_tmpd(self.tmp, 'install', 'snapf1', path="snapf1.snap", |
723 | - cfgfile="snapf1.config"), |
724 | - makeop_tmpd(self.tmp, 'install', 'snapf2', path="snapf2.snap"), |
725 | - makeop('install', 'pkg1')]) |
726 | - |
727 | - def test_package_ops_common_filename(self): |
728 | - # fish package name from filename |
729 | - # package names likely look like: pkgname.namespace_version_arch.snap |
730 | - |
731 | - # find filenames |
732 | - self.populate_tmp( |
733 | - {"pkg-ws.smoser_0.3.4_all.snap": "pkg-ws-snapdata", |
734 | - "pkg-ws.config": "pkg-ws-config", |
735 | - "pkg1.smoser_1.2.3_all.snap": "pkg1.snapdata", |
736 | - "pkg1.smoser.config": "pkg1.smoser.config-data", |
737 | - "pkg1.config": "pkg1.config-data", |
738 | - "pkg2.smoser_0.0_amd64.snap": "pkg2-snapdata", |
739 | - "pkg2.smoser_0.0_amd64.config": "pkg2.config"}) |
740 | - |
741 | - ret = get_package_ops( |
742 | - packages=[], configs={}, installed=[], fspath=self.tmp) |
743 | - self.assertEqual( |
744 | - ret, |
745 | - [makeop_tmpd(self.tmp, 'install', 'pkg-ws.smoser', |
746 | - path="pkg-ws.smoser_0.3.4_all.snap", |
747 | - cfgfile="pkg-ws.config"), |
748 | - makeop_tmpd(self.tmp, 'install', 'pkg1.smoser', |
749 | - path="pkg1.smoser_1.2.3_all.snap", |
750 | - cfgfile="pkg1.smoser.config"), |
751 | - makeop_tmpd(self.tmp, 'install', 'pkg2.smoser', |
752 | - path="pkg2.smoser_0.0_amd64.snap", |
753 | - cfgfile="pkg2.smoser_0.0_amd64.config"), |
754 | - ]) |
755 | - |
756 | - def test_package_ops_config_overrides_file(self): |
757 | - # config data overrides local file .config |
758 | - self.populate_tmp( |
759 | - {"snapf1.snap": b"foo1", "snapf1.config": b"snapf1cfg"}) |
760 | - ret = get_package_ops( |
761 | - packages=[], configs={'snapf1': 'snapf1cfg-config'}, |
762 | - installed=[], fspath=self.tmp) |
763 | - self.assertEqual( |
764 | - ret, [makeop_tmpd(self.tmp, 'install', 'snapf1', |
765 | - path="snapf1.snap", config="snapf1cfg-config")]) |
766 | - |
767 | - def test_package_ops_namespacing(self): |
768 | - cfgs = { |
769 | - 'config-example': {'k1': 'v1'}, |
770 | - 'pkg1': {'p1': 'p2'}, |
771 | - 'ubuntu-core': {'c1': 'c2'}, |
772 | - 'notinstalled.smoser': {'s1': 's2'}, |
773 | - } |
774 | - ret = get_package_ops( |
775 | - packages=['config-example.canonical'], configs=cfgs, |
776 | - installed=['config-example.smoser', 'pkg1.canonical', |
777 | - 'ubuntu-core']) |
778 | - |
779 | - expected_configs = [ |
780 | - makeop('config', 'pkg1', config=cfgs['pkg1']), |
781 | - makeop('config', 'ubuntu-core', config=cfgs['ubuntu-core'])] |
782 | - expected_installs = [ |
783 | - makeop('install', 'config-example.canonical', |
784 | - config=cfgs['config-example'])] |
785 | - |
786 | - installs = [i for i in ret if i['op'] == 'install'] |
787 | - configs = [c for c in ret if c['op'] == 'config'] |
788 | - |
789 | - self.assertEqual(installs, expected_installs) |
790 | - # configs are not ordered |
791 | - self.assertEqual(len(configs), len(expected_configs)) |
792 | - self.assertTrue(all(found in expected_configs for found in configs)) |
793 | - |
794 | - def test_render_op_localsnap(self): |
795 | - self.populate_tmp({"snapf1.snap": b"foo1"}) |
796 | - op = makeop_tmpd(self.tmp, 'install', 'snapf1', |
797 | - path='snapf1.snap') |
798 | - render_snap_op(**op) |
799 | - self.assertEqual( |
800 | - self.snapcmds, [['install', op['path'], None]]) |
801 | - |
802 | - def test_render_op_localsnap_localconfig(self): |
803 | - self.populate_tmp( |
804 | - {"snapf1.snap": b"foo1", 'snapf1.config': b'snapf1cfg'}) |
805 | - op = makeop_tmpd(self.tmp, 'install', 'snapf1', |
806 | - path='snapf1.snap', cfgfile='snapf1.config') |
807 | - render_snap_op(**op) |
808 | - self.assertEqual( |
809 | - self.snapcmds, [['install', op['path'], 'snapf1cfg']]) |
810 | - |
811 | - def test_render_op_snap(self): |
812 | - op = makeop('install', 'snapf1') |
813 | - render_snap_op(**op) |
814 | - self.assertEqual( |
815 | - self.snapcmds, [['install', 'snapf1', None]]) |
816 | - |
817 | - def test_render_op_snap_config(self): |
818 | - mycfg = {'key1': 'value1'} |
819 | - name = "snapf1" |
820 | - op = makeop('install', name, config=mycfg) |
821 | - render_snap_op(**op) |
822 | - self.assertEqual( |
823 | - self.snapcmds, [['install', name, {'config': {name: mycfg}}]]) |
824 | - |
825 | - def test_render_op_config_bytes(self): |
826 | - name = "snapf1" |
827 | - mycfg = b'myconfig' |
828 | - op = makeop('config', name, config=mycfg) |
829 | - render_snap_op(**op) |
830 | - self.assertEqual( |
831 | - self.snapcmds, [['config', 'snapf1', {'config': {name: mycfg}}]]) |
832 | - |
833 | - def test_render_op_config_string(self): |
834 | - name = 'snapf1' |
835 | - mycfg = 'myconfig: foo\nhisconfig: bar\n' |
836 | - op = makeop('config', name, config=mycfg) |
837 | - render_snap_op(**op) |
838 | - self.assertEqual( |
839 | - self.snapcmds, [['config', 'snapf1', {'config': {name: mycfg}}]]) |
840 | - |
841 | - def test_render_op_config_dict(self): |
842 | - # config entry for package can be a dict, not a string blob |
843 | - mycfg = {'foo': 'bar'} |
844 | - name = 'snapf1' |
845 | - op = makeop('config', name, config=mycfg) |
846 | - render_snap_op(**op) |
847 | - # snapcmds is a list of 3-entry lists. data_found will be the |
848 | - # blob of data in the file in 'snappy install --config=<file>' |
849 | - data_found = self.snapcmds[0][2] |
850 | - self.assertEqual(mycfg, data_found['config'][name]) |
851 | - |
852 | - def test_render_op_config_list(self): |
853 | - # config entry for package can be a list, not a string blob |
854 | - mycfg = ['foo', 'bar', 'wark', {'f1': 'b1'}] |
855 | - name = "snapf1" |
856 | - op = makeop('config', name, config=mycfg) |
857 | - render_snap_op(**op) |
858 | - data_found = self.snapcmds[0][2] |
859 | - self.assertEqual(mycfg, data_found['config'][name]) |
860 | - |
861 | - def test_render_op_config_int(self): |
862 | - # config entry for package can be a list, not a string blob |
863 | - mycfg = 1 |
864 | - name = 'snapf1' |
865 | - op = makeop('config', name, config=mycfg) |
866 | - render_snap_op(**op) |
867 | - data_found = self.snapcmds[0][2] |
868 | - self.assertEqual(mycfg, data_found['config'][name]) |
869 | - |
870 | - def test_render_long_configs_short(self): |
871 | - # install a namespaced package should have un-namespaced config |
872 | - mycfg = {'k1': 'k2'} |
873 | - name = 'snapf1' |
874 | - op = makeop('install', name + ".smoser", config=mycfg) |
875 | - render_snap_op(**op) |
876 | - data_found = self.snapcmds[0][2] |
877 | - self.assertEqual(mycfg, data_found['config'][name]) |
878 | - |
879 | - def test_render_does_not_pad_cfgfile(self): |
880 | - # package_ops with cfgfile should not modify --file= content. |
881 | - mydata = "foo1: bar1\nk: [l1, l2, l3]\n" |
882 | - self.populate_tmp( |
883 | - {"snapf1.snap": b"foo1", "snapf1.config": mydata.encode()}) |
884 | - ret = get_package_ops( |
885 | - packages=[], configs={}, installed=[], fspath=self.tmp) |
886 | - self.assertEqual( |
887 | - ret, |
888 | - [makeop_tmpd(self.tmp, 'install', 'snapf1', path="snapf1.snap", |
889 | - cfgfile="snapf1.config")]) |
890 | - |
891 | - # now the op was ok, but test that render didn't mess it up. |
892 | - render_snap_op(**ret[0]) |
893 | - data_found = self.snapcmds[0][2] |
894 | - # the data found gets loaded in the snapcmd interpretation |
895 | - # so this comparison is a bit lossy, but input to snappy config |
896 | - # is expected to be yaml loadable, so it should be OK. |
897 | - self.assertEqual(yaml.safe_load(mydata), data_found) |
898 | - |
899 | - |
900 | -class TestSnapConfig(FilesystemMockingTestCase): |
901 | - |
902 | - SYSTEM_USER_ASSERTION = textwrap.dedent(""" |
903 | - type: system-user |
904 | - authority-id: LqvZQdfyfGlYvtep4W6Oj6pFXP9t1Ksp |
905 | - brand-id: LqvZQdfyfGlYvtep4W6Oj6pFXP9t1Ksp |
906 | - email: foo@bar.com |
907 | - password: $6$E5YiAuMIPAwX58jG$miomhVNui/vf7f/3ctB/f0RWSKFxG0YXzrJ9rtJ1ikvzt |
908 | - series: |
909 | - - 16 |
910 | - since: 2016-09-10T16:34:00+03:00 |
911 | - until: 2017-11-10T16:34:00+03:00 |
912 | - username: baz |
913 | - sign-key-sha3-384: RuVvnp4n52GilycjfbbTCI3_L8Y6QlIE75wxMc0KzGV3AUQqVd9GuXoj |
914 | - |
915 | - AcLBXAQAAQoABgUCV/UU1wAKCRBKnlMoJQLkZVeLD/9/+hIeVywtzsDA3oxl+P+u9D13y9s6svP |
916 | - Jd6Wnf4FTw6sq1GjBE4ZA7lrwSaRCUJ9Vcsvf2q9OGPY7mOb2TBxaDe0PbUMjrSrqllSSQwhpNI |
917 | - zG+NxkkKuxsUmLzFa+k9m6cyojNbw5LFhQZBQCGlr3JYqC0tIREq/UsZxj+90TUC87lDJwkU8GF |
918 | - s4CR+rejZj4itIcDcVxCSnJH6hv6j2JrJskJmvObqTnoOlcab+JXdamXqbldSP3UIhWoyVjqzkj |
919 | - +to7mXgx+cCUA9+ngNCcfUG+1huGGTWXPCYkZ78HvErcRlIdeo4d3xwtz1cl/w3vYnq9og1XwsP |
920 | - Yfetr3boig2qs1Y+j/LpsfYBYncgWjeDfAB9ZZaqQz/oc8n87tIPZDJHrusTlBfop8CqcM4xsKS |
921 | - d+wnEY8e/F24mdSOYmS1vQCIDiRU3MKb6x138Ud6oHXFlRBbBJqMMctPqWDunWzb5QJ7YR0I39q |
922 | - BrnEqv5NE0G7w6HOJ1LSPG5Hae3P4T2ea+ATgkb03RPr3KnXnzXg4TtBbW1nytdlgoNc/BafE1H |
923 | - f3NThcq9gwX4xWZ2PAWnqVPYdDMyCtzW3Ck+o6sIzx+dh4gDLPHIi/6TPe/pUuMop9CBpWwez7V |
924 | - v1z+1+URx6Xlq3Jq18y5pZ6fY3IDJ6km2nQPMzcm4Q==""") |
925 | - |
926 | - ACCOUNT_ASSERTION = textwrap.dedent(""" |
927 | - type: account-key |
928 | - authority-id: canonical |
929 | - revision: 2 |
930 | - public-key-sha3-384: BWDEoaqyr25nF5SNCvEv2v7QnM9QsfCc0PBMYD_i2NGSQ32EF2d4D0 |
931 | - account-id: canonical |
932 | - name: store |
933 | - since: 2016-04-01T00:00:00.0Z |
934 | - body-length: 717 |
935 | - sign-key-sha3-384: -CvQKAwRQ5h3Ffn10FILJoEZUXOv6km9FwA80-Rcj-f-6jadQ89VRswH |
936 | - |
937 | - AcbBTQRWhcGAARAA0KKYYQWuHOrsFVi4p4l7ZzSvX7kLgJFFeFgOkzdWKBTHEnsMKjl5mefFe9j |
938 | - qe8NlmJdfY7BenP7XeBtwKp700H/t9lLrZbpTNAPHXYxEWFJp5bPqIcJYBZ+29oLVLN1Tc5X482 |
939 | - vCiDqL8+pPYqBrK2fNlyPlNNSum9wI70rDDL4r6FVvr+osTnGejibdV8JphWX+lrSQDnRSdM8KJ |
940 | - UM43vTgLGTi9W54oRhsA2OFexRfRksTrnqGoonCjqX5wO3OFSaMDzMsO2MJ/hPfLgDqw53qjzuK |
941 | - Iec9OL3k5basvu2cj5u9tKwVFDsCKK2GbKUsWWpx2KTpOifmhmiAbzkTHbH9KaoMS7p0kJwhTQG |
942 | - o9aJ9VMTWHJc/NCBx7eu451u6d46sBPCXS/OMUh2766fQmoRtO1OwCTxsRKG2kkjbMn54UdFULl |
943 | - VfzvyghMNRKIezsEkmM8wueTqGUGZWa6CEZqZKwhe/PROxOPYzqtDH18XZknbU1n5lNb7vNfem9 |
944 | - 2ai+3+JyFnW9UhfvpVF7gzAgdyCqNli4C6BIN43uwoS8HkykocZS/+Gv52aUQ/NZ8BKOHLw+7an |
945 | - Q0o8W9ltSLZbEMxFIPSN0stiZlkXAp6DLyvh1Y4wXSynDjUondTpej2fSvSlCz/W5v5V7qA4nIc |
946 | - vUvV7RjVzv17ut0AEQEAAQ== |
947 | - |
948 | - AcLDXAQAAQoABgUCV83k9QAKCRDUpVvql9g3IBT8IACKZ7XpiBZ3W4lqbPssY6On81WmxQLtvsM |
949 | - WTp6zZpl/wWOSt2vMNUk9pvcmrNq1jG9CuhDfWFLGXEjcrrmVkN3YuCOajMSPFCGrxsIBLSRt/b |
950 | - nrKykdLAAzMfG8rP1d82bjFFiIieE+urQ0Kcv09Jtdvavq3JT1Tek5mFyyfhHNlQEKOzWqmRWiL |
951 | - 3c3VOZUs1ZD8TSlnuq/x+5T0X0YtOyGjSlVxk7UybbyMNd6MZfNaMpIG4x+mxD3KHFtBAC7O6kL |
952 | - eX3i6j5nCY5UABfA3DZEAkWP4zlmdBEOvZ9t293NaDdOpzsUHRkoi0Zez/9BHQ/kwx/uNc2WqrY |
953 | - inCmu16JGNeXqsyinnLl7Ghn2RwhvDMlLxF6RTx8xdx1yk6p3PBTwhZMUvuZGjUtN/AG8BmVJQ1 |
954 | - rsGSRkkSywvnhVJRB2sudnrMBmNS2goJbzSbmJnOlBrd2WsV0T9SgNMWZBiov3LvU4o2SmAb6b+ |
955 | - rYwh8H5QHcuuYJuxDjFhPswIp6Wes5T6hUicf3SWtObcDS4HSkVS4ImBjjX9YgCuFy7QdnooOWE |
956 | - aPvkRw3XCVeYq0K6w9GRsk1YFErD4XmXXZjDYY650MX9v42Sz5MmphHV8jdIY5ssbadwFSe2rCQ |
957 | - 6UX08zy7RsIb19hTndE6ncvSNDChUR9eEnCm73eYaWTWTnq1cxdVP/s52r8uss++OYOkPWqh5nO |
958 | - haRn7INjH/yZX4qXjNXlTjo0PnHH0q08vNKDwLhxS+D9du+70FeacXFyLIbcWllSbJ7DmbumGpF |
959 | - yYbtj3FDDPzachFQdIG3lSt+cSUGeyfSs6wVtc3cIPka/2Urx7RprfmoWSI6+a5NcLdj0u2z8O9 |
960 | - HxeIgxDpg/3gT8ZIuFKePMcLDM19Fh/p0ysCsX+84B9chNWtsMSmIaE57V+959MVtsLu7SLb9gi |
961 | - skrju0pQCwsu2wHMLTNd1f3PTHmrr49hxetTus07HSQUApMtAGKzQilF5zqFjbyaTd4xgQbd+PK |
962 | - CjFyzQTDOcUhXpuUGt/IzlqiFfsCsmbj2K4KdSNYMlqIgZ3Azu8KvZLIhsyN7v5vNIZSPfEbjde |
963 | - ClU9r0VRiJmtYBUjcSghD9LWn+yRLwOxhfQVjm0cBwIt5R/yPF/qC76yIVuWUtM5Y2/zJR1J8OF |
964 | - qWchvlImHtvDzS9FQeLyzJAOjvZ2CnWp2gILgUz0WQdOk1Dq8ax7KS9BQ42zxw9EZAEPw3PEFqR |
965 | - IQsRTONp+iVS8YxSmoYZjDlCgRMWUmawez/Fv5b9Fb/XkO5Eq4e+KfrpUujXItaipb+tV8h5v3t |
966 | - oG3Ie3WOHrVjCLXIdYslpL1O4nadqR6Xv58pHj6k""") |
967 | - |
968 | - test_assertions = [ACCOUNT_ASSERTION, SYSTEM_USER_ASSERTION] |
969 | - |
970 | - def setUp(self): |
971 | - super(TestSnapConfig, self).setUp() |
972 | - self.subp = util.subp |
973 | - self.new_root = tempfile.mkdtemp() |
974 | - self.addCleanup(shutil.rmtree, self.new_root) |
975 | - |
976 | - def _get_cloud(self, distro, metadata=None): |
977 | - self.patchUtils(self.new_root) |
978 | - paths = helpers.Paths({}) |
979 | - cls = distros.fetch(distro) |
980 | - mydist = cls(distro, {}, paths) |
981 | - myds = DataSourceNone.DataSourceNone({}, mydist, paths) |
982 | - if metadata: |
983 | - myds.metadata.update(metadata) |
984 | - return cloud.Cloud(myds, paths, {}, mydist, None) |
985 | - |
986 | - @mock.patch('cloudinit.util.write_file') |
987 | - @mock.patch('cloudinit.util.subp') |
988 | - def test_snap_config_add_assertions(self, msubp, mwrite): |
989 | - add_assertions(self.test_assertions) |
990 | - |
991 | - combined = "\n".join(self.test_assertions) |
992 | - mwrite.assert_any_call(ASSERTIONS_FILE, combined.encode('utf-8')) |
993 | - msubp.assert_called_with(['snap', 'ack', ASSERTIONS_FILE], |
994 | - capture=True) |
995 | - |
996 | - def test_snap_config_add_assertions_empty(self): |
997 | - self.assertRaises(ValueError, add_assertions, []) |
998 | - |
999 | - def test_add_assertions_nonlist(self): |
1000 | - self.assertRaises(ValueError, add_assertions, {}) |
1001 | - |
1002 | - @mock.patch('cloudinit.util.write_file') |
1003 | - @mock.patch('cloudinit.util.subp') |
1004 | - def test_snap_config_add_assertions_ack_fails(self, msubp, mwrite): |
1005 | - msubp.side_effect = [util.ProcessExecutionError("Invalid assertion")] |
1006 | - self.assertRaises(util.ProcessExecutionError, add_assertions, |
1007 | - self.test_assertions) |
1008 | - |
1009 | - @mock.patch('cloudinit.config.cc_snap_config.add_assertions') |
1010 | - @mock.patch('cloudinit.config.cc_snap_config.util') |
1011 | - def test_snap_config_handle_no_config(self, mock_util, mock_add): |
1012 | - cfg = {} |
1013 | - cc = self._get_cloud('ubuntu') |
1014 | - cc.distro = mock.MagicMock() |
1015 | - cc.distro.name = 'ubuntu' |
1016 | - mock_util.which.return_value = None |
1017 | - snap_handle('snap_config', cfg, cc, LOG, None) |
1018 | - mock_add.assert_not_called() |
1019 | - |
1020 | - def test_snap_config_add_snap_user_no_config(self): |
1021 | - usercfg = add_snap_user(cfg=None) |
1022 | - self.assertIsNone(usercfg) |
1023 | - |
1024 | - def test_snap_config_add_snap_user_not_dict(self): |
1025 | - cfg = ['foobar'] |
1026 | - self.assertRaises(ValueError, add_snap_user, cfg) |
1027 | - |
1028 | - def test_snap_config_add_snap_user_no_email(self): |
1029 | - cfg = {'assertions': [], 'known': True} |
1030 | - usercfg = add_snap_user(cfg=cfg) |
1031 | - self.assertIsNone(usercfg) |
1032 | - |
1033 | - @mock.patch('cloudinit.config.cc_snap_config.util') |
1034 | - def test_snap_config_add_snap_user_email_only(self, mock_util): |
1035 | - email = 'janet@planetjanet.org' |
1036 | - cfg = {'email': email} |
1037 | - mock_util.which.return_value = None |
1038 | - mock_util.system_is_snappy.return_value = True |
1039 | - mock_util.subp.side_effect = [ |
1040 | - ("false\n", ""), # snap managed |
1041 | - ] |
1042 | - |
1043 | - usercfg = add_snap_user(cfg=cfg) |
1044 | - |
1045 | - self.assertEqual(usercfg, {'snapuser': email, 'known': False}) |
1046 | - |
1047 | - @mock.patch('cloudinit.config.cc_snap_config.util') |
1048 | - def test_snap_config_add_snap_user_email_known(self, mock_util): |
1049 | - email = 'janet@planetjanet.org' |
1050 | - known = True |
1051 | - cfg = {'email': email, 'known': known} |
1052 | - mock_util.which.return_value = None |
1053 | - mock_util.system_is_snappy.return_value = True |
1054 | - mock_util.subp.side_effect = [ |
1055 | - ("false\n", ""), # snap managed |
1056 | - (self.SYSTEM_USER_ASSERTION, ""), # snap known system-user |
1057 | - ] |
1058 | - |
1059 | - usercfg = add_snap_user(cfg=cfg) |
1060 | - |
1061 | - self.assertEqual(usercfg, {'snapuser': email, 'known': known}) |
1062 | - |
1063 | - @mock.patch('cloudinit.config.cc_snap_config.add_assertions') |
1064 | - @mock.patch('cloudinit.config.cc_snap_config.util') |
1065 | - def test_snap_config_handle_system_not_snappy(self, mock_util, mock_add): |
1066 | - cfg = {'snappy': {'assertions': self.test_assertions}} |
1067 | - cc = self._get_cloud('ubuntu') |
1068 | - cc.distro = mock.MagicMock() |
1069 | - cc.distro.name = 'ubuntu' |
1070 | - mock_util.which.return_value = None |
1071 | - mock_util.system_is_snappy.return_value = False |
1072 | - |
1073 | - snap_handle('snap_config', cfg, cc, LOG, None) |
1074 | - |
1075 | - mock_add.assert_not_called() |
1076 | - |
1077 | - @mock.patch('cloudinit.config.cc_snap_config.add_assertions') |
1078 | - @mock.patch('cloudinit.config.cc_snap_config.util') |
1079 | - def test_snap_config_handle_snapuser(self, mock_util, mock_add): |
1080 | - email = 'janet@planetjanet.org' |
1081 | - cfg = { |
1082 | - 'snappy': { |
1083 | - 'assertions': self.test_assertions, |
1084 | - 'email': email, |
1085 | - } |
1086 | - } |
1087 | - cc = self._get_cloud('ubuntu') |
1088 | - cc.distro = mock.MagicMock() |
1089 | - cc.distro.name = 'ubuntu' |
1090 | - mock_util.which.return_value = None |
1091 | - mock_util.system_is_snappy.return_value = True |
1092 | - mock_util.subp.side_effect = [ |
1093 | - ("false\n", ""), # snap managed |
1094 | - ] |
1095 | - |
1096 | - snap_handle('snap_config', cfg, cc, LOG, None) |
1097 | - |
1098 | - mock_add.assert_called_with(self.test_assertions) |
1099 | - usercfg = {'snapuser': email, 'known': False} |
1100 | - cc.distro.create_user.assert_called_with(email, **usercfg) |
1101 | - |
1102 | - @mock.patch('cloudinit.config.cc_snap_config.add_assertions') |
1103 | - @mock.patch('cloudinit.config.cc_snap_config.util') |
1104 | - def test_snap_config_handle_snapuser_known(self, mock_util, mock_add): |
1105 | - email = 'janet@planetjanet.org' |
1106 | - cfg = { |
1107 | - 'snappy': { |
1108 | - 'assertions': self.test_assertions, |
1109 | - 'email': email, |
1110 | - 'known': True, |
1111 | - } |
1112 | - } |
1113 | - cc = self._get_cloud('ubuntu') |
1114 | - cc.distro = mock.MagicMock() |
1115 | - cc.distro.name = 'ubuntu' |
1116 | - mock_util.which.return_value = None |
1117 | - mock_util.system_is_snappy.return_value = True |
1118 | - mock_util.subp.side_effect = [ |
1119 | - ("false\n", ""), # snap managed |
1120 | - (self.SYSTEM_USER_ASSERTION, ""), # snap known system-user |
1121 | - ] |
1122 | - |
1123 | - snap_handle('snap_config', cfg, cc, LOG, None) |
1124 | - |
1125 | - mock_add.assert_called_with(self.test_assertions) |
1126 | - usercfg = {'snapuser': email, 'known': True} |
1127 | - cc.distro.create_user.assert_called_with(email, **usercfg) |
1128 | - |
1129 | - @mock.patch('cloudinit.config.cc_snap_config.add_assertions') |
1130 | - @mock.patch('cloudinit.config.cc_snap_config.util') |
1131 | - def test_snap_config_handle_snapuser_known_managed(self, mock_util, |
1132 | - mock_add): |
1133 | - email = 'janet@planetjanet.org' |
1134 | - cfg = { |
1135 | - 'snappy': { |
1136 | - 'assertions': self.test_assertions, |
1137 | - 'email': email, |
1138 | - 'known': True, |
1139 | - } |
1140 | - } |
1141 | - cc = self._get_cloud('ubuntu') |
1142 | - cc.distro = mock.MagicMock() |
1143 | - cc.distro.name = 'ubuntu' |
1144 | - mock_util.which.return_value = None |
1145 | - mock_util.system_is_snappy.return_value = True |
1146 | - mock_util.subp.side_effect = [ |
1147 | - ("true\n", ""), # snap managed |
1148 | - ] |
1149 | - |
1150 | - snap_handle('snap_config', cfg, cc, LOG, None) |
1151 | - |
1152 | - mock_add.assert_called_with(self.test_assertions) |
1153 | - cc.distro.create_user.assert_not_called() |
1154 | - |
1155 | - @mock.patch('cloudinit.config.cc_snap_config.add_assertions') |
1156 | - @mock.patch('cloudinit.config.cc_snap_config.util') |
1157 | - def test_snap_config_handle_snapuser_known_no_assertion(self, mock_util, |
1158 | - mock_add): |
1159 | - email = 'janet@planetjanet.org' |
1160 | - cfg = { |
1161 | - 'snappy': { |
1162 | - 'assertions': [self.ACCOUNT_ASSERTION], |
1163 | - 'email': email, |
1164 | - 'known': True, |
1165 | - } |
1166 | - } |
1167 | - cc = self._get_cloud('ubuntu') |
1168 | - cc.distro = mock.MagicMock() |
1169 | - cc.distro.name = 'ubuntu' |
1170 | - mock_util.which.return_value = None |
1171 | - mock_util.system_is_snappy.return_value = True |
1172 | - mock_util.subp.side_effect = [ |
1173 | - ("true\n", ""), # snap managed |
1174 | - ("", ""), # snap known system-user |
1175 | - ] |
1176 | - |
1177 | - snap_handle('snap_config', cfg, cc, LOG, None) |
1178 | - |
1179 | - mock_add.assert_called_with([self.ACCOUNT_ASSERTION]) |
1180 | - cc.distro.create_user.assert_not_called() |
1181 | - |
1182 | - |
1183 | -def makeop_tmpd(tmpd, op, name, config=None, path=None, cfgfile=None): |
1184 | - if cfgfile: |
1185 | - cfgfile = os.path.sep.join([tmpd, cfgfile]) |
1186 | - if path: |
1187 | - path = os.path.sep.join([tmpd, path]) |
1188 | - return(makeop(op=op, name=name, config=config, path=path, cfgfile=cfgfile)) |
1189 | - |
1190 | - |
1191 | -def apply_patches(patches): |
1192 | - ret = [] |
1193 | - for (ref, name, replace) in patches: |
1194 | - if replace is None: |
1195 | - continue |
1196 | - orig = getattr(ref, name) |
1197 | - setattr(ref, name, replace) |
1198 | - ret.append((ref, name, orig)) |
1199 | - return ret |
1200 | - |
1201 | -# vi: ts=4 expandtab |
FAILED: Continuous integration, rev:a2d9c10f02a 47a7403f1102b7f 4694ea79961c11 /jenkins. ubuntu. com/server/ job/cloud- init-ci/ 555/
https:/
Executed test runs:
SUCCESS: Checkout
SUCCESS: Unit & Style Tests
SUCCESS: Ubuntu LTS: Build
FAILED: Ubuntu LTS: Integration
Click here to trigger a rebuild: /jenkins. ubuntu. com/server/ job/cloud- init-ci/ 555/rebuild
https:/