diff --git a/bootstrapvz/base/__init__.py b/bootstrapvz/base/__init__.py index 4bcf580..4a9e32e 100644 --- a/bootstrapvz/base/__init__.py +++ b/bootstrapvz/base/__init__.py @@ -32,3 +32,14 @@ def validate_manifest(data, validator, error): if release == squeeze: error('Grub installation on squeeze is not supported', ['system', 'bootloader']) + + # Check the provided apt.conf(5) options + if 'packages' in data: + for name, val in data['packages'].get('apt.conf.d', {}).iteritems(): + from bootstrapvz.common.tools import log_call + + status, _, _ = log_call(['apt-config', '-c=/dev/stdin', 'dump'], + stdin=val + '\n') + + if status != 0: + error('apt.conf(5) syntax error', ['packages', 'apt.conf.d', name]) diff --git a/bootstrapvz/base/manifest-schema.yml b/bootstrapvz/base/manifest-schema.yml index dcffd81..d0b6b97 100644 --- a/bootstrapvz/base/manifest-schema.yml +++ b/bootstrapvz/base/manifest-schema.yml @@ -100,6 +100,13 @@ properties: minItems: 1 minProperties: 1 additionalProperties: false + apt.conf.d: + type: object + patternProperties: + ^[0-9A-Za-z][0-9A-Za-z-_.]+$: + type: string + minProperties: 1 + additionalProperties: false sources: type: object patternProperties: diff --git a/bootstrapvz/common/task_groups.py b/bootstrapvz/common/task_groups.py index ee83c95..6320d22 100644 --- a/bootstrapvz/common/task_groups.py +++ b/bootstrapvz/common/task_groups.py @@ -125,6 +125,8 @@ def get_apt_group(manifest): if 'preferences' in manifest.packages: group.append(apt.AddManifestPreferences) group.append(apt.WritePreferences) + if 'apt.conf.d' in manifest.packages: + group.append(apt.WriteConfiguration) if 'install' in manifest.packages: group.append(packages.AddManifestPackages) if manifest.packages.get('install_standard', False): diff --git a/bootstrapvz/common/tasks/apt.py b/bootstrapvz/common/tasks/apt.py index a93deb9..61912da 100644 --- a/bootstrapvz/common/tasks/apt.py +++ b/bootstrapvz/common/tasks/apt.py @@ -80,6 +80,22 @@ class InstallTrustedKeys(Task): copy(key_path, destination) +class WriteConfiguration(Task): + decription = 'Write configuration to apt.conf.d from the manifest' + phase = phases.package_installation + + @classmethod + def run(cls, info): + for name, val in info.manifest.packages.get('apt.conf.d', {}).iteritems(): + if name == 'main': + path = os.path.join(info.root, 'etc/apt/apt.conf') + else: + path = os.path.join(info.root, 'etc/apt/apt.conf.d', name) + + with open(path, 'w') as conf_file: + conf_file.write(val + '\n') + + class WriteSources(Task): description = 'Writing aptitude sources to disk' phase = phases.package_installation @@ -138,7 +154,7 @@ class DisableDaemonAutostart(Task): class AptUpdate(Task): description = 'Updating the package cache' phase = phases.package_installation - predecessors = [locale.GenerateLocale, WriteSources, WritePreferences] + predecessors = [locale.GenerateLocale, WriteConfiguration, WriteSources, WritePreferences] @classmethod def run(cls, info): diff --git a/manifests/README.rst b/manifests/README.rst index 14dd16b..4771106 100644 --- a/manifests/README.rst +++ b/manifests/README.rst @@ -210,6 +210,11 @@ variety of sources. be added to the aptitude keyring of trusted signatures for repositories. ``optional`` +- ``apt.conf.d``: A map of ``apt.conf(5)`` configuration snippets. + The key become the filename in ``/etc/apt/apt.conf.d``, except + ``main`` which designates ``/etc/apt/apt.conf``. + The value is a string in the ``apt.conf(5)`` syntax. + ``optional`` - ``preferences``: Allows you to pin packages through `apt preferences `__. The setting is an object where the key is the preference filename in @@ -242,6 +247,11 @@ Example: - non-free trusted-keys: - /root/keys/puppet.gpg + apt.conf.d: + 00InstallRecommends: >- + APT::Install-Recommends "false"; + APT::Install-Suggests "false"; + 00IPv4: 'Acquire::ForceIPv4 "false";' preferences: main: - package: *