Merge lp:~paelzer/curtin/bug-1574113-derived-repositories into lp:~curtin-dev/curtin/trunk
- bug-1574113-derived-repositories
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 410 |
Proposed branch: | lp:~paelzer/curtin/bug-1574113-derived-repositories |
Merge into: | lp:~curtin-dev/curtin/trunk |
Diff against target: |
4008 lines (+3551/-146) 25 files modified
curtin/__init__.py (+2/-0) curtin/commands/apt_config.py (+691/-0) curtin/commands/curthooks.py (+11/-135) curtin/commands/main.py (+1/-1) curtin/gpg.py (+74/-0) curtin/util.py (+144/-2) doc/devel/README-vmtest.txt (+3/-3) doc/topics/apt_source.rst (+152/-0) examples/apt-source.yaml (+239/-0) examples/tests/apt_config_command.yaml (+85/-0) examples/tests/apt_source_custom.yaml (+97/-0) examples/tests/apt_source_modify.yaml (+92/-0) examples/tests/apt_source_modify_arches.yaml (+102/-0) examples/tests/apt_source_modify_disable_suite.yaml (+92/-0) examples/tests/apt_source_preserve.yaml (+98/-0) examples/tests/apt_source_search.yaml (+97/-0) examples/tests/apt_source_search_dns.yaml (+21/-0) examples/tests/test_old_apt_features.yaml (+10/-0) examples/tests/test_old_apt_features_ports.yaml (+10/-0) tests/unittests/test_apt_custom_sources_list.py (+172/-0) tests/unittests/test_apt_source.py (+927/-0) tests/vmtests/__init__.py (+19/-5) tests/vmtests/test_apt_config_cmd.py (+55/-0) tests/vmtests/test_apt_source.py (+277/-0) tests/vmtests/test_old_apt_features.py (+80/-0) |
To merge this branch: | bzr merge lp:~paelzer/curtin/bug-1574113-derived-repositories |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Server Team CI bot | continuous-integration | Approve | |
Ryan Harper (community) | Approve | ||
Review via email: mp+296118@code.launchpad.net |
Commit message
Adding apt features to curtin.
This allows to define derived repositories by being able to control various apt configurations, proxies, mirrors, ppa's, sources.list content and pgp keys trusted by apt.
See examples/
Along the actual features a huge list of related unit- and vm-tests is added.
Description of the change
Adding apt_source features for the install stage of curtin.
This is inherited from cloud-init, but simplified (as we don't have to care about some features and old compatibility).
And then added plenty of unit- and vm-tests for the functionality.
Server Team CI bot (server-team-bot) wrote : | # |
- 442. By Christian Ehrhardt
-
test_mir_
apt_list_ rename fix assertion of call depending on the unittest environment the rename calls can differ in order
and amount. Convert the check to any_call - 443. By Christian Ehrhardt
-
test_mir_
apt_list_ rename mockup source filename Depending on the unittest environment the source file could be wrong.
E.g. if a developer runs with a non default mirror.
Mock up the check for this file and by that, fixup the test in various
environments. - 444. By Christian Ehrhardt
-
fix premission error in unit test
depending on the environment it could have had the side effect of really trying
to rename files. That was bad for either the permission error or the actual
rename.
So we mock the rename to keep it free of side effects. - 445. By Christian Ehrhardt
-
drop reinstalling the mocked subp as it is not needed anymore
In the simplified test subp is not mocked to begin with, so there is no reason
to restore it. - 446. By Christian Ehrhardt
-
convert all apt_custom_
sources_ list tests to fakerelease That makes them independent to the execution environment
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:446
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Christian Ehrhardt (paelzer) wrote : | # |
The jenkins bot had identified a few issues with the unittests in Trusty environments which are now fixed.
Ryan Harper (raharper) wrote : | # |
This is really nice.
A couple of nits in the code.
Super happy to see unittests AND vmtests +1
One last request, might be a doc/topics/
I think most of it can be copied out of your example files which included lots of
documentation, but in general, I'd like to see some documentation that we'd hand
to the MAAS team about how to use the new dictionary config to pass through the
landscape derived repo.
Christian Ehrhardt (paelzer) wrote : | # |
Hi,
thanks again for the review.
I added some comments to your feedback where appropriate.
ALmost all is accepted and integrated, just sometimes in slightly modified ways and the comments state the reasons.
Any non commented feedback is acked and integrated as suggested.
My own unit and vmtests are fine still, I'll run a full suite of vmtests and if successful push to the MP for the next round of review or acceptance.
- 447. By Christian Ehrhardt
-
clarify docstring for mirror2lists_
fileprefix - 448. By Christian Ehrhardt
-
make lists_d a global constant in the form of APT_LISTS
- 449. By Christian Ehrhardt
-
fix whitespace issue
- 450. By Christian Ehrhardt
-
fix docstrings to always use triple quotes
- 451. By Christian Ehrhardt
-
degrade test_apt_
srcl_custom to static method - 452. By Christian Ehrhardt
-
handle potential exception on os.rename
- 453. By Christian Ehrhardt
-
replace get_release usage with already existing lsb_release
- 454. By Christian Ehrhardt
-
add sanity checks and early exit to render_
string_ to_file - 455. By Christian Ehrhardt
-
move BASIC_MATCHER up to global variables
- 456. By Christian Ehrhardt
-
improve error message if add_key_raw fails
- 457. By Christian Ehrhardt
-
improve docstring of method add_key
- 458. By Christian Ehrhardt
-
make default mirror and keyserver global variables
- 459. By Christian Ehrhardt
-
add unittest for specifying a custom keyserver
- 460. By Christian Ehrhardt
-
simplify find_apt_
mirror_ info by using DEFAULT_MIRRORS This now shares a single default definition with rename_apt_lists
- 461. By Christian Ehrhardt
-
dropping unrelated changes
FYI - rharper will carry those in his docu update branch
- 462. By Christian Ehrhardt
-
optimize apt_source unittest imports
- 463. By Christian Ehrhardt
-
apt_source: add doc in rst format and improve example yaml
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:463
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 464. By Christian Ehrhardt
-
improve rst formatting
Christian Ehrhardt (paelzer) wrote : | # |
Ok, I found an rst format checker and was able to improve that as well.
Should be available for another round of review towards acceptance now.
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:464
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Ryan Harper (raharper) : | # |
Christian Ehrhardt (paelzer) wrote : | # |
Hi,
thanks again for all the feedback.
Every section not explicitly mentiones is acked and integrated.
For everything else see the comment why/how I have modified the suggestions.
Running a full round of tests again before next upload.
- 465. By Christian Ehrhardt
-
convert gpg key handling to pure python
- 466. By Christian Ehrhardt
-
rename mirror2lists_
fileprefix to mirrorurl_ to_apt_ fileprefix This much more reflects what it does, so it helps code readability
- 467. By Christian Ehrhardt
-
include exception info on the OSError exception for file renaming
- 468. By Christian Ehrhardt
-
move generic gpg functions to util
- 469. By Christian Ehrhardt
-
move generic part of template rendering to util
- 470. By Christian Ehrhardt
-
add apt name portion to name add_key[_raw]
- 471. By Christian Ehrhardt
-
backup sources.list before writing to it
- 472. By Christian Ehrhardt
-
rename add_sources to the more appropriate add_apt_sources
- 473. By Christian Ehrhardt
-
simply control-flow in apt_source
- 474. By Christian Ehrhardt
-
simplify error handling in handle_apt_source
- 475. By Christian Ehrhardt
-
remove unused import
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:475
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 476. By Christian Ehrhardt
-
unify key tests for real keys in apt_src_keyid_real
- 477. By Christian Ehrhardt
-
fix gpg key based unitests to work in networkless environments as well
- 478. By Christian Ehrhardt
-
add test for alternative keyserver
- 479. By Christian Ehrhardt
-
capture output of gpg calls to avoid messing up stdout/stderr
- 480. By Christian Ehrhardt
-
fix fallback key import
- 481. By Christian Ehrhardt
-
drop gpg activity from apt-source key tests
While the unittest gets a bit less real by that change, it will work in
protected environment (e.g. sbuild) and leave the developers .gpg keyring
Christian Ehrhardt (paelzer) wrote : | # |
This now also includes some extensions/fixes created and discussed on the cloud-init side of things.
There is no reason to wait and find them again in the curtin code.
I could build fine in sbuild, but was unable to test in a ppa for now (gets rejected for bin/source mismatch for some reason).
I started to mess around with the changes file trying to fix it, but I guess smoser has a much nicer and faster way to throw that at a ppa - I'd be happy about a discussion what was missing.
Ready for another round of review for getting merged.
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:481
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Ryan Harper (raharper) wrote : | # |
This is really nice. Just a couple of minor issues with naming and logging.
- 482. By Christian Ehrhardt
-
improve debug message
- 483. By Christian Ehrhardt
-
report stacktrace on high level exception handler
- 484. By Christian Ehrhardt
-
typo fix fule->file
- 485. By Christian Ehrhardt
-
lower debug level of renaming apt list message
- 486. By Christian Ehrhardt
-
fix exception handler that had a unreferenced %s
- 487. By Christian Ehrhardt
-
prefix getkeybyid with gpg_ as the other related functions
- 488. By Christian Ehrhardt
-
rename basic_render to basic_template_
render for readability
Christian Ehrhardt (paelzer) wrote : | # |
All integrated, except one that I discussed on IRC
Christian Ehrhardt (paelzer) wrote : | # |
Ready for another review or acceptance
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:488
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 489. By Christian Ehrhardt
-
improve error handling of gpg functions
Christian Ehrhardt (paelzer) wrote : | # |
Added another fix that came up when working on the cloud-init portion.
Ready for review towards merging again.
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:489
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Ryan Harper (raharper) wrote : | # |
Looks great. Should get this merged today or tomorrow.
Scott Moser (smoser) wrote : | # |
mostly nitpicks
some to make it like what is in cloud-init trunk.
Christian Ehrhardt (paelzer) wrote : | # |
Hi,
thanks for the review - all accepted and integrated except one.
I commented below and catch you on IRC for that one.
- 490. By Christian Ehrhardt
-
move docsting after copyright
- 491. By Christian Ehrhardt
-
move gpg functions to their own file
- 492. By Christian Ehrhardt
-
drop unused self.orig_
gpg_recv_ key - 493. By Christian Ehrhardt
-
add curtin/gpg.py
- 494. By Christian Ehrhardt
-
drop rstrip from gpg function
Christian Ehrhardt (paelzer) wrote : | # |
That is the integration of the last feedback, ready for review/merge again
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:494
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Scott Moser (smoser) wrote : | # |
further reading and thinking.
I think that the implementation doens't actually solve the thing we need solved.
apt_sources configuration to curtin declares what the target's apt should be configured with (much the same as the storage_config or 'kernel' configuration is about the installed environment not the host).
So, the apt_sources needs to apply to the target.
For maas, to get all of this working together, it has to
a.) declare to cloud-init that certain apt sources are necessary in the ephemeral environment
b.) declare to curtin that the target environment must include apt configured with a set of apt sources.
'a' is done in cloud-init user-data
'b' is done in curtin config.
Christian Ehrhardt (paelzer) wrote : | # |
Hi Scott,
I've implemented it the "new" way now and adapted all around that was needed.
Please read the comments I added below as answer to your feedback - to see if my assumptions when implementing made sense.
Everything else in the next round of code review (just doing a full round of tests and build before to be sure).
- 495. By Christian Ehrhardt
-
Merge with upstream to avoid conflicts
pending merges:
Ryan Harper 2016-06-14 [merge] reporting: set webhook handler level to DEBUG, no filtering
Ryan Harper 2016-06-14 [merge] merge from trunk
Ryan Harper 2016-06-14 reporting: default webhook handler level to DEBUG, no filtering
Scott Moser 2016-06-14 [merge] improve net-meta network configuration
Scott Moser 2016-06-13 spelling
Scott Moser 2016-06-13 log cleanup
Scott Moser 2016-06-13 improve net-meta network configuration
Ryan Harper 2016-06-03 [merge] curtin/net: fix inet value for subnets, don't add interface attributes to alias
Ryan Harper 2016-06-03 [merge] curtin/net: calculate the inet value for each subnet independently
Mike Pontillo 2016-06-03 Address review comment.
Mike Pontillo 2016-06-02 Don't append the '6' to IPv4 aliases if an IPv6 alias preceded it.
Mike Pontillo 2016-06-02 Add failing test case for bug #1588547
Ryan Harper 2016-06-03 [merge] curtin/net: Don't add interface attributes to alias interfaces
Mike Pontillo 2016-06-03 Don't add additional parameters to alias interfaces. (Rebase from trunk and address review comments.) - 496. By Christian Ehrhardt
-
add docstring to apt_source.py's POPULATE_SUBCMD
- 497. By Christian Ehrhardt
-
avoid python checker warnings by making POPULATE_SUBCMD lower case
- 498. By Christian Ehrhardt
-
add --target parameter to apt-source command
This allows to modify the target environment as needed.
But given it is an argment can work in arbitrary chroots as long as the tools
like gpg, apt-key as well as the files it modifies are there. - 499. By Christian Ehrhardt
-
adapt apt-source tests to check the target environment
- 500. By Christian Ehrhardt
-
report checked files in output_files_exist
This can help to quickly identify which file is missing in case a long list
of files is checked. - 501. By Christian Ehrhardt
-
lsb_release to support target
- 502. By Christian Ehrhardt
-
propagate and use target throughout apt-source handling
- 503. By Christian Ehrhardt
-
fix issue in ChrootableTarget if resolv.conf didn't yet exist in target
- 504. By Christian Ehrhardt
-
ensure errorlist contains only strings
- 505. By Christian Ehrhardt
-
improve error handling to not silently ignore program execution issues
- 506. By Christian Ehrhardt
-
order config builtin in execution order
- 507. By Christian Ehrhardt
-
extend builtin key of CONFIG_BUILTIN
It is a single namespace per stage - just "builtin" is too ambiguous.
- 508. By Christian Ehrhardt
-
insert apt-source after extract
- 509. By Christian Ehrhardt
-
remove useless warn if no source is specified
This can be a quite common case since we allo keys without surce now.
No need to flood the log with warnings that didn't even tell you much. - 510. By Christian Ehrhardt
-
revert rev 503: fix issue in ChrootableTarget if resolv.conf
- 511. By Christian Ehrhardt
-
update apt data after changing configuration and/or source.lists
- 512. By Christian Ehrhardt
-
mock out apt_update in apt-source unit tests
- 513. By Christian Ehrhardt
-
allow a testcase to provide custom cloud-init data to the booted system
- 514. By Christian Ehrhardt
-
apt-source vmtest now uses boot_cloudconf
This allows the vmtest to avoid having cloud-init to rewrite its just laid
down sources list. Just as a final user is expected to set this conf when
using curtin apt-source feature the test is using itnow as well. - 515. By Christian Ehrhardt
-
doc: update for apt-source now having a target specification
- 516. By Christian Ehrhardt
-
don't skip cloud-init if we run in preserved mode
- 517. By Christian Ehrhardt
-
take back individual builtin naming
- 518. By Christian Ehrhardt
-
hook apt-source handling at curthooks
- 519. By Christian Ehrhardt
-
doc: update new placement of apt-source in curthooks
- 520. By Christian Ehrhardt
-
harden apt-source unittests for more test environments
In some environments the lower levels run a few extra udevadm settle.
This makes the unittests resilent against those slightly different, but
acceptable changes in behavior.
Christian Ehrhardt (paelzer) wrote : | # |
Ran full testsuite, tested build in sbuild and on ppa.
Ready for review and inclusion again.
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:520
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 521. By Christian Ehrhardt
-
remove gpg_ prefix not that related functions are in a gpg.py
- 522. By Christian Ehrhardt
-
drop builtin sources.list
In case there is no custom source list specified we will fall back to modify
the one we find on the given target. That is done with as few dependencies to
the source.list content as possible, to avoid issues in case that changes.
If expected content isn't found curtin will warn about it but not fail.
That means we have time to adapt/fix in case of changes and in the worst case
one can always fix things with a custom template. - 523. By Christian Ehrhardt
-
drop unused method load_tfile_or_url in tests
- 524. By Christian Ehrhardt
-
adapt documentation and examples
Christian Ehrhardt (paelzer) wrote : | # |
Integrated the changes due to our discussion about having no "builtin" source.list.
If no custom template is provided we now fall back to modify whatever we find in the target.
All tests that should be affected passed already as well as an sbuild.
I'm running a ppa build and a full test-suite just to be sure and give this thread another ping then.
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:524
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Christian Ehrhardt (paelzer) wrote : | # |
All tests and ppa build went well, ready for re-review and inclusion.
- 525. By Christian Ehrhardt
-
merge with latest trunk to avoid later merge conflicts
- 526. By Christian Ehrhardt
-
restore populate_subcmd to old coding style, ignoring pylint complaint
This should keep the MP free of unrelated changes
- 527. By Christian Ehrhardt
-
remove unrelated change in curtin/
commands/ install. py That was needed/intended when we still wired it up as extra builtin command.
But no more now that we move to curthooks integration. - 528. By Christian Ehrhardt
-
remove stale merge artifacts
- 529. By Christian Ehrhardt
-
integrate apt in curthooks
This makes the apt feature run by curthooks (but a noop of no config provided).
And additionally keeps the standalone command for other configs/targets. - 530. By Christian Ehrhardt
-
fix apt handling if no config is provided
- 531. By Christian Ehrhardt
-
fix debconf if only provided for unconfigurable packages
- 532. By Christian Ehrhardt
-
log apt_proxy configuration
- 533. By Christian Ehrhardt
-
fix apt conf to match upper/lower case of apt-config
- 534. By Christian Ehrhardt
-
add Testcases for old curtin apt features
- 535. By Christian Ehrhardt
-
match aptproxy config path as specified
- 536. By Christian Ehrhardt
-
translate old curtin apt features to new format
This includes (re-)moving of old curtin code.
All apt related configuration is handled in apt.py now.
In a config that specified old&new content it fails with a proper error
message as they are mutually exclusive (curtin can't decide which one to keep). - 537. By Christian Ehrhardt
-
modify existing functionality and tests to follow the new apt config format
- 538. By Christian Ehrhardt
-
improve mirror and source_list handling
Replace the full string found in config, set the full specified string.
This gets rid of // or no / in testcases.
Set the mirror to what was specified, that is what has to be done.
Also fixup some references to the old custom_source_list to source_list - 539. By Christian Ehrhardt
-
add search and search_dns features
This inherits the cloud-init capabilities for these two features.
But it follows the new apt config format with split options for
primary/secondary for that as well.
Code could be simplified and unified a lot so that despite the extra split
primary/secondary it is mre readable now.
As discussed some fallbacks of cloud-init that rely on cloud-datasource are
dropped in the curtin handling of that configuration. - 540. By Christian Ehrhardt
-
add unittest test_mirror_search
- 541. By Christian Ehrhardt
-
add unittest test_mirror_
search_ dns - 542. By Christian Ehrhardt
-
add unittests test_mirror_
search_ many2 and test_mirror_ search_ many3 - 543. By Christian Ehrhardt
-
drop second subcheck that is already covered by test_mirror_
search_ many3 Would require some extra mocking as now search is hit for dns and non_dns cases.
Since it is covered already drop that part. - 544. By Scott Moser
-
list feature APT_CONFIG_V1
- 545. By Christian Ehrhardt
-
fixed urlparse call path
- 546. By Christian Ehrhardt
-
fix py2/py3 compatibility import of urlparse
- 547. By Christian Ehrhardt
-
add unittests for is_resolvable_url
- 548. By Christian Ehrhardt
-
add vmtest for mirror_search features
- 549. By Christian Ehrhardt
-
make dns search resilent against fqdn not being avavilable
- 550. By Christian Ehrhardt
-
add vmtest for dns_search feature
- 551. By Christian Ehrhardt
-
adapt example to cover search and search_dns features
- 552. By Christian Ehrhardt
-
move primary/security mirror specifications into a dict - code
- 553. By Christian Ehrhardt
-
move primary/security mirror specifications into a dict - examples
- 554. By Christian Ehrhardt
-
move primary/security mirror specifications into a dict - testcases
- 555. By Christian Ehrhardt
-
fix TestAptSrcModify reference to test yaml
- 556. By Christian Ehrhardt
-
make mirror specs per acrhitecture - code
- 557. By Christian Ehrhardt
-
make mirror specs per acrhitecture - examples
- 558. By Christian Ehrhardt
-
make mirror specs per acrhitecture - testcases
- 559. By Christian Ehrhardt
-
arches and repositioned mirrors adapted in doc
- 560. By Christian Ehrhardt
-
add unittest test_mirror
- 561. By Christian Ehrhardt
-
add unittest test_mirror_default
- 562. By Christian Ehrhardt
-
add unittest test_mirror_arches
- 563. By Christian Ehrhardt
-
add unittest test_mirror_
arches_ default - 564. By Christian Ehrhardt
-
add unittest test_mirror_
arches_ sysdefault - 565. By Christian Ehrhardt
-
add vmtest TestAptSrcModif
yArches - 566. By Christian Ehrhardt
-
make replaced archive arch dependent
- 567. By Christian Ehrhardt
-
make tetsing old apt features work cross platforms
- 568. By Christian Ehrhardt
-
make use of new arch-dependent mirrors in unittests
This should also make the tests more likely to work on non amd64 architectures.
- 569. By Christian Ehrhardt
-
make find apt mirror info tests work on ubuntu ports
- 570. By Christian Ehrhardt
-
disable_pockets feature - code
- 571. By Christian Ehrhardt
-
disable_pockets feature - example
- 572. By Christian Ehrhardt
-
disable_pockets feature - unittest
- 573. By Christian Ehrhardt
-
disable_pockets feature - vmtest
- 574. By Christian Ehrhardt
-
update example in rst doc with disable_pockets feature
- 575. By Christian Ehrhardt
-
update docu with some more use cases
- 576. By Christian Ehrhardt
-
adapt old apt feature entry path to new mirrr config
Christian Ehrhardt (paelzer) wrote : | # |
Ready for review - curtin implementation of the new definition as in the gdoc.
I need to update the commit message thou ..
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:576
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:576
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Christian Ehrhardt (paelzer) wrote : | # |
That seems to be stuff that only triggers in an environment even more
restricted than I have tested on horse.
I'll try to fix and push over the day, ...
Christian Ehrhardt
Software Engineer, Ubuntu Server
Canonical Ltd
On Wed, Jul 20, 2016 at 8:08 PM, Server Team CI bot <
<email address hidden>> wrote:
> Review: Needs Fixing continuous-
>
> FAILED: Continuous integration, rev:576
> https:/
> Executed test runs:
> None:
> https:/
>
> Click here to trigger a rebuild:
> https:/
>
> --
>
> https:/
> You are the owner of lp:~paelzer/curtin/bug-1574113-derived-repositories.
>
Christian Ehrhardt (paelzer) wrote : | # |
Hmm,
seems to be about mocking out an object that it hard fetched not from mock
context or so.
What might be interesting for CI in general is that I can reproduce with:
"nosetests tests/unittests" (as called by jenkins), while "make check" runs
just fine.
Christian Ehrhardt
Software Engineer, Ubuntu Server
Canonical Ltd
On Thu, Jul 21, 2016 at 11:16 AM, Christian Ehrhardt <
<email address hidden>> wrote:
> That seems to be stuff that only triggers in an environment even more
> restricted than I have tested on horse.
> I'll try to fix and push over the day, ...
>
> Christian Ehrhardt
> Software Engineer, Ubuntu Server
> Canonical Ltd
>
> On Wed, Jul 20, 2016 at 8:08 PM, Server Team CI bot <
> <email address hidden>> wrote:
>
>> Review: Needs Fixing continuous-
>>
>> FAILED: Continuous integration, rev:576
>> https:/
>> Executed test runs:
>> None:
>> https:/
>>
>> Click here to trigger a rebuild:
>> https:/
>>
>> --
>>
>> https:/
>> You are the owner of lp:~paelzer/curtin/bug-1574113-derived-repositories.
>>
>
>
Christian Ehrhardt (paelzer) wrote : | # |
The magic switch seems to be "--nologcapture" which is kind of unexpected
...
With it enabled things work, without it seems that the mocked call to
get_mirror like:
pmirror = get_mirror(cfg, "primary", arch)
Gets "mocked wrong"
Christian Ehrhardt
Software Engineer, Ubuntu Server
Canonical Ltd
On Thu, Jul 21, 2016 at 11:24 AM, Christian Ehrhardt <
<email address hidden>> wrote:
> Hmm,
> seems to be about mocking out an object that it hard fetched not from mock
> context or so.
> What might be interesting for CI in general is that I can reproduce with:
> "nosetests tests/unittests" (as called by jenkins), while "make check" runs
> just fine.
>
> Christian Ehrhardt
> Software Engineer, Ubuntu Server
> Canonical Ltd
>
> On Thu, Jul 21, 2016 at 11:16 AM, Christian Ehrhardt <
> <email address hidden>> wrote:
>
>> That seems to be stuff that only triggers in an environment even more
>> restricted than I have tested on horse.
>> I'll try to fix and push over the day, ...
>>
>> Christian Ehrhardt
>> Software Engineer, Ubuntu Server
>> Canonical Ltd
>>
>> On Wed, Jul 20, 2016 at 8:08 PM, Server Team CI bot <
>> <email address hidden>> wrote:
>>
>>> Review: Needs Fixing continuous-
>>>
>>> FAILED: Continuous integration, rev:576
>>> https:/
>>> Executed test runs:
>>> None:
>>> https:/
>>>
>>> Click here to trigger a rebuild:
>>> https:/
>>>
>>> --
>>>
>>> https:/
>>> You are the owner of lp:~paelzer/curtin/bug-1574113-derived-repositories.
>>>
>>
>>
>
Christian Ehrhardt (paelzer) wrote : | # |
Ok, things make sense now.
Mocking without retvale sets pmirror to the mock.
That without disabled log leads to "LOG.info("got primary mirror: %s",
pmirror)" be a constructor call.
Ok, that should be fixable ...
Christian Ehrhardt
Software Engineer, Ubuntu Server
Canonical Ltd
On Thu, Jul 21, 2016 at 11:54 AM, Christian Ehrhardt <
<email address hidden>> wrote:
> The magic switch seems to be "--nologcapture" which is kind of unexpected
> ...
> With it enabled things work, without it seems that the mocked call to
> get_mirror like:
> pmirror = get_mirror(cfg, "primary", arch)
> Gets "mocked wrong"
>
> Christian Ehrhardt
> Software Engineer, Ubuntu Server
> Canonical Ltd
>
> On Thu, Jul 21, 2016 at 11:24 AM, Christian Ehrhardt <
> <email address hidden>> wrote:
>
>> Hmm,
>> seems to be about mocking out an object that it hard fetched not from
>> mock context or so.
>> What might be interesting for CI in general is that I can reproduce with:
>> "nosetests tests/unittests" (as called by jenkins), while "make check" runs
>> just fine.
>>
>> Christian Ehrhardt
>> Software Engineer, Ubuntu Server
>> Canonical Ltd
>>
>> On Thu, Jul 21, 2016 at 11:16 AM, Christian Ehrhardt <
>> <email address hidden>> wrote:
>>
>>> That seems to be stuff that only triggers in an environment even more
>>> restricted than I have tested on horse.
>>> I'll try to fix and push over the day, ...
>>>
>>> Christian Ehrhardt
>>> Software Engineer, Ubuntu Server
>>> Canonical Ltd
>>>
>>> On Wed, Jul 20, 2016 at 8:08 PM, Server Team CI bot <
>>> <email address hidden>> wrote:
>>>
>>>> Review: Needs Fixing continuous-
>>>>
>>>> FAILED: Continuous integration, rev:576
>>>> https:/
>>>> Executed test runs:
>>>> None:
>>>> https:/
>>>>
>>>> Click here to trigger a rebuild:
>>>> https:/
>>>>
>>>> --
>>>>
>>>> https:/
>>>> You are the owner of
>>>> lp:~paelzer/curtin/bug-1574113-derived-repositories.
>>>>
>>>
>>>
>>
>
- 577. By Christian Ehrhardt
-
make metohd of apt commandline handling less ambiguous
- 578. By Christian Ehrhardt
-
add docstring to clean_cloud_init
- 579. By Christian Ehrhardt
-
follow the "logging-not-lazy" warning of checkers and change string extension
- 580. By Christian Ehrhardt
-
fix unittests for cases without --nologcapture
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:580
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Christian Ehrhardt (paelzer) wrote : | # |
Hmm, that is tox now with a special case on urllib which changed py2->py3.
General question - should we make a tox run part of make check ?
- 581. By Christian Ehrhardt
-
avoid py2 pylint issue due to renamed urllib import
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:581
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:581
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Scott Moser (smoser) wrote : | # |
Started a vmtest run at
https:/
I dont think we have 'preserve_
Our doc says:
| preserve_
| # For cloud-init this defaults to false. By default, cloud-init renders
| # /etc/apt/
| # For Curtin this defaults to false. By default, curtin will always attempt to
| # replace mirrors inside the sources.list it finds in the image.
| # Curtin will configure cloud-init in the target via
| # /etc/cloud/
| # which causes cloud-init to not touch /etc/apt/
| # Unless explicitly requested by cloud-init userdata (overwriting to False).
| # Effectively this changes the default from False to True
I thought that in discussion you and I had agreed that this was in fact 'boolean', and that curtin would *always* replace /etc/apt/
That said, i do not see where curtin is configuring cloud-init in the target to set. curtin should always set cloud-init to preserve sources.list unless there is another use case that i'm missing.
I'm not done with the review yet, but wanted to hit 'submit' before losing context and losing what i had done.
Scott Moser (smoser) wrote : | # |
for disable_pockets, it looks to me like the string provided always has the release prepended.
for example:
disable_pockets = [updates]
will disable 'trusty-updates'.
that makes sense.
but for:
disable_pockets = ["mypocket", "unstable"]
this doesnt make so much sense.
I dont know how easily to do this other than special casing the words:
updates, release, security, backports
also, might want to just check that this content from my /etc/apt/
deb [arch=amd64] http://
Scott Moser (smoser) wrote : | # |
I thought that 'uri' would override 'search', does it?
Christian Ehrhardt (paelzer) wrote : | # |
> Started a vmtest run at
> https:/
Thanks, that one worked at least.
> I dont think we have 'preserve_
Yeah the tristate was dropped in our discussion yet the doc needs update (DONE now).
The placing of the config for cloud-init was missing (I missed to add to our todo's after the discussion).
Pushed in the next update to the MP.
Also all vmtests that take care to check.
So far I provided "preserve_
It seems I need something to make cloud-init to pick up the config thou - will contact you later today as I guess that is talked in 3 or searched in 15 minutes :-)
Christian Ehrhardt (paelzer) wrote : | # |
> I thought that 'uri' would override 'search', does it?
Yes it does:
see curtin/
1. uri
2. search
3. search_dns
As soon as one of 1-3 hits the others aren't checked anymore.
Also see the following unittests that ensure this is true:
test_mirror_
test_mirror_
Christian Ehrhardt (paelzer) wrote : | # |
> for disable_pockets, it looks to me like the string provided always has the
> release prepended.
> for example:
> disable_pockets = [updates]
> will disable 'trusty-updates'.
>
> that makes sense.
> but for:
> disable_pockets = ["mypocket", "unstable"]
> this doesnt make so much sense.
> I dont know how easily to do this other than special casing the words:
> updates, release, security, backports
I didn't think of "custom" pockets yet, but I see no other easy way than "special casing" them.
> also, might want to just check that this content from my
> /etc/apt/
> deb [arch=amd64] http://
Hrm, yeah man sources.list states this (options) in the section "ONE-LINE-STYLE FORMAT".
I need to adapt to work with them as well.
Although it is highly unlikely to find some in a source.list (disabling doesn't care about other files in sources.list.d) these days we should look ahead and be prepared.
Working on it ...
Christian Ehrhardt (paelzer) wrote : | # |
> > I dont know how easily to do this other than special casing the words:
> > updates, release, security, backports
>
> I didn't think of "custom" pockets yet, but I see no other easy way than
> "special casing" them.
I was missing an "... either" here.
But giving it some thought - if we go as far as to allow custom pocket names.
We need to cover custom pocket names that match the known names.
So what if someone has a "updates" pocket and it shall not become xenial-updates.
We already have a way to specify these and I think we should stick to that.
We can allow $RELEASE in there and replace it, just as we do when rendering sources.list in the first place.
That allows one to differentiate between: "$RELEASE-updates" and "updates"
That also covers the sepcial case of the main release pocket being "".
One can just specify "$RELEASE" and gets e.g. "xenial" which is just what we need in that case as well.
Christian Ehrhardt (paelzer) wrote : | # |
Reading more into it we should think about:
- what we called "pockets" is actually defined as "suite" - should we rename our option?
- long term (not for this bug & MP) think about supporting deb822 format as well
- 582. By Christian Ehrhardt
-
leave cloud-init config to prevent clobbering sources.list
- 583. By Christian Ehrhardt
-
add $RELEASE replacement to disable_pockets
- 584. By Christian Ehrhardt
-
improve doc wording
- 585. By Christian Ehrhardt
-
check for old apt_preserve_list config as we select th eold for compatibility
- 586. By Christian Ehrhardt
-
fix typo
- 587. By Christian Ehrhardt
-
support source.list lines with options
- 588. By Christian Ehrhardt
-
cover options in source.list lines in unittests
- 589. By Christian Ehrhardt
-
fix test_old_
apt_features vmtest - 590. By Christian Ehrhardt
-
switch apt_preserve_
sources_ list to True Now that all tests have succeeded we switch the apt_preserve_
sources_ list
that is passed to cloud-init to True to keep curtin rendered sources.list
intact unless overwritten by user data. - 591. By Christian Ehrhardt
-
rename pocket to suite following man sources.list
- 592. By Christian Ehrhardt
-
rename curtin-
preserve- sources. list to curtin- preserve- sources. cfg The example in the gdoc was uncommon, clout-init usually has .cfg files
- 593. By Christian Ehrhardt
-
rename vmtets yaml following the pockets to suite rename
- 594. By Christian Ehrhardt
-
fix preserve check in vmtest TestAptSrcPreserve
In this path the preserving of the target is not triggered, so the respective
checks need to be adapted.
Christian Ehrhardt (paelzer) wrote : | # |
All Feedback handled and a bit more (according to my comments to the review feedback before).
Ready again.
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:594
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
FAILED: Continuous integration, rev:594
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
- 595. By Christian Ehrhardt
-
make unittests runnable as non-privileged user in tox
- 596. By Christian Ehrhardt
-
let curtin exit with failure if protecting sources.list didn't work
- 597. By Christian Ehrhardt
-
make trusty pep8 happy which even complains about raw string length
Christian Ehrhardt (paelzer) wrote : | # |
de-toxed the unitests for disable_suites
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:597
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:597
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild:
https:/
Scott Moser (smoser) wrote : | # |
> > > I dont know how easily to do this other than special casing the words:
> > > updates, release, security, backports
> >
> > I didn't think of "custom" pockets yet, but I see no other easy way than
> > "special casing" them.
>
> I was missing an "... either" here.
>
> But giving it some thought - if we go as far as to allow custom pocket names.
> We need to cover custom pocket names that match the known names.
> So what if someone has a "updates" pocket and it shall not become xenial-
> updates.
>
> We already have a way to specify these and I think we should stick to that.
> We can allow $RELEASE in there and replace it, just as we do when rendering
> sources.list in the first place.
>
> That allows one to differentiate between: "$RELEASE-updates" and "updates"
>
> That also covers the sepcial case of the main release pocket being "".
> One can just specify "$RELEASE" and gets e.g. "xenial" which is just what we
> need in that case as well.
I'd really prefer to handle let the user specify 'updates', 'release' literally rather than '$RELEASE-updates'.
that does mean that these "well known names" block the user from using pockets literally named 'release'. I usually dont like such holes in design, but i think it might be worth it here for readability. The pocket names 'release', 'updates', 'proposed' and 'backports' are well known in Ubuntu (example https:/
given the same url there, i use that for justification of the name 'pockets'. If you'd like we can also support 'suites', but i think pocket is fine.
Scott Moser (smoser) wrote : | # |
I think you must not have seen my in-line comments in my review that starts with
'for disable_pockets, '
- 598. By Christian Ehrhardt
-
auto extend known ubunut suites by $RELEASE-
- 599. By Christian Ehrhardt
-
reduce default verbosity of apt feature by moving some info to debug
- 600. By Christian Ehrhardt
-
make old apt features less verbose
- 601. By Christian Ehrhardt
-
move old apt feature config conversion into own method and out of curthooks
- 602. By Christian Ehrhardt
-
rework apt standalone command entry path
This is dropping a lot of old artifacts from the command entry path.
- 603. By Christian Ehrhardt
-
minimal commandline call test for apt features
- 604. By Christian Ehrhardt
-
add spaced around string concat plus operators
- 605. By Christian Ehrhardt
-
merge rev 400: move uefi boot knowledge from launch and vmtest to xkvm
Christian Ehrhardt (paelzer) wrote : | # |
All we discussed yesterday night is in now, ready for review/merge
- 606. By Christian Ehrhardt
-
fix config of ChrootableTarget for apt command
- 607. By Christian Ehrhardt
-
adapt standalong command example to new invocation
- 608. By Christian Ehrhardt
-
change standalong apt command test to be vmtest based
- 609. By Christian Ehrhardt
-
rename apt to apt_config for stanalone command
That implies to rename the module name as well.
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:609
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
- 610. By Christian Ehrhardt
-
change apt to apt-config in vmtest
- 611. By Christian Ehrhardt
-
change ppa's and keys used to something under our control
- 612. By Christian Ehrhardt
-
change the preserve_
sources_ list default to True in curtin - 613. By Christian Ehrhardt
-
rework testing of standalone command
- 614. By Christian Ehrhardt
-
make copy in testcases release independent
- 615. By Christian Ehrhardt
-
add fallback if user did not add .list to source keys
Includes modification to one of the testcastes to cover that.
- 616. By Christian Ehrhardt
-
fixup test to check for content added by apt-add-repository
Server Team CI bot (server-team-bot) wrote : | # |
PASSED: Continuous integration, rev:616
https:/
Executed test runs:
SUCCESS: https:/
SUCCESS: https:/
Click here to trigger a rebuild:
https:/
Christian Ehrhardt (paelzer) wrote : | # |
Since we co-work on a branch that we can jointly push to now there is a new MP at https:/
This old MP here is kept open to have the discussion history available (not sure if it would go away when rejecting the old MP).
Preview Diff
1 | === modified file 'curtin/__init__.py' | |||
2 | --- curtin/__init__.py 2015-10-26 17:35:29 +0000 | |||
3 | +++ curtin/__init__.py 2016-07-26 19:53:43 +0000 | |||
4 | @@ -33,6 +33,8 @@ | |||
5 | 33 | 'SUBCOMMAND_SYSTEM_INSTALL', | 33 | 'SUBCOMMAND_SYSTEM_INSTALL', |
6 | 34 | # subcommand 'system-upgrade' is present | 34 | # subcommand 'system-upgrade' is present |
7 | 35 | 'SUBCOMMAND_SYSTEM_UPGRADE', | 35 | 'SUBCOMMAND_SYSTEM_UPGRADE', |
8 | 36 | # supports new format of apt configuration | ||
9 | 37 | 'APT_CONFIG_V1', | ||
10 | 36 | ] | 38 | ] |
11 | 37 | 39 | ||
12 | 38 | # vi: ts=4 expandtab syntax=python | 40 | # vi: ts=4 expandtab syntax=python |
13 | 39 | 41 | ||
14 | === added file 'curtin/commands/apt_config.py' | |||
15 | --- curtin/commands/apt_config.py 1970-01-01 00:00:00 +0000 | |||
16 | +++ curtin/commands/apt_config.py 2016-07-26 19:53:43 +0000 | |||
17 | @@ -0,0 +1,691 @@ | |||
18 | 1 | # Copyright (C) 2016 Canonical Ltd. | ||
19 | 2 | # | ||
20 | 3 | # Author: Christian Ehrhardt <christian.ehrhardt@canonical.com> | ||
21 | 4 | # | ||
22 | 5 | # Curtin is free software: you can redistribute it and/or modify it under | ||
23 | 6 | # the terms of the GNU Affero General Public License as published by the | ||
24 | 7 | # Free Software Foundation, either version 3 of the License, or (at your | ||
25 | 8 | # option) any later version. | ||
26 | 9 | # | ||
27 | 10 | # Curtin is distributed in the hope that it will be useful, but WITHOUT ANY | ||
28 | 11 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
29 | 12 | # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for | ||
30 | 13 | # more details. | ||
31 | 14 | # | ||
32 | 15 | # You should have received a copy of the GNU Affero General Public License | ||
33 | 16 | # along with Curtin. If not, see <http://www.gnu.org/licenses/>. | ||
34 | 17 | """ | ||
35 | 18 | apt.py | ||
36 | 19 | Handling the setup of apt related tasks like proxies, PGP keys, repositories. | ||
37 | 20 | """ | ||
38 | 21 | |||
39 | 22 | import argparse | ||
40 | 23 | import glob | ||
41 | 24 | import os | ||
42 | 25 | import re | ||
43 | 26 | import sys | ||
44 | 27 | import yaml | ||
45 | 28 | |||
46 | 29 | from curtin.log import LOG | ||
47 | 30 | from curtin import (config, util, gpg) | ||
48 | 31 | |||
49 | 32 | from . import populate_one_subcmd | ||
50 | 33 | |||
51 | 34 | # this will match 'XXX:YYY' (ie, 'cloud-archive:foo' or 'ppa:bar') | ||
52 | 35 | ADD_APT_REPO_MATCH = r"^[\w-]+:\w" | ||
53 | 36 | |||
54 | 37 | # place where apt stores cached repository data | ||
55 | 38 | APT_LISTS = "/var/lib/apt/lists" | ||
56 | 39 | |||
57 | 40 | # Files to store proxy information | ||
58 | 41 | APT_CONFIG_FN = "/etc/apt/apt.conf.d/94curtin-config" | ||
59 | 42 | APT_PROXY_FN = "/etc/apt/apt.conf.d/90curtin-aptproxy" | ||
60 | 43 | |||
61 | 44 | # Default keyserver to use | ||
62 | 45 | DEFAULT_KEYSERVER = "keyserver.ubuntu.com" | ||
63 | 46 | |||
64 | 47 | # Default archive mirrors | ||
65 | 48 | PRIMARY_ARCH_MIRRORS = {"PRIMARY": "http://archive.ubuntu.com/ubuntu/", | ||
66 | 49 | "SECURITY": "http://security.ubuntu.com/ubuntu/"} | ||
67 | 50 | PORTS_MIRRORS = {"PRIMARY": "http://ports.ubuntu.com/ubuntu-ports", | ||
68 | 51 | "SECURITY": "http://ports.ubuntu.com/ubuntu-ports"} | ||
69 | 52 | PRIMARY_ARCHES = ['amd64', 'i386'] | ||
70 | 53 | PORTS_ARCHES = ['s390x', 'arm64', 'armhf', 'powerpc', 'ppc64el'] | ||
71 | 54 | |||
72 | 55 | |||
73 | 56 | def get_default_mirrors(target=None): | ||
74 | 57 | """returns the default mirrors for the target. These depend on the | ||
75 | 58 | architecture, for more see: | ||
76 | 59 | https://wiki.ubuntu.com/UbuntuDevelopment/PackageArchive#Ports""" | ||
77 | 60 | arch = util.get_architecture(target) | ||
78 | 61 | if arch in PRIMARY_ARCHES: | ||
79 | 62 | return PRIMARY_ARCH_MIRRORS | ||
80 | 63 | if arch in PORTS_ARCHES: | ||
81 | 64 | return PORTS_MIRRORS | ||
82 | 65 | raise ValueError("No default mirror known for arch %s" % arch) | ||
83 | 66 | |||
84 | 67 | |||
85 | 68 | def handle_apt(cfg, target): | ||
86 | 69 | """ handle_apt | ||
87 | 70 | process the config for apt_config. This can be called from | ||
88 | 71 | curthooks if a global apt config was provided or via the "apt" | ||
89 | 72 | standalone command. | ||
90 | 73 | """ | ||
91 | 74 | release = util.lsb_release(target=target)['codename'] | ||
92 | 75 | mirrors = find_apt_mirror_info(cfg, target) | ||
93 | 76 | LOG.debug("Apt Mirror info: %s", mirrors) | ||
94 | 77 | |||
95 | 78 | apply_debconf_selections(cfg, target) | ||
96 | 79 | |||
97 | 80 | if not config.value_as_boolean(cfg.get('preserve_sources_list', | ||
98 | 81 | True)): | ||
99 | 82 | generate_sources_list(cfg, release, mirrors, target) | ||
100 | 83 | rename_apt_lists(mirrors, target) | ||
101 | 84 | |||
102 | 85 | try: | ||
103 | 86 | apply_apt_proxy_config(cfg, target + APT_PROXY_FN, | ||
104 | 87 | target + APT_CONFIG_FN) | ||
105 | 88 | except (IOError, OSError): | ||
106 | 89 | LOG.exception("Failed to apply proxy or apt config info:") | ||
107 | 90 | |||
108 | 91 | # Process 'apt_source -> sources {dict}' | ||
109 | 92 | if 'sources' in cfg: | ||
110 | 93 | params = mirrors | ||
111 | 94 | params['RELEASE'] = release | ||
112 | 95 | params['MIRROR'] = mirrors["MIRROR"] | ||
113 | 96 | |||
114 | 97 | matcher = None | ||
115 | 98 | matchcfg = cfg.get('add_apt_repo_match', ADD_APT_REPO_MATCH) | ||
116 | 99 | if matchcfg: | ||
117 | 100 | matcher = re.compile(matchcfg).search | ||
118 | 101 | |||
119 | 102 | add_apt_sources(cfg['sources'], target, | ||
120 | 103 | template_params=params, aa_repo_match=matcher) | ||
121 | 104 | |||
122 | 105 | |||
123 | 106 | def apply_debconf_selections(cfg, target): | ||
124 | 107 | """apply_debconf_selections - push content to debconf""" | ||
125 | 108 | # debconf_selections: | ||
126 | 109 | # set1: | | ||
127 | 110 | # cloud-init cloud-init/datasources multiselect MAAS | ||
128 | 111 | # set2: pkg pkg/value string bar | ||
129 | 112 | selsets = cfg.get('debconf_selections') | ||
130 | 113 | if not selsets: | ||
131 | 114 | LOG.debug("debconf_selections was not set in config") | ||
132 | 115 | return | ||
133 | 116 | |||
134 | 117 | # for each entry in selections, chroot and apply them. | ||
135 | 118 | # keep a running total of packages we've seen. | ||
136 | 119 | pkgs_cfgd = set() | ||
137 | 120 | for key, content in selsets.items(): | ||
138 | 121 | LOG.debug("setting for %s, %s", key, content) | ||
139 | 122 | util.subp(['chroot', target, 'debconf-set-selections'], | ||
140 | 123 | data=content.encode()) | ||
141 | 124 | for line in content.splitlines(): | ||
142 | 125 | if line.startswith("#"): | ||
143 | 126 | continue | ||
144 | 127 | pkg = re.sub(r"[:\s].*", "", line) | ||
145 | 128 | pkgs_cfgd.add(pkg) | ||
146 | 129 | |||
147 | 130 | pkgs_installed = util.get_installed_packages(target) | ||
148 | 131 | |||
149 | 132 | LOG.debug("pkgs_cfgd: %s", pkgs_cfgd) | ||
150 | 133 | LOG.debug("pkgs_installed: %s", pkgs_installed) | ||
151 | 134 | need_reconfig = pkgs_cfgd.intersection(pkgs_installed) | ||
152 | 135 | |||
153 | 136 | if len(need_reconfig) == 0: | ||
154 | 137 | LOG.debug("no need for reconfig") | ||
155 | 138 | return | ||
156 | 139 | |||
157 | 140 | # For any packages that are already installed, but have preseed data | ||
158 | 141 | # we populate the debconf database, but the filesystem configuration | ||
159 | 142 | # would be preferred on a subsequent dpkg-reconfigure. | ||
160 | 143 | # so, what we have to do is "know" information about certain packages | ||
161 | 144 | # to unconfigure them. | ||
162 | 145 | unhandled = [] | ||
163 | 146 | to_config = [] | ||
164 | 147 | for pkg in need_reconfig: | ||
165 | 148 | if pkg in CONFIG_CLEANERS: | ||
166 | 149 | LOG.debug("unconfiguring %s", pkg) | ||
167 | 150 | CONFIG_CLEANERS[pkg](target) | ||
168 | 151 | to_config.append(pkg) | ||
169 | 152 | else: | ||
170 | 153 | unhandled.append(pkg) | ||
171 | 154 | |||
172 | 155 | if len(unhandled): | ||
173 | 156 | LOG.warn("The following packages were installed and preseeded, " | ||
174 | 157 | "but cannot be unconfigured: %s", unhandled) | ||
175 | 158 | |||
176 | 159 | if len(to_config): | ||
177 | 160 | util.subp(['chroot', target, 'dpkg-reconfigure', | ||
178 | 161 | '--frontend=noninteractive'] + | ||
179 | 162 | list(to_config), data=None) | ||
180 | 163 | |||
181 | 164 | |||
182 | 165 | def clean_cloud_init(target): | ||
183 | 166 | """clean out any local cloud-init config""" | ||
184 | 167 | flist = glob.glob( | ||
185 | 168 | os.path.sep.join([target, "/etc/cloud/cloud.cfg.d/*dpkg*"])) | ||
186 | 169 | |||
187 | 170 | LOG.debug("cleaning cloud-init config from: %s", flist) | ||
188 | 171 | for dpkg_cfg in flist: | ||
189 | 172 | os.unlink(dpkg_cfg) | ||
190 | 173 | |||
191 | 174 | |||
192 | 175 | def mirrorurl_to_apt_fileprefix(mirror): | ||
193 | 176 | """ mirrorurl_to_apt_fileprefix | ||
194 | 177 | Convert a mirror url to the file prefix used by apt on disk to | ||
195 | 178 | store cache information for that mirror. | ||
196 | 179 | To do so do: | ||
197 | 180 | - take off ???:// | ||
198 | 181 | - drop tailing / | ||
199 | 182 | - convert in string / to _ | ||
200 | 183 | """ | ||
201 | 184 | string = mirror | ||
202 | 185 | if string.endswith("/"): | ||
203 | 186 | string = string[0:-1] | ||
204 | 187 | pos = string.find("://") | ||
205 | 188 | if pos >= 0: | ||
206 | 189 | string = string[pos + 3:] | ||
207 | 190 | string = string.replace("/", "_") | ||
208 | 191 | return string | ||
209 | 192 | |||
210 | 193 | |||
211 | 194 | def rename_apt_lists(new_mirrors, target): | ||
212 | 195 | """rename_apt_lists - rename apt lists to preserve old cache data""" | ||
213 | 196 | default_mirrors = get_default_mirrors(target) | ||
214 | 197 | for (name, omirror) in default_mirrors.items(): | ||
215 | 198 | nmirror = new_mirrors.get(name) | ||
216 | 199 | if not nmirror: | ||
217 | 200 | continue | ||
218 | 201 | oprefix = os.path.join(target, APT_LISTS, | ||
219 | 202 | mirrorurl_to_apt_fileprefix(omirror)) | ||
220 | 203 | nprefix = os.path.join(target, APT_LISTS, | ||
221 | 204 | mirrorurl_to_apt_fileprefix(nmirror)) | ||
222 | 205 | if oprefix == nprefix: | ||
223 | 206 | continue | ||
224 | 207 | olen = len(oprefix) | ||
225 | 208 | for filename in glob.glob("%s_*" % oprefix): | ||
226 | 209 | newname = "%s%s" % (nprefix, filename[olen:]) | ||
227 | 210 | LOG.debug("Renaming apt list %s to %s", filename, newname) | ||
228 | 211 | try: | ||
229 | 212 | os.rename(filename, newname) | ||
230 | 213 | except OSError: | ||
231 | 214 | # since this is a best effort task, warn with but don't fail | ||
232 | 215 | LOG.warn("Failed to rename apt list:", exc_info=True) | ||
233 | 216 | |||
234 | 217 | |||
235 | 218 | def mirror_to_placeholder(tmpl, mirror, placeholder): | ||
236 | 219 | """ mirror_to_placeholder | ||
237 | 220 | replace the specified mirror in a template with a placeholder string | ||
238 | 221 | Checks for existance of the expected mirror and warns if not found | ||
239 | 222 | """ | ||
240 | 223 | if mirror not in tmpl: | ||
241 | 224 | LOG.warn("Expected mirror '%s' not found in: %s", mirror, tmpl) | ||
242 | 225 | return tmpl.replace(mirror, placeholder) | ||
243 | 226 | |||
244 | 227 | |||
245 | 228 | def map_known_suites(suite): | ||
246 | 229 | """there are a few default names which will be auto-extended. | ||
247 | 230 | This comes at the inability to use those names literally as suites, | ||
248 | 231 | but on the other hand increases readability of the cfg quite a lot""" | ||
249 | 232 | mapping = {'updates': '$RELEASE-updates', | ||
250 | 233 | 'backports': '$RELEASE-backports', | ||
251 | 234 | 'security': '$RELEASE-security', | ||
252 | 235 | 'proposed': '$RELEASE-proposed', | ||
253 | 236 | 'release': '$RELEASE'} | ||
254 | 237 | try: | ||
255 | 238 | retsuite = mapping[suite] | ||
256 | 239 | except KeyError: | ||
257 | 240 | retsuite = suite | ||
258 | 241 | return retsuite | ||
259 | 242 | |||
260 | 243 | |||
261 | 244 | def disable_suites(cfg, src, release): | ||
262 | 245 | """reads the config for suites to be disabled and removes those | ||
263 | 246 | from the template""" | ||
264 | 247 | retsrc = src | ||
265 | 248 | suites_to_disable = cfg.get('disable_suites', None) | ||
266 | 249 | if suites_to_disable is not None: | ||
267 | 250 | for suite in suites_to_disable: | ||
268 | 251 | suite = map_known_suites(suite) | ||
269 | 252 | releasesuite = util.render_string(suite, {'RELEASE': release}) | ||
270 | 253 | LOG.debug("Disabling suite %s as %s", suite, releasesuite) | ||
271 | 254 | |||
272 | 255 | newsrc = "" | ||
273 | 256 | for line in retsrc.splitlines(True): | ||
274 | 257 | if line.startswith("#"): | ||
275 | 258 | newsrc += line | ||
276 | 259 | continue | ||
277 | 260 | |||
278 | 261 | # sources.list allow options in cols[1] which can have spaces | ||
279 | 262 | # so the actual suite can be [2] or later | ||
280 | 263 | cols = line.split() | ||
281 | 264 | pcol = 2 | ||
282 | 265 | if cols[1].startswith("["): | ||
283 | 266 | for col in cols[1:]: | ||
284 | 267 | pcol += 1 | ||
285 | 268 | if col.endswith("]"): | ||
286 | 269 | break | ||
287 | 270 | |||
288 | 271 | if cols[pcol] == releasesuite: | ||
289 | 272 | line = '# suite disabled by curtin: %s' % line | ||
290 | 273 | newsrc += line | ||
291 | 274 | retsrc = newsrc | ||
292 | 275 | |||
293 | 276 | return retsrc | ||
294 | 277 | |||
295 | 278 | |||
296 | 279 | def generate_sources_list(cfg, release, mirrors, target): | ||
297 | 280 | """ generate_sources_list | ||
298 | 281 | create a source.list file based on a custom or default template | ||
299 | 282 | by replacing mirrors and release in the template | ||
300 | 283 | """ | ||
301 | 284 | default_mirrors = get_default_mirrors(target) | ||
302 | 285 | aptsrc = "/etc/apt/sources.list" | ||
303 | 286 | params = {'RELEASE': release} | ||
304 | 287 | for k in mirrors: | ||
305 | 288 | params[k] = mirrors[k] | ||
306 | 289 | |||
307 | 290 | tmpl = cfg.get('sources_list', None) | ||
308 | 291 | if tmpl is None: | ||
309 | 292 | LOG.info("No custom template provided, fall back to modify" | ||
310 | 293 | "mirrors in %s on the target system", aptsrc) | ||
311 | 294 | tmpl = util.load_file(target + aptsrc) | ||
312 | 295 | # Strategy if no custom template was provided: | ||
313 | 296 | # - Only replacing mirrors | ||
314 | 297 | # - no reason to replace "release" as it is from target anyway | ||
315 | 298 | # - The less we depend upon, the more stable this is against changes | ||
316 | 299 | # - warn if expected original content wasn't found | ||
317 | 300 | tmpl = mirror_to_placeholder(tmpl, default_mirrors['PRIMARY'], | ||
318 | 301 | "$MIRROR") | ||
319 | 302 | tmpl = mirror_to_placeholder(tmpl, default_mirrors['SECURITY'], | ||
320 | 303 | "$SECURITY") | ||
321 | 304 | try: | ||
322 | 305 | os.rename(target + aptsrc, | ||
323 | 306 | target + aptsrc + ".curtin") | ||
324 | 307 | except OSError: | ||
325 | 308 | LOG.exception("failed to backup %s/%s", target, aptsrc) | ||
326 | 309 | |||
327 | 310 | rendered = util.render_string(tmpl, params) | ||
328 | 311 | disabled = disable_suites(cfg, rendered, release) | ||
329 | 312 | util.write_file(target + aptsrc, disabled, mode=0o644) | ||
330 | 313 | |||
331 | 314 | # protect the just generated sources.list from cloud-init | ||
332 | 315 | clouddir = "/etc/cloud/cloud.cfg.d" | ||
333 | 316 | cloudfile = clouddir + "/" + "curtin-preserve-sources.cfg" | ||
334 | 317 | # this has to work with older cloud-init as well, so use old key | ||
335 | 318 | cloudconf = yaml.dump({'apt_preserve_sources_list': True}, indent=1) | ||
336 | 319 | util.subp(['mkdir', '-p', target + clouddir], rcs=[0, 1]) | ||
337 | 320 | try: | ||
338 | 321 | util.write_file(target + cloudfile, cloudconf, mode=0o644) | ||
339 | 322 | except IOError: | ||
340 | 323 | LOG.exception("Failed to protect source.list from cloud-init in (%s)", | ||
341 | 324 | target + cloudfile) | ||
342 | 325 | raise | ||
343 | 326 | |||
344 | 327 | |||
345 | 328 | def add_apt_key_raw(key, target): | ||
346 | 329 | """ | ||
347 | 330 | actual adding of a key as defined in key argument | ||
348 | 331 | to the system | ||
349 | 332 | """ | ||
350 | 333 | LOG.debug("Adding key:\n'%s'", key) | ||
351 | 334 | try: | ||
352 | 335 | with util.RunInChroot(target, allow_daemons=True) as in_chroot: | ||
353 | 336 | in_chroot(['apt-key', 'add', '-'], data=key.encode()) | ||
354 | 337 | except util.ProcessExecutionError: | ||
355 | 338 | LOG.exception("failed to add apt GPG Key to apt keyring") | ||
356 | 339 | raise | ||
357 | 340 | |||
358 | 341 | |||
359 | 342 | def add_apt_key(ent, target): | ||
360 | 343 | """ | ||
361 | 344 | Add key to the system as defined in ent (if any). | ||
362 | 345 | Supports raw keys or keyid's | ||
363 | 346 | The latter will as a first step fetched to get the raw key | ||
364 | 347 | """ | ||
365 | 348 | if 'keyid' in ent and 'key' not in ent: | ||
366 | 349 | keyserver = DEFAULT_KEYSERVER | ||
367 | 350 | if 'keyserver' in ent: | ||
368 | 351 | keyserver = ent['keyserver'] | ||
369 | 352 | |||
370 | 353 | ent['key'] = gpg.getkeybyid(ent['keyid'], keyserver) | ||
371 | 354 | |||
372 | 355 | if 'key' in ent: | ||
373 | 356 | add_apt_key_raw(ent['key'], target) | ||
374 | 357 | |||
375 | 358 | |||
376 | 359 | def add_apt_sources(srcdict, target, template_params=None, aa_repo_match=None): | ||
377 | 360 | """ | ||
378 | 361 | add entries in /etc/apt/sources.list.d for each abbreviated | ||
379 | 362 | sources.list entry in 'srcdict'. When rendering template, also | ||
380 | 363 | include the values in dictionary searchList | ||
381 | 364 | """ | ||
382 | 365 | if template_params is None: | ||
383 | 366 | template_params = {} | ||
384 | 367 | |||
385 | 368 | if aa_repo_match is None: | ||
386 | 369 | raise ValueError('did not get a valid repo matcher') | ||
387 | 370 | |||
388 | 371 | if not isinstance(srcdict, dict): | ||
389 | 372 | raise TypeError('unknown apt format: %s' % (srcdict)) | ||
390 | 373 | |||
391 | 374 | for filename in srcdict: | ||
392 | 375 | ent = srcdict[filename] | ||
393 | 376 | if 'filename' not in ent: | ||
394 | 377 | ent['filename'] = filename | ||
395 | 378 | |||
396 | 379 | add_apt_key(ent, target) | ||
397 | 380 | |||
398 | 381 | if 'source' not in ent: | ||
399 | 382 | continue | ||
400 | 383 | source = ent['source'] | ||
401 | 384 | source = util.render_string(source, template_params) | ||
402 | 385 | |||
403 | 386 | if not ent['filename'].startswith("/"): | ||
404 | 387 | ent['filename'] = os.path.join("/etc/apt/sources.list.d/", | ||
405 | 388 | ent['filename']) | ||
406 | 389 | if not ent['filename'].endswith(".list"): | ||
407 | 390 | ent['filename'] += ".list" | ||
408 | 391 | |||
409 | 392 | if aa_repo_match(source): | ||
410 | 393 | try: | ||
411 | 394 | with util.RunInChroot(target, allow_daemons=True) as in_chroot: | ||
412 | 395 | in_chroot(["add-apt-repository", source]) | ||
413 | 396 | except util.ProcessExecutionError: | ||
414 | 397 | LOG.exception("add-apt-repository failed.") | ||
415 | 398 | raise | ||
416 | 399 | continue | ||
417 | 400 | |||
418 | 401 | sourcefn = target + ent['filename'] | ||
419 | 402 | try: | ||
420 | 403 | contents = "%s\n" % (source) | ||
421 | 404 | util.write_file(sourcefn, contents, omode="a") | ||
422 | 405 | except IOError as detail: | ||
423 | 406 | LOG.exception("failed write to file %s: %s", sourcefn, detail) | ||
424 | 407 | raise | ||
425 | 408 | |||
426 | 409 | util.apt_update(target=target, force=True, | ||
427 | 410 | comment="apt-source changed config") | ||
428 | 411 | |||
429 | 412 | return | ||
430 | 413 | |||
431 | 414 | |||
432 | 415 | def search_for_mirror(candidates): | ||
433 | 416 | """ | ||
434 | 417 | Search through a list of mirror urls for one that works | ||
435 | 418 | This needs to return quickly. | ||
436 | 419 | """ | ||
437 | 420 | if candidates is None: | ||
438 | 421 | return None | ||
439 | 422 | |||
440 | 423 | for cand in candidates: | ||
441 | 424 | try: | ||
442 | 425 | if util.is_resolvable_url(cand): | ||
443 | 426 | return cand | ||
444 | 427 | except Exception: | ||
445 | 428 | pass | ||
446 | 429 | return None | ||
447 | 430 | |||
448 | 431 | |||
449 | 432 | def search_for_mirror_dns(enabled, mirrortext): | ||
450 | 433 | "builds a list of potential mirror to check" | ||
451 | 434 | if enabled is None or not enabled: | ||
452 | 435 | return None | ||
453 | 436 | |||
454 | 437 | mydom = "" | ||
455 | 438 | doms = [] | ||
456 | 439 | |||
457 | 440 | # curtin has no fqdn/hostname in config as cloud-init | ||
458 | 441 | # but if we got a hostname by dhcp, then search its domain portion first | ||
459 | 442 | try: | ||
460 | 443 | (fqdn, _) = util.subp(["hostname", "--fqdn"], rcs=[0], capture=True) | ||
461 | 444 | mydom = ".".join(fqdn.split(".")[1:]) | ||
462 | 445 | if mydom: | ||
463 | 446 | doms.append(".%s" % mydom) | ||
464 | 447 | except util.ProcessExecutionError: | ||
465 | 448 | # this can happen if /etc/hostname isn't set up properly yet | ||
466 | 449 | # so log, but don't fail | ||
467 | 450 | LOG.exception("failed to get fqdn") | ||
468 | 451 | |||
469 | 452 | doms.extend((".localdomain", "",)) | ||
470 | 453 | |||
471 | 454 | potential_mirror_list = [] | ||
472 | 455 | # for curtin just ubuntu instead of fetching from datasource | ||
473 | 456 | distro = "ubuntu" | ||
474 | 457 | mirrorfmt = "http://%s-%s%s/%s" % (distro, mirrortext, "%s", distro) | ||
475 | 458 | for post in doms: | ||
476 | 459 | potential_mirror_list.append(mirrorfmt % (post)) | ||
477 | 460 | |||
478 | 461 | return search_for_mirror(potential_mirror_list) | ||
479 | 462 | |||
480 | 463 | |||
481 | 464 | def update_mirror_info(pmirror, smirror, target=None): | ||
482 | 465 | """sets security mirror to primary if not defined. | ||
483 | 466 | returns defaults if no mirrors are defined""" | ||
484 | 467 | if pmirror is not None: | ||
485 | 468 | if smirror is None: | ||
486 | 469 | smirror = pmirror | ||
487 | 470 | return {'PRIMARY': pmirror, | ||
488 | 471 | 'SECURITY': smirror} | ||
489 | 472 | return get_default_mirrors(target) | ||
490 | 473 | |||
491 | 474 | |||
492 | 475 | def get_arch_mirrorconfig(cfg, mirrortype, arch): | ||
493 | 476 | """out of a list of potential mirror configurations select | ||
494 | 477 | and return the one matching the architecture (or default)""" | ||
495 | 478 | # select the mirror specification (if-any) | ||
496 | 479 | mirror_cfg_list = cfg.get(mirrortype, None) | ||
497 | 480 | if mirror_cfg_list is None: | ||
498 | 481 | return None | ||
499 | 482 | |||
500 | 483 | # select the specification matching the target arch | ||
501 | 484 | default = None | ||
502 | 485 | for mirror_cfg_elem in mirror_cfg_list: | ||
503 | 486 | arches = mirror_cfg_elem.get("arches") | ||
504 | 487 | if arch in arches: | ||
505 | 488 | return mirror_cfg_elem | ||
506 | 489 | if "default" in arches: | ||
507 | 490 | default = mirror_cfg_elem | ||
508 | 491 | return default | ||
509 | 492 | |||
510 | 493 | |||
511 | 494 | def get_mirror(cfg, mirrortype, arch): | ||
512 | 495 | """pass the three potential stages of mirror specification | ||
513 | 496 | returns None is neither of them found anything otherwise the first | ||
514 | 497 | hit is returned""" | ||
515 | 498 | mcfg = get_arch_mirrorconfig(cfg, mirrortype, arch) | ||
516 | 499 | if mcfg is None: | ||
517 | 500 | return None | ||
518 | 501 | |||
519 | 502 | # directly specified | ||
520 | 503 | mirror = mcfg.get("uri", None) | ||
521 | 504 | if mirror is None: | ||
522 | 505 | # list of mirrors to try to resolve | ||
523 | 506 | mirror = search_for_mirror(mcfg.get("search", None)) | ||
524 | 507 | |||
525 | 508 | if mirror is None: | ||
526 | 509 | # search for predfined dns patterns | ||
527 | 510 | if mirrortype == "primary": | ||
528 | 511 | pattern = "mirror" | ||
529 | 512 | else: | ||
530 | 513 | pattern = "%s-mirror" % mirrortype | ||
531 | 514 | mirror = search_for_mirror_dns(mcfg.get("search_dns", None), pattern) | ||
532 | 515 | |||
533 | 516 | return mirror | ||
534 | 517 | |||
535 | 518 | |||
536 | 519 | def find_apt_mirror_info(cfg, target=None): | ||
537 | 520 | """find_apt_mirror_info | ||
538 | 521 | find an apt_mirror given the cfg provided. | ||
539 | 522 | It can check for separate config of primary and security mirrors | ||
540 | 523 | If only primary is given security is assumed to be equal to primary | ||
541 | 524 | If the generic apt_mirror is given that is defining for both | ||
542 | 525 | """ | ||
543 | 526 | |||
544 | 527 | arch = util.get_architecture(target) | ||
545 | 528 | LOG.debug("got arch for mirror selection: %s", arch) | ||
546 | 529 | pmirror = get_mirror(cfg, "primary", arch) | ||
547 | 530 | LOG.debug("got primary mirror: %s", pmirror) | ||
548 | 531 | smirror = get_mirror(cfg, "security", arch) | ||
549 | 532 | LOG.debug("got security mirror: %s", smirror) | ||
550 | 533 | |||
551 | 534 | # Note: curtin has no cloud-datasource fallback | ||
552 | 535 | |||
553 | 536 | mirror_info = update_mirror_info(pmirror, smirror, target) | ||
554 | 537 | |||
555 | 538 | # less complex replacements use only MIRROR, derive from primary | ||
556 | 539 | mirror_info["MIRROR"] = mirror_info["PRIMARY"] | ||
557 | 540 | |||
558 | 541 | return mirror_info | ||
559 | 542 | |||
560 | 543 | |||
561 | 544 | def apply_apt_proxy_config(cfg, proxy_fname, config_fname): | ||
562 | 545 | """apply_apt_proxy_config | ||
563 | 546 | Applies any apt*proxy config from if specified | ||
564 | 547 | """ | ||
565 | 548 | # Set up any apt proxy | ||
566 | 549 | cfgs = (('proxy', 'Acquire::http::Proxy "%s";'), | ||
567 | 550 | ('http_proxy', 'Acquire::http::Proxy "%s";'), | ||
568 | 551 | ('ftp_proxy', 'Acquire::ftp::Proxy "%s";'), | ||
569 | 552 | ('https_proxy', 'Acquire::https::Proxy "%s";')) | ||
570 | 553 | |||
571 | 554 | proxies = [fmt % cfg.get(name) for (name, fmt) in cfgs if cfg.get(name)] | ||
572 | 555 | if len(proxies): | ||
573 | 556 | LOG.debug("write apt proxy info to %s", proxy_fname) | ||
574 | 557 | util.write_file(proxy_fname, '\n'.join(proxies) + '\n') | ||
575 | 558 | elif os.path.isfile(proxy_fname): | ||
576 | 559 | util.del_file(proxy_fname) | ||
577 | 560 | LOG.debug("no apt proxy configured, removed %s", proxy_fname) | ||
578 | 561 | |||
579 | 562 | if cfg.get('conf', None): | ||
580 | 563 | LOG.debug("write apt config info to %s", config_fname) | ||
581 | 564 | util.write_file(config_fname, cfg.get('conf')) | ||
582 | 565 | elif os.path.isfile(config_fname): | ||
583 | 566 | util.del_file(config_fname) | ||
584 | 567 | LOG.debug("no apt config configured, removed %s", config_fname) | ||
585 | 568 | |||
586 | 569 | |||
587 | 570 | def apt_command(args): | ||
588 | 571 | """ Main entry point for curtin apt-config standalone command | ||
589 | 572 | This does not read the global config as handled by curthooks, but | ||
590 | 573 | instead one can specify a different "target" and a new cfg via --config | ||
591 | 574 | """ | ||
592 | 575 | cfg = config.load_command_config(args, {}) | ||
593 | 576 | |||
594 | 577 | if args.target is not None: | ||
595 | 578 | target = args.target | ||
596 | 579 | else: | ||
597 | 580 | state = util.load_command_environment() | ||
598 | 581 | target = state['target'] | ||
599 | 582 | |||
600 | 583 | if target is None: | ||
601 | 584 | sys.stderr.write("Unable to find target. " | ||
602 | 585 | "Use --target or set TARGET_MOUNT_POINT\n") | ||
603 | 586 | sys.exit(2) | ||
604 | 587 | |||
605 | 588 | apt_cfg = cfg.get("apt") | ||
606 | 589 | # if no apt config section is available, do nothing | ||
607 | 590 | if apt_cfg is not None: | ||
608 | 591 | LOG.debug("Handling apt to target %s with config %s", | ||
609 | 592 | target, apt_cfg) | ||
610 | 593 | try: | ||
611 | 594 | with util.ChrootableTarget(target, allow_daemons=False, | ||
612 | 595 | sys_resolvconf=True): | ||
613 | 596 | handle_apt(apt_cfg, target) | ||
614 | 597 | except (RuntimeError, TypeError, ValueError, IOError): | ||
615 | 598 | LOG.exception("Failed to configure apt features '%s'", apt_cfg) | ||
616 | 599 | sys.exit(1) | ||
617 | 600 | else: | ||
618 | 601 | LOG.info("No apt config provided, skipping") | ||
619 | 602 | |||
620 | 603 | sys.exit(0) | ||
621 | 604 | |||
622 | 605 | |||
623 | 606 | def translate_old_apt_features(cfg): | ||
624 | 607 | """translate the few old apt related features into the new config format""" | ||
625 | 608 | predef_apt_cfg = cfg.get("apt") | ||
626 | 609 | if predef_apt_cfg is None: | ||
627 | 610 | cfg['apt'] = {} | ||
628 | 611 | predef_apt_cfg = cfg.get("apt") | ||
629 | 612 | |||
630 | 613 | if cfg.get('apt_proxy') is not None: | ||
631 | 614 | if predef_apt_cfg.get('proxy') is not None: | ||
632 | 615 | msg = ("Error in apt_proxy configuration: " | ||
633 | 616 | "old and new format of apt features " | ||
634 | 617 | "are mutually exclusive") | ||
635 | 618 | LOG.error(msg) | ||
636 | 619 | raise ValueError(msg) | ||
637 | 620 | |||
638 | 621 | cfg['apt']['proxy'] = cfg.get('apt_proxy') | ||
639 | 622 | LOG.debug("Transferred %s into new format: %s", cfg.get('apt_proxy'), | ||
640 | 623 | cfg.get('apte')) | ||
641 | 624 | del cfg['apt_proxy'] | ||
642 | 625 | |||
643 | 626 | if cfg.get('apt_mirrors') is not None: | ||
644 | 627 | if predef_apt_cfg.get('mirrors') is not None: | ||
645 | 628 | msg = ("Error in apt_mirror configuration: " | ||
646 | 629 | "old and new format of apt features " | ||
647 | 630 | "are mutually exclusive") | ||
648 | 631 | LOG.error(msg) | ||
649 | 632 | raise ValueError(msg) | ||
650 | 633 | |||
651 | 634 | old = cfg.get('apt_mirrors') | ||
652 | 635 | cfg['apt']['primary'] = [{"arches": ["default"], | ||
653 | 636 | "uri": old.get('ubuntu_archive')}] | ||
654 | 637 | cfg['apt']['security'] = [{"arches": ["default"], | ||
655 | 638 | "uri": old.get('ubuntu_security')}] | ||
656 | 639 | LOG.debug("Transferred %s into new format: %s", cfg.get('apt_mirror'), | ||
657 | 640 | cfg.get('apt')) | ||
658 | 641 | del cfg['apt_mirrors'] | ||
659 | 642 | # to work this also needs to disable the default protection | ||
660 | 643 | psl = predef_apt_cfg.get('preserve_sources_list') | ||
661 | 644 | if psl is not None: | ||
662 | 645 | if config.value_as_boolean(psl) is True: | ||
663 | 646 | msg = ("Error in apt_mirror configuration: " | ||
664 | 647 | "apt_mirrors and preserve_sources_list: True " | ||
665 | 648 | "are mutually exclusive") | ||
666 | 649 | LOG.error(msg) | ||
667 | 650 | raise ValueError(msg) | ||
668 | 651 | cfg['apt']['preserve_sources_list'] = False | ||
669 | 652 | |||
670 | 653 | if cfg.get('debconf_selections') is not None: | ||
671 | 654 | if predef_apt_cfg.get('debconf_selections') is not None: | ||
672 | 655 | msg = ("Error in debconf_selections configuration: " | ||
673 | 656 | "old and new format of apt features " | ||
674 | 657 | "are mutually exclusive") | ||
675 | 658 | LOG.error(msg) | ||
676 | 659 | raise ValueError(msg) | ||
677 | 660 | |||
678 | 661 | selsets = cfg.get('debconf_selections') | ||
679 | 662 | cfg['apt']['debconf_selections'] = selsets | ||
680 | 663 | LOG.info("Transferred %s into new format: %s", | ||
681 | 664 | cfg.get('debconf_selections'), | ||
682 | 665 | cfg.get('apt')) | ||
683 | 666 | del cfg['debconf_selections'] | ||
684 | 667 | |||
685 | 668 | return cfg | ||
686 | 669 | |||
687 | 670 | |||
688 | 671 | CMD_ARGUMENTS = ( | ||
689 | 672 | ((('-c', '--config'), | ||
690 | 673 | {'help': 'read configuration from cfg', 'action': util.MergedCmdAppend, | ||
691 | 674 | 'metavar': 'FILE', 'type': argparse.FileType("rb"), | ||
692 | 675 | 'dest': 'cfgopts', 'default': []}), | ||
693 | 676 | (('-t', '--target'), | ||
694 | 677 | {'help': 'chroot to target. default is env[TARGET_MOUNT_POINT]', | ||
695 | 678 | 'action': 'store', 'metavar': 'TARGET', | ||
696 | 679 | 'default': os.environ.get('TARGET_MOUNT_POINT')}),) | ||
697 | 680 | ) | ||
698 | 681 | |||
699 | 682 | |||
700 | 683 | def POPULATE_SUBCMD(parser): | ||
701 | 684 | """Populate subcommand option parsing for apt-config""" | ||
702 | 685 | populate_one_subcmd(parser, CMD_ARGUMENTS, apt_command) | ||
703 | 686 | |||
704 | 687 | CONFIG_CLEANERS = { | ||
705 | 688 | 'cloud-init': clean_cloud_init, | ||
706 | 689 | } | ||
707 | 690 | |||
708 | 691 | # vi: ts=4 expandtab syntax=python | ||
709 | 0 | 692 | ||
710 | === modified file 'curtin/commands/curthooks.py' | |||
711 | --- curtin/commands/curthooks.py 2016-06-24 19:27:52 +0000 | |||
712 | +++ curtin/commands/curthooks.py 2016-07-26 19:53:43 +0000 | |||
713 | @@ -16,10 +16,8 @@ | |||
714 | 16 | # along with Curtin. If not, see <http://www.gnu.org/licenses/>. | 16 | # along with Curtin. If not, see <http://www.gnu.org/licenses/>. |
715 | 17 | 17 | ||
716 | 18 | import copy | 18 | import copy |
717 | 19 | import glob | ||
718 | 20 | import os | 19 | import os |
719 | 21 | import platform | 20 | import platform |
720 | 22 | import re | ||
721 | 23 | import sys | 21 | import sys |
722 | 24 | import shutil | 22 | import shutil |
723 | 25 | import textwrap | 23 | import textwrap |
724 | @@ -32,6 +30,7 @@ | |||
725 | 32 | from curtin import util | 30 | from curtin import util |
726 | 33 | from curtin import net | 31 | from curtin import net |
727 | 34 | from curtin.reporter import events | 32 | from curtin.reporter import events |
728 | 33 | from curtin.commands import apt_config | ||
729 | 35 | 34 | ||
730 | 36 | from . import populate_one_subcmd | 35 | from . import populate_one_subcmd |
731 | 37 | 36 | ||
732 | @@ -90,45 +89,15 @@ | |||
733 | 90 | info.get('perms', "0644"))) | 89 | info.get('perms', "0644"))) |
734 | 91 | 90 | ||
735 | 92 | 91 | ||
745 | 93 | def apt_config(cfg, target): | 92 | def do_apt_config(cfg, target): |
746 | 94 | # cfg['apt_proxy'] | 93 | cfg = apt_config.translate_old_apt_features(cfg) |
747 | 95 | 94 | apt_cfg = cfg.get("apt") | |
748 | 96 | proxy_cfg_path = os.path.sep.join( | 95 | if apt_cfg is not None: |
749 | 97 | [target, '/etc/apt/apt.conf.d/90curtin-aptproxy']) | 96 | LOG.info("curthooks handling apt to target %s with config %s", |
750 | 98 | if cfg.get('apt_proxy'): | 97 | target, apt_cfg) |
751 | 99 | util.write_file( | 98 | apt_config.handle_apt(apt_cfg, target) |
743 | 100 | proxy_cfg_path, | ||
744 | 101 | content='Acquire::HTTP::Proxy "%s";\n' % cfg['apt_proxy']) | ||
752 | 102 | else: | 99 | else: |
782 | 103 | if os.path.isfile(proxy_cfg_path): | 100 | LOG.info("No apt config provided, skipping") |
754 | 104 | os.unlink(proxy_cfg_path) | ||
755 | 105 | |||
756 | 106 | # cfg['apt_mirrors'] | ||
757 | 107 | # apt_mirrors: | ||
758 | 108 | # ubuntu_archive: http://local.archive/ubuntu | ||
759 | 109 | # ubuntu_security: http://local.archive/ubuntu | ||
760 | 110 | sources_list = os.path.sep.join([target, '/etc/apt/sources.list']) | ||
761 | 111 | if (isinstance(cfg.get('apt_mirrors'), dict) and | ||
762 | 112 | os.path.isfile(sources_list)): | ||
763 | 113 | repls = [ | ||
764 | 114 | ('ubuntu_archive', r'http://\S*[.]*archive.ubuntu.com/\S*'), | ||
765 | 115 | ('ubuntu_security', r'http://security.ubuntu.com/\S*'), | ||
766 | 116 | ] | ||
767 | 117 | content = None | ||
768 | 118 | for name, regex in repls: | ||
769 | 119 | mirror = cfg['apt_mirrors'].get(name) | ||
770 | 120 | if not mirror: | ||
771 | 121 | continue | ||
772 | 122 | |||
773 | 123 | if content is None: | ||
774 | 124 | with open(sources_list) as fp: | ||
775 | 125 | content = fp.read() | ||
776 | 126 | util.write_file(sources_list + ".dist", content) | ||
777 | 127 | |||
778 | 128 | content = re.sub(regex, mirror + " ", content) | ||
779 | 129 | |||
780 | 130 | if content is not None: | ||
781 | 131 | util.write_file(sources_list, content) | ||
783 | 132 | 101 | ||
784 | 133 | 102 | ||
785 | 134 | def disable_overlayroot(cfg, target): | 103 | def disable_overlayroot(cfg, target): |
786 | @@ -140,15 +109,6 @@ | |||
787 | 140 | shutil.move(local_conf, local_conf + ".old") | 109 | shutil.move(local_conf, local_conf + ".old") |
788 | 141 | 110 | ||
789 | 142 | 111 | ||
790 | 143 | def clean_cloud_init(target): | ||
791 | 144 | flist = glob.glob( | ||
792 | 145 | os.path.sep.join([target, "/etc/cloud/cloud.cfg.d/*dpkg*"])) | ||
793 | 146 | |||
794 | 147 | LOG.debug("cleaning cloud-init config from: %s" % flist) | ||
795 | 148 | for dpkg_cfg in flist: | ||
796 | 149 | os.unlink(dpkg_cfg) | ||
797 | 150 | |||
798 | 151 | |||
799 | 152 | def _maybe_remove_legacy_eth0(target, | 112 | def _maybe_remove_legacy_eth0(target, |
800 | 153 | path="/etc/network/interfaces.d/eth0.cfg"): | 113 | path="/etc/network/interfaces.d/eth0.cfg"): |
801 | 154 | """Ubuntu cloud images previously included a 'eth0.cfg' that had | 114 | """Ubuntu cloud images previously included a 'eth0.cfg' that had |
802 | @@ -293,85 +253,6 @@ | |||
803 | 293 | " System may not boot.", package) | 253 | " System may not boot.", package) |
804 | 294 | 254 | ||
805 | 295 | 255 | ||
806 | 296 | def apply_debconf_selections(cfg, target): | ||
807 | 297 | # debconf_selections: | ||
808 | 298 | # set1: | | ||
809 | 299 | # cloud-init cloud-init/datasources multiselect MAAS | ||
810 | 300 | # set2: pkg pkg/value string bar | ||
811 | 301 | selsets = cfg.get('debconf_selections') | ||
812 | 302 | if not selsets: | ||
813 | 303 | LOG.debug("debconf_selections was not set in config") | ||
814 | 304 | return | ||
815 | 305 | |||
816 | 306 | # for each entry in selections, chroot and apply them. | ||
817 | 307 | # keep a running total of packages we've seen. | ||
818 | 308 | pkgs_cfgd = set() | ||
819 | 309 | for key, content in selsets.items(): | ||
820 | 310 | LOG.debug("setting for %s, %s" % (key, content)) | ||
821 | 311 | util.subp(['chroot', target, 'debconf-set-selections'], | ||
822 | 312 | data=content.encode()) | ||
823 | 313 | for line in content.splitlines(): | ||
824 | 314 | if line.startswith("#"): | ||
825 | 315 | continue | ||
826 | 316 | pkg = re.sub(r"[:\s].*", "", line) | ||
827 | 317 | pkgs_cfgd.add(pkg) | ||
828 | 318 | |||
829 | 319 | pkgs_installed = get_installed_packages(target) | ||
830 | 320 | |||
831 | 321 | LOG.debug("pkgs_cfgd: %s" % pkgs_cfgd) | ||
832 | 322 | LOG.debug("pkgs_installed: %s" % pkgs_installed) | ||
833 | 323 | need_reconfig = pkgs_cfgd.intersection(pkgs_installed) | ||
834 | 324 | |||
835 | 325 | if len(need_reconfig) == 0: | ||
836 | 326 | LOG.debug("no need for reconfig") | ||
837 | 327 | return | ||
838 | 328 | |||
839 | 329 | # For any packages that are already installed, but have preseed data | ||
840 | 330 | # we populate the debconf database, but the filesystem configuration | ||
841 | 331 | # would be preferred on a subsequent dpkg-reconfigure. | ||
842 | 332 | # so, what we have to do is "know" information about certain packages | ||
843 | 333 | # to unconfigure them. | ||
844 | 334 | unhandled = [] | ||
845 | 335 | to_config = [] | ||
846 | 336 | for pkg in need_reconfig: | ||
847 | 337 | if pkg in CONFIG_CLEANERS: | ||
848 | 338 | LOG.debug("unconfiguring %s" % pkg) | ||
849 | 339 | CONFIG_CLEANERS[pkg](target) | ||
850 | 340 | to_config.append(pkg) | ||
851 | 341 | else: | ||
852 | 342 | unhandled.append(pkg) | ||
853 | 343 | |||
854 | 344 | if len(unhandled): | ||
855 | 345 | LOG.warn("The following packages were installed and preseeded, " | ||
856 | 346 | "but cannot be unconfigured: %s", unhandled) | ||
857 | 347 | |||
858 | 348 | util.subp(['chroot', target, 'dpkg-reconfigure', | ||
859 | 349 | '--frontend=noninteractive'] + | ||
860 | 350 | list(to_config), data=None) | ||
861 | 351 | |||
862 | 352 | |||
863 | 353 | def get_installed_packages(target=None): | ||
864 | 354 | cmd = [] | ||
865 | 355 | if target is not None: | ||
866 | 356 | cmd = ['chroot', target] | ||
867 | 357 | cmd.extend(['dpkg-query', '--list']) | ||
868 | 358 | |||
869 | 359 | (out, _err) = util.subp(cmd, capture=True) | ||
870 | 360 | if isinstance(out, bytes): | ||
871 | 361 | out = out.decode() | ||
872 | 362 | |||
873 | 363 | pkgs_inst = set() | ||
874 | 364 | for line in out.splitlines(): | ||
875 | 365 | try: | ||
876 | 366 | (state, pkg, other) = line.split(None, 2) | ||
877 | 367 | except ValueError: | ||
878 | 368 | continue | ||
879 | 369 | if state.startswith("hi") or state.startswith("ii"): | ||
880 | 370 | pkgs_inst.add(re.sub(":.*", "", pkg)) | ||
881 | 371 | |||
882 | 372 | return pkgs_inst | ||
883 | 373 | |||
884 | 374 | |||
885 | 375 | def setup_grub(cfg, target): | 256 | def setup_grub(cfg, target): |
886 | 376 | # target is the path to the mounted filesystem | 257 | # target is the path to the mounted filesystem |
887 | 377 | 258 | ||
888 | @@ -740,7 +621,7 @@ | |||
889 | 740 | } | 621 | } |
890 | 741 | 622 | ||
891 | 742 | needed_packages = [] | 623 | needed_packages = [] |
893 | 743 | installed_packages = get_installed_packages(target) | 624 | installed_packages = util.get_installed_packages(target) |
894 | 744 | for cust_cfg, pkg_reqs in custom_configs.items(): | 625 | for cust_cfg, pkg_reqs in custom_configs.items(): |
895 | 745 | if cust_cfg not in cfg: | 626 | if cust_cfg not in cfg: |
896 | 746 | continue | 627 | continue |
897 | @@ -820,7 +701,7 @@ | |||
898 | 820 | name=stack_prefix, reporting_enabled=True, level="INFO", | 701 | name=stack_prefix, reporting_enabled=True, level="INFO", |
899 | 821 | description="writing config files and configuring apt"): | 702 | description="writing config files and configuring apt"): |
900 | 822 | write_files(cfg, target) | 703 | write_files(cfg, target) |
902 | 823 | apt_config(cfg, target) | 704 | do_apt_config(cfg, target) |
903 | 824 | disable_overlayroot(cfg, target) | 705 | disable_overlayroot(cfg, target) |
904 | 825 | 706 | ||
905 | 826 | # packages may be needed prior to installing kernel | 707 | # packages may be needed prior to installing kernel |
906 | @@ -843,7 +724,6 @@ | |||
907 | 843 | setup_zipl(cfg, target) | 724 | setup_zipl(cfg, target) |
908 | 844 | install_kernel(cfg, target) | 725 | install_kernel(cfg, target) |
909 | 845 | run_zipl(cfg, target) | 726 | run_zipl(cfg, target) |
910 | 846 | apply_debconf_selections(cfg, target) | ||
911 | 847 | 727 | ||
912 | 848 | restore_dist_interfaces(cfg, target) | 728 | restore_dist_interfaces(cfg, target) |
913 | 849 | 729 | ||
914 | @@ -906,8 +786,4 @@ | |||
915 | 906 | populate_one_subcmd(parser, CMD_ARGUMENTS, curthooks) | 786 | populate_one_subcmd(parser, CMD_ARGUMENTS, curthooks) |
916 | 907 | 787 | ||
917 | 908 | 788 | ||
918 | 909 | CONFIG_CLEANERS = { | ||
919 | 910 | 'cloud-init': clean_cloud_init, | ||
920 | 911 | } | ||
921 | 912 | |||
922 | 913 | # vi: ts=4 expandtab syntax=python | 789 | # vi: ts=4 expandtab syntax=python |
923 | 914 | 790 | ||
924 | === modified file 'curtin/commands/main.py' | |||
925 | --- curtin/commands/main.py 2016-04-04 20:12:01 +0000 | |||
926 | +++ curtin/commands/main.py 2016-07-26 19:53:43 +0000 | |||
927 | @@ -27,7 +27,7 @@ | |||
928 | 27 | 27 | ||
929 | 28 | SUB_COMMAND_MODULES = [ | 28 | SUB_COMMAND_MODULES = [ |
930 | 29 | 'apply_net', 'block-meta', 'block-wipe', 'curthooks', 'extract', | 29 | 'apply_net', 'block-meta', 'block-wipe', 'curthooks', 'extract', |
932 | 30 | 'hook', 'in-target', 'install', 'mkfs', 'net-meta', | 30 | 'hook', 'in-target', 'install', 'mkfs', 'net-meta', 'apt-config', |
933 | 31 | 'pack', 'swap', 'system-install', 'system-upgrade'] | 31 | 'pack', 'swap', 'system-install', 'system-upgrade'] |
934 | 32 | 32 | ||
935 | 33 | 33 | ||
936 | 34 | 34 | ||
937 | === added file 'curtin/gpg.py' | |||
938 | --- curtin/gpg.py 1970-01-01 00:00:00 +0000 | |||
939 | +++ curtin/gpg.py 2016-07-26 19:53:43 +0000 | |||
940 | @@ -0,0 +1,74 @@ | |||
941 | 1 | # Copyright (C) 2016 Canonical Ltd. | ||
942 | 2 | # | ||
943 | 3 | # Author: Scott Moser <scott.moser@canonical.com> | ||
944 | 4 | # Christian Ehrhardt <christian.ehrhardt@canonical.com> | ||
945 | 5 | # | ||
946 | 6 | # Curtin is free software: you can redistribute it and/or modify it under | ||
947 | 7 | # the terms of the GNU Affero General Public License as published by the | ||
948 | 8 | # Free Software Foundation, either version 3 of the License, or (at your | ||
949 | 9 | # option) any later version. | ||
950 | 10 | # | ||
951 | 11 | # Curtin is distributed in the hope that it will be useful, but WITHOUT ANY | ||
952 | 12 | # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | ||
953 | 13 | # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for | ||
954 | 14 | # more details. | ||
955 | 15 | # | ||
956 | 16 | # You should have received a copy of the GNU Affero General Public License | ||
957 | 17 | # along with Curtin. If not, see <http://www.gnu.org/licenses/>. | ||
958 | 18 | """ gpg.py | ||
959 | 19 | gpg related utilities to get raw keys data by their id | ||
960 | 20 | """ | ||
961 | 21 | |||
962 | 22 | from curtin import util | ||
963 | 23 | |||
964 | 24 | from .log import LOG | ||
965 | 25 | |||
966 | 26 | |||
967 | 27 | def export_armour(key): | ||
968 | 28 | """Export gpg key, armoured key gets returned""" | ||
969 | 29 | try: | ||
970 | 30 | (armour, _) = util.subp(["gpg", "--export", "--armour", key], | ||
971 | 31 | capture=True) | ||
972 | 32 | except util.ProcessExecutionError as error: | ||
973 | 33 | # debug, since it happens for any key not on the system initially | ||
974 | 34 | LOG.debug('Failed to export armoured key "%s": %s', key, error) | ||
975 | 35 | armour = None | ||
976 | 36 | return armour | ||
977 | 37 | |||
978 | 38 | |||
979 | 39 | def recv_key(key, keyserver): | ||
980 | 40 | """Receive gpg key from the specified keyserver""" | ||
981 | 41 | LOG.debug('Receive gpg key "%s"', key) | ||
982 | 42 | try: | ||
983 | 43 | util.subp(["gpg", "--keyserver", keyserver, "--recv", key], | ||
984 | 44 | capture=True) | ||
985 | 45 | except util.ProcessExecutionError as error: | ||
986 | 46 | raise ValueError(('Failed to import key "%s" ' | ||
987 | 47 | 'from server "%s" - error %s') % | ||
988 | 48 | (key, keyserver, error)) | ||
989 | 49 | |||
990 | 50 | |||
991 | 51 | def delete_key(key): | ||
992 | 52 | """Delete the specified key from the local gpg ring""" | ||
993 | 53 | try: | ||
994 | 54 | util.subp(["gpg", "--batch", "--yes", "--delete-keys", key], | ||
995 | 55 | capture=True) | ||
996 | 56 | except util.ProcessExecutionError as error: | ||
997 | 57 | LOG.warn('Failed delete key "%s": %s', key, error) | ||
998 | 58 | |||
999 | 59 | |||
1000 | 60 | def getkeybyid(keyid, keyserver='keyserver.ubuntu.com'): | ||
1001 | 61 | """get gpg keyid from keyserver""" | ||
1002 | 62 | armour = export_armour(keyid) | ||
1003 | 63 | if not armour: | ||
1004 | 64 | try: | ||
1005 | 65 | recv_key(keyid, keyserver=keyserver) | ||
1006 | 66 | armour = export_armour(keyid) | ||
1007 | 67 | except ValueError: | ||
1008 | 68 | LOG.exception('Failed to obtain gpg key %s', keyid) | ||
1009 | 69 | raise | ||
1010 | 70 | finally: | ||
1011 | 71 | # delete just imported key to leave environment as it was before | ||
1012 | 72 | delete_key(keyid) | ||
1013 | 73 | |||
1014 | 74 | return armour | ||
1015 | 0 | 75 | ||
1016 | === modified file 'curtin/util.py' | |||
1017 | --- curtin/util.py 2016-06-24 19:27:52 +0000 | |||
1018 | +++ curtin/util.py 2016-07-26 19:53:43 +0000 | |||
1019 | @@ -16,18 +16,30 @@ | |||
1020 | 16 | # along with Curtin. If not, see <http://www.gnu.org/licenses/>. | 16 | # along with Curtin. If not, see <http://www.gnu.org/licenses/>. |
1021 | 17 | 17 | ||
1022 | 18 | import argparse | 18 | import argparse |
1023 | 19 | import collections | ||
1024 | 19 | import errno | 20 | import errno |
1025 | 20 | import glob | 21 | import glob |
1026 | 21 | import json | 22 | import json |
1027 | 22 | import os | 23 | import os |
1028 | 23 | import platform | 24 | import platform |
1029 | 25 | import re | ||
1030 | 24 | import shutil | 26 | import shutil |
1031 | 27 | import socket | ||
1032 | 25 | import subprocess | 28 | import subprocess |
1033 | 26 | import stat | 29 | import stat |
1034 | 27 | import sys | 30 | import sys |
1035 | 28 | import tempfile | 31 | import tempfile |
1036 | 29 | import time | 32 | import time |
1037 | 30 | 33 | ||
1038 | 34 | # avoid the dependency to python3-six as used in cloud-init | ||
1039 | 35 | try: | ||
1040 | 36 | from urlparse import urlparse | ||
1041 | 37 | except ImportError: | ||
1042 | 38 | # python3 | ||
1043 | 39 | # avoid triggering pylint, https://github.com/PyCQA/pylint/issues/769 | ||
1044 | 40 | # pylint:disable=import-error,no-name-in-module | ||
1045 | 41 | from urllib.parse import urlparse | ||
1046 | 42 | |||
1047 | 31 | from .log import LOG | 43 | from .log import LOG |
1048 | 32 | 44 | ||
1049 | 33 | _INSTALLED_HELPERS_PATH = '/usr/lib/curtin/helpers' | 45 | _INSTALLED_HELPERS_PATH = '/usr/lib/curtin/helpers' |
1050 | @@ -35,6 +47,11 @@ | |||
1051 | 35 | 47 | ||
1052 | 36 | _LSB_RELEASE = {} | 48 | _LSB_RELEASE = {} |
1053 | 37 | 49 | ||
1054 | 50 | _DNS_REDIRECT_IP = None | ||
1055 | 51 | |||
1056 | 52 | # matcher used in template rendering functions | ||
1057 | 53 | BASIC_MATCHER = re.compile(r'\$\{([A-Za-z0-9_.]+)\}|\$([A-Za-z0-9_.]+)') | ||
1058 | 54 | |||
1059 | 38 | 55 | ||
1060 | 39 | def _subp(args, data=None, rcs=None, env=None, capture=False, shell=False, | 56 | def _subp(args, data=None, rcs=None, env=None, capture=False, shell=False, |
1061 | 40 | logstring=False, decode="replace"): | 57 | logstring=False, decode="replace"): |
1062 | @@ -486,6 +503,28 @@ | |||
1063 | 486 | return False | 503 | return False |
1064 | 487 | 504 | ||
1065 | 488 | 505 | ||
1066 | 506 | def get_installed_packages(target=None): | ||
1067 | 507 | cmd = [] | ||
1068 | 508 | if target is not None: | ||
1069 | 509 | cmd = ['chroot', target] | ||
1070 | 510 | cmd.extend(['dpkg-query', '--list']) | ||
1071 | 511 | |||
1072 | 512 | (out, _) = subp(cmd, capture=True) | ||
1073 | 513 | if isinstance(out, bytes): | ||
1074 | 514 | out = out.decode() | ||
1075 | 515 | |||
1076 | 516 | pkgs_inst = set() | ||
1077 | 517 | for line in out.splitlines(): | ||
1078 | 518 | try: | ||
1079 | 519 | (state, pkg, _) = line.split(None, 2) | ||
1080 | 520 | except ValueError: | ||
1081 | 521 | continue | ||
1082 | 522 | if state.startswith("hi") or state.startswith("ii"): | ||
1083 | 523 | pkgs_inst.add(re.sub(":.*", "", pkg)) | ||
1084 | 524 | |||
1085 | 525 | return pkgs_inst | ||
1086 | 526 | |||
1087 | 527 | |||
1088 | 489 | def has_pkg_installed(pkg, target=None): | 528 | def has_pkg_installed(pkg, target=None): |
1089 | 490 | chroot = [] | 529 | chroot = [] |
1090 | 491 | if target is not None: | 530 | if target is not None: |
1091 | @@ -846,14 +885,17 @@ | |||
1092 | 846 | return (isinstance(exc, IOError) and exc.errno == errno.ENOENT) | 885 | return (isinstance(exc, IOError) and exc.errno == errno.ENOENT) |
1093 | 847 | 886 | ||
1094 | 848 | 887 | ||
1096 | 849 | def lsb_release(): | 888 | def lsb_release(target=None): |
1097 | 850 | fmap = {'Codename': 'codename', 'Description': 'description', | 889 | fmap = {'Codename': 'codename', 'Description': 'description', |
1098 | 851 | 'Distributor ID': 'id', 'Release': 'release'} | 890 | 'Distributor ID': 'id', 'Release': 'release'} |
1099 | 891 | chroot = [] | ||
1100 | 892 | if target is not None: | ||
1101 | 893 | chroot = ['chroot', target] | ||
1102 | 852 | global _LSB_RELEASE | 894 | global _LSB_RELEASE |
1103 | 853 | if not _LSB_RELEASE: | 895 | if not _LSB_RELEASE: |
1104 | 854 | data = {} | 896 | data = {} |
1105 | 855 | try: | 897 | try: |
1107 | 856 | out, err = subp(['lsb_release', '--all'], capture=True) | 898 | out, err = subp(chroot + ['lsb_release', '--all'], capture=True) |
1108 | 857 | for line in out.splitlines(): | 899 | for line in out.splitlines(): |
1109 | 858 | fname, tok, val = line.partition(":") | 900 | fname, tok, val = line.partition(":") |
1110 | 859 | if fname in fmap: | 901 | if fname in fmap: |
1111 | @@ -895,4 +937,104 @@ | |||
1112 | 895 | } | 937 | } |
1113 | 896 | return platform2arch.get(platform.machine(), platform.machine()) | 938 | return platform2arch.get(platform.machine(), platform.machine()) |
1114 | 897 | 939 | ||
1115 | 940 | |||
1116 | 941 | def basic_template_render(content, params): | ||
1117 | 942 | """This does simple replacement of bash variable like templates. | ||
1118 | 943 | |||
1119 | 944 | It identifies patterns like ${a} or $a and can also identify patterns like | ||
1120 | 945 | ${a.b} or $a.b which will look for a key 'b' in the dictionary rooted | ||
1121 | 946 | by key 'a'. | ||
1122 | 947 | """ | ||
1123 | 948 | |||
1124 | 949 | def replacer(match): | ||
1125 | 950 | """ replacer | ||
1126 | 951 | replacer used in regex match to replace content | ||
1127 | 952 | """ | ||
1128 | 953 | # Only 1 of the 2 groups will actually have a valid entry. | ||
1129 | 954 | name = match.group(1) | ||
1130 | 955 | if name is None: | ||
1131 | 956 | name = match.group(2) | ||
1132 | 957 | if name is None: | ||
1133 | 958 | raise RuntimeError("Match encountered but no valid group present") | ||
1134 | 959 | path = collections.deque(name.split(".")) | ||
1135 | 960 | selected_params = params | ||
1136 | 961 | while len(path) > 1: | ||
1137 | 962 | key = path.popleft() | ||
1138 | 963 | if not isinstance(selected_params, dict): | ||
1139 | 964 | raise TypeError("Can not traverse into" | ||
1140 | 965 | " non-dictionary '%s' of type %s while" | ||
1141 | 966 | " looking for subkey '%s'" | ||
1142 | 967 | % (selected_params, | ||
1143 | 968 | selected_params.__class__.__name__, | ||
1144 | 969 | key)) | ||
1145 | 970 | selected_params = selected_params[key] | ||
1146 | 971 | key = path.popleft() | ||
1147 | 972 | if not isinstance(selected_params, dict): | ||
1148 | 973 | raise TypeError("Can not extract key '%s' from non-dictionary" | ||
1149 | 974 | " '%s' of type %s" | ||
1150 | 975 | % (key, selected_params, | ||
1151 | 976 | selected_params.__class__.__name__)) | ||
1152 | 977 | return str(selected_params[key]) | ||
1153 | 978 | |||
1154 | 979 | return BASIC_MATCHER.sub(replacer, content) | ||
1155 | 980 | |||
1156 | 981 | |||
1157 | 982 | def render_string(content, params): | ||
1158 | 983 | """ render_string | ||
1159 | 984 | render a string following replacement rules as defined in | ||
1160 | 985 | basic_template_render returning the string | ||
1161 | 986 | """ | ||
1162 | 987 | if not params: | ||
1163 | 988 | params = {} | ||
1164 | 989 | return basic_template_render(content, params) | ||
1165 | 990 | |||
1166 | 991 | |||
1167 | 992 | def is_resolvable(name): | ||
1168 | 993 | """determine if a url is resolvable, return a boolean | ||
1169 | 994 | This also attempts to be resilent against dns redirection. | ||
1170 | 995 | |||
1171 | 996 | Note, that normal nsswitch resolution is used here. So in order | ||
1172 | 997 | to avoid any utilization of 'search' entries in /etc/resolv.conf | ||
1173 | 998 | we have to append '.'. | ||
1174 | 999 | |||
1175 | 1000 | The top level 'invalid' domain is invalid per RFC. And example.com | ||
1176 | 1001 | should also not exist. The random entry will be resolved inside | ||
1177 | 1002 | the search list. | ||
1178 | 1003 | """ | ||
1179 | 1004 | global _DNS_REDIRECT_IP | ||
1180 | 1005 | if _DNS_REDIRECT_IP is None: | ||
1181 | 1006 | badips = set() | ||
1182 | 1007 | badnames = ("does-not-exist.example.com.", "example.invalid.") | ||
1183 | 1008 | badresults = {} | ||
1184 | 1009 | for iname in badnames: | ||
1185 | 1010 | try: | ||
1186 | 1011 | result = socket.getaddrinfo(iname, None, 0, 0, | ||
1187 | 1012 | socket.SOCK_STREAM, | ||
1188 | 1013 | socket.AI_CANONNAME) | ||
1189 | 1014 | badresults[iname] = [] | ||
1190 | 1015 | for (_, _, _, cname, sockaddr) in result: | ||
1191 | 1016 | badresults[iname].append("%s: %s" % (cname, sockaddr[0])) | ||
1192 | 1017 | badips.add(sockaddr[0]) | ||
1193 | 1018 | except (socket.gaierror, socket.error): | ||
1194 | 1019 | pass | ||
1195 | 1020 | _DNS_REDIRECT_IP = badips | ||
1196 | 1021 | if badresults: | ||
1197 | 1022 | LOG.debug("detected dns redirection: %s", badresults) | ||
1198 | 1023 | |||
1199 | 1024 | try: | ||
1200 | 1025 | result = socket.getaddrinfo(name, None) | ||
1201 | 1026 | # check first result's sockaddr field | ||
1202 | 1027 | addr = result[0][4][0] | ||
1203 | 1028 | if addr in _DNS_REDIRECT_IP: | ||
1204 | 1029 | return False | ||
1205 | 1030 | return True | ||
1206 | 1031 | except (socket.gaierror, socket.error): | ||
1207 | 1032 | return False | ||
1208 | 1033 | |||
1209 | 1034 | |||
1210 | 1035 | def is_resolvable_url(url): | ||
1211 | 1036 | """determine if this url is resolvable (existing or ip).""" | ||
1212 | 1037 | return is_resolvable(urlparse(url).hostname) | ||
1213 | 1038 | |||
1214 | 1039 | |||
1215 | 898 | # vi: ts=4 expandtab syntax=python | 1040 | # vi: ts=4 expandtab syntax=python |
1216 | 899 | 1041 | ||
1217 | === modified file 'doc/devel/README-vmtest.txt' | |||
1218 | --- doc/devel/README-vmtest.txt 2016-01-08 17:37:01 +0000 | |||
1219 | +++ doc/devel/README-vmtest.txt 2016-07-26 19:53:43 +0000 | |||
1220 | @@ -90,13 +90,13 @@ | |||
1221 | 90 | The tests themselves don't actually have to run as root, but the | 90 | The tests themselves don't actually have to run as root, but the |
1222 | 91 | test setup does. | 91 | test setup does. |
1223 | 92 | * the 'tools' directory must be in your path. | 92 | * the 'tools' directory must be in your path. |
1226 | 93 | * test will set apt_proxy in the guests to the value of | 93 | * test will set apt: { proxy } in the guests to the value of |
1227 | 94 | 'apt_proxy' environment variable. If that is not set it will | 94 | 'apt_proxy' environment variable. If that is not set it will |
1228 | 95 | look at the host's apt config and read 'Acquire::HTTP::Proxy' | 95 | look at the host's apt config and read 'Acquire::HTTP::Proxy' |
1229 | 96 | 96 | ||
1230 | 97 | == Environment Variables == | 97 | == Environment Variables == |
1231 | 98 | Some environment variables affect the running of vmtest | 98 | Some environment variables affect the running of vmtest |
1233 | 99 | * apt_proxy: | 99 | * apt_proxy: |
1234 | 100 | test will set apt_proxy in the guests to the value of 'apt_proxy'. | 100 | test will set apt_proxy in the guests to the value of 'apt_proxy'. |
1235 | 101 | If that is not set it will look at the host's apt config and read | 101 | If that is not set it will look at the host's apt config and read |
1236 | 102 | 'Acquire::HTTP::Proxy' | 102 | 'Acquire::HTTP::Proxy' |
1237 | 103 | 103 | ||
1238 | === added file 'doc/topics/apt_source.rst' | |||
1239 | --- doc/topics/apt_source.rst 1970-01-01 00:00:00 +0000 | |||
1240 | +++ doc/topics/apt_source.rst 2016-07-26 19:53:43 +0000 | |||
1241 | @@ -0,0 +1,152 @@ | |||
1242 | 1 | ========== | ||
1243 | 2 | APT Source | ||
1244 | 3 | ========== | ||
1245 | 4 | |||
1246 | 5 | This part of curtin is meant to allow influencing the apt behaviour and configuration. | ||
1247 | 6 | |||
1248 | 7 | By default - if no apt config is provided - it does nothing. That keeps behavior compatible on upgrades. | ||
1249 | 8 | |||
1250 | 9 | The feature has a target argument which - by default - is used to modify the environment that curtin currently installs (@TARGET_MOUNT_POINT). | ||
1251 | 10 | |||
1252 | 11 | Features | ||
1253 | 12 | -------- | ||
1254 | 13 | |||
1255 | 14 | * Add PGP keys to the APT trusted keyring | ||
1256 | 15 | |||
1257 | 16 | - add via short keyid | ||
1258 | 17 | |||
1259 | 18 | - add via long key fingerprint | ||
1260 | 19 | |||
1261 | 20 | - specify a custom keyserver to pull from | ||
1262 | 21 | |||
1263 | 22 | - add raw keys (which makes you independent of keyservers) | ||
1264 | 23 | |||
1265 | 24 | * Influence global apt configuration | ||
1266 | 25 | |||
1267 | 26 | - adding ppa's | ||
1268 | 27 | |||
1269 | 28 | - replacing mirror, security mirror and release in sources.list | ||
1270 | 29 | |||
1271 | 30 | - able to provide a fully custom template for sources.list | ||
1272 | 31 | |||
1273 | 32 | - add arbitrary apt.conf settings | ||
1274 | 33 | |||
1275 | 34 | |||
1276 | 35 | Configuration | ||
1277 | 36 | ------------- | ||
1278 | 37 | |||
1279 | 38 | The general configuration of the apt feature is under an element called ``apt``. | ||
1280 | 39 | |||
1281 | 40 | This can have various "global" subelements as listed in the examples below. | ||
1282 | 41 | These global configurations are valid throughput all of the apt feature. | ||
1283 | 42 | So for exmaple a global specification of ``primary`` for a mirror will apply to all rendered sources entries. | ||
1284 | 43 | |||
1285 | 44 | Then there is a section ``sources`` which can hold a number of subelements itself. | ||
1286 | 45 | The key is the filename and will be prepended by /etc/apt/sources.list.d/ if it doesn't start with a ``/``. | ||
1287 | 46 | There are certain cases - where no content is written into a source.list file where the filename will be ignored - yet it can still be used as index for merging. | ||
1288 | 47 | |||
1289 | 48 | The values inside the entries consist of the following optional entries:: | ||
1290 | 49 | * ``source``: a sources.list entry (some variable replacements apply) | ||
1291 | 50 | |||
1292 | 51 | * ``keyid``: providing a key to import via shortid or fingerprint | ||
1293 | 52 | |||
1294 | 53 | * ``key``: providing a raw PGP key | ||
1295 | 54 | |||
1296 | 55 | * ``keyserver``: specify an alternate keyserver to pull keys from that were specified by keyid | ||
1297 | 56 | |||
1298 | 57 | * ``filename``: for compatibility with the older format (now the key to this dictionary is the filename). If specified this overwrites the filename given as key. | ||
1299 | 58 | |||
1300 | 59 | The section "sources" is is a dictionary (unlike most block/net configs which are lists). This format allows merging between multiple input files than a list like:: | ||
1301 | 60 | sources: | ||
1302 | 61 | s1: {'key': 'key1', 'source': 'source1'} | ||
1303 | 62 | |||
1304 | 63 | sources: | ||
1305 | 64 | s2: {'key': 'key2'} | ||
1306 | 65 | s1: {'filename': 'foo'} | ||
1307 | 66 | |||
1308 | 67 | This would be merged into | ||
1309 | 68 | s1: {'key': 'key1', 'source': 'source1', filename: 'foo'} | ||
1310 | 69 | s2: {'key': 'key2'} | ||
1311 | 70 | |||
1312 | 71 | Here is just one of the most common examples that could be used to install with curtin in a closed environment (derived repository): | ||
1313 | 72 | |||
1314 | 73 | What do we need for that: | ||
1315 | 74 | * insert the PGP key of the local repository to be trusted | ||
1316 | 75 | |||
1317 | 76 | - since you are locked down you can't pull from keyserver.ubuntu.com | ||
1318 | 77 | |||
1319 | 78 | - if you have an internal keyserver you could pull from there, but let us assume you don't even have that; so you have to provide the raw key | ||
1320 | 79 | |||
1321 | 80 | - in the example I'll use the key of the "Ubuntu CD Image Automatic Signing Key" which makes no sense as it is in the trusted keyring anyway, but it is a good example. (Also the key is shortened to stay readable) | ||
1322 | 81 | |||
1323 | 82 | :: | ||
1324 | 83 | |||
1325 | 84 | -----BEGIN PGP PUBLIC KEY BLOCK----- | ||
1326 | 85 | Version: GnuPG v1 | ||
1327 | 86 | mQGiBEFEnz8RBAC7LstGsKD7McXZgd58oN68KquARLBl6rjA2vdhwl77KkPPOr3O | ||
1328 | 87 | RwIbDAAKCRBAl26vQ30FtdxYAJsFjU+xbex7gevyGQ2/mhqidES4MwCggqQyo+w1 | ||
1329 | 88 | Twx6DKLF+3rF5nf1F3Q= | ||
1330 | 89 | =PBAe | ||
1331 | 90 | -----END PGP PUBLIC KEY BLOCK----- | ||
1332 | 91 | |||
1333 | 92 | * replace the mirror from apt pulls repository data | ||
1334 | 93 | |||
1335 | 94 | - lets consider we have a local mirror at ``mymirror.local`` but otherwise following the usual paths | ||
1336 | 95 | |||
1337 | 96 | - make an example with a partial mirror that doesn't mirror the backports suite, so backports have to be disabled | ||
1338 | 97 | |||
1339 | 98 | That would be specified as | ||
1340 | 99 | :: | ||
1341 | 100 | |||
1342 | 101 | apt: | ||
1343 | 102 | primary: | ||
1344 | 103 | - arches [default] | ||
1345 | 104 | uri: http://mymirror.local/ubuntu/ | ||
1346 | 105 | disable_suites: [backports] | ||
1347 | 106 | sources: | ||
1348 | 107 | localrepokey: | ||
1349 | 108 | key: | # full key as block | ||
1350 | 109 | -----BEGIN PGP PUBLIC KEY BLOCK----- | ||
1351 | 110 | Version: GnuPG v1 | ||
1352 | 111 | |||
1353 | 112 | mQGiBEFEnz8RBAC7LstGsKD7McXZgd58oN68KquARLBl6rjA2vdhwl77KkPPOr3O | ||
1354 | 113 | RwIbDAAKCRBAl26vQ30FtdxYAJsFjU+xbex7gevyGQ2/mhqidES4MwCggqQyo+w1 | ||
1355 | 114 | Twx6DKLF+3rF5nf1F3Q= | ||
1356 | 115 | =PBAe | ||
1357 | 116 | -----END PGP PUBLIC KEY BLOCK----- | ||
1358 | 117 | |||
1359 | 118 | Please also read the section ``Dependencies`` below to avoid loosing some of the configuration content on first boot. | ||
1360 | 119 | |||
1361 | 120 | The file examples/apt-source.yaml holds various further examples that can be configured with this feature. | ||
1362 | 121 | |||
1363 | 122 | Common snippets | ||
1364 | 123 | --------------- | ||
1365 | 124 | This is a collection of additional ideas people can use the feature for customizing their to-be-installed system. | ||
1366 | 125 | |||
1367 | 126 | * enable proposed on installing | ||
1368 | 127 | apt: | ||
1369 | 128 | sources: | ||
1370 | 129 | proposed.list: deb $MIRROR $RELEASE-proposed main restricted universe multiverse | ||
1371 | 130 | |||
1372 | 131 | * Make debug symbols available | ||
1373 | 132 | apt: | ||
1374 | 133 | sources: | ||
1375 | 134 | ddebs.list: | | ||
1376 | 135 | deb http://ddebs.ubuntu.com $RELEASE main restricted universe multiverse | ||
1377 | 136 | deb http://ddebs.ubuntu.com $RELEASE-updates main restricted universe multiverse | ||
1378 | 137 | deb http://ddebs.ubuntu.com $RELEASE-security main restricted universe multiverse | ||
1379 | 138 | deb http://ddebs.ubuntu.com $RELEASE-proposed main restricted universe multiverse | ||
1380 | 139 | |||
1381 | 140 | Timing | ||
1382 | 141 | ------ | ||
1383 | 142 | The feature is implemented at the stage of curthooks_commands, after which runs just after curtin has extracted the image to the target. | ||
1384 | 143 | It can be ran as standalong command "curtin -v --config <yourconfigfile> apt-config". | ||
1385 | 144 | |||
1386 | 145 | This will pick up the target from the environment variable that is set by curtin, if you want to use it to a different target or outside of usual curtin handling you can add ``--target <path>`` to it to overwrite the target path. | ||
1387 | 146 | This target should have at least a minimal system with apt and dpkg installed for the functionality to work. | ||
1388 | 147 | |||
1389 | 148 | |||
1390 | 149 | Dependencies | ||
1391 | 150 | ------------ | ||
1392 | 151 | Cloud-init might need to resolve dependencies and install packages in the ephemeral environment to run curtin. | ||
1393 | 152 | Therefore it is recommended to not only configure curtin for the target, but also the install environment with proper apt configuration via cloud-init. | ||
1394 | 0 | 153 | ||
1395 | === added file 'examples/apt-source.yaml' | |||
1396 | --- examples/apt-source.yaml 1970-01-01 00:00:00 +0000 | |||
1397 | +++ examples/apt-source.yaml 2016-07-26 19:53:43 +0000 | |||
1398 | @@ -0,0 +1,239 @@ | |||
1399 | 1 | # YAML example of an apt config. | ||
1400 | 2 | apt: | ||
1401 | 3 | sources: | ||
1402 | 4 | # This is a dictionary (unlike most block/net which are lists) | ||
1403 | 5 | # The key is the filename and will be prepended by /etc/apt/sources.list.d/ | ||
1404 | 6 | # if it doesn't start with a '/'. | ||
1405 | 7 | # There are certain cases - where no content is written into a source.list | ||
1406 | 8 | # file where the filename will be ignored - yet it can still be used as | ||
1407 | 9 | # index for merging. | ||
1408 | 10 | # The values inside the entries consost of the following optional entries: | ||
1409 | 11 | # 'source': a sources.list entry (some variable replacements apply) | ||
1410 | 12 | # 'keyid': providing a key to import via shortid or fingerprint | ||
1411 | 13 | # 'key': providing a raw PGP key | ||
1412 | 14 | # 'keyserver': specify an alternate keyserver to pull keys from that | ||
1413 | 15 | # were specified by keyid | ||
1414 | 16 | # 'filename': for compatibility with the older format (now the key to | ||
1415 | 17 | # this dictionary is the filename). If specified this | ||
1416 | 18 | # overwrites the filename given as key. | ||
1417 | 19 | |||
1418 | 20 | # The new format allows merging between multiple input files than a list | ||
1419 | 21 | # like: | ||
1420 | 22 | # cloud-config1 | ||
1421 | 23 | # sources: | ||
1422 | 24 | # s1: {'key': 'key1', 'source': 'source1'} | ||
1423 | 25 | # cloud-config2 | ||
1424 | 26 | # sources: | ||
1425 | 27 | # s2: {'key': 'key2'} | ||
1426 | 28 | # s1: {'filename': 'foo'} | ||
1427 | 29 | # This would be merged to | ||
1428 | 30 | # sources: | ||
1429 | 31 | # s1: | ||
1430 | 32 | # filename: foo | ||
1431 | 33 | # key: key1 | ||
1432 | 34 | # source: source1 | ||
1433 | 35 | # s2: | ||
1434 | 36 | # key: key2 | ||
1435 | 37 | |||
1436 | 38 | curtin-dev-ppa.list: | ||
1437 | 39 | source: "deb http://ppa.launchpad.net/curtin-dev/test-archive/ubuntu xenial main" | ||
1438 | 40 | keyid: F430BBA5 # GPG key ID published on a key server | ||
1439 | 41 | # adding a source.list line, importing a gpg key for a given key id and | ||
1440 | 42 | # storing the deb entry in /etc/apt/sources.list.d/curtin-dev-ppa.list | ||
1441 | 43 | |||
1442 | 44 | # PPA shortcut: | ||
1443 | 45 | # * Setup correct apt sources.list line | ||
1444 | 46 | # * Import the signing key from LP | ||
1445 | 47 | # | ||
1446 | 48 | # See https://help.launchpad.net/Packaging/PPA for more information | ||
1447 | 49 | # this requires 'add-apt-repository' | ||
1448 | 50 | # due to that the filename key is ignored in this case | ||
1449 | 51 | ignored1: | ||
1450 | 52 | source: "ppa:curtin-dev/test-archive" # Quote the string | ||
1451 | 53 | |||
1452 | 54 | # additional custom deb source config: | ||
1453 | 55 | # * Creates a file in /etc/apt/sources.list.d/ for the sources list entry | ||
1454 | 56 | # * [optional] Import the apt signing key from the keyserver | ||
1455 | 57 | # * Defaults: | ||
1456 | 58 | # + keyserver: keyserver.ubuntu.com | ||
1457 | 59 | # | ||
1458 | 60 | # See sources.list man page for more information about the format | ||
1459 | 61 | my-repo1.list: | ||
1460 | 62 | source: deb http://archive.ubuntu.com/ubuntu xenial-backports main universe multiverse restricted | ||
1461 | 63 | |||
1462 | 64 | # sources can use $MIRROR and $RELEASE and they will be replaced | ||
1463 | 65 | # with the default or specified mirror and the running release. | ||
1464 | 66 | # The entry below would be possibly turned into: | ||
1465 | 67 | # source: deb http://archive.ubuntu.com/ubuntu xenial multiverse | ||
1466 | 68 | # see below at apt*mirror for more | ||
1467 | 69 | my-repo2.list: | ||
1468 | 70 | source: deb $MIRROR $RELEASE multiverse | ||
1469 | 71 | |||
1470 | 72 | # this would have the same end effect as 'ppa:curtin-dev/test-archive' | ||
1471 | 73 | my-repo3.list: | ||
1472 | 74 | source: "deb http://ppa.launchpad.net/curtin-dev/test-archive/ubuntu xenial main" | ||
1473 | 75 | keyid: F430BBA5 # GPG key ID published on a key server | ||
1474 | 76 | filename: curtin-dev-ppa.list | ||
1475 | 77 | |||
1476 | 78 | # this would only import the key without adding a ppa or other source spec | ||
1477 | 79 | # since this doesn't generate a source.list file the filename key is ignored | ||
1478 | 80 | ignored2: | ||
1479 | 81 | keyid: F430BBA5 # GPG key ID published on a key server | ||
1480 | 82 | |||
1481 | 83 | # In general keyid's can also be specified via their long fingerprints | ||
1482 | 84 | # since this doesn't generate a source.list file the filename key is ignored | ||
1483 | 85 | ignored3: | ||
1484 | 86 | keyid: B59D 5F15 97A5 04B7 E230 6DCA 0620 BBCF 0368 3F77 | ||
1485 | 87 | |||
1486 | 88 | # Custom apt repository: | ||
1487 | 89 | # * The apt signing key can also be specified | ||
1488 | 90 | # by providing a pgp public key block | ||
1489 | 91 | # * Providing the PGP key here is the most robust method for | ||
1490 | 92 | # specifying a key, as it removes dependency on a remote key server | ||
1491 | 93 | my-repo4.list: | ||
1492 | 94 | source: deb http://ppa.launchpad.net/curtin-dev/test-archive/ubuntu xenial main | ||
1493 | 95 | key: | # The value needs to start with -----BEGIN PGP PUBLIC KEY BLOCK----- | ||
1494 | 96 | -----BEGIN PGP PUBLIC KEY BLOCK----- | ||
1495 | 97 | Version: SKS 1.0.10 | ||
1496 | 98 | |||
1497 | 99 | mI0ESpA3UQEEALdZKVIMq0j6qWAXAyxSlF63SvPVIgxHPb9Nk0DZUixn+akqytxG4zKCONz6 | ||
1498 | 100 | qLjoBBfHnynyVLfT4ihg9an1PqxRnTO+JKQxl8NgKGz6Pon569GtAOdWNKw15XKinJTDLjnj | ||
1499 | 101 | 9y96ljJqRcpV9t/WsIcdJPcKFR5voHTEoABE2aEXABEBAAG0GUxhdW5jaHBhZCBQUEEgZm9y | ||
1500 | 102 | IEFsZXN0aWOItgQTAQIAIAUCSpA3UQIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEA7H | ||
1501 | 103 | 5Qi+CcVxWZ8D/1MyYvfj3FJPZUm2Yo1zZsQ657vHI9+pPouqflWOayRR9jbiyUFIn0VdQBrP | ||
1502 | 104 | t0FwvnOFArUovUWoKAEdqR8hPy3M3APUZjl5K4cMZR/xaMQeQRZ5CHpS4DBKURKAHC0ltS5o | ||
1503 | 105 | uBJKQOZm5iltJp15cgyIkBkGe8Mx18VFyVglAZey | ||
1504 | 106 | =Y2oI | ||
1505 | 107 | -----END PGP PUBLIC KEY BLOCK----- | ||
1506 | 108 | |||
1507 | 109 | # Custom gpg key: | ||
1508 | 110 | # * As with keyid, a key may also be specified without a related source. | ||
1509 | 111 | # * all other facts mentioned above still apply | ||
1510 | 112 | # since this doesn't generate a source.list file the filename key is ignored | ||
1511 | 113 | ignored4: | ||
1512 | 114 | key: | # The value needs to start with -----BEGIN PGP PUBLIC KEY BLOCK----- | ||
1513 | 115 | -----BEGIN PGP PUBLIC KEY BLOCK----- | ||
1514 | 116 | Version: SKS 1.0.10 | ||
1515 | 117 | |||
1516 | 118 | mI0ESpA3UQEEALdZKVIMq0j6qWAXAyxSlF63SvPVIgxHPb9Nk0DZUixn+akqytxG4zKCONz6 | ||
1517 | 119 | qLjoBBfHnynyVLfT4ihg9an1PqxRnTO+JKQxl8NgKGz6Pon569GtAOdWNKw15XKinJTDLjnj | ||
1518 | 120 | 9y96ljJqRcpV9t/WsIcdJPcKFR5voHTEoABE2aEXABEBAAG0GUxhdW5jaHBhZCBQUEEgZm9y | ||
1519 | 121 | IEFsZXN0aWOItgQTAQIAIAUCSpA3UQIbAwYLCQgHAwIEFQIIAwQWAgMBAh4BAheAAAoJEA7H | ||
1520 | 122 | 5Qi+CcVxWZ8D/1MyYvfj3FJPZUm2Yo1zZsQ657vHI9+pPouqflWOayRR9jbiyUFIn0VdQBrP | ||
1521 | 123 | t0FwvnOFArUovUWoKAEdqR8hPy3M3APUZjl5K4cMZR/xaMQeQRZ5CHpS4DBKURKAHC0ltS5o | ||
1522 | 124 | uBJKQOZm5iltJp15cgyIkBkGe8Mx18VFyVglAZey | ||
1523 | 125 | =Y2oI | ||
1524 | 126 | -----END PGP PUBLIC KEY BLOCK----- | ||
1525 | 127 | # end of apt dictionary | ||
1526 | 128 | |||
1527 | 129 | |||
1528 | 130 | # | ||
1529 | 131 | # All of the following are auxillary configurations to the apt handling | ||
1530 | 132 | # | ||
1531 | 133 | |||
1532 | 134 | # Preserve existing /etc/apt/sources.list | ||
1533 | 135 | # Default: True - do not overwrite sources_list. If staying at true | ||
1534 | 136 | # then any "mirrors" configuration above will have no effect | ||
1535 | 137 | # Set to False to affect sources.list with the configuration. Without only | ||
1536 | 138 | # extra source specifications will be written into /etc/apt/sources.list.d/. | ||
1537 | 139 | preserve_sources_list: false | ||
1538 | 140 | |||
1539 | 141 | # disable_suites by default it is an empty list, so nothing is removed. | ||
1540 | 142 | # If given, those suites are removed from source.list after all other | ||
1541 | 143 | # modifications have been made. | ||
1542 | 144 | # suites are even disabled if no other modification was made, | ||
1543 | 145 | # but not if is preserve_sources_list is active. | ||
1544 | 146 | # There is a special alias “$RELEASE” as in the sources that will be replace | ||
1545 | 147 | # by the matching release. | ||
1546 | 148 | # To ease configuration and improve readability the following common ubuntu | ||
1547 | 149 | # suites will be automatically mapped to their full definition. | ||
1548 | 150 | # updates => $RELEASE-updates | ||
1549 | 151 | # backports => $RELEASE-backports | ||
1550 | 152 | # security => $RELEASE-security | ||
1551 | 153 | # proposed => $RELEASE-proposed | ||
1552 | 154 | # release => $RELEASE | ||
1553 | 155 | # Note: Lines don’t get deleted, but disabled by being converted to a comment. | ||
1554 | 156 | # The following example disables all defaults except $RELEASE-security. On top | ||
1555 | 157 | # it disables a custom suite called "mysuite" | ||
1556 | 158 | disable_suites: [$RELEASE-updates, backports, $RELEASE, mysuite] | ||
1557 | 159 | |||
1558 | 160 | # a custom (e.g. localized) mirror that will be set in sources.list and | ||
1559 | 161 | # deb / deb-src lines | ||
1560 | 162 | # one can set primary and security mirror to different uri's | ||
1561 | 163 | # the child elements to the keys primary and secondary are equivalent | ||
1562 | 164 | primary: | ||
1563 | 165 | # arches is list of architectures the following config applies to | ||
1564 | 166 | # the special keyword "default" applies to any architecture not explicitly | ||
1565 | 167 | # listed. | ||
1566 | 168 | - arches: [amd64, i386, default] | ||
1567 | 169 | # uri is just defining the target as-is | ||
1568 | 170 | uri: http://us.archive.ubuntu.com/ubuntu | ||
1569 | 171 | # | ||
1570 | 172 | # via search one can define lists that are | ||
1571 | 173 | # tried one by one. The first with a working DNS resolution (or if it is an | ||
1572 | 174 | # IP) will be picked. That way one can keep one configuration for multiple | ||
1573 | 175 | # subenvironments that select the working one. | ||
1574 | 176 | search: | ||
1575 | 177 | - http://cool.but-sometimes-unreachable.com/ubuntu | ||
1576 | 178 | - http://us.archive.ubuntu.com/ubuntu | ||
1577 | 179 | # | ||
1578 | 180 | # This will search for <distro>-mirror locally and at the fqdn of the system. | ||
1579 | 181 | # If resolving that will be used as archive. That allows configuring local | ||
1580 | 182 | # mirrors via providing certin DNS names via a local nameserver. | ||
1581 | 183 | # These can even be set to resolve to the public names of defaults like | ||
1582 | 184 | # archive.ubuntu.com as long as they are reachable from the target. | ||
1583 | 185 | # For security it will search <distro>-security-mirror | ||
1584 | 186 | search_dns: True | ||
1585 | 187 | # | ||
1586 | 188 | # If multiple of a category are given | ||
1587 | 189 | # 1. uri | ||
1588 | 190 | # 2. search | ||
1589 | 191 | # 3. search_dns | ||
1590 | 192 | # are given the first defining a valid mirror wins (in the | ||
1591 | 193 | # order as defined here, not the one it is listed in the config). | ||
1592 | 194 | - arches: [s390x, arm64] | ||
1593 | 195 | # as above, allowing to have one config for different per arch mirrors | ||
1594 | 196 | # security is optional, if not defined it is set to the value of primary | ||
1595 | 197 | security: | ||
1596 | 198 | uri: http://security.ubuntu.com/ubuntu | ||
1597 | 199 | [...] | ||
1598 | 200 | # | ||
1599 | 201 | # if no mirrors are specified at all, or all lookups fail it will use: | ||
1600 | 202 | # primary: http://archive.ubuntu.com/ubuntu | ||
1601 | 203 | # security: http://security.ubuntu.com/ubuntu | ||
1602 | 204 | |||
1603 | 205 | # Provide a custom template for rendering sources.list | ||
1604 | 206 | # without one provided curtin will try to modify the sources.list it find | ||
1605 | 207 | # in the target at /etc/apt/. | ||
1606 | 208 | # Within these source.list templates you can use the following replacement | ||
1607 | 209 | # variables (all have sane ubuntu defaults, see above for details): | ||
1608 | 210 | # $RELEASE, $MIRROR, $PRIMARY, $SECURITY | ||
1609 | 211 | sources_list: | # written by curtin custom template | ||
1610 | 212 | deb $MIRROR $RELEASE main restricted | ||
1611 | 213 | deb-src $MIRROR $RELEASE main restricted | ||
1612 | 214 | deb $PRIMARY $RELEASE universe restricted | ||
1613 | 215 | deb $SECURITY $RELEASE-security multiverse | ||
1614 | 216 | |||
1615 | 217 | # any apt config string that will be made available to apt | ||
1616 | 218 | # see the APT.CONF(5) man page for details what can be specified | ||
1617 | 219 | conf: | # APT config | ||
1618 | 220 | APT { | ||
1619 | 221 | Get { | ||
1620 | 222 | Assume-Yes "true"; | ||
1621 | 223 | Fix-Broken "true"; | ||
1622 | 224 | }; | ||
1623 | 225 | }; | ||
1624 | 226 | |||
1625 | 227 | # proxies are the most common conf option that is set there is a | ||
1626 | 228 | # shortcut via apt*proxy. Those get automatically translated into the | ||
1627 | 229 | # correct Acquire::*::Proxy statements. | ||
1628 | 230 | proxy: http://[[user][:pass]@]host[:port]/ | ||
1629 | 231 | http_proxy: http://[[user][:pass]@]host[:port]/ | ||
1630 | 232 | ftp_proxy: ftp://[[user][:pass]@]host[:port]/ | ||
1631 | 233 | https_proxy: https://[[user][:pass]@]host[:port]/ | ||
1632 | 234 | # note: proxy actually being a short synonym to http_proxy | ||
1633 | 235 | |||
1634 | 236 | # 'source' entries in apt-sources that match this python regex | ||
1635 | 237 | # expression will be passed to add-apt-repository | ||
1636 | 238 | # The following example is also the builtin default if nothing is specified | ||
1637 | 239 | add_apt_repo_match: '^[\w-]+:\w' | ||
1638 | 0 | 240 | ||
1639 | === added file 'examples/tests/apt_config_command.yaml' | |||
1640 | --- examples/tests/apt_config_command.yaml 1970-01-01 00:00:00 +0000 | |||
1641 | +++ examples/tests/apt_config_command.yaml 2016-07-26 19:53:43 +0000 | |||
1642 | @@ -0,0 +1,85 @@ | |||
1643 | 1 | # This pushes curtin through a automatic installation | ||
1644 | 2 | # where no storage configuration is necessary. | ||
1645 | 3 | # exercising the standalong curtin apt-config command | ||
1646 | 4 | -placeholder_simple_install: unused | ||
1647 | 5 | bucket: | ||
1648 | 6 | - &run_with_stdin | | ||
1649 | 7 | #!/bin/sh | ||
1650 | 8 | input="$1" | ||
1651 | 9 | shift | ||
1652 | 10 | printf "%s\n" "$input" | "$@" | ||
1653 | 11 | |||
1654 | 12 | - &run_apt_config_file | | ||
1655 | 13 | #!/bin/sh | ||
1656 | 14 | # take the first argument, write it to a tmp file and execute | ||
1657 | 15 | # curtin apt --config=<tmpfile> "$@" | ||
1658 | 16 | set -e | ||
1659 | 17 | config="$1" | ||
1660 | 18 | shift | ||
1661 | 19 | TEMP_D=$(mktemp -d "${TMPDIR:-/tmp}/${0##*/}.XXXXXX") | ||
1662 | 20 | trap cleanup EXIT | ||
1663 | 21 | cleanup() { [ -z "${TEMP_D}" || rm -Rf "${TEMP_D}"; } | ||
1664 | 22 | cfg_file="${TEMP_D}/curtin-apt.conf" | ||
1665 | 23 | printf "%s\n" "$config" > "${cfg_file}" | ||
1666 | 24 | curtin apt-config "--config=${cfg_file}" "$@" | ||
1667 | 25 | |||
1668 | 26 | - &apt_config_ppa | | ||
1669 | 27 | # this is just a large string | ||
1670 | 28 | apt: | ||
1671 | 29 | sources: | ||
1672 | 30 | ignored: | ||
1673 | 31 | source: "ppa:curtin-dev/test-archive" | ||
1674 | 32 | curtin-test1.list: | ||
1675 | 33 | source: "deb $MIRROR $RELEASE-proposed main" | ||
1676 | 34 | |||
1677 | 35 | - &apt_config_source | | ||
1678 | 36 | apt: | ||
1679 | 37 | preserve_sources_list: false | ||
1680 | 38 | sources: | ||
1681 | 39 | ignored: | ||
1682 | 40 | source: "ppa:curtin-dev/test-archive" | ||
1683 | 41 | # apt-add-repositroy adds the key anyway, but lets pass that code | ||
1684 | 42 | # path of adding once more in this scope | ||
1685 | 43 | key: | | ||
1686 | 44 | -----BEGIN PGP PUBLIC KEY BLOCK----- | ||
1687 | 45 | Version: GnuPG v1 | ||
1688 | 46 | |||
1689 | 47 | mQINBFazYtEBEADXrW53tDOvwcnHwchLapTKK89+wBWR2qQKXx5Mymtjkrb688Fs | ||
1690 | 48 | ciXcCsvClnNGJ9bEhrJTucyb7WF0KcDVQcvOd0C4HOSEAc0DANBu1Mdp/tmCWuiW | ||
1691 | 49 | 1TbbhomyHAcHNdbuSZeMDh5xi9M3DYPVq72PwYwjrE4lotVxHeX5nYEH304U+5nJ | ||
1692 | 50 | tBNpVon91k3ItymQ6Jii+9gVoQ7ujiH1/Gw4/J/1/5zQ3C1mOjq68vLunz5iw1Kn | ||
1693 | 51 | 7TMVyID6qwq2UFEgudpseLfFZcb/p7KgI0m3S/OViwzSc44m63ggTPMmbeHW51xA | ||
1694 | 52 | 1rpUChSU+cm0cJ4tNtAcYHRYRltWAo/3J1OzB6Ut5P7vIC5r+QcCyyMbku9NjYaw | ||
1695 | 53 | dWX4DDKqW3is3qJ/7EeOKPL4N8wuKwuWUC7s2wqsIZL8EmsvR+ZOnTJ3bHZFvsLg | ||
1696 | 54 | p/OKqmhxMGYXiXOWDOEJ+vwboPxrvhD90JZl8weNGPnpla+EkxRDBSpEb31Vgt5X | ||
1697 | 55 | AIoxE7XxwfuXS3MGMA7fSqkGPGHfSLYQFFk+CAIeTUV+ypKW94hIxXKgqRxa7dxz | ||
1698 | 56 | Ymqs+wgIGaWJCnx7z1Kpd3HD9iTAYjyWyhlQ/Tjt43kwUBdALhTL0vYUTGQyTgKt | ||
1699 | 57 | tAriVf5bqHb6Hj5PS5YZQ/+YoCUI2OTrAWWNyH9rIEZGsFc30oJFPHj3fQARAQAB | ||
1700 | 58 | tCNMYXVuY2hwYWQgUFBBIGZvciBjdXJ0aW4gZGV2ZWxvcGVyc4kCOAQTAQIAIgUC | ||
1701 | 59 | VrNi0QIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQVf58jAFlAT4TGg// | ||
1702 | 60 | SV7vWmkJqr5TSlT9JqCBfmtFjgudxTGG8XM2zwnta+m/3YVOMo0ZjyGL4fUKjCmN | ||
1703 | 61 | eh6eYihwpRtfdawziaEOydDxNfdjwscV4Qcy7FjHX+DQnNzQyzK+WgWRJwNWloCw | ||
1704 | 62 | skg2tF+EDRajalTRjHJAn+5zAilXVn71T/hhOCxkF0PBiH9s/e7pW/KcgBEC1MYV | ||
1705 | 63 | Fs0fLST8SYhsIxttVRWuRkJDrtEY1zeVhkvk+PN6UuCY6/gyRSQ1rhhBF3ePqiba | ||
1706 | 64 | CmLiUjnJMEm1OJOkuD33IMNPKQi99TZhr8y3AGCcrmAQtJsYLvVDPcsOsjGQHXP4 | ||
1707 | 65 | 2qQXK+jE/AAUycCQ6tgrAqCcUNQiClP8xUPkZOiDNvVMiPvIj/s79ShkoRaWLMb7 | ||
1708 | 66 | n9jyDOhs3L7dtmKQwHWq9qJ56fzx1L0/jxSanzm+ZJ/Q7t6E/GFxY1RsAk7xtI1C | ||
1709 | 67 | SzSmrGKmtlbWlOyqqQb6zhULIJpaXvh/GaYyo0xI3rA+QvPDt/fgUJEBiSidwabW | ||
1710 | 68 | Q8JU9iI5HXQxbVq1gSdy/z31fue5JuZSqjnjCjgho/UrXa4i1RPtqsY3FoTk7Hmo | ||
1711 | 69 | C1z2cJc8HQI8JnEX/4qJXvPMRM2JsMD9DqvgsUJG5M9Qchy8cymYY+xeiBVYzJI+ | ||
1712 | 70 | WHCq6LHqnVxYZ+RM858lSsD6wetN44vguIjL3qJJ+wU= | ||
1713 | 71 | curtin-test1.list: | ||
1714 | 72 | source: "deb $MIRROR $RELEASE-proposed main" | ||
1715 | 73 | |||
1716 | 74 | # into ephemeral environment | ||
1717 | 75 | early_commands: | ||
1718 | 76 | 00_add_archive: [sh, -c, *run_with_stdin, "curtin-apt", | ||
1719 | 77 | *apt_config_ppa, curtin, apt-config, --config=-, --target=/] | ||
1720 | 78 | # tests itself by installing a packet only available in that ppa | ||
1721 | 79 | 00_install_package: [apt-get, install, --assume-yes, smello] | ||
1722 | 80 | |||
1723 | 81 | # into target environment | ||
1724 | 82 | late_commands: | ||
1725 | 83 | 00_add_archive: [sh, -c, *run_apt_config_file, "curtin-apt-file", | ||
1726 | 84 | *apt_config_source] | ||
1727 | 85 | 00_install_package: [curtin, in-target, --, apt-get, install, --assume-yes, smello] | ||
1728 | 0 | 86 | ||
1729 | === added file 'examples/tests/apt_source_custom.yaml' | |||
1730 | --- examples/tests/apt_source_custom.yaml 1970-01-01 00:00:00 +0000 | |||
1731 | +++ examples/tests/apt_source_custom.yaml 2016-07-26 19:53:43 +0000 | |||
1732 | @@ -0,0 +1,97 @@ | |||
1733 | 1 | showtrace: true | ||
1734 | 2 | apt: | ||
1735 | 3 | preserve_sources_list: false | ||
1736 | 4 | primary: | ||
1737 | 5 | - arches: [default] | ||
1738 | 6 | uri: http://us.archive.ubuntu.com/ubuntu | ||
1739 | 7 | security: | ||
1740 | 8 | - arches: [default] | ||
1741 | 9 | uri: http://security.ubuntu.com/ubuntu | ||
1742 | 10 | sources_list: | # written by curtin custom template | ||
1743 | 11 | deb $MIRROR $RELEASE main restricted | ||
1744 | 12 | deb-src $MIRROR $RELEASE main restricted | ||
1745 | 13 | deb $PRIMARY $RELEASE universe restricted | ||
1746 | 14 | deb $SECURITY $RELEASE-security multiverse | ||
1747 | 15 | # nice line to check in test | ||
1748 | 16 | conf: | # APT config | ||
1749 | 17 | ACQUIRE { | ||
1750 | 18 | Retries "3"; | ||
1751 | 19 | }; | ||
1752 | 20 | sources: | ||
1753 | 21 | curtin-dev-ppa.list: | ||
1754 | 22 | source: "deb http://ppa.launchpad.net/curtin-dev/test-archive/ubuntu xenial main" | ||
1755 | 23 | keyid: F430BBA5 | ||
1756 | 24 | ignored1: | ||
1757 | 25 | source: "ppa:curtin-dev/test-archive" | ||
1758 | 26 | my-repo2.list: | ||
1759 | 27 | source: deb $MIRROR $RELEASE multiverse | ||
1760 | 28 | ignored3: | ||
1761 | 29 | keyid: 0E72 9061 0D2F 6DC4 D65E A921 9A31 4EC5 F470 A0AC | ||
1762 | 30 | my-repo4.list: | ||
1763 | 31 | source: deb http://ppa.launchpad.net/curtin-dev/test-archive/ubuntu xenial main | ||
1764 | 32 | key: | | ||
1765 | 33 | -----BEGIN PGP PUBLIC KEY BLOCK----- | ||
1766 | 34 | Version: GnuPG v1 | ||
1767 | 35 | |||
1768 | 36 | mQINBFXJ3NcBEAC85PMdaKdItkdjCT1vRJrdwNqj4lN5mu6z4dDVfeZlmozRDBGb | ||
1769 | 37 | ENSOWCiYz3meANO7bKthQQCqAETSBV72rrDCqFZUpXeyG3zCN98Z/UdJ8zpQD9uw | ||
1770 | 38 | mq2CaAqWMk6ty+PkHQ4gtIc390lGfRbHNoZ5HaWJNVOK7FCB2hBmnTZW7AViYiYa | ||
1771 | 39 | YswOjYxaCkwQ/DsMOPD7S5OjwbLucs2YGjkBm7YF1nnXNzyt+BwieKQW/sQ2+ga1 | ||
1772 | 40 | mkgLW1BTQN3+JreBpeHy/yrRdK4dOZZUar4WPZitZzOW2eNpaaf6hKNA14LB/96a | ||
1773 | 41 | tEguK8VazoqSQGvNV/R3PjIYmurVP3/Z9bEVgOKhMCflgwKCYgx+tBUypN3zFWv9 | ||
1774 | 42 | pgVq3iHx1MFCvoP9FsNB7I6jzOxlQP4z25BzR3ympx/QexkFw5CBFXhdrU+qNVBl | ||
1775 | 43 | SSnz69aLEjCRXqBOnQEr0irs/e/35+yLJdEuw89vSwWwrzbV5r1Y7uxinEGWSydT | ||
1776 | 44 | qddj97uKOWeMmnp20Be4+nhDDW/BMiTFI4Y3bYeDTrftbWMaSEmtSTw5HHxtAFtg | ||
1777 | 45 | X9Hyx0Q3eN1w3gRZgIdm0xYTe7bNTofFRdfXzB/9wtNIcaW10+IlODShFHPCnh+d | ||
1778 | 46 | i56a8LCdZcXiiLfCIhEcnqmM37BVvhjIQKSyOU1eMEgX148aVEz36OVuMwARAQAB | ||
1779 | 47 | tCdDaHJpc3RpYW4gRWhyaGFyZHQgPGNwYWVsemVyQGdtYWlsLmNvbT6JAjgEEwEC | ||
1780 | 48 | ACIFAlXJ3NcCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJELo+KTOCgLJC | ||
1781 | 49 | BugP/ir0ES3wCzvHMnkz2UlXt9FR4KqY0L9uFmwu9VYpmfAploEVIOi2HcuxpcRp | ||
1782 | 50 | hgoQlUtkz3lRhUeZzCxuB1ljM2JKTJiezP1tFTTGCbVYhPyA0LmUiHDWylG7FzPb | ||
1783 | 51 | TX96HY/G0jf+m4CfR8q3HNHjeDi4VeA2ppBxdHcVE5I7HihDgRPJd+CvCa3nYdAb | ||
1784 | 52 | nXDKlQZz5aZc7AgrRVamr4mshkzWuwNNCwOt3AIgHDkU/HzA5xlXfwHxOoP6scWH | ||
1785 | 53 | /T7vFsd/vOikBphGseWPgKm6w1zyQ5Dk/wjRL8UeSJZW+Rh4PuBMbxg01lAZpPTq | ||
1786 | 54 | tu/bePeNty3g5bhwO6oHMpWhprn3dO37R680qo6UnBPzICeuBUnSYgpPnsQC9maz | ||
1787 | 55 | FEjiBtMsXSanU5vww7TpxY1JHjk5KFcmKx4sBeablznsm+GuVaDFN8R4eDjrM14r | ||
1788 | 56 | SOzA9cV0bSQr4dMqA9fZFSx6qLTacIeMfptybW3zaDX/pJOeBBWRAtoAfZIFbBnu | ||
1789 | 57 | /ZxDDgiQtZzpVK4UkYk5rjjtV/CPVXx64AnTHi35YfUn14KkE+k3odHdvPfBiv9+ | ||
1790 | 58 | NxfkTuV/koOgpD3+lTIYXyVHS9gwvhfRD/YfdrnVGl7bRZe68j7bfWDuQuSqIhSA | ||
1791 | 59 | jpeJslJCawnqv6fVB6buj6jjcgHIxqCVn99chaPFSblEIPfXtDVDaHJpc3RpYW4g | ||
1792 | 60 | RWhyaGFyZHQgPGNocmlzdGlhbi5laHJoYXJkdEBjYW5vbmljYWwuY29tPokCOAQT | ||
1793 | 61 | AQIAIgUCVsbUOgIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQuj4pM4KA | ||
1794 | 62 | skJNPg/7BF/iXHHdSBigWKXCCvQz58uInoc/R4beIegxRCMq7wkYEey4B7Fd35zY | ||
1795 | 63 | zv9CBOTV3hZePMCg9jxl4ki2kSsrZSCIEJw4L/aXDtJtx3HT18uTW0QKoU3nK/ro | ||
1796 | 64 | OtthVqBqmiSEi40UUU+5MGrUjwLSm+PjaaSapjK/lddf0KbXBB78/BtR/XT0gxWM | ||
1797 | 65 | +o68Oei9Nj1S3h6UndJwNAQ1xaDWmU2T7CRJet3F+cXZd3aDuS2axOTSTZbraSq7 | ||
1798 | 66 | zdl1xUiKtzXZIp8X1ewne+dzkewZuWj7DOwOBEFK26UhxCjKd5mUr7jpWQ4ampFX | ||
1799 | 67 | 6xfd/MK8SJFY+iHOBKyzq9po40tE23dqWuaHB+T3MxOgQ9JHCo9x22XNvEuKZW/V | ||
1800 | 68 | 4WaoGHVkR+jtWNC8Qv/xCMHL3CEvAklKJR68WDhozwUYTgNt5vCoJOviMlbhDSwf | ||
1801 | 69 | 0zVXpQwMR//4c0QSA0+BPpIEPDnx5vTIHBVXHy4bBBHU2Vi87QIDS0AtiBpNcspN | ||
1802 | 70 | 6AG0ktuldkE/pqfSTJ2A9HpHZyU+8boagRS5/z102Pjtmf/mzUkcHmfRb9o0DE15 | ||
1803 | 71 | X5fqpA3lYyx9eHIAgH4eaB1+G20Ez/EY5hr8IMS2nNBSem491UW6DXDYRu6eBLrR | ||
1804 | 72 | sRmtrJ6DlTZFRFlqVZ47bce/SbeM/xljvRkBxWG6RtDRsTyNVI65Ag0EVcnc1wEQ | ||
1805 | 73 | ANzk9W058tSHqf05UEtJGrN0K8DLriCvPd7QdFA8yVIZM3WD+m0AMBGXjd8BT5c2 | ||
1806 | 74 | lt0GmhB8klonHZvPiVLTRTLcSsc3NBopr1HL1bWsgOczwWiXSrc62oGAHUOQT/bv | ||
1807 | 75 | vS6KIkZgez+qtCo/DCOGJrADaoJBiBCLSsZgowpzazZZDPUF7rAsfcryVCFvftK0 | ||
1808 | 76 | wAe1OdvUG77NHrMrE1oX3zh82hTqR5azBre6Y81lNwxxug/Xl/RHjNhEOYohcsLS | ||
1809 | 77 | /xl0m2X831fHzcGGpoISRgrfel+M4RoC7KsLrwVhrF8koCD/ZQlevfLpuRl5LNpO | ||
1810 | 78 | s1ZtEi8ZvLliih+H+BOlBD0zUc3zZrrks/NCpm1eZba0Z6L48r4TIHW08SGlHx7o | ||
1811 | 79 | SrXgkq3mtoM8C4uDiLwjav5KxiF7n68s/9LF82aAr7YjNXd+xYZNjsmmFlYj9CGI | ||
1812 | 80 | lL4jVt4v4EtTONa6pbtCNv5ezOLDZ6BBcQ36xdkrWzdpjQjL2mnh3sqIAGIPu7tH | ||
1813 | 81 | N8euQ5L1zIvIjVqYlR1eJssp96QYPWYxF7TosfML4BUhCP631IWfuD9X/K2LzDmv | ||
1814 | 82 | B2gVZo9fbhSC+P7GYVG+tV4VLAMbspAxRXXL69+j98aeV5g59f8OFQPbGpKE/SAY | ||
1815 | 83 | eIXtq8DD+PYUXXq3VUI2brVLv42LBVdSJpKNKG3decIBABEBAAGJAh8EGAECAAkF | ||
1816 | 84 | AlXJ3NcCGwwACgkQuj4pM4KAskKzeg/9FxXJLV3eWwY4nn2VhwYTHnHtSUpi8usk | ||
1817 | 85 | RzIa3Mcj6OEVjU2LZaT3UQF8h6dLM9y+CemcwyjMqm1RQ5+ogfrItby1AaBXwCvm | ||
1818 | 86 | XCUGw2zFOAnyzSHHoDFj27sllFxDmfSiBY5KP8M+/ywHKZDkRb6EjzMPx5oKFeGW | ||
1819 | 87 | Hmqaj5FDmTeWChSIHd1ZxobashFauOZDbS/ijRRMsVGFulU2Nb/4QJK73g3orfhY | ||
1820 | 88 | 5mq1TMkQ5Kcbqh4OmYYYayLtJQcpa6ZVopaRhAJFe30P83zW9pM5LQDpP9JIyY+S | ||
1821 | 89 | DjasEY4ekYtw6oCKAjpqlwaaNDjl27OkJ7R7laFKy4grZ2TSB/2KTjn/Ea3CH/pA | ||
1822 | 90 | SrpVis1LvC90XytbBnsEKYXU55H943wmBc6oj+itQhx4WyIiv+UgtHI/DbnYbUru | ||
1823 | 91 | 71wpfapqGBXYfu/zAra8PITngOFuizeYu+idemu55ANO3keJPKr3ZBUSBBpNFauT | ||
1824 | 92 | VUUCSnrLt+kpSLopYESiNdsPW/aQTFgFvA4BkBJTIMQsQZXicuXUePYlg5xFzXOv | ||
1825 | 93 | XgiqkjRA9xBI5JAIUgLRk3ulVFt2bIsTG9XgtGyphEs86Q0MOIMo0WbZGtAYDrZO | ||
1826 | 94 | DITbm2KzVLGVLn/ZJiW11RSHPNiwgg66/puKdFWrSogYYDJdDEUJtLIhypZ+ORxe | ||
1827 | 95 | 7oh88hTkC1w= | ||
1828 | 96 | =UNSw | ||
1829 | 97 | -----END PGP PUBLIC KEY BLOCK----- | ||
1830 | 0 | 98 | ||
1831 | === added file 'examples/tests/apt_source_modify.yaml' | |||
1832 | --- examples/tests/apt_source_modify.yaml 1970-01-01 00:00:00 +0000 | |||
1833 | +++ examples/tests/apt_source_modify.yaml 2016-07-26 19:53:43 +0000 | |||
1834 | @@ -0,0 +1,92 @@ | |||
1835 | 1 | showtrace: true | ||
1836 | 2 | apt: | ||
1837 | 3 | preserve_sources_list: false | ||
1838 | 4 | primary: | ||
1839 | 5 | - arches: [default] | ||
1840 | 6 | uri: http://us.archive.ubuntu.com/ubuntu | ||
1841 | 7 | security: | ||
1842 | 8 | - arches: [default] | ||
1843 | 9 | uri: http://security.ubuntu.com/ubuntu | ||
1844 | 10 | conf: | # APT config | ||
1845 | 11 | ACQUIRE { | ||
1846 | 12 | Retries "3"; | ||
1847 | 13 | }; | ||
1848 | 14 | sources: | ||
1849 | 15 | curtin-dev-ppa.list: | ||
1850 | 16 | source: "deb http://ppa.launchpad.net/curtin-dev/test-archive/ubuntu xenial main" | ||
1851 | 17 | keyid: F430BBA5 | ||
1852 | 18 | ignored1: | ||
1853 | 19 | source: "ppa:curtin-dev/test-archive" | ||
1854 | 20 | # intentionally dropped the .list here, has to be added by the code | ||
1855 | 21 | my-repo2: | ||
1856 | 22 | source: deb $MIRROR $RELEASE multiverse | ||
1857 | 23 | ignored3: | ||
1858 | 24 | keyid: 0E72 9061 0D2F 6DC4 D65E A921 9A31 4EC5 F470 A0AC | ||
1859 | 25 | my-repo4.list: | ||
1860 | 26 | source: deb http://ppa.launchpad.net/curtin-dev/test-archive/ubuntu xenial main | ||
1861 | 27 | key: | | ||
1862 | 28 | -----BEGIN PGP PUBLIC KEY BLOCK----- | ||
1863 | 29 | Version: GnuPG v1 | ||
1864 | 30 | |||
1865 | 31 | mQINBFXJ3NcBEAC85PMdaKdItkdjCT1vRJrdwNqj4lN5mu6z4dDVfeZlmozRDBGb | ||
1866 | 32 | ENSOWCiYz3meANO7bKthQQCqAETSBV72rrDCqFZUpXeyG3zCN98Z/UdJ8zpQD9uw | ||
1867 | 33 | mq2CaAqWMk6ty+PkHQ4gtIc390lGfRbHNoZ5HaWJNVOK7FCB2hBmnTZW7AViYiYa | ||
1868 | 34 | YswOjYxaCkwQ/DsMOPD7S5OjwbLucs2YGjkBm7YF1nnXNzyt+BwieKQW/sQ2+ga1 | ||
1869 | 35 | mkgLW1BTQN3+JreBpeHy/yrRdK4dOZZUar4WPZitZzOW2eNpaaf6hKNA14LB/96a | ||
1870 | 36 | tEguK8VazoqSQGvNV/R3PjIYmurVP3/Z9bEVgOKhMCflgwKCYgx+tBUypN3zFWv9 | ||
1871 | 37 | pgVq3iHx1MFCvoP9FsNB7I6jzOxlQP4z25BzR3ympx/QexkFw5CBFXhdrU+qNVBl | ||
1872 | 38 | SSnz69aLEjCRXqBOnQEr0irs/e/35+yLJdEuw89vSwWwrzbV5r1Y7uxinEGWSydT | ||
1873 | 39 | qddj97uKOWeMmnp20Be4+nhDDW/BMiTFI4Y3bYeDTrftbWMaSEmtSTw5HHxtAFtg | ||
1874 | 40 | X9Hyx0Q3eN1w3gRZgIdm0xYTe7bNTofFRdfXzB/9wtNIcaW10+IlODShFHPCnh+d | ||
1875 | 41 | i56a8LCdZcXiiLfCIhEcnqmM37BVvhjIQKSyOU1eMEgX148aVEz36OVuMwARAQAB | ||
1876 | 42 | tCdDaHJpc3RpYW4gRWhyaGFyZHQgPGNwYWVsemVyQGdtYWlsLmNvbT6JAjgEEwEC | ||
1877 | 43 | ACIFAlXJ3NcCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJELo+KTOCgLJC | ||
1878 | 44 | BugP/ir0ES3wCzvHMnkz2UlXt9FR4KqY0L9uFmwu9VYpmfAploEVIOi2HcuxpcRp | ||
1879 | 45 | hgoQlUtkz3lRhUeZzCxuB1ljM2JKTJiezP1tFTTGCbVYhPyA0LmUiHDWylG7FzPb | ||
1880 | 46 | TX96HY/G0jf+m4CfR8q3HNHjeDi4VeA2ppBxdHcVE5I7HihDgRPJd+CvCa3nYdAb | ||
1881 | 47 | nXDKlQZz5aZc7AgrRVamr4mshkzWuwNNCwOt3AIgHDkU/HzA5xlXfwHxOoP6scWH | ||
1882 | 48 | /T7vFsd/vOikBphGseWPgKm6w1zyQ5Dk/wjRL8UeSJZW+Rh4PuBMbxg01lAZpPTq | ||
1883 | 49 | tu/bePeNty3g5bhwO6oHMpWhprn3dO37R680qo6UnBPzICeuBUnSYgpPnsQC9maz | ||
1884 | 50 | FEjiBtMsXSanU5vww7TpxY1JHjk5KFcmKx4sBeablznsm+GuVaDFN8R4eDjrM14r | ||
1885 | 51 | SOzA9cV0bSQr4dMqA9fZFSx6qLTacIeMfptybW3zaDX/pJOeBBWRAtoAfZIFbBnu | ||
1886 | 52 | /ZxDDgiQtZzpVK4UkYk5rjjtV/CPVXx64AnTHi35YfUn14KkE+k3odHdvPfBiv9+ | ||
1887 | 53 | NxfkTuV/koOgpD3+lTIYXyVHS9gwvhfRD/YfdrnVGl7bRZe68j7bfWDuQuSqIhSA | ||
1888 | 54 | jpeJslJCawnqv6fVB6buj6jjcgHIxqCVn99chaPFSblEIPfXtDVDaHJpc3RpYW4g | ||
1889 | 55 | RWhyaGFyZHQgPGNocmlzdGlhbi5laHJoYXJkdEBjYW5vbmljYWwuY29tPokCOAQT | ||
1890 | 56 | AQIAIgUCVsbUOgIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQuj4pM4KA | ||
1891 | 57 | skJNPg/7BF/iXHHdSBigWKXCCvQz58uInoc/R4beIegxRCMq7wkYEey4B7Fd35zY | ||
1892 | 58 | zv9CBOTV3hZePMCg9jxl4ki2kSsrZSCIEJw4L/aXDtJtx3HT18uTW0QKoU3nK/ro | ||
1893 | 59 | OtthVqBqmiSEi40UUU+5MGrUjwLSm+PjaaSapjK/lddf0KbXBB78/BtR/XT0gxWM | ||
1894 | 60 | +o68Oei9Nj1S3h6UndJwNAQ1xaDWmU2T7CRJet3F+cXZd3aDuS2axOTSTZbraSq7 | ||
1895 | 61 | zdl1xUiKtzXZIp8X1ewne+dzkewZuWj7DOwOBEFK26UhxCjKd5mUr7jpWQ4ampFX | ||
1896 | 62 | 6xfd/MK8SJFY+iHOBKyzq9po40tE23dqWuaHB+T3MxOgQ9JHCo9x22XNvEuKZW/V | ||
1897 | 63 | 4WaoGHVkR+jtWNC8Qv/xCMHL3CEvAklKJR68WDhozwUYTgNt5vCoJOviMlbhDSwf | ||
1898 | 64 | 0zVXpQwMR//4c0QSA0+BPpIEPDnx5vTIHBVXHy4bBBHU2Vi87QIDS0AtiBpNcspN | ||
1899 | 65 | 6AG0ktuldkE/pqfSTJ2A9HpHZyU+8boagRS5/z102Pjtmf/mzUkcHmfRb9o0DE15 | ||
1900 | 66 | X5fqpA3lYyx9eHIAgH4eaB1+G20Ez/EY5hr8IMS2nNBSem491UW6DXDYRu6eBLrR | ||
1901 | 67 | sRmtrJ6DlTZFRFlqVZ47bce/SbeM/xljvRkBxWG6RtDRsTyNVI65Ag0EVcnc1wEQ | ||
1902 | 68 | ANzk9W058tSHqf05UEtJGrN0K8DLriCvPd7QdFA8yVIZM3WD+m0AMBGXjd8BT5c2 | ||
1903 | 69 | lt0GmhB8klonHZvPiVLTRTLcSsc3NBopr1HL1bWsgOczwWiXSrc62oGAHUOQT/bv | ||
1904 | 70 | vS6KIkZgez+qtCo/DCOGJrADaoJBiBCLSsZgowpzazZZDPUF7rAsfcryVCFvftK0 | ||
1905 | 71 | wAe1OdvUG77NHrMrE1oX3zh82hTqR5azBre6Y81lNwxxug/Xl/RHjNhEOYohcsLS | ||
1906 | 72 | /xl0m2X831fHzcGGpoISRgrfel+M4RoC7KsLrwVhrF8koCD/ZQlevfLpuRl5LNpO | ||
1907 | 73 | s1ZtEi8ZvLliih+H+BOlBD0zUc3zZrrks/NCpm1eZba0Z6L48r4TIHW08SGlHx7o | ||
1908 | 74 | SrXgkq3mtoM8C4uDiLwjav5KxiF7n68s/9LF82aAr7YjNXd+xYZNjsmmFlYj9CGI | ||
1909 | 75 | lL4jVt4v4EtTONa6pbtCNv5ezOLDZ6BBcQ36xdkrWzdpjQjL2mnh3sqIAGIPu7tH | ||
1910 | 76 | N8euQ5L1zIvIjVqYlR1eJssp96QYPWYxF7TosfML4BUhCP631IWfuD9X/K2LzDmv | ||
1911 | 77 | B2gVZo9fbhSC+P7GYVG+tV4VLAMbspAxRXXL69+j98aeV5g59f8OFQPbGpKE/SAY | ||
1912 | 78 | eIXtq8DD+PYUXXq3VUI2brVLv42LBVdSJpKNKG3decIBABEBAAGJAh8EGAECAAkF | ||
1913 | 79 | AlXJ3NcCGwwACgkQuj4pM4KAskKzeg/9FxXJLV3eWwY4nn2VhwYTHnHtSUpi8usk | ||
1914 | 80 | RzIa3Mcj6OEVjU2LZaT3UQF8h6dLM9y+CemcwyjMqm1RQ5+ogfrItby1AaBXwCvm | ||
1915 | 81 | XCUGw2zFOAnyzSHHoDFj27sllFxDmfSiBY5KP8M+/ywHKZDkRb6EjzMPx5oKFeGW | ||
1916 | 82 | Hmqaj5FDmTeWChSIHd1ZxobashFauOZDbS/ijRRMsVGFulU2Nb/4QJK73g3orfhY | ||
1917 | 83 | 5mq1TMkQ5Kcbqh4OmYYYayLtJQcpa6ZVopaRhAJFe30P83zW9pM5LQDpP9JIyY+S | ||
1918 | 84 | DjasEY4ekYtw6oCKAjpqlwaaNDjl27OkJ7R7laFKy4grZ2TSB/2KTjn/Ea3CH/pA | ||
1919 | 85 | SrpVis1LvC90XytbBnsEKYXU55H943wmBc6oj+itQhx4WyIiv+UgtHI/DbnYbUru | ||
1920 | 86 | 71wpfapqGBXYfu/zAra8PITngOFuizeYu+idemu55ANO3keJPKr3ZBUSBBpNFauT | ||
1921 | 87 | VUUCSnrLt+kpSLopYESiNdsPW/aQTFgFvA4BkBJTIMQsQZXicuXUePYlg5xFzXOv | ||
1922 | 88 | XgiqkjRA9xBI5JAIUgLRk3ulVFt2bIsTG9XgtGyphEs86Q0MOIMo0WbZGtAYDrZO | ||
1923 | 89 | DITbm2KzVLGVLn/ZJiW11RSHPNiwgg66/puKdFWrSogYYDJdDEUJtLIhypZ+ORxe | ||
1924 | 90 | 7oh88hTkC1w= | ||
1925 | 91 | =UNSw | ||
1926 | 92 | -----END PGP PUBLIC KEY BLOCK----- | ||
1927 | 0 | 93 | ||
1928 | === added file 'examples/tests/apt_source_modify_arches.yaml' | |||
1929 | --- examples/tests/apt_source_modify_arches.yaml 1970-01-01 00:00:00 +0000 | |||
1930 | +++ examples/tests/apt_source_modify_arches.yaml 2016-07-26 19:53:43 +0000 | |||
1931 | @@ -0,0 +1,102 @@ | |||
1932 | 1 | showtrace: true | ||
1933 | 2 | apt: | ||
1934 | 3 | preserve_sources_list: false | ||
1935 | 4 | primary: | ||
1936 | 5 | # we don't know on which arch this will run, so we can't put the "right" | ||
1937 | 6 | # config in an arch, but we can provide various confusing alternatives | ||
1938 | 7 | # and orders and it has to pick default out of them | ||
1939 | 8 | - arches: [x86_2048, x86_4096, x86_8192, amd18.5, "foobar"] | ||
1940 | 9 | uri: http://notthis.com/ubuntu | ||
1941 | 10 | - arches: ["*"] | ||
1942 | 11 | uri: http://notthis.com/ubuntu | ||
1943 | 12 | - arches: [default] | ||
1944 | 13 | uri: http://us.archive.ubuntu.com/ubuntu | ||
1945 | 14 | - arches: [] | ||
1946 | 15 | uri: http://notthis.com/ubuntu | ||
1947 | 16 | security: | ||
1948 | 17 | - arches: [default] | ||
1949 | 18 | uri: http://security.ubuntu.com/ubuntu | ||
1950 | 19 | - arches: ["supersecurearchthatdoesnexist"] | ||
1951 | 20 | uri: http://notthat.com/ubuntu | ||
1952 | 21 | conf: | # APT config | ||
1953 | 22 | ACQUIRE { | ||
1954 | 23 | Retries "3"; | ||
1955 | 24 | }; | ||
1956 | 25 | sources: | ||
1957 | 26 | curtin-dev-ppa.list: | ||
1958 | 27 | source: "deb http://ppa.launchpad.net/curtin-dev/test-archive/ubuntu xenial main" | ||
1959 | 28 | keyid: F430BBA5 | ||
1960 | 29 | ignored1: | ||
1961 | 30 | source: "ppa:curtin-dev/test-archive" | ||
1962 | 31 | my-repo2.list: | ||
1963 | 32 | source: deb $MIRROR $RELEASE multiverse | ||
1964 | 33 | ignored3: | ||
1965 | 34 | keyid: 0E72 9061 0D2F 6DC4 D65E A921 9A31 4EC5 F470 A0AC | ||
1966 | 35 | my-repo4.list: | ||
1967 | 36 | source: deb http://ppa.launchpad.net/curtin-dev/test-archive/ubuntu xenial main | ||
1968 | 37 | key: | | ||
1969 | 38 | -----BEGIN PGP PUBLIC KEY BLOCK----- | ||
1970 | 39 | Version: GnuPG v1 | ||
1971 | 40 | |||
1972 | 41 | mQINBFXJ3NcBEAC85PMdaKdItkdjCT1vRJrdwNqj4lN5mu6z4dDVfeZlmozRDBGb | ||
1973 | 42 | ENSOWCiYz3meANO7bKthQQCqAETSBV72rrDCqFZUpXeyG3zCN98Z/UdJ8zpQD9uw | ||
1974 | 43 | mq2CaAqWMk6ty+PkHQ4gtIc390lGfRbHNoZ5HaWJNVOK7FCB2hBmnTZW7AViYiYa | ||
1975 | 44 | YswOjYxaCkwQ/DsMOPD7S5OjwbLucs2YGjkBm7YF1nnXNzyt+BwieKQW/sQ2+ga1 | ||
1976 | 45 | mkgLW1BTQN3+JreBpeHy/yrRdK4dOZZUar4WPZitZzOW2eNpaaf6hKNA14LB/96a | ||
1977 | 46 | tEguK8VazoqSQGvNV/R3PjIYmurVP3/Z9bEVgOKhMCflgwKCYgx+tBUypN3zFWv9 | ||
1978 | 47 | pgVq3iHx1MFCvoP9FsNB7I6jzOxlQP4z25BzR3ympx/QexkFw5CBFXhdrU+qNVBl | ||
1979 | 48 | SSnz69aLEjCRXqBOnQEr0irs/e/35+yLJdEuw89vSwWwrzbV5r1Y7uxinEGWSydT | ||
1980 | 49 | qddj97uKOWeMmnp20Be4+nhDDW/BMiTFI4Y3bYeDTrftbWMaSEmtSTw5HHxtAFtg | ||
1981 | 50 | X9Hyx0Q3eN1w3gRZgIdm0xYTe7bNTofFRdfXzB/9wtNIcaW10+IlODShFHPCnh+d | ||
1982 | 51 | i56a8LCdZcXiiLfCIhEcnqmM37BVvhjIQKSyOU1eMEgX148aVEz36OVuMwARAQAB | ||
1983 | 52 | tCdDaHJpc3RpYW4gRWhyaGFyZHQgPGNwYWVsemVyQGdtYWlsLmNvbT6JAjgEEwEC | ||
1984 | 53 | ACIFAlXJ3NcCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJELo+KTOCgLJC | ||
1985 | 54 | BugP/ir0ES3wCzvHMnkz2UlXt9FR4KqY0L9uFmwu9VYpmfAploEVIOi2HcuxpcRp | ||
1986 | 55 | hgoQlUtkz3lRhUeZzCxuB1ljM2JKTJiezP1tFTTGCbVYhPyA0LmUiHDWylG7FzPb | ||
1987 | 56 | TX96HY/G0jf+m4CfR8q3HNHjeDi4VeA2ppBxdHcVE5I7HihDgRPJd+CvCa3nYdAb | ||
1988 | 57 | nXDKlQZz5aZc7AgrRVamr4mshkzWuwNNCwOt3AIgHDkU/HzA5xlXfwHxOoP6scWH | ||
1989 | 58 | /T7vFsd/vOikBphGseWPgKm6w1zyQ5Dk/wjRL8UeSJZW+Rh4PuBMbxg01lAZpPTq | ||
1990 | 59 | tu/bePeNty3g5bhwO6oHMpWhprn3dO37R680qo6UnBPzICeuBUnSYgpPnsQC9maz | ||
1991 | 60 | FEjiBtMsXSanU5vww7TpxY1JHjk5KFcmKx4sBeablznsm+GuVaDFN8R4eDjrM14r | ||
1992 | 61 | SOzA9cV0bSQr4dMqA9fZFSx6qLTacIeMfptybW3zaDX/pJOeBBWRAtoAfZIFbBnu | ||
1993 | 62 | /ZxDDgiQtZzpVK4UkYk5rjjtV/CPVXx64AnTHi35YfUn14KkE+k3odHdvPfBiv9+ | ||
1994 | 63 | NxfkTuV/koOgpD3+lTIYXyVHS9gwvhfRD/YfdrnVGl7bRZe68j7bfWDuQuSqIhSA | ||
1995 | 64 | jpeJslJCawnqv6fVB6buj6jjcgHIxqCVn99chaPFSblEIPfXtDVDaHJpc3RpYW4g | ||
1996 | 65 | RWhyaGFyZHQgPGNocmlzdGlhbi5laHJoYXJkdEBjYW5vbmljYWwuY29tPokCOAQT | ||
1997 | 66 | AQIAIgUCVsbUOgIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQuj4pM4KA | ||
1998 | 67 | skJNPg/7BF/iXHHdSBigWKXCCvQz58uInoc/R4beIegxRCMq7wkYEey4B7Fd35zY | ||
1999 | 68 | zv9CBOTV3hZePMCg9jxl4ki2kSsrZSCIEJw4L/aXDtJtx3HT18uTW0QKoU3nK/ro | ||
2000 | 69 | OtthVqBqmiSEi40UUU+5MGrUjwLSm+PjaaSapjK/lddf0KbXBB78/BtR/XT0gxWM | ||
2001 | 70 | +o68Oei9Nj1S3h6UndJwNAQ1xaDWmU2T7CRJet3F+cXZd3aDuS2axOTSTZbraSq7 | ||
2002 | 71 | zdl1xUiKtzXZIp8X1ewne+dzkewZuWj7DOwOBEFK26UhxCjKd5mUr7jpWQ4ampFX | ||
2003 | 72 | 6xfd/MK8SJFY+iHOBKyzq9po40tE23dqWuaHB+T3MxOgQ9JHCo9x22XNvEuKZW/V | ||
2004 | 73 | 4WaoGHVkR+jtWNC8Qv/xCMHL3CEvAklKJR68WDhozwUYTgNt5vCoJOviMlbhDSwf | ||
2005 | 74 | 0zVXpQwMR//4c0QSA0+BPpIEPDnx5vTIHBVXHy4bBBHU2Vi87QIDS0AtiBpNcspN | ||
2006 | 75 | 6AG0ktuldkE/pqfSTJ2A9HpHZyU+8boagRS5/z102Pjtmf/mzUkcHmfRb9o0DE15 | ||
2007 | 76 | X5fqpA3lYyx9eHIAgH4eaB1+G20Ez/EY5hr8IMS2nNBSem491UW6DXDYRu6eBLrR | ||
2008 | 77 | sRmtrJ6DlTZFRFlqVZ47bce/SbeM/xljvRkBxWG6RtDRsTyNVI65Ag0EVcnc1wEQ | ||
2009 | 78 | ANzk9W058tSHqf05UEtJGrN0K8DLriCvPd7QdFA8yVIZM3WD+m0AMBGXjd8BT5c2 | ||
2010 | 79 | lt0GmhB8klonHZvPiVLTRTLcSsc3NBopr1HL1bWsgOczwWiXSrc62oGAHUOQT/bv | ||
2011 | 80 | vS6KIkZgez+qtCo/DCOGJrADaoJBiBCLSsZgowpzazZZDPUF7rAsfcryVCFvftK0 | ||
2012 | 81 | wAe1OdvUG77NHrMrE1oX3zh82hTqR5azBre6Y81lNwxxug/Xl/RHjNhEOYohcsLS | ||
2013 | 82 | /xl0m2X831fHzcGGpoISRgrfel+M4RoC7KsLrwVhrF8koCD/ZQlevfLpuRl5LNpO | ||
2014 | 83 | s1ZtEi8ZvLliih+H+BOlBD0zUc3zZrrks/NCpm1eZba0Z6L48r4TIHW08SGlHx7o | ||
2015 | 84 | SrXgkq3mtoM8C4uDiLwjav5KxiF7n68s/9LF82aAr7YjNXd+xYZNjsmmFlYj9CGI | ||
2016 | 85 | lL4jVt4v4EtTONa6pbtCNv5ezOLDZ6BBcQ36xdkrWzdpjQjL2mnh3sqIAGIPu7tH | ||
2017 | 86 | N8euQ5L1zIvIjVqYlR1eJssp96QYPWYxF7TosfML4BUhCP631IWfuD9X/K2LzDmv | ||
2018 | 87 | B2gVZo9fbhSC+P7GYVG+tV4VLAMbspAxRXXL69+j98aeV5g59f8OFQPbGpKE/SAY | ||
2019 | 88 | eIXtq8DD+PYUXXq3VUI2brVLv42LBVdSJpKNKG3decIBABEBAAGJAh8EGAECAAkF | ||
2020 | 89 | AlXJ3NcCGwwACgkQuj4pM4KAskKzeg/9FxXJLV3eWwY4nn2VhwYTHnHtSUpi8usk | ||
2021 | 90 | RzIa3Mcj6OEVjU2LZaT3UQF8h6dLM9y+CemcwyjMqm1RQ5+ogfrItby1AaBXwCvm | ||
2022 | 91 | XCUGw2zFOAnyzSHHoDFj27sllFxDmfSiBY5KP8M+/ywHKZDkRb6EjzMPx5oKFeGW | ||
2023 | 92 | Hmqaj5FDmTeWChSIHd1ZxobashFauOZDbS/ijRRMsVGFulU2Nb/4QJK73g3orfhY | ||
2024 | 93 | 5mq1TMkQ5Kcbqh4OmYYYayLtJQcpa6ZVopaRhAJFe30P83zW9pM5LQDpP9JIyY+S | ||
2025 | 94 | DjasEY4ekYtw6oCKAjpqlwaaNDjl27OkJ7R7laFKy4grZ2TSB/2KTjn/Ea3CH/pA | ||
2026 | 95 | SrpVis1LvC90XytbBnsEKYXU55H943wmBc6oj+itQhx4WyIiv+UgtHI/DbnYbUru | ||
2027 | 96 | 71wpfapqGBXYfu/zAra8PITngOFuizeYu+idemu55ANO3keJPKr3ZBUSBBpNFauT | ||
2028 | 97 | VUUCSnrLt+kpSLopYESiNdsPW/aQTFgFvA4BkBJTIMQsQZXicuXUePYlg5xFzXOv | ||
2029 | 98 | XgiqkjRA9xBI5JAIUgLRk3ulVFt2bIsTG9XgtGyphEs86Q0MOIMo0WbZGtAYDrZO | ||
2030 | 99 | DITbm2KzVLGVLn/ZJiW11RSHPNiwgg66/puKdFWrSogYYDJdDEUJtLIhypZ+ORxe | ||
2031 | 100 | 7oh88hTkC1w= | ||
2032 | 101 | =UNSw | ||
2033 | 102 | -----END PGP PUBLIC KEY BLOCK----- | ||
2034 | 0 | 103 | ||
2035 | === added file 'examples/tests/apt_source_modify_disable_suite.yaml' | |||
2036 | --- examples/tests/apt_source_modify_disable_suite.yaml 1970-01-01 00:00:00 +0000 | |||
2037 | +++ examples/tests/apt_source_modify_disable_suite.yaml 2016-07-26 19:53:43 +0000 | |||
2038 | @@ -0,0 +1,92 @@ | |||
2039 | 1 | showtrace: true | ||
2040 | 2 | apt: | ||
2041 | 3 | preserve_sources_list: false | ||
2042 | 4 | primary: | ||
2043 | 5 | - arches: [default] | ||
2044 | 6 | uri: http://us.archive.ubuntu.com/ubuntu | ||
2045 | 7 | security: | ||
2046 | 8 | - arches: [default] | ||
2047 | 9 | uri: http://security.ubuntu.com/ubuntu | ||
2048 | 10 | disable_suites: [$RELEASE-updates] | ||
2049 | 11 | conf: | # APT config | ||
2050 | 12 | ACQUIRE { | ||
2051 | 13 | Retries "3"; | ||
2052 | 14 | }; | ||
2053 | 15 | sources: | ||
2054 | 16 | curtin-dev-ppa.list: | ||
2055 | 17 | source: "deb http://ppa.launchpad.net/curtin-dev/test-archive/ubuntu xenial main" | ||
2056 | 18 | keyid: F430BBA5 | ||
2057 | 19 | ignored1: | ||
2058 | 20 | source: "ppa:curtin-dev/test-archive" | ||
2059 | 21 | my-repo2.list: | ||
2060 | 22 | source: deb $MIRROR $RELEASE multiverse | ||
2061 | 23 | ignored3: | ||
2062 | 24 | keyid: 0E72 9061 0D2F 6DC4 D65E A921 9A31 4EC5 F470 A0AC | ||
2063 | 25 | my-repo4.list: | ||
2064 | 26 | source: deb http://ppa.launchpad.net/curtin-dev/test-archive/ubuntu xenial main | ||
2065 | 27 | key: | | ||
2066 | 28 | -----BEGIN PGP PUBLIC KEY BLOCK----- | ||
2067 | 29 | Version: GnuPG v1 | ||
2068 | 30 | |||
2069 | 31 | mQINBFXJ3NcBEAC85PMdaKdItkdjCT1vRJrdwNqj4lN5mu6z4dDVfeZlmozRDBGb | ||
2070 | 32 | ENSOWCiYz3meANO7bKthQQCqAETSBV72rrDCqFZUpXeyG3zCN98Z/UdJ8zpQD9uw | ||
2071 | 33 | mq2CaAqWMk6ty+PkHQ4gtIc390lGfRbHNoZ5HaWJNVOK7FCB2hBmnTZW7AViYiYa | ||
2072 | 34 | YswOjYxaCkwQ/DsMOPD7S5OjwbLucs2YGjkBm7YF1nnXNzyt+BwieKQW/sQ2+ga1 | ||
2073 | 35 | mkgLW1BTQN3+JreBpeHy/yrRdK4dOZZUar4WPZitZzOW2eNpaaf6hKNA14LB/96a | ||
2074 | 36 | tEguK8VazoqSQGvNV/R3PjIYmurVP3/Z9bEVgOKhMCflgwKCYgx+tBUypN3zFWv9 | ||
2075 | 37 | pgVq3iHx1MFCvoP9FsNB7I6jzOxlQP4z25BzR3ympx/QexkFw5CBFXhdrU+qNVBl | ||
2076 | 38 | SSnz69aLEjCRXqBOnQEr0irs/e/35+yLJdEuw89vSwWwrzbV5r1Y7uxinEGWSydT | ||
2077 | 39 | qddj97uKOWeMmnp20Be4+nhDDW/BMiTFI4Y3bYeDTrftbWMaSEmtSTw5HHxtAFtg | ||
2078 | 40 | X9Hyx0Q3eN1w3gRZgIdm0xYTe7bNTofFRdfXzB/9wtNIcaW10+IlODShFHPCnh+d | ||
2079 | 41 | i56a8LCdZcXiiLfCIhEcnqmM37BVvhjIQKSyOU1eMEgX148aVEz36OVuMwARAQAB | ||
2080 | 42 | tCdDaHJpc3RpYW4gRWhyaGFyZHQgPGNwYWVsemVyQGdtYWlsLmNvbT6JAjgEEwEC | ||
2081 | 43 | ACIFAlXJ3NcCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJELo+KTOCgLJC | ||
2082 | 44 | BugP/ir0ES3wCzvHMnkz2UlXt9FR4KqY0L9uFmwu9VYpmfAploEVIOi2HcuxpcRp | ||
2083 | 45 | hgoQlUtkz3lRhUeZzCxuB1ljM2JKTJiezP1tFTTGCbVYhPyA0LmUiHDWylG7FzPb | ||
2084 | 46 | TX96HY/G0jf+m4CfR8q3HNHjeDi4VeA2ppBxdHcVE5I7HihDgRPJd+CvCa3nYdAb | ||
2085 | 47 | nXDKlQZz5aZc7AgrRVamr4mshkzWuwNNCwOt3AIgHDkU/HzA5xlXfwHxOoP6scWH | ||
2086 | 48 | /T7vFsd/vOikBphGseWPgKm6w1zyQ5Dk/wjRL8UeSJZW+Rh4PuBMbxg01lAZpPTq | ||
2087 | 49 | tu/bePeNty3g5bhwO6oHMpWhprn3dO37R680qo6UnBPzICeuBUnSYgpPnsQC9maz | ||
2088 | 50 | FEjiBtMsXSanU5vww7TpxY1JHjk5KFcmKx4sBeablznsm+GuVaDFN8R4eDjrM14r | ||
2089 | 51 | SOzA9cV0bSQr4dMqA9fZFSx6qLTacIeMfptybW3zaDX/pJOeBBWRAtoAfZIFbBnu | ||
2090 | 52 | /ZxDDgiQtZzpVK4UkYk5rjjtV/CPVXx64AnTHi35YfUn14KkE+k3odHdvPfBiv9+ | ||
2091 | 53 | NxfkTuV/koOgpD3+lTIYXyVHS9gwvhfRD/YfdrnVGl7bRZe68j7bfWDuQuSqIhSA | ||
2092 | 54 | jpeJslJCawnqv6fVB6buj6jjcgHIxqCVn99chaPFSblEIPfXtDVDaHJpc3RpYW4g | ||
2093 | 55 | RWhyaGFyZHQgPGNocmlzdGlhbi5laHJoYXJkdEBjYW5vbmljYWwuY29tPokCOAQT | ||
2094 | 56 | AQIAIgUCVsbUOgIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQuj4pM4KA | ||
2095 | 57 | skJNPg/7BF/iXHHdSBigWKXCCvQz58uInoc/R4beIegxRCMq7wkYEey4B7Fd35zY | ||
2096 | 58 | zv9CBOTV3hZePMCg9jxl4ki2kSsrZSCIEJw4L/aXDtJtx3HT18uTW0QKoU3nK/ro | ||
2097 | 59 | OtthVqBqmiSEi40UUU+5MGrUjwLSm+PjaaSapjK/lddf0KbXBB78/BtR/XT0gxWM | ||
2098 | 60 | +o68Oei9Nj1S3h6UndJwNAQ1xaDWmU2T7CRJet3F+cXZd3aDuS2axOTSTZbraSq7 | ||
2099 | 61 | zdl1xUiKtzXZIp8X1ewne+dzkewZuWj7DOwOBEFK26UhxCjKd5mUr7jpWQ4ampFX | ||
2100 | 62 | 6xfd/MK8SJFY+iHOBKyzq9po40tE23dqWuaHB+T3MxOgQ9JHCo9x22XNvEuKZW/V | ||
2101 | 63 | 4WaoGHVkR+jtWNC8Qv/xCMHL3CEvAklKJR68WDhozwUYTgNt5vCoJOviMlbhDSwf | ||
2102 | 64 | 0zVXpQwMR//4c0QSA0+BPpIEPDnx5vTIHBVXHy4bBBHU2Vi87QIDS0AtiBpNcspN | ||
2103 | 65 | 6AG0ktuldkE/pqfSTJ2A9HpHZyU+8boagRS5/z102Pjtmf/mzUkcHmfRb9o0DE15 | ||
2104 | 66 | X5fqpA3lYyx9eHIAgH4eaB1+G20Ez/EY5hr8IMS2nNBSem491UW6DXDYRu6eBLrR | ||
2105 | 67 | sRmtrJ6DlTZFRFlqVZ47bce/SbeM/xljvRkBxWG6RtDRsTyNVI65Ag0EVcnc1wEQ | ||
2106 | 68 | ANzk9W058tSHqf05UEtJGrN0K8DLriCvPd7QdFA8yVIZM3WD+m0AMBGXjd8BT5c2 | ||
2107 | 69 | lt0GmhB8klonHZvPiVLTRTLcSsc3NBopr1HL1bWsgOczwWiXSrc62oGAHUOQT/bv | ||
2108 | 70 | vS6KIkZgez+qtCo/DCOGJrADaoJBiBCLSsZgowpzazZZDPUF7rAsfcryVCFvftK0 | ||
2109 | 71 | wAe1OdvUG77NHrMrE1oX3zh82hTqR5azBre6Y81lNwxxug/Xl/RHjNhEOYohcsLS | ||
2110 | 72 | /xl0m2X831fHzcGGpoISRgrfel+M4RoC7KsLrwVhrF8koCD/ZQlevfLpuRl5LNpO | ||
2111 | 73 | s1ZtEi8ZvLliih+H+BOlBD0zUc3zZrrks/NCpm1eZba0Z6L48r4TIHW08SGlHx7o | ||
2112 | 74 | SrXgkq3mtoM8C4uDiLwjav5KxiF7n68s/9LF82aAr7YjNXd+xYZNjsmmFlYj9CGI | ||
2113 | 75 | lL4jVt4v4EtTONa6pbtCNv5ezOLDZ6BBcQ36xdkrWzdpjQjL2mnh3sqIAGIPu7tH | ||
2114 | 76 | N8euQ5L1zIvIjVqYlR1eJssp96QYPWYxF7TosfML4BUhCP631IWfuD9X/K2LzDmv | ||
2115 | 77 | B2gVZo9fbhSC+P7GYVG+tV4VLAMbspAxRXXL69+j98aeV5g59f8OFQPbGpKE/SAY | ||
2116 | 78 | eIXtq8DD+PYUXXq3VUI2brVLv42LBVdSJpKNKG3decIBABEBAAGJAh8EGAECAAkF | ||
2117 | 79 | AlXJ3NcCGwwACgkQuj4pM4KAskKzeg/9FxXJLV3eWwY4nn2VhwYTHnHtSUpi8usk | ||
2118 | 80 | RzIa3Mcj6OEVjU2LZaT3UQF8h6dLM9y+CemcwyjMqm1RQ5+ogfrItby1AaBXwCvm | ||
2119 | 81 | XCUGw2zFOAnyzSHHoDFj27sllFxDmfSiBY5KP8M+/ywHKZDkRb6EjzMPx5oKFeGW | ||
2120 | 82 | Hmqaj5FDmTeWChSIHd1ZxobashFauOZDbS/ijRRMsVGFulU2Nb/4QJK73g3orfhY | ||
2121 | 83 | 5mq1TMkQ5Kcbqh4OmYYYayLtJQcpa6ZVopaRhAJFe30P83zW9pM5LQDpP9JIyY+S | ||
2122 | 84 | DjasEY4ekYtw6oCKAjpqlwaaNDjl27OkJ7R7laFKy4grZ2TSB/2KTjn/Ea3CH/pA | ||
2123 | 85 | SrpVis1LvC90XytbBnsEKYXU55H943wmBc6oj+itQhx4WyIiv+UgtHI/DbnYbUru | ||
2124 | 86 | 71wpfapqGBXYfu/zAra8PITngOFuizeYu+idemu55ANO3keJPKr3ZBUSBBpNFauT | ||
2125 | 87 | VUUCSnrLt+kpSLopYESiNdsPW/aQTFgFvA4BkBJTIMQsQZXicuXUePYlg5xFzXOv | ||
2126 | 88 | XgiqkjRA9xBI5JAIUgLRk3ulVFt2bIsTG9XgtGyphEs86Q0MOIMo0WbZGtAYDrZO | ||
2127 | 89 | DITbm2KzVLGVLn/ZJiW11RSHPNiwgg66/puKdFWrSogYYDJdDEUJtLIhypZ+ORxe | ||
2128 | 90 | 7oh88hTkC1w= | ||
2129 | 91 | =UNSw | ||
2130 | 92 | -----END PGP PUBLIC KEY BLOCK----- | ||
2131 | 0 | 93 | ||
2132 | === added file 'examples/tests/apt_source_preserve.yaml' | |||
2133 | --- examples/tests/apt_source_preserve.yaml 1970-01-01 00:00:00 +0000 | |||
2134 | +++ examples/tests/apt_source_preserve.yaml 2016-07-26 19:53:43 +0000 | |||
2135 | @@ -0,0 +1,98 @@ | |||
2136 | 1 | showtrace: true | ||
2137 | 2 | apt: | ||
2138 | 3 | # this is like the other apt_source test but with preserve true | ||
2139 | 4 | # this is the default now preserve_sources_list: true | ||
2140 | 5 | primary: | ||
2141 | 6 | - arches: [default] | ||
2142 | 7 | uri: http://us.archive.ubuntu.com/ubuntu | ||
2143 | 8 | security: | ||
2144 | 9 | - arches: [default] | ||
2145 | 10 | uri: http://security.ubuntu.com/ubuntu | ||
2146 | 11 | sources_list: | # written by curtin custom template | ||
2147 | 12 | deb $MIRROR $RELEASE main restricted | ||
2148 | 13 | deb-src $MIRROR $RELEASE main restricted | ||
2149 | 14 | deb $PRIMARY $RELEASE universe restricted | ||
2150 | 15 | deb $SECURITY $RELEASE-security multiverse | ||
2151 | 16 | # nice line to check in test | ||
2152 | 17 | conf: | # APT config | ||
2153 | 18 | ACQUIRE { | ||
2154 | 19 | Retries "3"; | ||
2155 | 20 | }; | ||
2156 | 21 | sources: | ||
2157 | 22 | curtin-dev-ppa.list: | ||
2158 | 23 | source: "deb http://ppa.launchpad.net/curtin-dev/test-archive/ubuntu xenial main" | ||
2159 | 24 | keyid: F430BBA5 | ||
2160 | 25 | ignored1: | ||
2161 | 26 | source: "ppa:curtin-dev/test-archive" | ||
2162 | 27 | my-repo2.list: | ||
2163 | 28 | source: deb $MIRROR $RELEASE multiverse | ||
2164 | 29 | ignored3: | ||
2165 | 30 | keyid: 0E72 9061 0D2F 6DC4 D65E A921 9A31 4EC5 F470 A0AC | ||
2166 | 31 | my-repo4.list: | ||
2167 | 32 | source: deb http://ppa.launchpad.net/curtin-dev/test-archive/ubuntu xenial main | ||
2168 | 33 | key: | | ||
2169 | 34 | -----BEGIN PGP PUBLIC KEY BLOCK----- | ||
2170 | 35 | Version: GnuPG v1 | ||
2171 | 36 | |||
2172 | 37 | mQINBFXJ3NcBEAC85PMdaKdItkdjCT1vRJrdwNqj4lN5mu6z4dDVfeZlmozRDBGb | ||
2173 | 38 | ENSOWCiYz3meANO7bKthQQCqAETSBV72rrDCqFZUpXeyG3zCN98Z/UdJ8zpQD9uw | ||
2174 | 39 | mq2CaAqWMk6ty+PkHQ4gtIc390lGfRbHNoZ5HaWJNVOK7FCB2hBmnTZW7AViYiYa | ||
2175 | 40 | YswOjYxaCkwQ/DsMOPD7S5OjwbLucs2YGjkBm7YF1nnXNzyt+BwieKQW/sQ2+ga1 | ||
2176 | 41 | mkgLW1BTQN3+JreBpeHy/yrRdK4dOZZUar4WPZitZzOW2eNpaaf6hKNA14LB/96a | ||
2177 | 42 | tEguK8VazoqSQGvNV/R3PjIYmurVP3/Z9bEVgOKhMCflgwKCYgx+tBUypN3zFWv9 | ||
2178 | 43 | pgVq3iHx1MFCvoP9FsNB7I6jzOxlQP4z25BzR3ympx/QexkFw5CBFXhdrU+qNVBl | ||
2179 | 44 | SSnz69aLEjCRXqBOnQEr0irs/e/35+yLJdEuw89vSwWwrzbV5r1Y7uxinEGWSydT | ||
2180 | 45 | qddj97uKOWeMmnp20Be4+nhDDW/BMiTFI4Y3bYeDTrftbWMaSEmtSTw5HHxtAFtg | ||
2181 | 46 | X9Hyx0Q3eN1w3gRZgIdm0xYTe7bNTofFRdfXzB/9wtNIcaW10+IlODShFHPCnh+d | ||
2182 | 47 | i56a8LCdZcXiiLfCIhEcnqmM37BVvhjIQKSyOU1eMEgX148aVEz36OVuMwARAQAB | ||
2183 | 48 | tCdDaHJpc3RpYW4gRWhyaGFyZHQgPGNwYWVsemVyQGdtYWlsLmNvbT6JAjgEEwEC | ||
2184 | 49 | ACIFAlXJ3NcCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJELo+KTOCgLJC | ||
2185 | 50 | BugP/ir0ES3wCzvHMnkz2UlXt9FR4KqY0L9uFmwu9VYpmfAploEVIOi2HcuxpcRp | ||
2186 | 51 | hgoQlUtkz3lRhUeZzCxuB1ljM2JKTJiezP1tFTTGCbVYhPyA0LmUiHDWylG7FzPb | ||
2187 | 52 | TX96HY/G0jf+m4CfR8q3HNHjeDi4VeA2ppBxdHcVE5I7HihDgRPJd+CvCa3nYdAb | ||
2188 | 53 | nXDKlQZz5aZc7AgrRVamr4mshkzWuwNNCwOt3AIgHDkU/HzA5xlXfwHxOoP6scWH | ||
2189 | 54 | /T7vFsd/vOikBphGseWPgKm6w1zyQ5Dk/wjRL8UeSJZW+Rh4PuBMbxg01lAZpPTq | ||
2190 | 55 | tu/bePeNty3g5bhwO6oHMpWhprn3dO37R680qo6UnBPzICeuBUnSYgpPnsQC9maz | ||
2191 | 56 | FEjiBtMsXSanU5vww7TpxY1JHjk5KFcmKx4sBeablznsm+GuVaDFN8R4eDjrM14r | ||
2192 | 57 | SOzA9cV0bSQr4dMqA9fZFSx6qLTacIeMfptybW3zaDX/pJOeBBWRAtoAfZIFbBnu | ||
2193 | 58 | /ZxDDgiQtZzpVK4UkYk5rjjtV/CPVXx64AnTHi35YfUn14KkE+k3odHdvPfBiv9+ | ||
2194 | 59 | NxfkTuV/koOgpD3+lTIYXyVHS9gwvhfRD/YfdrnVGl7bRZe68j7bfWDuQuSqIhSA | ||
2195 | 60 | jpeJslJCawnqv6fVB6buj6jjcgHIxqCVn99chaPFSblEIPfXtDVDaHJpc3RpYW4g | ||
2196 | 61 | RWhyaGFyZHQgPGNocmlzdGlhbi5laHJoYXJkdEBjYW5vbmljYWwuY29tPokCOAQT | ||
2197 | 62 | AQIAIgUCVsbUOgIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQuj4pM4KA | ||
2198 | 63 | skJNPg/7BF/iXHHdSBigWKXCCvQz58uInoc/R4beIegxRCMq7wkYEey4B7Fd35zY | ||
2199 | 64 | zv9CBOTV3hZePMCg9jxl4ki2kSsrZSCIEJw4L/aXDtJtx3HT18uTW0QKoU3nK/ro | ||
2200 | 65 | OtthVqBqmiSEi40UUU+5MGrUjwLSm+PjaaSapjK/lddf0KbXBB78/BtR/XT0gxWM | ||
2201 | 66 | +o68Oei9Nj1S3h6UndJwNAQ1xaDWmU2T7CRJet3F+cXZd3aDuS2axOTSTZbraSq7 | ||
2202 | 67 | zdl1xUiKtzXZIp8X1ewne+dzkewZuWj7DOwOBEFK26UhxCjKd5mUr7jpWQ4ampFX | ||
2203 | 68 | 6xfd/MK8SJFY+iHOBKyzq9po40tE23dqWuaHB+T3MxOgQ9JHCo9x22XNvEuKZW/V | ||
2204 | 69 | 4WaoGHVkR+jtWNC8Qv/xCMHL3CEvAklKJR68WDhozwUYTgNt5vCoJOviMlbhDSwf | ||
2205 | 70 | 0zVXpQwMR//4c0QSA0+BPpIEPDnx5vTIHBVXHy4bBBHU2Vi87QIDS0AtiBpNcspN | ||
2206 | 71 | 6AG0ktuldkE/pqfSTJ2A9HpHZyU+8boagRS5/z102Pjtmf/mzUkcHmfRb9o0DE15 | ||
2207 | 72 | X5fqpA3lYyx9eHIAgH4eaB1+G20Ez/EY5hr8IMS2nNBSem491UW6DXDYRu6eBLrR | ||
2208 | 73 | sRmtrJ6DlTZFRFlqVZ47bce/SbeM/xljvRkBxWG6RtDRsTyNVI65Ag0EVcnc1wEQ | ||
2209 | 74 | ANzk9W058tSHqf05UEtJGrN0K8DLriCvPd7QdFA8yVIZM3WD+m0AMBGXjd8BT5c2 | ||
2210 | 75 | lt0GmhB8klonHZvPiVLTRTLcSsc3NBopr1HL1bWsgOczwWiXSrc62oGAHUOQT/bv | ||
2211 | 76 | vS6KIkZgez+qtCo/DCOGJrADaoJBiBCLSsZgowpzazZZDPUF7rAsfcryVCFvftK0 | ||
2212 | 77 | wAe1OdvUG77NHrMrE1oX3zh82hTqR5azBre6Y81lNwxxug/Xl/RHjNhEOYohcsLS | ||
2213 | 78 | /xl0m2X831fHzcGGpoISRgrfel+M4RoC7KsLrwVhrF8koCD/ZQlevfLpuRl5LNpO | ||
2214 | 79 | s1ZtEi8ZvLliih+H+BOlBD0zUc3zZrrks/NCpm1eZba0Z6L48r4TIHW08SGlHx7o | ||
2215 | 80 | SrXgkq3mtoM8C4uDiLwjav5KxiF7n68s/9LF82aAr7YjNXd+xYZNjsmmFlYj9CGI | ||
2216 | 81 | lL4jVt4v4EtTONa6pbtCNv5ezOLDZ6BBcQ36xdkrWzdpjQjL2mnh3sqIAGIPu7tH | ||
2217 | 82 | N8euQ5L1zIvIjVqYlR1eJssp96QYPWYxF7TosfML4BUhCP631IWfuD9X/K2LzDmv | ||
2218 | 83 | B2gVZo9fbhSC+P7GYVG+tV4VLAMbspAxRXXL69+j98aeV5g59f8OFQPbGpKE/SAY | ||
2219 | 84 | eIXtq8DD+PYUXXq3VUI2brVLv42LBVdSJpKNKG3decIBABEBAAGJAh8EGAECAAkF | ||
2220 | 85 | AlXJ3NcCGwwACgkQuj4pM4KAskKzeg/9FxXJLV3eWwY4nn2VhwYTHnHtSUpi8usk | ||
2221 | 86 | RzIa3Mcj6OEVjU2LZaT3UQF8h6dLM9y+CemcwyjMqm1RQ5+ogfrItby1AaBXwCvm | ||
2222 | 87 | XCUGw2zFOAnyzSHHoDFj27sllFxDmfSiBY5KP8M+/ywHKZDkRb6EjzMPx5oKFeGW | ||
2223 | 88 | Hmqaj5FDmTeWChSIHd1ZxobashFauOZDbS/ijRRMsVGFulU2Nb/4QJK73g3orfhY | ||
2224 | 89 | 5mq1TMkQ5Kcbqh4OmYYYayLtJQcpa6ZVopaRhAJFe30P83zW9pM5LQDpP9JIyY+S | ||
2225 | 90 | DjasEY4ekYtw6oCKAjpqlwaaNDjl27OkJ7R7laFKy4grZ2TSB/2KTjn/Ea3CH/pA | ||
2226 | 91 | SrpVis1LvC90XytbBnsEKYXU55H943wmBc6oj+itQhx4WyIiv+UgtHI/DbnYbUru | ||
2227 | 92 | 71wpfapqGBXYfu/zAra8PITngOFuizeYu+idemu55ANO3keJPKr3ZBUSBBpNFauT | ||
2228 | 93 | VUUCSnrLt+kpSLopYESiNdsPW/aQTFgFvA4BkBJTIMQsQZXicuXUePYlg5xFzXOv | ||
2229 | 94 | XgiqkjRA9xBI5JAIUgLRk3ulVFt2bIsTG9XgtGyphEs86Q0MOIMo0WbZGtAYDrZO | ||
2230 | 95 | DITbm2KzVLGVLn/ZJiW11RSHPNiwgg66/puKdFWrSogYYDJdDEUJtLIhypZ+ORxe | ||
2231 | 96 | 7oh88hTkC1w= | ||
2232 | 97 | =UNSw | ||
2233 | 98 | -----END PGP PUBLIC KEY BLOCK----- | ||
2234 | 0 | 99 | ||
2235 | === added file 'examples/tests/apt_source_search.yaml' | |||
2236 | --- examples/tests/apt_source_search.yaml 1970-01-01 00:00:00 +0000 | |||
2237 | +++ examples/tests/apt_source_search.yaml 2016-07-26 19:53:43 +0000 | |||
2238 | @@ -0,0 +1,97 @@ | |||
2239 | 1 | showtrace: true | ||
2240 | 2 | apt: | ||
2241 | 3 | preserve_sources_list: false | ||
2242 | 4 | primary: | ||
2243 | 5 | - arches: [default] | ||
2244 | 6 | search: | ||
2245 | 7 | - http://does.not.exist/ubuntu | ||
2246 | 8 | - http://does.also.not.exist/ubuntu | ||
2247 | 9 | - http://us.archive.ubuntu.com/ubuntu | ||
2248 | 10 | security: | ||
2249 | 11 | - arches: [default] | ||
2250 | 12 | search: | ||
2251 | 13 | - http://does.not.exist/ubuntu | ||
2252 | 14 | - http://does.also.not.exist/ubuntu | ||
2253 | 15 | - http://security.ubuntu.com/ubuntu | ||
2254 | 16 | conf: | # APT config | ||
2255 | 17 | ACQUIRE { | ||
2256 | 18 | Retries "3"; | ||
2257 | 19 | }; | ||
2258 | 20 | sources: | ||
2259 | 21 | curtin-dev-ppa.list: | ||
2260 | 22 | source: "deb http://ppa.launchpad.net/curtin-dev/test-archive/ubuntu xenial main" | ||
2261 | 23 | keyid: F430BBA5 | ||
2262 | 24 | ignored1: | ||
2263 | 25 | source: "ppa:curtin-dev/test-archive" | ||
2264 | 26 | my-repo2.list: | ||
2265 | 27 | source: deb $MIRROR $RELEASE multiverse | ||
2266 | 28 | ignored3: | ||
2267 | 29 | keyid: 0E72 9061 0D2F 6DC4 D65E A921 9A31 4EC5 F470 A0AC | ||
2268 | 30 | my-repo4.list: | ||
2269 | 31 | source: deb http://ppa.launchpad.net/curtin-dev/test-archive/ubuntu xenial main | ||
2270 | 32 | key: | | ||
2271 | 33 | -----BEGIN PGP PUBLIC KEY BLOCK----- | ||
2272 | 34 | Version: GnuPG v1 | ||
2273 | 35 | |||
2274 | 36 | mQINBFXJ3NcBEAC85PMdaKdItkdjCT1vRJrdwNqj4lN5mu6z4dDVfeZlmozRDBGb | ||
2275 | 37 | ENSOWCiYz3meANO7bKthQQCqAETSBV72rrDCqFZUpXeyG3zCN98Z/UdJ8zpQD9uw | ||
2276 | 38 | mq2CaAqWMk6ty+PkHQ4gtIc390lGfRbHNoZ5HaWJNVOK7FCB2hBmnTZW7AViYiYa | ||
2277 | 39 | YswOjYxaCkwQ/DsMOPD7S5OjwbLucs2YGjkBm7YF1nnXNzyt+BwieKQW/sQ2+ga1 | ||
2278 | 40 | mkgLW1BTQN3+JreBpeHy/yrRdK4dOZZUar4WPZitZzOW2eNpaaf6hKNA14LB/96a | ||
2279 | 41 | tEguK8VazoqSQGvNV/R3PjIYmurVP3/Z9bEVgOKhMCflgwKCYgx+tBUypN3zFWv9 | ||
2280 | 42 | pgVq3iHx1MFCvoP9FsNB7I6jzOxlQP4z25BzR3ympx/QexkFw5CBFXhdrU+qNVBl | ||
2281 | 43 | SSnz69aLEjCRXqBOnQEr0irs/e/35+yLJdEuw89vSwWwrzbV5r1Y7uxinEGWSydT | ||
2282 | 44 | qddj97uKOWeMmnp20Be4+nhDDW/BMiTFI4Y3bYeDTrftbWMaSEmtSTw5HHxtAFtg | ||
2283 | 45 | X9Hyx0Q3eN1w3gRZgIdm0xYTe7bNTofFRdfXzB/9wtNIcaW10+IlODShFHPCnh+d | ||
2284 | 46 | i56a8LCdZcXiiLfCIhEcnqmM37BVvhjIQKSyOU1eMEgX148aVEz36OVuMwARAQAB | ||
2285 | 47 | tCdDaHJpc3RpYW4gRWhyaGFyZHQgPGNwYWVsemVyQGdtYWlsLmNvbT6JAjgEEwEC | ||
2286 | 48 | ACIFAlXJ3NcCGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4BAheAAAoJELo+KTOCgLJC | ||
2287 | 49 | BugP/ir0ES3wCzvHMnkz2UlXt9FR4KqY0L9uFmwu9VYpmfAploEVIOi2HcuxpcRp | ||
2288 | 50 | hgoQlUtkz3lRhUeZzCxuB1ljM2JKTJiezP1tFTTGCbVYhPyA0LmUiHDWylG7FzPb | ||
2289 | 51 | TX96HY/G0jf+m4CfR8q3HNHjeDi4VeA2ppBxdHcVE5I7HihDgRPJd+CvCa3nYdAb | ||
2290 | 52 | nXDKlQZz5aZc7AgrRVamr4mshkzWuwNNCwOt3AIgHDkU/HzA5xlXfwHxOoP6scWH | ||
2291 | 53 | /T7vFsd/vOikBphGseWPgKm6w1zyQ5Dk/wjRL8UeSJZW+Rh4PuBMbxg01lAZpPTq | ||
2292 | 54 | tu/bePeNty3g5bhwO6oHMpWhprn3dO37R680qo6UnBPzICeuBUnSYgpPnsQC9maz | ||
2293 | 55 | FEjiBtMsXSanU5vww7TpxY1JHjk5KFcmKx4sBeablznsm+GuVaDFN8R4eDjrM14r | ||
2294 | 56 | SOzA9cV0bSQr4dMqA9fZFSx6qLTacIeMfptybW3zaDX/pJOeBBWRAtoAfZIFbBnu | ||
2295 | 57 | /ZxDDgiQtZzpVK4UkYk5rjjtV/CPVXx64AnTHi35YfUn14KkE+k3odHdvPfBiv9+ | ||
2296 | 58 | NxfkTuV/koOgpD3+lTIYXyVHS9gwvhfRD/YfdrnVGl7bRZe68j7bfWDuQuSqIhSA | ||
2297 | 59 | jpeJslJCawnqv6fVB6buj6jjcgHIxqCVn99chaPFSblEIPfXtDVDaHJpc3RpYW4g | ||
2298 | 60 | RWhyaGFyZHQgPGNocmlzdGlhbi5laHJoYXJkdEBjYW5vbmljYWwuY29tPokCOAQT | ||
2299 | 61 | AQIAIgUCVsbUOgIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQuj4pM4KA | ||
2300 | 62 | skJNPg/7BF/iXHHdSBigWKXCCvQz58uInoc/R4beIegxRCMq7wkYEey4B7Fd35zY | ||
2301 | 63 | zv9CBOTV3hZePMCg9jxl4ki2kSsrZSCIEJw4L/aXDtJtx3HT18uTW0QKoU3nK/ro | ||
2302 | 64 | OtthVqBqmiSEi40UUU+5MGrUjwLSm+PjaaSapjK/lddf0KbXBB78/BtR/XT0gxWM | ||
2303 | 65 | +o68Oei9Nj1S3h6UndJwNAQ1xaDWmU2T7CRJet3F+cXZd3aDuS2axOTSTZbraSq7 | ||
2304 | 66 | zdl1xUiKtzXZIp8X1ewne+dzkewZuWj7DOwOBEFK26UhxCjKd5mUr7jpWQ4ampFX | ||
2305 | 67 | 6xfd/MK8SJFY+iHOBKyzq9po40tE23dqWuaHB+T3MxOgQ9JHCo9x22XNvEuKZW/V | ||
2306 | 68 | 4WaoGHVkR+jtWNC8Qv/xCMHL3CEvAklKJR68WDhozwUYTgNt5vCoJOviMlbhDSwf | ||
2307 | 69 | 0zVXpQwMR//4c0QSA0+BPpIEPDnx5vTIHBVXHy4bBBHU2Vi87QIDS0AtiBpNcspN | ||
2308 | 70 | 6AG0ktuldkE/pqfSTJ2A9HpHZyU+8boagRS5/z102Pjtmf/mzUkcHmfRb9o0DE15 | ||
2309 | 71 | X5fqpA3lYyx9eHIAgH4eaB1+G20Ez/EY5hr8IMS2nNBSem491UW6DXDYRu6eBLrR | ||
2310 | 72 | sRmtrJ6DlTZFRFlqVZ47bce/SbeM/xljvRkBxWG6RtDRsTyNVI65Ag0EVcnc1wEQ | ||
2311 | 73 | ANzk9W058tSHqf05UEtJGrN0K8DLriCvPd7QdFA8yVIZM3WD+m0AMBGXjd8BT5c2 | ||
2312 | 74 | lt0GmhB8klonHZvPiVLTRTLcSsc3NBopr1HL1bWsgOczwWiXSrc62oGAHUOQT/bv | ||
2313 | 75 | vS6KIkZgez+qtCo/DCOGJrADaoJBiBCLSsZgowpzazZZDPUF7rAsfcryVCFvftK0 | ||
2314 | 76 | wAe1OdvUG77NHrMrE1oX3zh82hTqR5azBre6Y81lNwxxug/Xl/RHjNhEOYohcsLS | ||
2315 | 77 | /xl0m2X831fHzcGGpoISRgrfel+M4RoC7KsLrwVhrF8koCD/ZQlevfLpuRl5LNpO | ||
2316 | 78 | s1ZtEi8ZvLliih+H+BOlBD0zUc3zZrrks/NCpm1eZba0Z6L48r4TIHW08SGlHx7o | ||
2317 | 79 | SrXgkq3mtoM8C4uDiLwjav5KxiF7n68s/9LF82aAr7YjNXd+xYZNjsmmFlYj9CGI | ||
2318 | 80 | lL4jVt4v4EtTONa6pbtCNv5ezOLDZ6BBcQ36xdkrWzdpjQjL2mnh3sqIAGIPu7tH | ||
2319 | 81 | N8euQ5L1zIvIjVqYlR1eJssp96QYPWYxF7TosfML4BUhCP631IWfuD9X/K2LzDmv | ||
2320 | 82 | B2gVZo9fbhSC+P7GYVG+tV4VLAMbspAxRXXL69+j98aeV5g59f8OFQPbGpKE/SAY | ||
2321 | 83 | eIXtq8DD+PYUXXq3VUI2brVLv42LBVdSJpKNKG3decIBABEBAAGJAh8EGAECAAkF | ||
2322 | 84 | AlXJ3NcCGwwACgkQuj4pM4KAskKzeg/9FxXJLV3eWwY4nn2VhwYTHnHtSUpi8usk | ||
2323 | 85 | RzIa3Mcj6OEVjU2LZaT3UQF8h6dLM9y+CemcwyjMqm1RQ5+ogfrItby1AaBXwCvm | ||
2324 | 86 | XCUGw2zFOAnyzSHHoDFj27sllFxDmfSiBY5KP8M+/ywHKZDkRb6EjzMPx5oKFeGW | ||
2325 | 87 | Hmqaj5FDmTeWChSIHd1ZxobashFauOZDbS/ijRRMsVGFulU2Nb/4QJK73g3orfhY | ||
2326 | 88 | 5mq1TMkQ5Kcbqh4OmYYYayLtJQcpa6ZVopaRhAJFe30P83zW9pM5LQDpP9JIyY+S | ||
2327 | 89 | DjasEY4ekYtw6oCKAjpqlwaaNDjl27OkJ7R7laFKy4grZ2TSB/2KTjn/Ea3CH/pA | ||
2328 | 90 | SrpVis1LvC90XytbBnsEKYXU55H943wmBc6oj+itQhx4WyIiv+UgtHI/DbnYbUru | ||
2329 | 91 | 71wpfapqGBXYfu/zAra8PITngOFuizeYu+idemu55ANO3keJPKr3ZBUSBBpNFauT | ||
2330 | 92 | VUUCSnrLt+kpSLopYESiNdsPW/aQTFgFvA4BkBJTIMQsQZXicuXUePYlg5xFzXOv | ||
2331 | 93 | XgiqkjRA9xBI5JAIUgLRk3ulVFt2bIsTG9XgtGyphEs86Q0MOIMo0WbZGtAYDrZO | ||
2332 | 94 | DITbm2KzVLGVLn/ZJiW11RSHPNiwgg66/puKdFWrSogYYDJdDEUJtLIhypZ+ORxe | ||
2333 | 95 | 7oh88hTkC1w= | ||
2334 | 96 | =UNSw | ||
2335 | 97 | -----END PGP PUBLIC KEY BLOCK----- | ||
2336 | 0 | 98 | ||
2337 | === added file 'examples/tests/apt_source_search_dns.yaml' | |||
2338 | --- examples/tests/apt_source_search_dns.yaml 1970-01-01 00:00:00 +0000 | |||
2339 | +++ examples/tests/apt_source_search_dns.yaml 2016-07-26 19:53:43 +0000 | |||
2340 | @@ -0,0 +1,21 @@ | |||
2341 | 1 | showtrace: true | ||
2342 | 2 | # fake up something that works in vmtets environment without dependency to external dns setup | ||
2343 | 3 | early_commands: | ||
2344 | 4 | xx_prep_fake_dns_search0: 'echo foo.bar > /etc/hostname' | ||
2345 | 5 | xx_prep_fake_dns_search1: 'echo "$(getent ahosts us.archive.ubuntu.com | cut --fields=1 --delimiter " " | grep -v : | head -n 1) ubuntu-mirror" >> /etc/hosts' | ||
2346 | 6 | xx_prep_fake_dns_search2: 'echo "$(getent ahosts security.ubuntu.com | cut --fields=1 --delimiter " " | grep -v : | head -n 1) ubuntu-security-mirror" >> /etc/hosts' | ||
2347 | 7 | apt: | ||
2348 | 8 | primary: | ||
2349 | 9 | - arches: [default] | ||
2350 | 10 | search_dns: True | ||
2351 | 11 | security: | ||
2352 | 12 | - arches: [default] | ||
2353 | 13 | search_dns: True | ||
2354 | 14 | # avoiding issues with these fake mirrors we only set them in a disabled list | ||
2355 | 15 | # this is the default now preserve_sources_list: true | ||
2356 | 16 | sources: | ||
2357 | 17 | dnssearch.list.disabled: | ||
2358 | 18 | source: | | ||
2359 | 19 | deb $MIRROR $RELEASE multiverse | ||
2360 | 20 | deb $PRIMARY $RELEASE universe | ||
2361 | 21 | deb $SECURITY $RELEASE main | ||
2362 | 0 | 22 | ||
2363 | === added file 'examples/tests/test_old_apt_features.yaml' | |||
2364 | --- examples/tests/test_old_apt_features.yaml 1970-01-01 00:00:00 +0000 | |||
2365 | +++ examples/tests/test_old_apt_features.yaml 2016-07-26 19:53:43 +0000 | |||
2366 | @@ -0,0 +1,10 @@ | |||
2367 | 1 | showtrace: true | ||
2368 | 2 | # apt_proxy gets configured by tools/launch and tests/vmtests/__init__.py | ||
2369 | 3 | apt_mirrors: | ||
2370 | 4 | # we need a mirror that works (even in CI) but isn't the default | ||
2371 | 5 | ubuntu_archive: http://us.archive.ubuntu.com/ubuntu | ||
2372 | 6 | ubuntu_security: http://archive.ubuntu.com/ubuntu | ||
2373 | 7 | # set some key that surely is available to a non-default value | ||
2374 | 8 | debconf_selections: | ||
2375 | 9 | set1: | | ||
2376 | 10 | debconf debconf/priority select low | ||
2377 | 0 | 11 | ||
2378 | === added file 'examples/tests/test_old_apt_features_ports.yaml' | |||
2379 | --- examples/tests/test_old_apt_features_ports.yaml 1970-01-01 00:00:00 +0000 | |||
2380 | +++ examples/tests/test_old_apt_features_ports.yaml 2016-07-26 19:53:43 +0000 | |||
2381 | @@ -0,0 +1,10 @@ | |||
2382 | 1 | showtrace: true | ||
2383 | 2 | # apt_proxy gets configured by tools/launch and tests/vmtests/__init__.py | ||
2384 | 3 | apt_mirrors: | ||
2385 | 4 | # For ports there is no non-default alternative we could use | ||
2386 | 5 | ubuntu_archive: http://ports.ubuntu.com/ubuntu-ports | ||
2387 | 6 | ubuntu_security: http://ports.ubuntu.com/ubuntu-ports | ||
2388 | 7 | # set some key that surely is available to a non-default value | ||
2389 | 8 | debconf_selections: | ||
2390 | 9 | set1: | | ||
2391 | 10 | debconf debconf/priority select low | ||
2392 | 0 | 11 | ||
2393 | === added file 'tests/unittests/test_apt_custom_sources_list.py' | |||
2394 | --- tests/unittests/test_apt_custom_sources_list.py 1970-01-01 00:00:00 +0000 | |||
2395 | +++ tests/unittests/test_apt_custom_sources_list.py 2016-07-26 19:53:43 +0000 | |||
2396 | @@ -0,0 +1,172 @@ | |||
2397 | 1 | """ test_apt_custom_sources_list | ||
2398 | 2 | Test templating of custom sources list | ||
2399 | 3 | """ | ||
2400 | 4 | import logging | ||
2401 | 5 | import os | ||
2402 | 6 | import shutil | ||
2403 | 7 | import tempfile | ||
2404 | 8 | |||
2405 | 9 | from unittest import TestCase | ||
2406 | 10 | |||
2407 | 11 | import yaml | ||
2408 | 12 | import mock | ||
2409 | 13 | from mock import call | ||
2410 | 14 | |||
2411 | 15 | from curtin import util | ||
2412 | 16 | from curtin.commands import apt_config | ||
2413 | 17 | |||
2414 | 18 | LOG = logging.getLogger(__name__) | ||
2415 | 19 | |||
2416 | 20 | TARGET = "/" | ||
2417 | 21 | |||
2418 | 22 | # Input and expected output for the custom template | ||
2419 | 23 | YAML_TEXT_CUSTOM_SL = """ | ||
2420 | 24 | preserve_sources_list: false | ||
2421 | 25 | primary: | ||
2422 | 26 | - arches: [default] | ||
2423 | 27 | uri: http://test.ubuntu.com/ubuntu/ | ||
2424 | 28 | security: | ||
2425 | 29 | - arches: [default] | ||
2426 | 30 | uri: http://testsec.ubuntu.com/ubuntu/ | ||
2427 | 31 | sources_list: | | ||
2428 | 32 | |||
2429 | 33 | ## Note, this file is written by curtin at install time. It should not end | ||
2430 | 34 | ## up on the installed system itself. | ||
2431 | 35 | # | ||
2432 | 36 | # See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to | ||
2433 | 37 | # newer versions of the distribution. | ||
2434 | 38 | deb $MIRROR $RELEASE main restricted | ||
2435 | 39 | deb-src $MIRROR $RELEASE main restricted | ||
2436 | 40 | deb $PRIMARY $RELEASE universe restricted | ||
2437 | 41 | deb $SECURITY $RELEASE-security multiverse | ||
2438 | 42 | # FIND_SOMETHING_SPECIAL | ||
2439 | 43 | """ | ||
2440 | 44 | |||
2441 | 45 | EXPECTED_CONVERTED_CONTENT = """ | ||
2442 | 46 | ## Note, this file is written by curtin at install time. It should not end | ||
2443 | 47 | ## up on the installed system itself. | ||
2444 | 48 | # | ||
2445 | 49 | # See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to | ||
2446 | 50 | # newer versions of the distribution. | ||
2447 | 51 | deb http://test.ubuntu.com/ubuntu/ fakerel main restricted | ||
2448 | 52 | deb-src http://test.ubuntu.com/ubuntu/ fakerel main restricted | ||
2449 | 53 | deb http://test.ubuntu.com/ubuntu/ fakerel universe restricted | ||
2450 | 54 | deb http://testsec.ubuntu.com/ubuntu/ fakerel-security multiverse | ||
2451 | 55 | # FIND_SOMETHING_SPECIAL | ||
2452 | 56 | """ | ||
2453 | 57 | |||
2454 | 58 | # mocked to be independent to the unittest system | ||
2455 | 59 | MOCKED_APT_SRC_LIST = """ | ||
2456 | 60 | deb http://test.ubuntu.com/ubuntu/ notouched main restricted | ||
2457 | 61 | deb-src http://test.ubuntu.com/ubuntu/ notouched main restricted | ||
2458 | 62 | deb http://test.ubuntu.com/ubuntu/ notouched-updates main restricted | ||
2459 | 63 | deb http://testsec.ubuntu.com/ubuntu/ notouched-security main restricted | ||
2460 | 64 | """ | ||
2461 | 65 | |||
2462 | 66 | EXPECTED_BASE_CONTENT = (""" | ||
2463 | 67 | deb http://test.ubuntu.com/ubuntu/ notouched main restricted | ||
2464 | 68 | deb-src http://test.ubuntu.com/ubuntu/ notouched main restricted | ||
2465 | 69 | deb http://test.ubuntu.com/ubuntu/ notouched-updates main restricted | ||
2466 | 70 | deb http://testsec.ubuntu.com/ubuntu/ notouched-security main restricted | ||
2467 | 71 | """) | ||
2468 | 72 | |||
2469 | 73 | EXPECTED_MIRROR_CONTENT = (""" | ||
2470 | 74 | deb http://test.ubuntu.com/ubuntu/ notouched main restricted | ||
2471 | 75 | deb-src http://test.ubuntu.com/ubuntu/ notouched main restricted | ||
2472 | 76 | deb http://test.ubuntu.com/ubuntu/ notouched-updates main restricted | ||
2473 | 77 | deb http://test.ubuntu.com/ubuntu/ notouched-security main restricted | ||
2474 | 78 | """) | ||
2475 | 79 | |||
2476 | 80 | EXPECTED_PRIMSEC_CONTENT = (""" | ||
2477 | 81 | deb http://test.ubuntu.com/ubuntu/ notouched main restricted | ||
2478 | 82 | deb-src http://test.ubuntu.com/ubuntu/ notouched main restricted | ||
2479 | 83 | deb http://test.ubuntu.com/ubuntu/ notouched-updates main restricted | ||
2480 | 84 | deb http://testsec.ubuntu.com/ubuntu/ notouched-security main restricted | ||
2481 | 85 | """) | ||
2482 | 86 | |||
2483 | 87 | |||
2484 | 88 | class TestAptSourceConfigSourceList(TestCase): | ||
2485 | 89 | """TestAptSourceConfigSourceList - Class to test sources list rendering""" | ||
2486 | 90 | def setUp(self): | ||
2487 | 91 | super(TestAptSourceConfigSourceList, self).setUp() | ||
2488 | 92 | self.new_root = tempfile.mkdtemp() | ||
2489 | 93 | self.addCleanup(shutil.rmtree, self.new_root) | ||
2490 | 94 | # self.patchUtils(self.new_root) | ||
2491 | 95 | |||
2492 | 96 | @staticmethod | ||
2493 | 97 | def _apt_source_list(cfg, expected): | ||
2494 | 98 | "_apt_source_list - Test rendering from template (generic)" | ||
2495 | 99 | |||
2496 | 100 | arch = util.get_architecture() | ||
2497 | 101 | # would fail inside the unittest context | ||
2498 | 102 | with mock.patch.object(util, 'get_architecture', | ||
2499 | 103 | return_value=arch) as mockga: | ||
2500 | 104 | with mock.patch.object(util, 'write_file') as mockwrite: | ||
2501 | 105 | # keep it side effect free and avoid permission errors | ||
2502 | 106 | with mock.patch.object(os, 'rename'): | ||
2503 | 107 | # make test independent to executing system | ||
2504 | 108 | with mock.patch.object(util, 'load_file', | ||
2505 | 109 | return_value=MOCKED_APT_SRC_LIST): | ||
2506 | 110 | with mock.patch.object(util, 'lsb_release', | ||
2507 | 111 | return_value={'codename': | ||
2508 | 112 | 'fakerel'}): | ||
2509 | 113 | apt_config.handle_apt(cfg, TARGET) | ||
2510 | 114 | |||
2511 | 115 | mockga.assert_called_with("/") | ||
2512 | 116 | |||
2513 | 117 | cloudfile = '/etc/cloud/cloud.cfg.d/curtin-preserve-sources.cfg' | ||
2514 | 118 | cloudconf = yaml.dump({'apt_preserve_sources_list': True}, indent=1) | ||
2515 | 119 | calls = [call(TARGET + '/etc/apt/sources.list', | ||
2516 | 120 | expected, | ||
2517 | 121 | mode=0o644), | ||
2518 | 122 | call(TARGET + cloudfile, | ||
2519 | 123 | cloudconf, | ||
2520 | 124 | mode=0o644)] | ||
2521 | 125 | mockwrite.assert_has_calls(calls) | ||
2522 | 126 | |||
2523 | 127 | def test_apt_source_list(self): | ||
2524 | 128 | """test_apt_source_list - Test with neither custom sources nor parms""" | ||
2525 | 129 | cfg = {'preserve_sources_list': False} | ||
2526 | 130 | |||
2527 | 131 | self._apt_source_list(cfg, EXPECTED_BASE_CONTENT) | ||
2528 | 132 | |||
2529 | 133 | def test_apt_source_list_psm(self): | ||
2530 | 134 | """test_apt_source_list_psm - Test specifying prim+sec mirrors""" | ||
2531 | 135 | cfg = {'preserve_sources_list': False, | ||
2532 | 136 | 'primary': [{'arches': ["default"], | ||
2533 | 137 | 'uri': 'http://test.ubuntu.com/ubuntu/'}], | ||
2534 | 138 | 'security': [{'arches': ["default"], | ||
2535 | 139 | 'uri': 'http://testsec.ubuntu.com/ubuntu/'}]} | ||
2536 | 140 | |||
2537 | 141 | self._apt_source_list(cfg, EXPECTED_PRIMSEC_CONTENT) | ||
2538 | 142 | |||
2539 | 143 | @staticmethod | ||
2540 | 144 | def test_apt_srcl_custom(): | ||
2541 | 145 | """test_apt_srcl_custom - Test rendering a custom source template""" | ||
2542 | 146 | cfg = yaml.safe_load(YAML_TEXT_CUSTOM_SL) | ||
2543 | 147 | |||
2544 | 148 | arch = util.get_architecture() | ||
2545 | 149 | # would fail inside the unittest context | ||
2546 | 150 | with mock.patch.object(util, 'get_architecture', | ||
2547 | 151 | return_value=arch) as mockga: | ||
2548 | 152 | with mock.patch.object(util, 'write_file') as mockwrite: | ||
2549 | 153 | # keep it side effect free and avoid permission errors | ||
2550 | 154 | with mock.patch.object(os, 'rename'): | ||
2551 | 155 | with mock.patch.object(util, 'lsb_release', | ||
2552 | 156 | return_value={'codename': | ||
2553 | 157 | 'fakerel'}): | ||
2554 | 158 | apt_config.handle_apt(cfg, TARGET) | ||
2555 | 159 | |||
2556 | 160 | mockga.assert_called_with("/") | ||
2557 | 161 | cloudfile = '/etc/cloud/cloud.cfg.d/curtin-preserve-sources.cfg' | ||
2558 | 162 | cloudconf = yaml.dump({'apt_preserve_sources_list': True}, indent=1) | ||
2559 | 163 | calls = [call(TARGET + '/etc/apt/sources.list', | ||
2560 | 164 | EXPECTED_CONVERTED_CONTENT, | ||
2561 | 165 | mode=0o644), | ||
2562 | 166 | call(TARGET + cloudfile, | ||
2563 | 167 | cloudconf, | ||
2564 | 168 | mode=0o644)] | ||
2565 | 169 | mockwrite.assert_has_calls(calls) | ||
2566 | 170 | |||
2567 | 171 | |||
2568 | 172 | # vi: ts=4 expandtab | ||
2569 | 0 | 173 | ||
2570 | === added file 'tests/unittests/test_apt_source.py' | |||
2571 | --- tests/unittests/test_apt_source.py 1970-01-01 00:00:00 +0000 | |||
2572 | +++ tests/unittests/test_apt_source.py 2016-07-26 19:53:43 +0000 | |||
2573 | @@ -0,0 +1,927 @@ | |||
2574 | 1 | """ test_apt_source | ||
2575 | 2 | Testing various config variations of the apt_source custom config | ||
2576 | 3 | """ | ||
2577 | 4 | import glob | ||
2578 | 5 | import os | ||
2579 | 6 | import re | ||
2580 | 7 | import shutil | ||
2581 | 8 | import socket | ||
2582 | 9 | import tempfile | ||
2583 | 10 | |||
2584 | 11 | from unittest import TestCase | ||
2585 | 12 | |||
2586 | 13 | import mock | ||
2587 | 14 | from mock import call | ||
2588 | 15 | |||
2589 | 16 | from curtin import util | ||
2590 | 17 | from curtin import gpg | ||
2591 | 18 | from curtin.commands import apt_config | ||
2592 | 19 | |||
2593 | 20 | |||
2594 | 21 | EXPECTEDKEY = u"""-----BEGIN PGP PUBLIC KEY BLOCK----- | ||
2595 | 22 | Version: GnuPG v1 | ||
2596 | 23 | |||
2597 | 24 | mI0ESuZLUgEEAKkqq3idtFP7g9hzOu1a8+v8ImawQN4TrvlygfScMU1TIS1eC7UQ | ||
2598 | 25 | NUA8Qqgr9iUaGnejb0VciqftLrU9D6WYHSKz+EITefgdyJ6SoQxjoJdsCpJ7o9Jy | ||
2599 | 26 | 8PQnpRttiFm4qHu6BVnKnBNxw/z3ST9YMqW5kbMQpfxbGe+obRox59NpABEBAAG0 | ||
2600 | 27 | HUxhdW5jaHBhZCBQUEEgZm9yIFNjb3R0IE1vc2VyiLYEEwECACAFAkrmS1ICGwMG | ||
2601 | 28 | CwkIBwMCBBUCCAMEFgIDAQIeAQIXgAAKCRAGILvPA2g/d3aEA/9tVjc10HOZwV29 | ||
2602 | 29 | OatVuTeERjjrIbxflO586GLA8cp0C9RQCwgod/R+cKYdQcHjbqVcP0HqxveLg0RZ | ||
2603 | 30 | FJpWLmWKamwkABErwQLGlM/Hwhjfade8VvEQutH5/0JgKHmzRsoqfR+LMO6OS+Sm | ||
2604 | 31 | S0ORP6HXET3+jC8BMG4tBWCTK/XEZw== | ||
2605 | 32 | =ACB2 | ||
2606 | 33 | -----END PGP PUBLIC KEY BLOCK-----""" | ||
2607 | 34 | |||
2608 | 35 | ADD_APT_REPO_MATCH = r"^[\w-]+:\w" | ||
2609 | 36 | |||
2610 | 37 | TARGET = "/" | ||
2611 | 38 | |||
2612 | 39 | |||
2613 | 40 | def load_tfile(filename): | ||
2614 | 41 | """ load_tfile | ||
2615 | 42 | load file and return content after decoding | ||
2616 | 43 | """ | ||
2617 | 44 | try: | ||
2618 | 45 | content = util.load_file(filename, mode="r") | ||
2619 | 46 | except Exception as error: | ||
2620 | 47 | print('failed to load file content for test: %s' % error) | ||
2621 | 48 | raise | ||
2622 | 49 | |||
2623 | 50 | return content | ||
2624 | 51 | |||
2625 | 52 | |||
2626 | 53 | class TestAptSourceConfig(TestCase): | ||
2627 | 54 | """ TestAptSourceConfig | ||
2628 | 55 | Main Class to test apt configs | ||
2629 | 56 | """ | ||
2630 | 57 | def setUp(self): | ||
2631 | 58 | super(TestAptSourceConfig, self).setUp() | ||
2632 | 59 | self.tmp = tempfile.mkdtemp() | ||
2633 | 60 | self.addCleanup(shutil.rmtree, self.tmp) | ||
2634 | 61 | self.aptlistfile = os.path.join(self.tmp, "single-deb.list") | ||
2635 | 62 | self.aptlistfile2 = os.path.join(self.tmp, "single-deb2.list") | ||
2636 | 63 | self.aptlistfile3 = os.path.join(self.tmp, "single-deb3.list") | ||
2637 | 64 | self.join = os.path.join | ||
2638 | 65 | self.matcher = re.compile(ADD_APT_REPO_MATCH).search | ||
2639 | 66 | |||
2640 | 67 | @staticmethod | ||
2641 | 68 | def _add_apt_sources(*args, **kwargs): | ||
2642 | 69 | with mock.patch.object(util, 'apt_update'): | ||
2643 | 70 | apt_config.add_apt_sources(*args, **kwargs) | ||
2644 | 71 | |||
2645 | 72 | @staticmethod | ||
2646 | 73 | def _get_default_params(): | ||
2647 | 74 | """ get_default_params | ||
2648 | 75 | Get the most basic default mrror and release info to be used in tests | ||
2649 | 76 | """ | ||
2650 | 77 | params = {} | ||
2651 | 78 | params['RELEASE'] = util.lsb_release()['codename'] | ||
2652 | 79 | params['MIRROR'] = apt_config.get_default_mirrors()["PRIMARY"] | ||
2653 | 80 | return params | ||
2654 | 81 | |||
2655 | 82 | def _myjoin(self, *args, **kwargs): | ||
2656 | 83 | """ _myjoin - redir into writable tmpdir""" | ||
2657 | 84 | if (args[0] == "/etc/apt/sources.list.d/" and | ||
2658 | 85 | args[1] == "cloud_config_sources.list" and | ||
2659 | 86 | len(args) == 2): | ||
2660 | 87 | return self.join(self.tmp, args[0].lstrip("/"), args[1]) | ||
2661 | 88 | else: | ||
2662 | 89 | return self.join(*args, **kwargs) | ||
2663 | 90 | |||
2664 | 91 | def _apt_src_basic(self, filename, cfg): | ||
2665 | 92 | """ _apt_src_basic | ||
2666 | 93 | Test Fix deb source string, has to overwrite mirror conf in params | ||
2667 | 94 | """ | ||
2668 | 95 | params = self._get_default_params() | ||
2669 | 96 | |||
2670 | 97 | self._add_apt_sources(cfg, TARGET, template_params=params, | ||
2671 | 98 | aa_repo_match=self.matcher) | ||
2672 | 99 | |||
2673 | 100 | self.assertTrue(os.path.isfile(filename)) | ||
2674 | 101 | |||
2675 | 102 | contents = load_tfile(filename) | ||
2676 | 103 | self.assertTrue(re.search(r"%s %s %s %s\n" % | ||
2677 | 104 | ("deb", "http://test.ubuntu.com/ubuntu", | ||
2678 | 105 | "karmic-backports", | ||
2679 | 106 | "main universe multiverse restricted"), | ||
2680 | 107 | contents, flags=re.IGNORECASE)) | ||
2681 | 108 | |||
2682 | 109 | def test_apt_src_basic(self): | ||
2683 | 110 | """test_apt_src_basic - Test fix deb source string""" | ||
2684 | 111 | cfg = {self.aptlistfile: {'source': | ||
2685 | 112 | ('deb http://test.ubuntu.com/ubuntu' | ||
2686 | 113 | ' karmic-backports' | ||
2687 | 114 | ' main universe multiverse restricted')}} | ||
2688 | 115 | self._apt_src_basic(self.aptlistfile, cfg) | ||
2689 | 116 | |||
2690 | 117 | def test_apt_src_basic_tri(self): | ||
2691 | 118 | """test_apt_src_basic_tri - Test multiple fix deb source strings""" | ||
2692 | 119 | cfg = {self.aptlistfile: {'source': | ||
2693 | 120 | ('deb http://test.ubuntu.com/ubuntu' | ||
2694 | 121 | ' karmic-backports' | ||
2695 | 122 | ' main universe multiverse restricted')}, | ||
2696 | 123 | self.aptlistfile2: {'source': | ||
2697 | 124 | ('deb http://test.ubuntu.com/ubuntu' | ||
2698 | 125 | ' precise-backports' | ||
2699 | 126 | ' main universe multiverse restricted')}, | ||
2700 | 127 | self.aptlistfile3: {'source': | ||
2701 | 128 | ('deb http://test.ubuntu.com/ubuntu' | ||
2702 | 129 | ' lucid-backports' | ||
2703 | 130 | ' main universe multiverse restricted')}} | ||
2704 | 131 | self._apt_src_basic(self.aptlistfile, cfg) | ||
2705 | 132 | |||
2706 | 133 | # extra verify on two extra files of this test | ||
2707 | 134 | contents = load_tfile(self.aptlistfile2) | ||
2708 | 135 | self.assertTrue(re.search(r"%s %s %s %s\n" % | ||
2709 | 136 | ("deb", "http://test.ubuntu.com/ubuntu", | ||
2710 | 137 | "precise-backports", | ||
2711 | 138 | "main universe multiverse restricted"), | ||
2712 | 139 | contents, flags=re.IGNORECASE)) | ||
2713 | 140 | contents = load_tfile(self.aptlistfile3) | ||
2714 | 141 | self.assertTrue(re.search(r"%s %s %s %s\n" % | ||
2715 | 142 | ("deb", "http://test.ubuntu.com/ubuntu", | ||
2716 | 143 | "lucid-backports", | ||
2717 | 144 | "main universe multiverse restricted"), | ||
2718 | 145 | contents, flags=re.IGNORECASE)) | ||
2719 | 146 | |||
2720 | 147 | def _apt_src_replacement(self, filename, cfg): | ||
2721 | 148 | """ apt_src_replace | ||
2722 | 149 | Test Autoreplacement of MIRROR and RELEASE in source specs | ||
2723 | 150 | """ | ||
2724 | 151 | params = self._get_default_params() | ||
2725 | 152 | self._add_apt_sources(cfg, TARGET, template_params=params, | ||
2726 | 153 | aa_repo_match=self.matcher) | ||
2727 | 154 | |||
2728 | 155 | self.assertTrue(os.path.isfile(filename)) | ||
2729 | 156 | |||
2730 | 157 | contents = load_tfile(filename) | ||
2731 | 158 | self.assertTrue(re.search(r"%s %s %s %s\n" % | ||
2732 | 159 | ("deb", params['MIRROR'], params['RELEASE'], | ||
2733 | 160 | "multiverse"), | ||
2734 | 161 | contents, flags=re.IGNORECASE)) | ||
2735 | 162 | |||
2736 | 163 | def test_apt_src_replace(self): | ||
2737 | 164 | """test_apt_src_replace - Test Autoreplacement of MIRROR and RELEASE""" | ||
2738 | 165 | cfg = {self.aptlistfile: {'source': 'deb $MIRROR $RELEASE multiverse'}} | ||
2739 | 166 | self._apt_src_replacement(self.aptlistfile, cfg) | ||
2740 | 167 | |||
2741 | 168 | def test_apt_src_replace_fn(self): | ||
2742 | 169 | """test_apt_src_replace_fn - Test filename being overwritten in dict""" | ||
2743 | 170 | cfg = {'ignored': {'source': 'deb $MIRROR $RELEASE multiverse', | ||
2744 | 171 | 'filename': self.aptlistfile}} | ||
2745 | 172 | # second file should overwrite the dict key | ||
2746 | 173 | self._apt_src_replacement(self.aptlistfile, cfg) | ||
2747 | 174 | |||
2748 | 175 | def _apt_src_replace_tri(self, cfg): | ||
2749 | 176 | """ _apt_src_replace_tri | ||
2750 | 177 | Test three autoreplacements of MIRROR and RELEASE in source specs with | ||
2751 | 178 | generic part | ||
2752 | 179 | """ | ||
2753 | 180 | self._apt_src_replacement(self.aptlistfile, cfg) | ||
2754 | 181 | |||
2755 | 182 | # extra verify on two extra files of this test | ||
2756 | 183 | params = self._get_default_params() | ||
2757 | 184 | contents = load_tfile(self.aptlistfile2) | ||
2758 | 185 | self.assertTrue(re.search(r"%s %s %s %s\n" % | ||
2759 | 186 | ("deb", params['MIRROR'], params['RELEASE'], | ||
2760 | 187 | "main"), | ||
2761 | 188 | contents, flags=re.IGNORECASE)) | ||
2762 | 189 | contents = load_tfile(self.aptlistfile3) | ||
2763 | 190 | self.assertTrue(re.search(r"%s %s %s %s\n" % | ||
2764 | 191 | ("deb", params['MIRROR'], params['RELEASE'], | ||
2765 | 192 | "universe"), | ||
2766 | 193 | contents, flags=re.IGNORECASE)) | ||
2767 | 194 | |||
2768 | 195 | def test_apt_src_replace_tri(self): | ||
2769 | 196 | """test_apt_src_replace_tri - Test multiple replacements/overwrites""" | ||
2770 | 197 | cfg = {self.aptlistfile: {'source': 'deb $MIRROR $RELEASE multiverse'}, | ||
2771 | 198 | 'notused': {'source': 'deb $MIRROR $RELEASE main', | ||
2772 | 199 | 'filename': self.aptlistfile2}, | ||
2773 | 200 | self.aptlistfile3: {'source': 'deb $MIRROR $RELEASE universe'}} | ||
2774 | 201 | self._apt_src_replace_tri(cfg) | ||
2775 | 202 | |||
2776 | 203 | def _apt_src_keyid(self, filename, cfg, keynum): | ||
2777 | 204 | """ _apt_src_keyid | ||
2778 | 205 | Test specification of a source + keyid | ||
2779 | 206 | """ | ||
2780 | 207 | params = self._get_default_params() | ||
2781 | 208 | |||
2782 | 209 | with mock.patch.object(util, 'subp', | ||
2783 | 210 | return_value=('fakekey 1234', '')) as mockobj: | ||
2784 | 211 | self._add_apt_sources(cfg, TARGET, template_params=params, | ||
2785 | 212 | aa_repo_match=self.matcher) | ||
2786 | 213 | |||
2787 | 214 | # check if it added the right ammount of keys | ||
2788 | 215 | calls = [] | ||
2789 | 216 | for _ in range(keynum): | ||
2790 | 217 | calls.append(call(['apt-key', 'add', '-'], data=b'fakekey 1234')) | ||
2791 | 218 | mockobj.assert_has_calls(calls, any_order=True) | ||
2792 | 219 | |||
2793 | 220 | self.assertTrue(os.path.isfile(filename)) | ||
2794 | 221 | |||
2795 | 222 | contents = load_tfile(filename) | ||
2796 | 223 | self.assertTrue(re.search(r"%s %s %s %s\n" % | ||
2797 | 224 | ("deb", | ||
2798 | 225 | ('http://ppa.launchpad.net/smoser/' | ||
2799 | 226 | 'cloud-init-test/ubuntu'), | ||
2800 | 227 | "xenial", "main"), | ||
2801 | 228 | contents, flags=re.IGNORECASE)) | ||
2802 | 229 | |||
2803 | 230 | def test_apt_src_keyid(self): | ||
2804 | 231 | """test_apt_src_keyid - Test source + keyid with filename being set""" | ||
2805 | 232 | cfg = {self.aptlistfile: {'source': ('deb ' | ||
2806 | 233 | 'http://ppa.launchpad.net/' | ||
2807 | 234 | 'smoser/cloud-init-test/ubuntu' | ||
2808 | 235 | ' xenial main'), | ||
2809 | 236 | 'keyid': "03683F77"}} | ||
2810 | 237 | self._apt_src_keyid(self.aptlistfile, cfg, 1) | ||
2811 | 238 | |||
2812 | 239 | def test_apt_src_keyid_tri(self): | ||
2813 | 240 | """test_apt_src_keyid_tri - Test multiple src+keyid+filen overwrites""" | ||
2814 | 241 | cfg = {self.aptlistfile: {'source': ('deb ' | ||
2815 | 242 | 'http://ppa.launchpad.net/' | ||
2816 | 243 | 'smoser/cloud-init-test/ubuntu' | ||
2817 | 244 | ' xenial main'), | ||
2818 | 245 | 'keyid': "03683F77"}, | ||
2819 | 246 | 'ignored': {'source': ('deb ' | ||
2820 | 247 | 'http://ppa.launchpad.net/' | ||
2821 | 248 | 'smoser/cloud-init-test/ubuntu' | ||
2822 | 249 | ' xenial universe'), | ||
2823 | 250 | 'keyid': "03683F77", | ||
2824 | 251 | 'filename': self.aptlistfile2}, | ||
2825 | 252 | self.aptlistfile3: {'source': ('deb ' | ||
2826 | 253 | 'http://ppa.launchpad.net/' | ||
2827 | 254 | 'smoser/cloud-init-test/ubuntu' | ||
2828 | 255 | ' xenial multiverse'), | ||
2829 | 256 | 'keyid': "03683F77"}} | ||
2830 | 257 | |||
2831 | 258 | self._apt_src_keyid(self.aptlistfile, cfg, 3) | ||
2832 | 259 | contents = load_tfile(self.aptlistfile2) | ||
2833 | 260 | self.assertTrue(re.search(r"%s %s %s %s\n" % | ||
2834 | 261 | ("deb", | ||
2835 | 262 | ('http://ppa.launchpad.net/smoser/' | ||
2836 | 263 | 'cloud-init-test/ubuntu'), | ||
2837 | 264 | "xenial", "universe"), | ||
2838 | 265 | contents, flags=re.IGNORECASE)) | ||
2839 | 266 | contents = load_tfile(self.aptlistfile3) | ||
2840 | 267 | self.assertTrue(re.search(r"%s %s %s %s\n" % | ||
2841 | 268 | ("deb", | ||
2842 | 269 | ('http://ppa.launchpad.net/smoser/' | ||
2843 | 270 | 'cloud-init-test/ubuntu'), | ||
2844 | 271 | "xenial", "multiverse"), | ||
2845 | 272 | contents, flags=re.IGNORECASE)) | ||
2846 | 273 | |||
2847 | 274 | def test_apt_src_key(self): | ||
2848 | 275 | """test_apt_src_key - Test source + key""" | ||
2849 | 276 | params = self._get_default_params() | ||
2850 | 277 | cfg = {self.aptlistfile: {'source': ('deb ' | ||
2851 | 278 | 'http://ppa.launchpad.net/' | ||
2852 | 279 | 'smoser/cloud-init-test/ubuntu' | ||
2853 | 280 | ' xenial main'), | ||
2854 | 281 | 'key': "fakekey 4321"}} | ||
2855 | 282 | |||
2856 | 283 | with mock.patch.object(util, 'subp') as mockobj: | ||
2857 | 284 | self._add_apt_sources(cfg, TARGET, template_params=params, | ||
2858 | 285 | aa_repo_match=self.matcher) | ||
2859 | 286 | |||
2860 | 287 | mockobj.assert_any_call(['apt-key', 'add', '-'], data=b'fakekey 4321') | ||
2861 | 288 | |||
2862 | 289 | self.assertTrue(os.path.isfile(self.aptlistfile)) | ||
2863 | 290 | |||
2864 | 291 | contents = load_tfile(self.aptlistfile) | ||
2865 | 292 | self.assertTrue(re.search(r"%s %s %s %s\n" % | ||
2866 | 293 | ("deb", | ||
2867 | 294 | ('http://ppa.launchpad.net/smoser/' | ||
2868 | 295 | 'cloud-init-test/ubuntu'), | ||
2869 | 296 | "xenial", "main"), | ||
2870 | 297 | contents, flags=re.IGNORECASE)) | ||
2871 | 298 | |||
2872 | 299 | def test_apt_src_keyonly(self): | ||
2873 | 300 | """test_apt_src_keyonly - Test key without source""" | ||
2874 | 301 | params = self._get_default_params() | ||
2875 | 302 | cfg = {self.aptlistfile: {'key': "fakekey 4242"}} | ||
2876 | 303 | |||
2877 | 304 | with mock.patch.object(util, 'subp') as mockobj: | ||
2878 | 305 | self._add_apt_sources(cfg, TARGET, template_params=params, | ||
2879 | 306 | aa_repo_match=self.matcher) | ||
2880 | 307 | |||
2881 | 308 | mockobj.assert_any_call(['apt-key', 'add', '-'], data=b'fakekey 4242') | ||
2882 | 309 | |||
2883 | 310 | # filename should be ignored on key only | ||
2884 | 311 | self.assertFalse(os.path.isfile(self.aptlistfile)) | ||
2885 | 312 | |||
2886 | 313 | def test_apt_src_keyidonly(self): | ||
2887 | 314 | """test_apt_src_keyidonly - Test keyid without source""" | ||
2888 | 315 | params = self._get_default_params() | ||
2889 | 316 | cfg = {self.aptlistfile: {'keyid': "03683F77"}} | ||
2890 | 317 | |||
2891 | 318 | with mock.patch.object(util, 'subp', | ||
2892 | 319 | return_value=('fakekey 1212', '')) as mockobj: | ||
2893 | 320 | self._add_apt_sources(cfg, TARGET, template_params=params, | ||
2894 | 321 | aa_repo_match=self.matcher) | ||
2895 | 322 | |||
2896 | 323 | mockobj.assert_any_call(['apt-key', 'add', '-'], data=b'fakekey 1212') | ||
2897 | 324 | |||
2898 | 325 | # filename should be ignored on key only | ||
2899 | 326 | self.assertFalse(os.path.isfile(self.aptlistfile)) | ||
2900 | 327 | |||
2901 | 328 | def apt_src_keyid_real(self, cfg, expectedkey): | ||
2902 | 329 | """apt_src_keyid_real | ||
2903 | 330 | Test specification of a keyid without source including | ||
2904 | 331 | up to addition of the key (add_apt_key_raw mocked to keep the | ||
2905 | 332 | environment as is) | ||
2906 | 333 | """ | ||
2907 | 334 | params = self._get_default_params() | ||
2908 | 335 | |||
2909 | 336 | with mock.patch.object(apt_config, 'add_apt_key_raw') as mockkey: | ||
2910 | 337 | with mock.patch.object(gpg, 'getkeybyid', | ||
2911 | 338 | return_value=expectedkey) as mockgetkey: | ||
2912 | 339 | self._add_apt_sources(cfg, TARGET, template_params=params, | ||
2913 | 340 | aa_repo_match=self.matcher) | ||
2914 | 341 | |||
2915 | 342 | keycfg = cfg[self.aptlistfile] | ||
2916 | 343 | mockgetkey.assert_called_with(keycfg['keyid'], | ||
2917 | 344 | keycfg.get('keyserver', | ||
2918 | 345 | 'keyserver.ubuntu.com')) | ||
2919 | 346 | mockkey.assert_called_with(expectedkey, TARGET) | ||
2920 | 347 | |||
2921 | 348 | # filename should be ignored on key only | ||
2922 | 349 | self.assertFalse(os.path.isfile(self.aptlistfile)) | ||
2923 | 350 | |||
2924 | 351 | def test_apt_src_keyid_real(self): | ||
2925 | 352 | """test_apt_src_keyid_real - Test keyid including key add""" | ||
2926 | 353 | keyid = "03683F77" | ||
2927 | 354 | cfg = {self.aptlistfile: {'keyid': keyid}} | ||
2928 | 355 | |||
2929 | 356 | self.apt_src_keyid_real(cfg, EXPECTEDKEY) | ||
2930 | 357 | |||
2931 | 358 | def test_apt_src_longkeyid_real(self): | ||
2932 | 359 | """test_apt_src_longkeyid_real Test long keyid including key add""" | ||
2933 | 360 | keyid = "B59D 5F15 97A5 04B7 E230 6DCA 0620 BBCF 0368 3F77" | ||
2934 | 361 | cfg = {self.aptlistfile: {'keyid': keyid}} | ||
2935 | 362 | |||
2936 | 363 | self.apt_src_keyid_real(cfg, EXPECTEDKEY) | ||
2937 | 364 | |||
2938 | 365 | def test_apt_src_longkeyid_ks_real(self): | ||
2939 | 366 | """test_apt_src_longkeyid_ks_real Test long keyid from other ks""" | ||
2940 | 367 | keyid = "B59D 5F15 97A5 04B7 E230 6DCA 0620 BBCF 0368 3F77" | ||
2941 | 368 | cfg = {self.aptlistfile: {'keyid': keyid, | ||
2942 | 369 | 'keyserver': 'keys.gnupg.net'}} | ||
2943 | 370 | |||
2944 | 371 | self.apt_src_keyid_real(cfg, EXPECTEDKEY) | ||
2945 | 372 | |||
2946 | 373 | def test_apt_src_keyid_keyserver(self): | ||
2947 | 374 | """test_apt_src_keyid_keyserver - Test custom keyserver""" | ||
2948 | 375 | keyid = "03683F77" | ||
2949 | 376 | params = self._get_default_params() | ||
2950 | 377 | cfg = {self.aptlistfile: {'keyid': keyid, | ||
2951 | 378 | 'keyserver': 'test.random.com'}} | ||
2952 | 379 | |||
2953 | 380 | # in some test environments only *.ubuntu.com is reachable | ||
2954 | 381 | # so mock the call and check if the config got there | ||
2955 | 382 | with mock.patch.object(gpg, 'getkeybyid', | ||
2956 | 383 | return_value="fakekey") as mockgetkey: | ||
2957 | 384 | with mock.patch.object(apt_config, 'add_apt_key_raw') as mockadd: | ||
2958 | 385 | self._add_apt_sources(cfg, TARGET, template_params=params, | ||
2959 | 386 | aa_repo_match=self.matcher) | ||
2960 | 387 | |||
2961 | 388 | mockgetkey.assert_called_with('03683F77', 'test.random.com') | ||
2962 | 389 | mockadd.assert_called_with('fakekey', TARGET) | ||
2963 | 390 | |||
2964 | 391 | # filename should be ignored on key only | ||
2965 | 392 | self.assertFalse(os.path.isfile(self.aptlistfile)) | ||
2966 | 393 | |||
2967 | 394 | def test_apt_src_ppa(self): | ||
2968 | 395 | """test_apt_src_ppa - Test specification of a ppa""" | ||
2969 | 396 | params = self._get_default_params() | ||
2970 | 397 | cfg = {self.aptlistfile: {'source': 'ppa:smoser/cloud-init-test'}} | ||
2971 | 398 | |||
2972 | 399 | with mock.patch.object(util, 'subp') as mockobj: | ||
2973 | 400 | self._add_apt_sources(cfg, TARGET, template_params=params, | ||
2974 | 401 | aa_repo_match=self.matcher) | ||
2975 | 402 | mockobj.assert_any_call(['add-apt-repository', | ||
2976 | 403 | 'ppa:smoser/cloud-init-test']) | ||
2977 | 404 | |||
2978 | 405 | # adding ppa should ignore filename (uses add-apt-repository) | ||
2979 | 406 | self.assertFalse(os.path.isfile(self.aptlistfile)) | ||
2980 | 407 | |||
2981 | 408 | def test_apt_src_ppa_tri(self): | ||
2982 | 409 | """test_apt_src_ppa_tri - Test specification of multiple ppa's""" | ||
2983 | 410 | params = self._get_default_params() | ||
2984 | 411 | cfg = {self.aptlistfile: {'source': 'ppa:smoser/cloud-init-test'}, | ||
2985 | 412 | self.aptlistfile2: {'source': 'ppa:smoser/cloud-init-test2'}, | ||
2986 | 413 | self.aptlistfile3: {'source': 'ppa:smoser/cloud-init-test3'}} | ||
2987 | 414 | |||
2988 | 415 | with mock.patch.object(util, 'subp') as mockobj: | ||
2989 | 416 | self._add_apt_sources(cfg, TARGET, template_params=params, | ||
2990 | 417 | aa_repo_match=self.matcher) | ||
2991 | 418 | calls = [call(['add-apt-repository', 'ppa:smoser/cloud-init-test']), | ||
2992 | 419 | call(['add-apt-repository', 'ppa:smoser/cloud-init-test2']), | ||
2993 | 420 | call(['add-apt-repository', 'ppa:smoser/cloud-init-test3'])] | ||
2994 | 421 | mockobj.assert_has_calls(calls, any_order=True) | ||
2995 | 422 | |||
2996 | 423 | # adding ppa should ignore all filenames (uses add-apt-repository) | ||
2997 | 424 | self.assertFalse(os.path.isfile(self.aptlistfile)) | ||
2998 | 425 | self.assertFalse(os.path.isfile(self.aptlistfile2)) | ||
2999 | 426 | self.assertFalse(os.path.isfile(self.aptlistfile3)) | ||
3000 | 427 | |||
3001 | 428 | def test_mir_apt_list_rename(self): | ||
3002 | 429 | """test_mir_apt_list_rename - Test find mirror and apt list renaming""" | ||
3003 | 430 | pre = "/var/lib/apt/lists" | ||
3004 | 431 | # filenames are archive dependent | ||
3005 | 432 | arch = util.get_architecture() | ||
3006 | 433 | if arch in apt_config.PRIMARY_ARCHES: | ||
3007 | 434 | component = "ubuntu" | ||
3008 | 435 | archive = "archive.ubuntu.com" | ||
3009 | 436 | else: | ||
3010 | 437 | component = "ubuntu-ports" | ||
3011 | 438 | archive = "ports.ubuntu.com" | ||
3012 | 439 | |||
3013 | 440 | cfg = {'primary': [{'arches': ["default"], | ||
3014 | 441 | 'uri': | ||
3015 | 442 | 'http://test.ubuntu.com/%s/' % component}], | ||
3016 | 443 | 'security': [{'arches': ["default"], | ||
3017 | 444 | 'uri': | ||
3018 | 445 | 'http://testsec.ubuntu.com/%s/' % component}]} | ||
3019 | 446 | post = ("%s_dists_%s-updates_InRelease" % | ||
3020 | 447 | (component, util.lsb_release()['codename'])) | ||
3021 | 448 | fromfn = ("%s/%s_%s" % (pre, archive, post)) | ||
3022 | 449 | tofn = ("%s/test.ubuntu.com_%s" % (pre, post)) | ||
3023 | 450 | |||
3024 | 451 | mirrors = apt_config.find_apt_mirror_info(cfg) | ||
3025 | 452 | |||
3026 | 453 | self.assertEqual(mirrors['MIRROR'], | ||
3027 | 454 | "http://test.ubuntu.com/%s/" % component) | ||
3028 | 455 | self.assertEqual(mirrors['PRIMARY'], | ||
3029 | 456 | "http://test.ubuntu.com/%s/" % component) | ||
3030 | 457 | self.assertEqual(mirrors['SECURITY'], | ||
3031 | 458 | "http://testsec.ubuntu.com/%s/" % component) | ||
3032 | 459 | |||
3033 | 460 | # get_architecture would fail inside the unittest context | ||
3034 | 461 | with mock.patch.object(util, 'get_architecture', return_value=arch): | ||
3035 | 462 | with mock.patch.object(os, 'rename') as mockren: | ||
3036 | 463 | with mock.patch.object(glob, 'glob', | ||
3037 | 464 | return_value=[fromfn]): | ||
3038 | 465 | apt_config.rename_apt_lists(mirrors, TARGET) | ||
3039 | 466 | |||
3040 | 467 | mockren.assert_any_call(fromfn, tofn) | ||
3041 | 468 | |||
3042 | 469 | @staticmethod | ||
3043 | 470 | def test_apt_proxy(): | ||
3044 | 471 | """test_mir_apt_list_rename - Test apt_*proxy configuration""" | ||
3045 | 472 | cfg = {"proxy": "foobar1", | ||
3046 | 473 | "http_proxy": "foobar2", | ||
3047 | 474 | "ftp_proxy": "foobar3", | ||
3048 | 475 | "https_proxy": "foobar4"} | ||
3049 | 476 | |||
3050 | 477 | with mock.patch.object(util, 'write_file') as mockobj: | ||
3051 | 478 | apt_config.apply_apt_proxy_config(cfg, "proxyfn", "notused") | ||
3052 | 479 | |||
3053 | 480 | mockobj.assert_called_with('proxyfn', | ||
3054 | 481 | ('Acquire::http::Proxy "foobar1";\n' | ||
3055 | 482 | 'Acquire::http::Proxy "foobar2";\n' | ||
3056 | 483 | 'Acquire::ftp::Proxy "foobar3";\n' | ||
3057 | 484 | 'Acquire::https::Proxy "foobar4";\n')) | ||
3058 | 485 | |||
3059 | 486 | def test_mirror(self): | ||
3060 | 487 | """test_mirror - Test defining a mirror""" | ||
3061 | 488 | pmir = "http://us.archive.ubuntu.com/ubuntu/" | ||
3062 | 489 | smir = "http://security.ubuntu.com/ubuntu/" | ||
3063 | 490 | cfg = {"primary": [{'arches': ["default"], | ||
3064 | 491 | "uri": pmir}], | ||
3065 | 492 | "security": [{'arches': ["default"], | ||
3066 | 493 | "uri": smir}]} | ||
3067 | 494 | |||
3068 | 495 | mirrors = apt_config.find_apt_mirror_info(cfg) | ||
3069 | 496 | |||
3070 | 497 | self.assertEqual(mirrors['MIRROR'], | ||
3071 | 498 | pmir) | ||
3072 | 499 | self.assertEqual(mirrors['PRIMARY'], | ||
3073 | 500 | pmir) | ||
3074 | 501 | self.assertEqual(mirrors['SECURITY'], | ||
3075 | 502 | smir) | ||
3076 | 503 | |||
3077 | 504 | def test_mirror_default(self): | ||
3078 | 505 | """test_mirror_default - Test without defining a mirror""" | ||
3079 | 506 | default_mirrors = apt_config.get_default_mirrors() | ||
3080 | 507 | pmir = default_mirrors["PRIMARY"] | ||
3081 | 508 | smir = default_mirrors["SECURITY"] | ||
3082 | 509 | mirrors = apt_config.find_apt_mirror_info({}) | ||
3083 | 510 | |||
3084 | 511 | self.assertEqual(mirrors['MIRROR'], | ||
3085 | 512 | pmir) | ||
3086 | 513 | self.assertEqual(mirrors['PRIMARY'], | ||
3087 | 514 | pmir) | ||
3088 | 515 | self.assertEqual(mirrors['SECURITY'], | ||
3089 | 516 | smir) | ||
3090 | 517 | |||
3091 | 518 | def test_mirror_arches(self): | ||
3092 | 519 | """test_mirror_arches - Test arches selection of mirror""" | ||
3093 | 520 | pmir = "http://us.archive.ubuntu.com/ubuntu/" | ||
3094 | 521 | smir = "http://security.ubuntu.com/ubuntu/" | ||
3095 | 522 | cfg = {"primary": [{'arches': ["default"], | ||
3096 | 523 | "uri": "notthis"}, | ||
3097 | 524 | {'arches': [util.get_architecture()], | ||
3098 | 525 | "uri": pmir}], | ||
3099 | 526 | "security": [{'arches': [util.get_architecture()], | ||
3100 | 527 | "uri": smir}, | ||
3101 | 528 | {'arches': ["default"], | ||
3102 | 529 | "uri": "nothat"}]} | ||
3103 | 530 | |||
3104 | 531 | mirrors = apt_config.find_apt_mirror_info(cfg) | ||
3105 | 532 | |||
3106 | 533 | self.assertEqual(mirrors['MIRROR'], | ||
3107 | 534 | pmir) | ||
3108 | 535 | self.assertEqual(mirrors['PRIMARY'], | ||
3109 | 536 | pmir) | ||
3110 | 537 | self.assertEqual(mirrors['SECURITY'], | ||
3111 | 538 | smir) | ||
3112 | 539 | |||
3113 | 540 | def test_mirror_arches_default(self): | ||
3114 | 541 | """test_mirror_arches - Test falling back to default arch""" | ||
3115 | 542 | pmir = "http://us.archive.ubuntu.com/ubuntu/" | ||
3116 | 543 | smir = "http://security.ubuntu.com/ubuntu/" | ||
3117 | 544 | cfg = {"primary": [{'arches': ["default"], | ||
3118 | 545 | "uri": pmir}, | ||
3119 | 546 | {'arches': ["thisarchdoesntexist"], | ||
3120 | 547 | "uri": "notthis"}], | ||
3121 | 548 | "security": [{'arches': ["thisarchdoesntexist"], | ||
3122 | 549 | "uri": "nothat"}, | ||
3123 | 550 | {'arches': ["default"], | ||
3124 | 551 | "uri": smir}]} | ||
3125 | 552 | |||
3126 | 553 | mirrors = apt_config.find_apt_mirror_info(cfg) | ||
3127 | 554 | |||
3128 | 555 | self.assertEqual(mirrors['MIRROR'], | ||
3129 | 556 | pmir) | ||
3130 | 557 | self.assertEqual(mirrors['PRIMARY'], | ||
3131 | 558 | pmir) | ||
3132 | 559 | self.assertEqual(mirrors['SECURITY'], | ||
3133 | 560 | smir) | ||
3134 | 561 | |||
3135 | 562 | def test_mirror_arches_sysdefault(self): | ||
3136 | 563 | """test_mirror_arches - Test arches falling back to sys default""" | ||
3137 | 564 | default_mirrors = apt_config.get_default_mirrors() | ||
3138 | 565 | pmir = default_mirrors["PRIMARY"] | ||
3139 | 566 | smir = default_mirrors["SECURITY"] | ||
3140 | 567 | cfg = {"primary": [{'arches': ["thisarchdoesntexist_64"], | ||
3141 | 568 | "uri": "notthis"}, | ||
3142 | 569 | {'arches': ["thisarchdoesntexist"], | ||
3143 | 570 | "uri": "notthiseither"}], | ||
3144 | 571 | "security": [{'arches': ["thisarchdoesntexist"], | ||
3145 | 572 | "uri": "nothat"}, | ||
3146 | 573 | {'arches': ["thisarchdoesntexist_64"], | ||
3147 | 574 | "uri": "nothateither"}]} | ||
3148 | 575 | |||
3149 | 576 | mirrors = apt_config.find_apt_mirror_info(cfg) | ||
3150 | 577 | |||
3151 | 578 | self.assertEqual(mirrors['MIRROR'], | ||
3152 | 579 | pmir) | ||
3153 | 580 | self.assertEqual(mirrors['PRIMARY'], | ||
3154 | 581 | pmir) | ||
3155 | 582 | self.assertEqual(mirrors['SECURITY'], | ||
3156 | 583 | smir) | ||
3157 | 584 | |||
3158 | 585 | def test_mirror_search(self): | ||
3159 | 586 | """test_mirror_search - Test searching mirrors in a list | ||
3160 | 587 | mock checks to avoid relying on network connectivity""" | ||
3161 | 588 | pmir = "http://us.archive.ubuntu.com/ubuntu/" | ||
3162 | 589 | smir = "http://security.ubuntu.com/ubuntu/" | ||
3163 | 590 | cfg = {"primary": [{'arches': ["default"], | ||
3164 | 591 | "search": ["pfailme", pmir]}], | ||
3165 | 592 | "security": [{'arches': ["default"], | ||
3166 | 593 | "search": ["sfailme", smir]}]} | ||
3167 | 594 | |||
3168 | 595 | with mock.patch.object(apt_config, 'search_for_mirror', | ||
3169 | 596 | side_effect=[pmir, smir]) as mocksearch: | ||
3170 | 597 | mirrors = apt_config.find_apt_mirror_info(cfg) | ||
3171 | 598 | |||
3172 | 599 | calls = [call(["pfailme", pmir]), | ||
3173 | 600 | call(["sfailme", smir])] | ||
3174 | 601 | mocksearch.assert_has_calls(calls) | ||
3175 | 602 | |||
3176 | 603 | self.assertEqual(mirrors['MIRROR'], | ||
3177 | 604 | pmir) | ||
3178 | 605 | self.assertEqual(mirrors['PRIMARY'], | ||
3179 | 606 | pmir) | ||
3180 | 607 | self.assertEqual(mirrors['SECURITY'], | ||
3181 | 608 | smir) | ||
3182 | 609 | |||
3183 | 610 | def test_mirror_search_dns(self): | ||
3184 | 611 | """test_mirror_search_dns - Test searching dns patterns""" | ||
3185 | 612 | pmir = "phit" | ||
3186 | 613 | smir = "shit" | ||
3187 | 614 | cfg = {"primary": [{'arches': ["default"], | ||
3188 | 615 | "search_dns": True}], | ||
3189 | 616 | "security": [{'arches': ["default"], | ||
3190 | 617 | "search_dns": True}]} | ||
3191 | 618 | |||
3192 | 619 | with mock.patch.object(apt_config, 'get_mirror', | ||
3193 | 620 | return_value="http://mocked/foo") as mockgm: | ||
3194 | 621 | mirrors = apt_config.find_apt_mirror_info(cfg) | ||
3195 | 622 | calls = [call(cfg, 'primary', util.get_architecture()), | ||
3196 | 623 | call(cfg, 'security', util.get_architecture())] | ||
3197 | 624 | mockgm.assert_has_calls(calls) | ||
3198 | 625 | |||
3199 | 626 | with mock.patch.object(apt_config, 'search_for_mirror_dns', | ||
3200 | 627 | return_value="http://mocked/foo") as mocksdns: | ||
3201 | 628 | mirrors = apt_config.find_apt_mirror_info(cfg) | ||
3202 | 629 | calls = [call(True, 'mirror'), | ||
3203 | 630 | call(True, 'security-mirror')] | ||
3204 | 631 | mocksdns.assert_has_calls(calls) | ||
3205 | 632 | |||
3206 | 633 | # first return is for the non-dns call before | ||
3207 | 634 | with mock.patch.object(apt_config, 'search_for_mirror', | ||
3208 | 635 | side_effect=[None, pmir, None, smir]) as mockse: | ||
3209 | 636 | with mock.patch.object(util, 'subp', | ||
3210 | 637 | return_value=('host.sub.com', '')) as mocks: | ||
3211 | 638 | mirrors = apt_config.find_apt_mirror_info(cfg) | ||
3212 | 639 | |||
3213 | 640 | calls = [call(None), | ||
3214 | 641 | call(['http://ubuntu-mirror.sub.com/ubuntu', | ||
3215 | 642 | 'http://ubuntu-mirror.localdomain/ubuntu', | ||
3216 | 643 | 'http://ubuntu-mirror/ubuntu']), | ||
3217 | 644 | call(None), | ||
3218 | 645 | call(['http://ubuntu-security-mirror.sub.com/ubuntu', | ||
3219 | 646 | 'http://ubuntu-security-mirror.localdomain/ubuntu', | ||
3220 | 647 | 'http://ubuntu-security-mirror/ubuntu'])] | ||
3221 | 648 | mockse.assert_has_calls(calls) | ||
3222 | 649 | mocks.assert_called_with(['hostname', '--fqdn'], capture=True, rcs=[0]) | ||
3223 | 650 | |||
3224 | 651 | self.assertEqual(mirrors['MIRROR'], | ||
3225 | 652 | pmir) | ||
3226 | 653 | self.assertEqual(mirrors['PRIMARY'], | ||
3227 | 654 | pmir) | ||
3228 | 655 | self.assertEqual(mirrors['SECURITY'], | ||
3229 | 656 | smir) | ||
3230 | 657 | |||
3231 | 658 | def test_mirror_search_many3(self): | ||
3232 | 659 | """test_mirror_search_many3 - Test all three mirrors specs at once""" | ||
3233 | 660 | pmir = "http://us.archive.ubuntu.com/ubuntu/" | ||
3234 | 661 | smir = "http://security.ubuntu.com/ubuntu/" | ||
3235 | 662 | cfg = {"primary": [{'arches': ["default"], | ||
3236 | 663 | "uri": pmir, | ||
3237 | 664 | "search_dns": True, | ||
3238 | 665 | "search": ["pfailme", "foo"]}], | ||
3239 | 666 | "security": [{'arches': ["default"], | ||
3240 | 667 | "uri": smir, | ||
3241 | 668 | "search_dns": True, | ||
3242 | 669 | "search": ["sfailme", "bar"]}]} | ||
3243 | 670 | |||
3244 | 671 | # should be called once per type, despite three configs each | ||
3245 | 672 | with mock.patch.object(apt_config, 'get_mirror', | ||
3246 | 673 | return_value="http://mocked/foo") as mockgm: | ||
3247 | 674 | mirrors = apt_config.find_apt_mirror_info(cfg) | ||
3248 | 675 | calls = [call(cfg, 'primary', util.get_architecture()), | ||
3249 | 676 | call(cfg, 'security', util.get_architecture())] | ||
3250 | 677 | mockgm.assert_has_calls(calls) | ||
3251 | 678 | |||
3252 | 679 | # should not be called, since primary is specified | ||
3253 | 680 | with mock.patch.object(apt_config, 'search_for_mirror_dns') as mockdns: | ||
3254 | 681 | mirrors = apt_config.find_apt_mirror_info(cfg) | ||
3255 | 682 | mockdns.assert_not_called() | ||
3256 | 683 | |||
3257 | 684 | # should not be called, since primary is specified | ||
3258 | 685 | with mock.patch.object(apt_config, 'search_for_mirror') as mockse: | ||
3259 | 686 | mirrors = apt_config.find_apt_mirror_info(cfg) | ||
3260 | 687 | mockse.assert_not_called() | ||
3261 | 688 | |||
3262 | 689 | self.assertEqual(mirrors['MIRROR'], | ||
3263 | 690 | pmir) | ||
3264 | 691 | self.assertEqual(mirrors['PRIMARY'], | ||
3265 | 692 | pmir) | ||
3266 | 693 | self.assertEqual(mirrors['SECURITY'], | ||
3267 | 694 | smir) | ||
3268 | 695 | |||
3269 | 696 | def test_mirror_search_many2(self): | ||
3270 | 697 | """test_mirror_search_many2 - Test the two search specs at once""" | ||
3271 | 698 | pmir = "http://us.archive.ubuntu.com/ubuntu/" | ||
3272 | 699 | smir = "http://security.ubuntu.com/ubuntu/" | ||
3273 | 700 | cfg = {"primary": [{'arches': ["default"], | ||
3274 | 701 | "search_dns": True, | ||
3275 | 702 | "search": ["pfailme", pmir]}], | ||
3276 | 703 | "security": [{'arches': ["default"], | ||
3277 | 704 | "search_dns": True, | ||
3278 | 705 | "search": ["sfailme", smir]}]} | ||
3279 | 706 | |||
3280 | 707 | # should be called once per type, despite three configs each | ||
3281 | 708 | with mock.patch.object(apt_config, 'get_mirror', | ||
3282 | 709 | return_value="http://mocked/foo") as mockgm: | ||
3283 | 710 | mirrors = apt_config.find_apt_mirror_info(cfg) | ||
3284 | 711 | calls = [call(cfg, 'primary', util.get_architecture()), | ||
3285 | 712 | call(cfg, 'security', util.get_architecture())] | ||
3286 | 713 | mockgm.assert_has_calls(calls) | ||
3287 | 714 | |||
3288 | 715 | # this should be the winner by priority, despite config order | ||
3289 | 716 | with mock.patch.object(apt_config, 'search_for_mirror', | ||
3290 | 717 | side_effect=[pmir, smir]) as mocksearch: | ||
3291 | 718 | mirrors = apt_config.find_apt_mirror_info(cfg) | ||
3292 | 719 | calls = [call(["pfailme", pmir]), | ||
3293 | 720 | call(["sfailme", smir])] | ||
3294 | 721 | mocksearch.assert_has_calls(calls) | ||
3295 | 722 | |||
3296 | 723 | self.assertEqual(mirrors['MIRROR'], | ||
3297 | 724 | pmir) | ||
3298 | 725 | self.assertEqual(mirrors['PRIMARY'], | ||
3299 | 726 | pmir) | ||
3300 | 727 | self.assertEqual(mirrors['SECURITY'], | ||
3301 | 728 | smir) | ||
3302 | 729 | |||
3303 | 730 | def test_url_resolvable(self): | ||
3304 | 731 | """test_url_resolvable - Test resolving urls""" | ||
3305 | 732 | |||
3306 | 733 | with mock.patch.object(util, 'is_resolvable') as mockresolve: | ||
3307 | 734 | util.is_resolvable_url("http://1.2.3.4/ubuntu") | ||
3308 | 735 | mockresolve.assert_called_with("1.2.3.4") | ||
3309 | 736 | |||
3310 | 737 | with mock.patch.object(util, 'is_resolvable') as mockresolve: | ||
3311 | 738 | util.is_resolvable_url("http://us.archive.ubuntu.com/ubuntu") | ||
3312 | 739 | mockresolve.assert_called_with("us.archive.ubuntu.com") | ||
3313 | 740 | |||
3314 | 741 | bad = [(None, None, None, "badname", ["10.3.2.1"])] | ||
3315 | 742 | good = [(None, None, None, "goodname", ["10.2.3.4"])] | ||
3316 | 743 | with mock.patch.object(socket, 'getaddrinfo', | ||
3317 | 744 | side_effect=[bad, bad, good, | ||
3318 | 745 | good]) as mocksock: | ||
3319 | 746 | ret = util.is_resolvable_url("http://us.archive.ubuntu.com/ubuntu") | ||
3320 | 747 | ret2 = util.is_resolvable_url("http://1.2.3.4/ubuntu") | ||
3321 | 748 | calls = [call('does-not-exist.example.com.', None, 0, 0, 1, 2), | ||
3322 | 749 | call('example.invalid.', None, 0, 0, 1, 2), | ||
3323 | 750 | call('us.archive.ubuntu.com', None), | ||
3324 | 751 | call('1.2.3.4', None)] | ||
3325 | 752 | mocksock.assert_has_calls(calls) | ||
3326 | 753 | self.assertTrue(ret) | ||
3327 | 754 | self.assertTrue(ret2) | ||
3328 | 755 | |||
3329 | 756 | # side effect need only bad ret after initial call | ||
3330 | 757 | with mock.patch.object(socket, 'getaddrinfo', | ||
3331 | 758 | side_effect=[bad]) as mocksock: | ||
3332 | 759 | ret3 = util.is_resolvable_url("http://failme.com/ubuntu") | ||
3333 | 760 | calls = [call('failme.com', None)] | ||
3334 | 761 | mocksock.assert_has_calls(calls) | ||
3335 | 762 | self.assertFalse(ret3) | ||
3336 | 763 | |||
3337 | 764 | def test_disable_suites(self): | ||
3338 | 765 | """test_disable_suites - disable_suites with many configurations""" | ||
3339 | 766 | release = "xenial" | ||
3340 | 767 | orig = """deb http://ubuntu.com//ubuntu xenial main | ||
3341 | 768 | deb http://ubuntu.com//ubuntu xenial-updates main | ||
3342 | 769 | deb http://ubuntu.com//ubuntu xenial-security main | ||
3343 | 770 | deb-src http://ubuntu.com//ubuntu universe multiverse | ||
3344 | 771 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" | ||
3345 | 772 | |||
3346 | 773 | # disable nothing | ||
3347 | 774 | cfg = {"disable_suites": []} | ||
3348 | 775 | expect = """deb http://ubuntu.com//ubuntu xenial main | ||
3349 | 776 | deb http://ubuntu.com//ubuntu xenial-updates main | ||
3350 | 777 | deb http://ubuntu.com//ubuntu xenial-security main | ||
3351 | 778 | deb-src http://ubuntu.com//ubuntu universe multiverse | ||
3352 | 779 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" | ||
3353 | 780 | result = apt_config.disable_suites(cfg, orig, release) | ||
3354 | 781 | self.assertEqual(expect, result) | ||
3355 | 782 | |||
3356 | 783 | # single disable release suite | ||
3357 | 784 | cfg = {"disable_suites": ["$RELEASE"]} | ||
3358 | 785 | expect = """\ | ||
3359 | 786 | # suite disabled by curtin: deb http://ubuntu.com//ubuntu xenial main | ||
3360 | 787 | deb http://ubuntu.com//ubuntu xenial-updates main | ||
3361 | 788 | deb http://ubuntu.com//ubuntu xenial-security main | ||
3362 | 789 | deb-src http://ubuntu.com//ubuntu universe multiverse | ||
3363 | 790 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" | ||
3364 | 791 | result = apt_config.disable_suites(cfg, orig, release) | ||
3365 | 792 | self.assertEqual(expect, result) | ||
3366 | 793 | |||
3367 | 794 | # single disable other suite | ||
3368 | 795 | cfg = {"disable_suites": ["$RELEASE-updates"]} | ||
3369 | 796 | expect = """deb http://ubuntu.com//ubuntu xenial main | ||
3370 | 797 | # suite disabled by curtin: deb http://ubuntu.com//ubuntu xenial-updates main | ||
3371 | 798 | deb http://ubuntu.com//ubuntu xenial-security main | ||
3372 | 799 | deb-src http://ubuntu.com//ubuntu universe multiverse | ||
3373 | 800 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" | ||
3374 | 801 | result = apt_config.disable_suites(cfg, orig, release) | ||
3375 | 802 | self.assertEqual(expect, result) | ||
3376 | 803 | |||
3377 | 804 | # multi disable | ||
3378 | 805 | cfg = {"disable_suites": ["$RELEASE-updates", "$RELEASE-security"]} | ||
3379 | 806 | expect = """deb http://ubuntu.com//ubuntu xenial main | ||
3380 | 807 | # suite disabled by curtin: deb http://ubuntu.com//ubuntu xenial-updates main | ||
3381 | 808 | # suite disabled by curtin: deb http://ubuntu.com//ubuntu xenial-security main | ||
3382 | 809 | deb-src http://ubuntu.com//ubuntu universe multiverse | ||
3383 | 810 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" | ||
3384 | 811 | result = apt_config.disable_suites(cfg, orig, release) | ||
3385 | 812 | self.assertEqual(expect, result) | ||
3386 | 813 | |||
3387 | 814 | # multi line disable (same suite multiple times in input) | ||
3388 | 815 | cfg = {"disable_suites": ["$RELEASE-updates", "$RELEASE-security"]} | ||
3389 | 816 | orig = """deb http://ubuntu.com//ubuntu xenial main | ||
3390 | 817 | deb http://ubuntu.com//ubuntu xenial-updates main | ||
3391 | 818 | deb http://ubuntu.com//ubuntu xenial-security main | ||
3392 | 819 | deb-src http://ubuntu.com//ubuntu universe multiverse | ||
3393 | 820 | deb http://UBUNTU.com//ubuntu xenial-updates main | ||
3394 | 821 | deb http://UBUNTU.COM//ubuntu xenial-updates main | ||
3395 | 822 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" | ||
3396 | 823 | expect = """deb http://ubuntu.com//ubuntu xenial main | ||
3397 | 824 | # suite disabled by curtin: deb http://ubuntu.com//ubuntu xenial-updates main | ||
3398 | 825 | # suite disabled by curtin: deb http://ubuntu.com//ubuntu xenial-security main | ||
3399 | 826 | deb-src http://ubuntu.com//ubuntu universe multiverse | ||
3400 | 827 | # suite disabled by curtin: deb http://UBUNTU.com//ubuntu xenial-updates main | ||
3401 | 828 | # suite disabled by curtin: deb http://UBUNTU.COM//ubuntu xenial-updates main | ||
3402 | 829 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" | ||
3403 | 830 | result = apt_config.disable_suites(cfg, orig, release) | ||
3404 | 831 | self.assertEqual(expect, result) | ||
3405 | 832 | |||
3406 | 833 | # comment in input | ||
3407 | 834 | cfg = {"disable_suites": ["$RELEASE-updates", "$RELEASE-security"]} | ||
3408 | 835 | orig = """deb http://ubuntu.com//ubuntu xenial main | ||
3409 | 836 | deb http://ubuntu.com//ubuntu xenial-updates main | ||
3410 | 837 | deb http://ubuntu.com//ubuntu xenial-security main | ||
3411 | 838 | deb-src http://ubuntu.com//ubuntu universe multiverse | ||
3412 | 839 | #foo | ||
3413 | 840 | #deb http://UBUNTU.com//ubuntu xenial-updates main | ||
3414 | 841 | deb http://UBUNTU.COM//ubuntu xenial-updates main | ||
3415 | 842 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" | ||
3416 | 843 | expect = """deb http://ubuntu.com//ubuntu xenial main | ||
3417 | 844 | # suite disabled by curtin: deb http://ubuntu.com//ubuntu xenial-updates main | ||
3418 | 845 | # suite disabled by curtin: deb http://ubuntu.com//ubuntu xenial-security main | ||
3419 | 846 | deb-src http://ubuntu.com//ubuntu universe multiverse | ||
3420 | 847 | #foo | ||
3421 | 848 | #deb http://UBUNTU.com//ubuntu xenial-updates main | ||
3422 | 849 | # suite disabled by curtin: deb http://UBUNTU.COM//ubuntu xenial-updates main | ||
3423 | 850 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" | ||
3424 | 851 | result = apt_config.disable_suites(cfg, orig, release) | ||
3425 | 852 | self.assertEqual(expect, result) | ||
3426 | 853 | |||
3427 | 854 | # single disable custom suite | ||
3428 | 855 | cfg = {"disable_suites": ["foobar"]} | ||
3429 | 856 | orig = """deb http://ubuntu.com//ubuntu xenial main | ||
3430 | 857 | deb http://ubuntu.com//ubuntu xenial-updates main | ||
3431 | 858 | deb http://ubuntu.com//ubuntu xenial-security main | ||
3432 | 859 | deb http://ubuntu.com/ubuntu/ foobar main""" | ||
3433 | 860 | expect = """deb http://ubuntu.com//ubuntu xenial main | ||
3434 | 861 | deb http://ubuntu.com//ubuntu xenial-updates main | ||
3435 | 862 | deb http://ubuntu.com//ubuntu xenial-security main | ||
3436 | 863 | # suite disabled by curtin: deb http://ubuntu.com/ubuntu/ foobar main""" | ||
3437 | 864 | result = apt_config.disable_suites(cfg, orig, release) | ||
3438 | 865 | self.assertEqual(expect, result) | ||
3439 | 866 | |||
3440 | 867 | # single disable non existing suite | ||
3441 | 868 | cfg = {"disable_suites": ["foobar"]} | ||
3442 | 869 | orig = """deb http://ubuntu.com//ubuntu xenial main | ||
3443 | 870 | deb http://ubuntu.com//ubuntu xenial-updates main | ||
3444 | 871 | deb http://ubuntu.com//ubuntu xenial-security main | ||
3445 | 872 | deb http://ubuntu.com/ubuntu/ notfoobar main""" | ||
3446 | 873 | expect = """deb http://ubuntu.com//ubuntu xenial main | ||
3447 | 874 | deb http://ubuntu.com//ubuntu xenial-updates main | ||
3448 | 875 | deb http://ubuntu.com//ubuntu xenial-security main | ||
3449 | 876 | deb http://ubuntu.com/ubuntu/ notfoobar main""" | ||
3450 | 877 | result = apt_config.disable_suites(cfg, orig, release) | ||
3451 | 878 | self.assertEqual(expect, result) | ||
3452 | 879 | |||
3453 | 880 | # single disable suite with option | ||
3454 | 881 | cfg = {"disable_suites": ["$RELEASE-updates"]} | ||
3455 | 882 | orig = """deb http://ubuntu.com//ubuntu xenial main | ||
3456 | 883 | deb [a=b] http://ubu.com//ubu xenial-updates main | ||
3457 | 884 | deb http://ubuntu.com//ubuntu xenial-security main | ||
3458 | 885 | deb-src http://ubuntu.com//ubuntu universe multiverse | ||
3459 | 886 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" | ||
3460 | 887 | expect = """deb http://ubuntu.com//ubuntu xenial main | ||
3461 | 888 | # suite disabled by curtin: deb [a=b] http://ubu.com//ubu xenial-updates main | ||
3462 | 889 | deb http://ubuntu.com//ubuntu xenial-security main | ||
3463 | 890 | deb-src http://ubuntu.com//ubuntu universe multiverse | ||
3464 | 891 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" | ||
3465 | 892 | result = apt_config.disable_suites(cfg, orig, release) | ||
3466 | 893 | self.assertEqual(expect, result) | ||
3467 | 894 | |||
3468 | 895 | # single disable suite with more options and auto $RELEASE expansion | ||
3469 | 896 | cfg = {"disable_suites": ["updates"]} | ||
3470 | 897 | orig = """deb http://ubuntu.com//ubuntu xenial main | ||
3471 | 898 | deb [a=b c=d] http://ubu.com//ubu xenial-updates main | ||
3472 | 899 | deb http://ubuntu.com//ubuntu xenial-security main | ||
3473 | 900 | deb-src http://ubuntu.com//ubuntu universe multiverse | ||
3474 | 901 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" | ||
3475 | 902 | expect = """deb http://ubuntu.com//ubuntu xenial main | ||
3476 | 903 | # suite disabled by curtin: deb [a=b c=d] \ | ||
3477 | 904 | http://ubu.com//ubu xenial-updates main | ||
3478 | 905 | deb http://ubuntu.com//ubuntu xenial-security main | ||
3479 | 906 | deb-src http://ubuntu.com//ubuntu universe multiverse | ||
3480 | 907 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" | ||
3481 | 908 | result = apt_config.disable_suites(cfg, orig, release) | ||
3482 | 909 | self.assertEqual(expect, result) | ||
3483 | 910 | |||
3484 | 911 | # single disable suite while options at others | ||
3485 | 912 | cfg = {"disable_suites": ["$RELEASE-security"]} | ||
3486 | 913 | orig = """deb http://ubuntu.com//ubuntu xenial main | ||
3487 | 914 | deb [arch=foo] http://ubuntu.com//ubuntu xenial-updates main | ||
3488 | 915 | deb http://ubuntu.com//ubuntu xenial-security main | ||
3489 | 916 | deb-src http://ubuntu.com//ubuntu universe multiverse | ||
3490 | 917 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" | ||
3491 | 918 | expect = """deb http://ubuntu.com//ubuntu xenial main | ||
3492 | 919 | deb [arch=foo] http://ubuntu.com//ubuntu xenial-updates main | ||
3493 | 920 | # suite disabled by curtin: deb http://ubuntu.com//ubuntu xenial-security main | ||
3494 | 921 | deb-src http://ubuntu.com//ubuntu universe multiverse | ||
3495 | 922 | deb http://ubuntu.com/ubuntu/ xenial-proposed main""" | ||
3496 | 923 | result = apt_config.disable_suites(cfg, orig, release) | ||
3497 | 924 | self.assertEqual(expect, result) | ||
3498 | 925 | |||
3499 | 926 | # | ||
3500 | 927 | # vi: ts=4 expandtab | ||
3501 | 0 | 928 | ||
3502 | === modified file 'tests/vmtests/__init__.py' | |||
3503 | --- tests/vmtests/__init__.py 2016-07-19 19:25:08 +0000 | |||
3504 | +++ tests/vmtests/__init__.py 2016-07-26 19:53:43 +0000 | |||
3505 | @@ -355,6 +355,7 @@ | |||
3506 | 355 | extra_kern_args = None | 355 | extra_kern_args = None |
3507 | 356 | fstab_expected = {} | 356 | fstab_expected = {} |
3508 | 357 | image_store_class = ImageStore | 357 | image_store_class = ImageStore |
3509 | 358 | boot_cloudconf = None | ||
3510 | 358 | install_timeout = 3000 | 359 | install_timeout = 3000 |
3511 | 359 | interactive = False | 360 | interactive = False |
3512 | 360 | multipath = False | 361 | multipath = False |
3513 | @@ -363,6 +364,7 @@ | |||
3514 | 363 | recorded_errors = 0 | 364 | recorded_errors = 0 |
3515 | 364 | recorded_failures = 0 | 365 | recorded_failures = 0 |
3516 | 365 | uefi = False | 366 | uefi = False |
3517 | 367 | proxy = None | ||
3518 | 366 | 368 | ||
3519 | 367 | # these get set from base_vm_classes | 369 | # these get set from base_vm_classes |
3520 | 368 | release = None | 370 | release = None |
3521 | @@ -392,7 +394,8 @@ | |||
3522 | 392 | # set up tempdir | 394 | # set up tempdir |
3523 | 393 | cls.td = TempDir( | 395 | cls.td = TempDir( |
3524 | 394 | name=cls.__name__, | 396 | name=cls.__name__, |
3526 | 395 | user_data=generate_user_data(collect_scripts=cls.collect_scripts)) | 397 | user_data=generate_user_data(collect_scripts=cls.collect_scripts, |
3527 | 398 | boot_cloudconf=cls.boot_cloudconf)) | ||
3528 | 396 | logger.info('Using tempdir: %s , Image: %s', cls.td.tmpdir, | 399 | logger.info('Using tempdir: %s , Image: %s', cls.td.tmpdir, |
3529 | 397 | img_verstr) | 400 | img_verstr) |
3530 | 398 | cls.install_log = os.path.join(cls.td.logs, 'install-serial.log') | 401 | cls.install_log = os.path.join(cls.td.logs, 'install-serial.log') |
3531 | @@ -492,11 +495,11 @@ | |||
3532 | 492 | 495 | ||
3533 | 493 | # proxy config | 496 | # proxy config |
3534 | 494 | configs = [cls.conf_file] | 497 | configs = [cls.conf_file] |
3537 | 495 | proxy = get_apt_proxy() | 498 | cls.proxy = get_apt_proxy() |
3538 | 496 | if get_apt_proxy is not None: | 499 | if cls.proxy is not None: |
3539 | 497 | proxy_config = os.path.join(cls.td.install, 'proxy.cfg') | 500 | proxy_config = os.path.join(cls.td.install, 'proxy.cfg') |
3540 | 498 | with open(proxy_config, "w") as fp: | 501 | with open(proxy_config, "w") as fp: |
3542 | 499 | fp.write(json.dumps({'apt_proxy': proxy}) + "\n") | 502 | fp.write(json.dumps({'apt_proxy': cls.proxy}) + "\n") |
3543 | 500 | configs.append(proxy_config) | 503 | configs.append(proxy_config) |
3544 | 501 | 504 | ||
3545 | 502 | uefi_flags = [] | 505 | uefi_flags = [] |
3546 | @@ -731,8 +734,14 @@ | |||
3547 | 731 | # Misc functions that are useful for many tests | 734 | # Misc functions that are useful for many tests |
3548 | 732 | def output_files_exist(self, files): | 735 | def output_files_exist(self, files): |
3549 | 733 | for f in files: | 736 | for f in files: |
3550 | 737 | logger.debug('checking file %s', f) | ||
3551 | 734 | self.assertTrue(os.path.exists(os.path.join(self.td.collect, f))) | 738 | self.assertTrue(os.path.exists(os.path.join(self.td.collect, f))) |
3552 | 735 | 739 | ||
3553 | 740 | def output_files_dont_exist(self, files): | ||
3554 | 741 | for f in files: | ||
3555 | 742 | logger.debug('checking file %s', f) | ||
3556 | 743 | self.assertFalse(os.path.exists(os.path.join(self.td.collect, f))) | ||
3557 | 744 | |||
3558 | 736 | def check_file_strippedline(self, filename, search): | 745 | def check_file_strippedline(self, filename, search): |
3559 | 737 | with open(os.path.join(self.td.collect, filename), "r") as fp: | 746 | with open(os.path.join(self.td.collect, filename), "r") as fp: |
3560 | 738 | data = list(i.strip() for i in fp.readlines()) | 747 | data = list(i.strip() for i in fp.readlines()) |
3561 | @@ -961,7 +970,8 @@ | |||
3562 | 961 | return None | 970 | return None |
3563 | 962 | 971 | ||
3564 | 963 | 972 | ||
3566 | 964 | def generate_user_data(collect_scripts=None, apt_proxy=None): | 973 | def generate_user_data(collect_scripts=None, apt_proxy=None, |
3567 | 974 | boot_cloudconf=None): | ||
3568 | 965 | # this returns the user data for the *booted* system | 975 | # this returns the user data for the *booted* system |
3569 | 966 | # its a cloud-config-archive type, which is | 976 | # its a cloud-config-archive type, which is |
3570 | 967 | # just a list of parts. the 'x-shellscript' parts | 977 | # just a list of parts. the 'x-shellscript' parts |
3571 | @@ -986,6 +996,10 @@ | |||
3572 | 986 | 'content': yaml.dump(base_cloudconfig, indent=1)}, | 996 | 'content': yaml.dump(base_cloudconfig, indent=1)}, |
3573 | 987 | {'type': 'text/cloud-config', 'content': ssh_keys}] | 997 | {'type': 'text/cloud-config', 'content': ssh_keys}] |
3574 | 988 | 998 | ||
3575 | 999 | if boot_cloudconf is not None: | ||
3576 | 1000 | parts.append({'type': 'text/cloud-config', 'content': | ||
3577 | 1001 | yaml.dump(boot_cloudconf, indent=1)}) | ||
3578 | 1002 | |||
3579 | 989 | output_dir = '/mnt/output' | 1003 | output_dir = '/mnt/output' |
3580 | 990 | output_dir_macro = 'OUTPUT_COLLECT_D' | 1004 | output_dir_macro = 'OUTPUT_COLLECT_D' |
3581 | 991 | output_device = '/dev/disk/by-id/virtio-%s' % OUTPUT_DISK_NAME | 1005 | output_device = '/dev/disk/by-id/virtio-%s' % OUTPUT_DISK_NAME |
3582 | 992 | 1006 | ||
3583 | === added file 'tests/vmtests/test_apt_config_cmd.py' | |||
3584 | --- tests/vmtests/test_apt_config_cmd.py 1970-01-01 00:00:00 +0000 | |||
3585 | +++ tests/vmtests/test_apt_config_cmd.py 2016-07-26 19:53:43 +0000 | |||
3586 | @@ -0,0 +1,55 @@ | |||
3587 | 1 | """ test_apt_config_cmd | ||
3588 | 2 | Collection of tests for the apt configuration features when called via the | ||
3589 | 3 | apt-config standalone command. | ||
3590 | 4 | """ | ||
3591 | 5 | import textwrap | ||
3592 | 6 | |||
3593 | 7 | from . import VMBaseClass | ||
3594 | 8 | from .releases import base_vm_classes as relbase | ||
3595 | 9 | |||
3596 | 10 | |||
3597 | 11 | class TestAptConfigCMD(VMBaseClass): | ||
3598 | 12 | """TestAptConfigCMD - test standalone command""" | ||
3599 | 13 | conf_file = "examples/tests/apt_config_command.yaml" | ||
3600 | 14 | interactive = False | ||
3601 | 15 | extra_disks = [] | ||
3602 | 16 | fstab_expected = {} | ||
3603 | 17 | disk_to_check = [] | ||
3604 | 18 | collect_scripts = [textwrap.dedent(""" | ||
3605 | 19 | cd OUTPUT_COLLECT_D | ||
3606 | 20 | cat /etc/fstab > fstab | ||
3607 | 21 | ls /dev/disk/by-dname > ls_dname | ||
3608 | 22 | find /etc/network/interfaces.d > find_interfacesd | ||
3609 | 23 | cp /etc/apt/sources.list.d/curtin-dev-ubuntu-test-archive-*.list . | ||
3610 | 24 | cp /etc/cloud/cloud.cfg.d/curtin-preserve-sources.cfg . | ||
3611 | 25 | apt-cache policy | grep proposed > proposed-enabled | ||
3612 | 26 | """)] | ||
3613 | 27 | |||
3614 | 28 | def test_cmd_proposed_enabled(self): | ||
3615 | 29 | """check if proposed was enabled""" | ||
3616 | 30 | self.output_files_exist(["proposed-enabled"]) | ||
3617 | 31 | self.check_file_regex("proposed-enabled", | ||
3618 | 32 | r"500.*%s-proposed" % self.release) | ||
3619 | 33 | |||
3620 | 34 | def test_cmd_ppa_enabled(self): | ||
3621 | 35 | """check if specified curtin-dev ppa was enabled""" | ||
3622 | 36 | self.output_files_exist( | ||
3623 | 37 | ["curtin-dev-ubuntu-test-archive-%s.list" % self.release]) | ||
3624 | 38 | self.check_file_regex("curtin-dev-ubuntu-test-archive-%s.list" % | ||
3625 | 39 | self.release, | ||
3626 | 40 | (r"http://ppa.launchpad.net/" | ||
3627 | 41 | r"curtin-dev/test-archive/ubuntu" | ||
3628 | 42 | r" %s main" % self.release)) | ||
3629 | 43 | |||
3630 | 44 | def test_cmd_preserve_source(self): | ||
3631 | 45 | """check if cloud-init was prevented from overwriting""" | ||
3632 | 46 | self.output_files_exist(["curtin-preserve-sources.cfg"]) | ||
3633 | 47 | self.check_file_regex("curtin-preserve-sources.cfg", | ||
3634 | 48 | "apt_preserve_sources_list.*true") | ||
3635 | 49 | |||
3636 | 50 | |||
3637 | 51 | class XenialTestAptConfigCMDCMD(relbase.xenial, TestAptConfigCMD): | ||
3638 | 52 | """ XenialTestAptSrcModifyCMD | ||
3639 | 53 | apt feature Test for Xenial using the standalone command | ||
3640 | 54 | """ | ||
3641 | 55 | __test__ = True | ||
3642 | 0 | 56 | ||
3643 | === added file 'tests/vmtests/test_apt_source.py' | |||
3644 | --- tests/vmtests/test_apt_source.py 1970-01-01 00:00:00 +0000 | |||
3645 | +++ tests/vmtests/test_apt_source.py 2016-07-26 19:53:43 +0000 | |||
3646 | @@ -0,0 +1,277 @@ | |||
3647 | 1 | """ test_apt_source | ||
3648 | 2 | Collection of tests for the apt configuration features | ||
3649 | 3 | """ | ||
3650 | 4 | import textwrap | ||
3651 | 5 | |||
3652 | 6 | from . import VMBaseClass | ||
3653 | 7 | from .releases import base_vm_classes as relbase | ||
3654 | 8 | |||
3655 | 9 | from unittest import SkipTest | ||
3656 | 10 | from curtin import util | ||
3657 | 11 | |||
3658 | 12 | |||
3659 | 13 | class TestAptSrcAbs(VMBaseClass): | ||
3660 | 14 | """TestAptSrcAbs - Basic tests for apt features of curtin""" | ||
3661 | 15 | interactive = False | ||
3662 | 16 | extra_disks = [] | ||
3663 | 17 | fstab_expected = {} | ||
3664 | 18 | disk_to_check = [] | ||
3665 | 19 | collect_scripts = [textwrap.dedent(""" | ||
3666 | 20 | cd OUTPUT_COLLECT_D | ||
3667 | 21 | cat /etc/fstab > fstab | ||
3668 | 22 | ls /dev/disk/by-dname > ls_dname | ||
3669 | 23 | find /etc/network/interfaces.d > find_interfacesd | ||
3670 | 24 | apt-key list "F430BBA5" > keyid-F430BBA5 | ||
3671 | 25 | apt-key list "0165013E" > keyppa-0165013E | ||
3672 | 26 | apt-key list "F470A0AC" > keylongid-F470A0AC | ||
3673 | 27 | apt-key list "8280B242" > keyraw-8280B242 | ||
3674 | 28 | ls -laF /etc/apt/sources.list.d/ > sources.list.d | ||
3675 | 29 | cp /etc/apt/sources.list.d/curtin-dev-ppa.list . | ||
3676 | 30 | cp /etc/apt/sources.list.d/my-repo2.list . | ||
3677 | 31 | cp /etc/apt/sources.list.d/my-repo4.list . | ||
3678 | 32 | cp /etc/apt/sources.list.d/curtin-dev-ubuntu-test-archive-*.list . | ||
3679 | 33 | find /etc/apt/sources.list.d/ -maxdepth 1 -name "*ignore*" | wc -l > ic | ||
3680 | 34 | apt-config dump | grep Retries > aptconf | ||
3681 | 35 | cp /etc/apt/sources.list sources.list | ||
3682 | 36 | cp /etc/cloud/cloud.cfg.d/curtin-preserve-sources.cfg . | ||
3683 | 37 | """)] | ||
3684 | 38 | mirror = "http://us.archive.ubuntu.com/ubuntu" | ||
3685 | 39 | secmirror = "http://security.ubuntu.com/ubuntu" | ||
3686 | 40 | |||
3687 | 41 | def test_output_files_exist(self): | ||
3688 | 42 | """test_output_files_exist - Check if all output files exist""" | ||
3689 | 43 | self.output_files_exist( | ||
3690 | 44 | ["fstab", "ic", "keyid-F430BBA5", "keylongid-F470A0AC", | ||
3691 | 45 | "keyraw-8280B242", "keyppa-0165013E", "aptconf", "sources.list", | ||
3692 | 46 | "curtin-dev-ppa.list", "my-repo2.list", "my-repo4.list"]) | ||
3693 | 47 | self.output_files_exist( | ||
3694 | 48 | ["curtin-dev-ubuntu-test-archive-%s.list" % self.release]) | ||
3695 | 49 | |||
3696 | 50 | def test_keys_imported(self): | ||
3697 | 51 | """test_keys_imported - Check if all keys are imported correctly""" | ||
3698 | 52 | self.check_file_regex("keyid-F430BBA5", | ||
3699 | 53 | r"Launchpad PPA for Ubuntu Screen Profile") | ||
3700 | 54 | self.check_file_regex("keylongid-F470A0AC", | ||
3701 | 55 | r"Ryan Harper") | ||
3702 | 56 | self.check_file_regex("keyppa-0165013E", | ||
3703 | 57 | r"Launchpad PPA for curtin developers") | ||
3704 | 58 | self.check_file_regex("keyraw-8280B242", | ||
3705 | 59 | r"Christian Ehrhardt") | ||
3706 | 60 | |||
3707 | 61 | def test_preserve_source(self): | ||
3708 | 62 | """test_preserve_source - no clobbering sources.list by cloud-init""" | ||
3709 | 63 | self.output_files_exist(["curtin-preserve-sources.cfg"]) | ||
3710 | 64 | self.check_file_regex("curtin-preserve-sources.cfg", | ||
3711 | 65 | "apt_preserve_sources_list.*true") | ||
3712 | 66 | |||
3713 | 67 | def test_source_files(self): | ||
3714 | 68 | """test_source_files - Check generated .lists for correct content""" | ||
3715 | 69 | # hard coded deb lines | ||
3716 | 70 | self.check_file_strippedline("curtin-dev-ppa.list", | ||
3717 | 71 | ("deb http://ppa.launchpad.net/curtin-dev" | ||
3718 | 72 | "/test-archive/ubuntu xenial main")) | ||
3719 | 73 | self.check_file_strippedline("my-repo4.list", | ||
3720 | 74 | ("deb http://ppa.launchpad.net/curtin-dev" | ||
3721 | 75 | "/test-archive/ubuntu xenial main")) | ||
3722 | 76 | # mirror and release replacement in deb line | ||
3723 | 77 | self.check_file_strippedline("my-repo2.list", "deb %s %s multiverse" % | ||
3724 | 78 | (self.mirror, self.release)) | ||
3725 | 79 | # auto creation by apt-add-repository | ||
3726 | 80 | self.check_file_regex("curtin-dev-ubuntu-test-archive-%s.list" % | ||
3727 | 81 | self.release, | ||
3728 | 82 | (r"http://ppa.launchpad.net/" | ||
3729 | 83 | r"curtin-dev/test-archive/ubuntu" | ||
3730 | 84 | r" %s main" % self.release)) | ||
3731 | 85 | |||
3732 | 86 | def test_ignore_count(self): | ||
3733 | 87 | """test_ignore_count - Check for files that should not be created""" | ||
3734 | 88 | self.check_file_strippedline("ic", "0") | ||
3735 | 89 | |||
3736 | 90 | def test_apt_conf(self): | ||
3737 | 91 | """test_apt_conf - Check if the selected apt conf was set""" | ||
3738 | 92 | self.check_file_strippedline("aptconf", 'Acquire::Retries "3";') | ||
3739 | 93 | |||
3740 | 94 | |||
3741 | 95 | class TestAptSrcCustom(TestAptSrcAbs): | ||
3742 | 96 | """TestAptSrcNormal - tests valid in the custom sources.list case""" | ||
3743 | 97 | conf_file = "examples/tests/apt_source_custom.yaml" | ||
3744 | 98 | |||
3745 | 99 | def test_custom_source_list(self): | ||
3746 | 100 | """test_custom_source_list - Check custom sources with replacement""" | ||
3747 | 101 | # check that all replacements happened | ||
3748 | 102 | self.check_file_strippedline("sources.list", | ||
3749 | 103 | "deb %s %s main restricted" % | ||
3750 | 104 | (self.mirror, self.release)) | ||
3751 | 105 | self.check_file_strippedline("sources.list", | ||
3752 | 106 | "deb-src %s %s main restricted" % | ||
3753 | 107 | (self.mirror, self.release)) | ||
3754 | 108 | self.check_file_strippedline("sources.list", | ||
3755 | 109 | "deb %s %s universe restricted" % | ||
3756 | 110 | (self.mirror, self.release)) | ||
3757 | 111 | self.check_file_strippedline("sources.list", | ||
3758 | 112 | "deb %s %s-security multiverse" % | ||
3759 | 113 | (self.secmirror, self.release)) | ||
3760 | 114 | # check for something that guarantees us to come from our test | ||
3761 | 115 | self.check_file_strippedline("sources.list", | ||
3762 | 116 | "# nice line to check in test") | ||
3763 | 117 | |||
3764 | 118 | |||
3765 | 119 | class TestAptSrcPreserve(TestAptSrcAbs): | ||
3766 | 120 | """TestAptSrcPreserve - tests valid in the preserved sources.list case""" | ||
3767 | 121 | conf_file = "examples/tests/apt_source_preserve.yaml" | ||
3768 | 122 | boot_cloudconf = None | ||
3769 | 123 | |||
3770 | 124 | def test_preserved_source_list(self): | ||
3771 | 125 | """test_preserved_source_list - Check sources to be preserved as-is""" | ||
3772 | 126 | # curtin didn't touch it, so we should find what curtin set as default | ||
3773 | 127 | self.check_file_regex("sources.list", | ||
3774 | 128 | r"this file is written by cloud-init") | ||
3775 | 129 | |||
3776 | 130 | # overwrite inherited check to match situation here | ||
3777 | 131 | def test_preserve_source(self): | ||
3778 | 132 | """test_preserve_source - check apt_preserve_sources_list not set""" | ||
3779 | 133 | self.output_files_dont_exist(["curtin-preserve-sources.cfg"]) | ||
3780 | 134 | |||
3781 | 135 | |||
3782 | 136 | class TestAptSrcModify(TestAptSrcAbs): | ||
3783 | 137 | """TestAptSrcModify - tests modifying sources.list""" | ||
3784 | 138 | conf_file = "examples/tests/apt_source_modify.yaml" | ||
3785 | 139 | |||
3786 | 140 | def test_modified_source_list(self): | ||
3787 | 141 | """test_modified_source_list - Check sources with replacement""" | ||
3788 | 142 | # we set us.archive which is non default, check for that | ||
3789 | 143 | # this will catch if a target ever changes the expected defaults we | ||
3790 | 144 | # have to replace in case there is no custom template | ||
3791 | 145 | self.check_file_regex("sources.list", | ||
3792 | 146 | r"us.archive.ubuntu.com") | ||
3793 | 147 | self.check_file_regex("sources.list", | ||
3794 | 148 | r"security.ubuntu.com") | ||
3795 | 149 | |||
3796 | 150 | |||
3797 | 151 | class TestAptSrcDisablePockets(TestAptSrcAbs): | ||
3798 | 152 | """TestAptSrcDisablePockets - tests disabling a suite in sources.list""" | ||
3799 | 153 | conf_file = "examples/tests/apt_source_modify_disable_suite.yaml" | ||
3800 | 154 | |||
3801 | 155 | def test_disabled_suite(self): | ||
3802 | 156 | """test_disabled_suite - Check if suites were disabled""" | ||
3803 | 157 | # two not disabled | ||
3804 | 158 | self.check_file_regex("sources.list", | ||
3805 | 159 | r"deb.*us.archive.ubuntu.com") | ||
3806 | 160 | self.check_file_regex("sources.list", | ||
3807 | 161 | r"deb.*security.ubuntu.com") | ||
3808 | 162 | # updates disabled | ||
3809 | 163 | self.check_file_regex("sources.list", | ||
3810 | 164 | r"# suite disabled by curtin:.*-updates") | ||
3811 | 165 | |||
3812 | 166 | |||
3813 | 167 | class TestAptSrcModifyArches(TestAptSrcModify): | ||
3814 | 168 | """TestAptSrcModify - tests modifying sources.list with per arch mirror""" | ||
3815 | 169 | # same test, just different yaml to specify the mirrors per arch | ||
3816 | 170 | conf_file = "examples/tests/apt_source_modify_arches.yaml" | ||
3817 | 171 | |||
3818 | 172 | |||
3819 | 173 | class TestAptSrcSearch(TestAptSrcAbs): | ||
3820 | 174 | """TestAptSrcSearch - tests checking a list of mirror options""" | ||
3821 | 175 | conf_file = "examples/tests/apt_source_search.yaml" | ||
3822 | 176 | |||
3823 | 177 | def test_mirror_search(self): | ||
3824 | 178 | """test_mirror_search | ||
3825 | 179 | Check searching through a mirror list | ||
3826 | 180 | This is checked in the test (late) intentionally. | ||
3827 | 181 | No matter if resolution worked or failed it shouldn't fail | ||
3828 | 182 | fatally (python error and trace). | ||
3829 | 183 | We just can't rely on the content to be found in that case | ||
3830 | 184 | so we skip the check then.""" | ||
3831 | 185 | res1 = util.is_resolvable_url("http://does.not.exist/ubuntu") | ||
3832 | 186 | res2 = util.is_resolvable_url("http://does.also.not.exist/ubuntu") | ||
3833 | 187 | res3 = util.is_resolvable_url("http://us.archive.ubuntu.com/ubuntu") | ||
3834 | 188 | res4 = util.is_resolvable_url("http://security.ubuntu.com/ubuntu") | ||
3835 | 189 | if res1 or res2 or not res3 or not res4: | ||
3836 | 190 | raise SkipTest(("Name resolution not as required" | ||
3837 | 191 | "(%s, %s, %s, %s)" % (res1, res2, res3, res4))) | ||
3838 | 192 | |||
3839 | 193 | self.check_file_regex("sources.list", | ||
3840 | 194 | r"us.archive.ubuntu.com") | ||
3841 | 195 | self.check_file_regex("sources.list", | ||
3842 | 196 | r"security.ubuntu.com") | ||
3843 | 197 | |||
3844 | 198 | |||
3845 | 199 | class TestAptSrcSearchDNS(VMBaseClass): | ||
3846 | 200 | """TestAptSrcSearchDNS - tests checking for predefined DNS names""" | ||
3847 | 201 | interactive = False | ||
3848 | 202 | extra_disks = [] | ||
3849 | 203 | fstab_expected = {} | ||
3850 | 204 | conf_file = "examples/tests/apt_source_search_dns.yaml" | ||
3851 | 205 | disk_to_check = [] | ||
3852 | 206 | collect_scripts = [textwrap.dedent(""" | ||
3853 | 207 | cd OUTPUT_COLLECT_D | ||
3854 | 208 | cat /etc/fstab > fstab | ||
3855 | 209 | ls /dev/disk/by-dname > ls_dname | ||
3856 | 210 | find /etc/network/interfaces.d > find_interfacesd | ||
3857 | 211 | cp /etc/apt/sources.list.d/dnssearch.list.disabled . | ||
3858 | 212 | """)] | ||
3859 | 213 | |||
3860 | 214 | def test_output_files_exist(self): | ||
3861 | 215 | """test_output_files_exist - Check if all output files exist""" | ||
3862 | 216 | self.output_files_exist(["fstab", "dnssearch.list.disabled"]) | ||
3863 | 217 | |||
3864 | 218 | def test_mirror_search_dns(self): | ||
3865 | 219 | """test_mirror_search_dns - tests checking for predefined DNS names""" | ||
3866 | 220 | # these should be the first it got resolved, so they should be in the | ||
3867 | 221 | # sources.list file. We want to see that .lcoaldomain was not picked | ||
3868 | 222 | # but instead what we added to the temp /etc/hosts | ||
3869 | 223 | self.check_file_regex("dnssearch.list.disabled", | ||
3870 | 224 | r"ubuntu-mirror/ubuntu.*multiverse") | ||
3871 | 225 | self.check_file_regex("dnssearch.list.disabled", | ||
3872 | 226 | r"ubuntu-mirror/ubuntu.*universe") | ||
3873 | 227 | self.check_file_regex("dnssearch.list.disabled", | ||
3874 | 228 | r"ubuntu-security-mirror/ubuntu.*main") | ||
3875 | 229 | |||
3876 | 230 | |||
3877 | 231 | class XenialTestAptSrcCustom(relbase.xenial, TestAptSrcCustom): | ||
3878 | 232 | """ XenialTestAptSrcCustom | ||
3879 | 233 | apt feature Test for Xenial with a custom template | ||
3880 | 234 | """ | ||
3881 | 235 | __test__ = True | ||
3882 | 236 | |||
3883 | 237 | |||
3884 | 238 | class XenialTestAptSrcPreserve(relbase.xenial, TestAptSrcPreserve): | ||
3885 | 239 | """ XenialTestAptSrcPreserve | ||
3886 | 240 | apt feature Test for Xenial with apt_preserve_sources_list enabled | ||
3887 | 241 | """ | ||
3888 | 242 | __test__ = True | ||
3889 | 243 | |||
3890 | 244 | |||
3891 | 245 | class XenialTestAptSrcModify(relbase.xenial, TestAptSrcModify): | ||
3892 | 246 | """ XenialTestAptSrcModify | ||
3893 | 247 | apt feature Test for Xenial modifying the sources.list of the image | ||
3894 | 248 | """ | ||
3895 | 249 | __test__ = True | ||
3896 | 250 | |||
3897 | 251 | |||
3898 | 252 | class XenialTestAptSrcSearch(relbase.xenial, TestAptSrcSearch): | ||
3899 | 253 | """ XenialTestAptSrcModify | ||
3900 | 254 | apt feature Test for Xenial searching for mirrors | ||
3901 | 255 | """ | ||
3902 | 256 | __test__ = True | ||
3903 | 257 | |||
3904 | 258 | |||
3905 | 259 | class XenialTestAptSrcSearchDNS(relbase.xenial, TestAptSrcSearchDNS): | ||
3906 | 260 | """ XenialTestAptSrcModify | ||
3907 | 261 | apt feature Test for Xenial searching for predefined DNS names | ||
3908 | 262 | """ | ||
3909 | 263 | __test__ = True | ||
3910 | 264 | |||
3911 | 265 | |||
3912 | 266 | class XenialTestAptSrcModifyArches(relbase.xenial, TestAptSrcModifyArches): | ||
3913 | 267 | """ XenialTestAptSrcModifyArches | ||
3914 | 268 | apt feature Test for Xenial checking per arch mirror specification | ||
3915 | 269 | """ | ||
3916 | 270 | __test__ = True | ||
3917 | 271 | |||
3918 | 272 | |||
3919 | 273 | class XenialTestAptSrcDisablePockets(relbase.xenial, TestAptSrcDisablePockets): | ||
3920 | 274 | """ XenialTestAptSrcDisablePockets | ||
3921 | 275 | apt feature Test for Xenial disabling a suite | ||
3922 | 276 | """ | ||
3923 | 277 | __test__ = True | ||
3924 | 0 | 278 | ||
3925 | === added file 'tests/vmtests/test_old_apt_features.py' | |||
3926 | --- tests/vmtests/test_old_apt_features.py 1970-01-01 00:00:00 +0000 | |||
3927 | +++ tests/vmtests/test_old_apt_features.py 2016-07-26 19:53:43 +0000 | |||
3928 | @@ -0,0 +1,80 @@ | |||
3929 | 1 | """ testold_apt_features | ||
3930 | 2 | Testing the former minimal apt features of curtin | ||
3931 | 3 | """ | ||
3932 | 4 | import re | ||
3933 | 5 | import textwrap | ||
3934 | 6 | |||
3935 | 7 | from . import VMBaseClass | ||
3936 | 8 | from .releases import base_vm_classes as relbase | ||
3937 | 9 | |||
3938 | 10 | from curtin import util | ||
3939 | 11 | |||
3940 | 12 | |||
3941 | 13 | class TestOldAptAbs(VMBaseClass): | ||
3942 | 14 | """TestOldAptAbs - Basic tests for old apt features of curtin""" | ||
3943 | 15 | interactive = False | ||
3944 | 16 | extra_disks = [] | ||
3945 | 17 | fstab_expected = {} | ||
3946 | 18 | disk_to_check = [] | ||
3947 | 19 | collect_scripts = [textwrap.dedent(""" | ||
3948 | 20 | cd OUTPUT_COLLECT_D | ||
3949 | 21 | cat /etc/fstab > fstab | ||
3950 | 22 | ls /dev/disk/by-dname > ls_dname | ||
3951 | 23 | find /etc/network/interfaces.d > find_interfacesd | ||
3952 | 24 | grep -A 3 "Name: debconf/priority" /var/cache/debconf/config.dat > debc | ||
3953 | 25 | apt-config dump > aptconf | ||
3954 | 26 | cp /etc/apt/apt.conf.d/90curtin-aptproxy . | ||
3955 | 27 | cp /etc/apt/sources.list . | ||
3956 | 28 | cp /etc/cloud/cloud.cfg.d/curtin-preserve-sources.cfg . | ||
3957 | 29 | """)] | ||
3958 | 30 | arch = util.get_architecture() | ||
3959 | 31 | if arch in ['amd64', 'i386']: | ||
3960 | 32 | conf_file = "examples/tests/test_old_apt_features.yaml" | ||
3961 | 33 | exp_mirror = "http://us.archive.ubuntu.com/ubuntu" | ||
3962 | 34 | exp_secmirror = "http://archive.ubuntu.com/ubuntu" | ||
3963 | 35 | if arch in ['s390x', 'arm64', 'armhf', 'powerpc', 'ppc64el']: | ||
3964 | 36 | conf_file = "examples/tests/test_old_apt_features_ports.yaml" | ||
3965 | 37 | exp_mirror = "http://ports.ubuntu.com/ubuntu-ports" | ||
3966 | 38 | exp_secmirror = "http://ports.ubuntu.com/ubuntu-ports" | ||
3967 | 39 | |||
3968 | 40 | def test_output_files_exist(self): | ||
3969 | 41 | """test_output_files_exist - Check if all output files exist""" | ||
3970 | 42 | self.output_files_exist( | ||
3971 | 43 | ["debc", "aptconf", "sources.list", "90curtin-aptproxy", | ||
3972 | 44 | "curtin-preserve-sources.cfg"]) | ||
3973 | 45 | |||
3974 | 46 | def test_preserve_source(self): | ||
3975 | 47 | """test_preserve_source - no clobbering sources.list by cloud-init""" | ||
3976 | 48 | self.check_file_regex("curtin-preserve-sources.cfg", | ||
3977 | 49 | "apt_preserve_sources_list.*true") | ||
3978 | 50 | |||
3979 | 51 | def test_debconf(self): | ||
3980 | 52 | """test_debconf - Check if debconf is in place""" | ||
3981 | 53 | self.check_file_strippedline("debc", "Value: low") | ||
3982 | 54 | |||
3983 | 55 | def test_aptconf(self): | ||
3984 | 56 | """test_aptconf - Check if apt conf for proxy is in place""" | ||
3985 | 57 | # this gets configured by tools/launch and get_apt_proxy in | ||
3986 | 58 | # tests/vmtests/__init__.py, so compare with those | ||
3987 | 59 | rproxy = r"Acquire::http::Proxy \"" + re.escape(self.proxy) + r"\";" | ||
3988 | 60 | self.check_file_regex("aptconf", rproxy) | ||
3989 | 61 | self.check_file_regex("90curtin-aptproxy", rproxy) | ||
3990 | 62 | |||
3991 | 63 | def test_mirrors(self): | ||
3992 | 64 | """test_mirrors - Check for mirrors placed in source.list""" | ||
3993 | 65 | |||
3994 | 66 | self.check_file_strippedline("sources.list", | ||
3995 | 67 | "deb %s %s" % | ||
3996 | 68 | (self.exp_mirror, self.release) + | ||
3997 | 69 | " main restricted universe multiverse") | ||
3998 | 70 | self.check_file_strippedline("sources.list", | ||
3999 | 71 | "deb %s %s-security" % | ||
4000 | 72 | (self.exp_secmirror, self.release) + | ||
4001 | 73 | " main restricted universe multiverse") | ||
4002 | 74 | |||
4003 | 75 | |||
4004 | 76 | class XenialTestOldApt(relbase.xenial, TestOldAptAbs): | ||
4005 | 77 | """ XenialTestOldApt | ||
4006 | 78 | Old apt features for Xenial | ||
4007 | 79 | """ | ||
4008 | 80 | __test__ = True |
FAILED: Continuous integration, rev:441 /server- team-jenkins. canonical. com/job/ curtin- ci/233/ /server- team-jenkins. canonical. com/job/ generic- update- mp/230/ console
https:/
Executed test runs:
None: https:/
Click here to trigger a rebuild: /server- team-jenkins. canonical. com/job/ curtin- ci/233/ rebuild
https:/