From 92d282ce8ae94111d3c7e07251667ed92ee7f892 Mon Sep 17 00:00:00 2001 From: Packit Service Date: Dec 09 2020 09:23:44 +0000 Subject: Prepare for a new update Reverting patches so we can apply the latest update and changes can be seen in the spec file and sources. --- diff --git a/cloudinit/config/cc_chef.py b/cloudinit/config/cc_chef.py index e4408a4..0ad6b7f 100644 --- a/cloudinit/config/cc_chef.py +++ b/cloudinit/config/cc_chef.py @@ -33,7 +33,7 @@ file). chef: directories: (defaulting to /etc/chef, /var/log/chef, /var/lib/chef, - /var/cache/chef, /var/backups/chef, /run/chef) + /var/cache/chef, /var/backups/chef, /var/run/chef) validation_cert: (optional string to be written to file validation_key) special value 'system' means set use existing file validation_key: (optional the path for validation_cert. default @@ -89,7 +89,7 @@ CHEF_DIRS = tuple([ '/var/lib/chef', '/var/cache/chef', '/var/backups/chef', - '/run/chef', + '/var/run/chef', ]) REQUIRED_CHEF_DIRS = tuple([ '/etc/chef', @@ -113,7 +113,7 @@ CHEF_RB_TPL_DEFAULTS = { 'json_attribs': CHEF_FB_PATH, 'file_cache_path': "/var/cache/chef", 'file_backup_path': "/var/backups/chef", - 'pid_file': "/run/chef/client.pid", + 'pid_file': "/var/run/chef/client.pid", 'show_time': True, 'encrypted_data_bag_secret': None, } diff --git a/cloudinit/ec2_utils.py b/cloudinit/ec2_utils.py index 34acfe8..57708c1 100644 --- a/cloudinit/ec2_utils.py +++ b/cloudinit/ec2_utils.py @@ -142,8 +142,7 @@ def skip_retry_on_codes(status_codes, _request_args, cause): def get_instance_userdata(api_version='latest', metadata_address='http://169.254.169.254', ssl_details=None, timeout=5, retries=5, - headers_cb=None, headers_redact=None, - exception_cb=None): + headers_cb=None, exception_cb=None): ud_url = url_helper.combine_url(metadata_address, api_version) ud_url = url_helper.combine_url(ud_url, 'user-data') user_data = '' @@ -156,8 +155,7 @@ def get_instance_userdata(api_version='latest', SKIP_USERDATA_CODES) response = url_helper.read_file_or_url( ud_url, ssl_details=ssl_details, timeout=timeout, - retries=retries, exception_cb=exception_cb, headers_cb=headers_cb, - headers_redact=headers_redact) + retries=retries, exception_cb=exception_cb, headers_cb=headers_cb) user_data = response.contents except url_helper.UrlError as e: if e.code not in SKIP_USERDATA_CODES: @@ -171,13 +169,11 @@ def _get_instance_metadata(tree, api_version='latest', metadata_address='http://169.254.169.254', ssl_details=None, timeout=5, retries=5, leaf_decoder=None, headers_cb=None, - headers_redact=None, exception_cb=None): md_url = url_helper.combine_url(metadata_address, api_version, tree) caller = functools.partial( url_helper.read_file_or_url, ssl_details=ssl_details, timeout=timeout, retries=retries, headers_cb=headers_cb, - headers_redact=headers_redact, exception_cb=exception_cb) def mcaller(url): @@ -201,7 +197,6 @@ def get_instance_metadata(api_version='latest', metadata_address='http://169.254.169.254', ssl_details=None, timeout=5, retries=5, leaf_decoder=None, headers_cb=None, - headers_redact=None, exception_cb=None): # Note, 'meta-data' explicitly has trailing /. # this is required for CloudStack (LP: #1356855) @@ -209,7 +204,6 @@ def get_instance_metadata(api_version='latest', metadata_address=metadata_address, ssl_details=ssl_details, timeout=timeout, retries=retries, leaf_decoder=leaf_decoder, - headers_redact=headers_redact, headers_cb=headers_cb, exception_cb=exception_cb) @@ -218,14 +212,12 @@ def get_instance_identity(api_version='latest', metadata_address='http://169.254.169.254', ssl_details=None, timeout=5, retries=5, leaf_decoder=None, headers_cb=None, - headers_redact=None, exception_cb=None): return _get_instance_metadata(tree='dynamic/instance-identity', api_version=api_version, metadata_address=metadata_address, ssl_details=ssl_details, timeout=timeout, retries=retries, leaf_decoder=leaf_decoder, - headers_redact=headers_redact, headers_cb=headers_cb, exception_cb=exception_cb) # vi: ts=4 expandtab diff --git a/cloudinit/net/sysconfig.py b/cloudinit/net/sysconfig.py index 810b283..310cdf0 100644 --- a/cloudinit/net/sysconfig.py +++ b/cloudinit/net/sysconfig.py @@ -272,6 +272,7 @@ class Renderer(renderer.Renderer): iface_defaults = tuple([ ('ONBOOT', True), ('USERCTL', False), + ('NM_CONTROLLED', False), ('BOOTPROTO', 'none'), ('STARTMODE', 'auto'), ]) @@ -754,16 +755,7 @@ class Renderer(renderer.Renderer): # Distros configuring /etc/sysconfig/network as a file e.g. Centos if sysconfig_path.endswith('network'): util.ensure_dir(os.path.dirname(sysconfig_path)) - netcfg = [] - for line in util.load_file(sysconfig_path, quiet=True).split('\n'): - if 'cloud-init' in line: - break - if not line.startswith(('NETWORKING=', - 'IPV6_AUTOCONF=', - 'NETWORKING_IPV6=')): - netcfg.append(line) - # Now generate the cloud-init portion of sysconfig/network - netcfg.extend([_make_header(), 'NETWORKING=yes']) + netcfg = [_make_header(), 'NETWORKING=yes'] if network_state.use_ipv6: netcfg.append('NETWORKING_IPV6=yes') netcfg.append('IPV6_AUTOCONF=no') diff --git a/cloudinit/settings.py b/cloudinit/settings.py index 439eee0..ca4ffa8 100644 --- a/cloudinit/settings.py +++ b/cloudinit/settings.py @@ -45,18 +45,14 @@ CFG_BUILTIN = { 'None', ], 'def_log_file': '/var/log/cloud-init.log', - 'def_log_file_mode': 0o600, 'log_cfgs': [], - 'mount_default_fields': [None, None, 'auto', 'defaults,nofail', '0', '2'], - 'ssh_deletekeys': False, - 'ssh_genkeytypes': [], - 'syslog_fix_perms': [], + 'syslog_fix_perms': ['syslog:adm', 'root:adm', 'root:wheel', 'root:root'], 'system_info': { 'paths': { 'cloud_dir': '/var/lib/cloud', 'templates_dir': '/etc/cloud/templates/', }, - 'distro': 'rhel', + 'distro': 'ubuntu', 'network': {'renderers': None}, }, 'vendor_data': {'enabled': True, 'prefix': []}, diff --git a/cloudinit/sources/DataSourceAzure.py b/cloudinit/sources/DataSourceAzure.py index 6fb889c..24f448c 100755 --- a/cloudinit/sources/DataSourceAzure.py +++ b/cloudinit/sources/DataSourceAzure.py @@ -256,7 +256,7 @@ def get_hostname(hostname_command='hostname'): def set_hostname(hostname, hostname_command='hostname'): - util.subp(['hostnamectl', 'set-hostname', str(hostname)]) + util.subp([hostname_command, hostname]) @azure_ds_telemetry_reporter diff --git a/cloudinit/sources/DataSourceEc2.py b/cloudinit/sources/DataSourceEc2.py index 0f2bfef..b9f346a 100644 --- a/cloudinit/sources/DataSourceEc2.py +++ b/cloudinit/sources/DataSourceEc2.py @@ -31,9 +31,6 @@ STRICT_ID_DEFAULT = "warn" API_TOKEN_ROUTE = 'latest/api/token' API_TOKEN_DISABLED = '_ec2_disable_api_token' AWS_TOKEN_TTL_SECONDS = '21600' -AWS_TOKEN_PUT_HEADER = 'X-aws-ec2-metadata-token' -AWS_TOKEN_REQ_HEADER = AWS_TOKEN_PUT_HEADER + '-ttl-seconds' -AWS_TOKEN_REDACT = [AWS_TOKEN_PUT_HEADER, AWS_TOKEN_REQ_HEADER] class CloudNames(object): @@ -161,8 +158,7 @@ class DataSourceEc2(sources.DataSource): for api_ver in self.extended_metadata_versions: url = url_tmpl.format(self.metadata_address, api_ver) try: - resp = uhelp.readurl(url=url, headers=headers, - headers_redact=AWS_TOKEN_REDACT) + resp = uhelp.readurl(url=url, headers=headers) except uhelp.UrlError as e: LOG.debug('url %s raised exception %s', url, e) else: @@ -184,7 +180,6 @@ class DataSourceEc2(sources.DataSource): self.identity = ec2.get_instance_identity( api_version, self.metadata_address, headers_cb=self._get_headers, - headers_redact=AWS_TOKEN_REDACT, exception_cb=self._refresh_stale_aws_token_cb).get( 'document', {}) return self.identity.get( @@ -210,8 +205,7 @@ class DataSourceEc2(sources.DataSource): LOG.debug('Fetching Ec2 IMDSv2 API Token') url, response = uhelp.wait_for_url( urls=urls, max_wait=1, timeout=1, status_cb=self._status_cb, - headers_cb=self._get_headers, request_method=request_method, - headers_redact=AWS_TOKEN_REDACT) + headers_cb=self._get_headers, request_method=request_method) if url and response: self._api_token = response @@ -258,8 +252,7 @@ class DataSourceEc2(sources.DataSource): url, _ = uhelp.wait_for_url( urls=urls, max_wait=url_params.max_wait_seconds, timeout=url_params.timeout_seconds, status_cb=LOG.warning, - headers_redact=AWS_TOKEN_REDACT, headers_cb=self._get_headers, - request_method=request_method) + headers_cb=self._get_headers, request_method=request_method) if url: metadata_address = url2base[url] @@ -427,7 +420,6 @@ class DataSourceEc2(sources.DataSource): if not self.wait_for_metadata_service(): return {} api_version = self.get_metadata_api_version() - redact = AWS_TOKEN_REDACT crawled_metadata = {} if self.cloud_name == CloudNames.AWS: exc_cb = self._refresh_stale_aws_token_cb @@ -437,17 +429,14 @@ class DataSourceEc2(sources.DataSource): try: crawled_metadata['user-data'] = ec2.get_instance_userdata( api_version, self.metadata_address, - headers_cb=self._get_headers, headers_redact=redact, - exception_cb=exc_cb_ud) + headers_cb=self._get_headers, exception_cb=exc_cb_ud) crawled_metadata['meta-data'] = ec2.get_instance_metadata( api_version, self.metadata_address, - headers_cb=self._get_headers, headers_redact=redact, - exception_cb=exc_cb) + headers_cb=self._get_headers, exception_cb=exc_cb) if self.cloud_name == CloudNames.AWS: identity = ec2.get_instance_identity( api_version, self.metadata_address, - headers_cb=self._get_headers, headers_redact=redact, - exception_cb=exc_cb) + headers_cb=self._get_headers, exception_cb=exc_cb) crawled_metadata['dynamic'] = {'instance-identity': identity} except Exception: util.logexc( @@ -466,12 +455,11 @@ class DataSourceEc2(sources.DataSource): if self.cloud_name != CloudNames.AWS: return None LOG.debug("Refreshing Ec2 metadata API token") - request_header = {AWS_TOKEN_REQ_HEADER: seconds} + request_header = {'X-aws-ec2-metadata-token-ttl-seconds': seconds} token_url = '{}/{}'.format(self.metadata_address, API_TOKEN_ROUTE) try: - response = uhelp.readurl(token_url, headers=request_header, - headers_redact=AWS_TOKEN_REDACT, - request_method="PUT") + response = uhelp.readurl( + token_url, headers=request_header, request_method="PUT") except uhelp.UrlError as e: LOG.warning( 'Unable to get API token: %s raised exception %s', @@ -512,7 +500,8 @@ class DataSourceEc2(sources.DataSource): API_TOKEN_DISABLED): return {} # Request a 6 hour token if URL is API_TOKEN_ROUTE - request_token_header = {AWS_TOKEN_REQ_HEADER: AWS_TOKEN_TTL_SECONDS} + request_token_header = { + 'X-aws-ec2-metadata-token-ttl-seconds': AWS_TOKEN_TTL_SECONDS} if API_TOKEN_ROUTE in url: return request_token_header if not self._api_token: @@ -522,7 +511,7 @@ class DataSourceEc2(sources.DataSource): self._api_token = self._refresh_api_token() if not self._api_token: return {} - return {AWS_TOKEN_PUT_HEADER: self._api_token} + return {'X-aws-ec2-metadata-token': self._api_token} class DataSourceEc2Local(DataSourceEc2): diff --git a/cloudinit/stages.py b/cloudinit/stages.py index 68b83af..71f3a49 100644 --- a/cloudinit/stages.py +++ b/cloudinit/stages.py @@ -149,9 +149,8 @@ class Init(object): def _initialize_filesystem(self): util.ensure_dirs(self._initial_subdirs()) log_file = util.get_cfg_option_str(self.cfg, 'def_log_file') - log_file_mode = util.get_cfg_option_int(self.cfg, 'def_log_file_mode') if log_file: - util.ensure_file(log_file, mode=log_file_mode) + util.ensure_file(log_file) perms = self.cfg.get('syslog_fix_perms') if not perms: perms = {} diff --git a/cloudinit/tests/test_url_helper.py b/cloudinit/tests/test_url_helper.py index 29b3937..1674120 100644 --- a/cloudinit/tests/test_url_helper.py +++ b/cloudinit/tests/test_url_helper.py @@ -1,8 +1,7 @@ # This file is part of cloud-init. See LICENSE file for license information. from cloudinit.url_helper import ( - NOT_FOUND, UrlError, REDACTED, oauth_headers, read_file_or_url, - retry_on_url_exc) + NOT_FOUND, UrlError, oauth_headers, read_file_or_url, retry_on_url_exc) from cloudinit.tests.helpers import CiTestCase, mock, skipIf from cloudinit import util from cloudinit import version @@ -51,9 +50,6 @@ class TestOAuthHeaders(CiTestCase): class TestReadFileOrUrl(CiTestCase): - - with_logs = True - def test_read_file_or_url_str_from_file(self): """Test that str(result.contents) on file is text version of contents. It should not be "b'data'", but just "'data'" """ @@ -75,34 +71,6 @@ class TestReadFileOrUrl(CiTestCase): self.assertEqual(result.contents, data) self.assertEqual(str(result), data.decode('utf-8')) - @httpretty.activate - def test_read_file_or_url_str_from_url_redacting_headers_from_logs(self): - """Headers are redacted from logs but unredacted in requests.""" - url = 'http://hostname/path' - headers = {'sensitive': 'sekret', 'server': 'blah'} - httpretty.register_uri(httpretty.GET, url) - - read_file_or_url(url, headers=headers, headers_redact=['sensitive']) - logs = self.logs.getvalue() - for k in headers.keys(): - self.assertEqual(headers[k], httpretty.last_request().headers[k]) - self.assertIn(REDACTED, logs) - self.assertNotIn('sekret', logs) - - @httpretty.activate - def test_read_file_or_url_str_from_url_redacts_noheaders(self): - """When no headers_redact, header values are in logs and requests.""" - url = 'http://hostname/path' - headers = {'sensitive': 'sekret', 'server': 'blah'} - httpretty.register_uri(httpretty.GET, url) - - read_file_or_url(url, headers=headers) - for k in headers.keys(): - self.assertEqual(headers[k], httpretty.last_request().headers[k]) - logs = self.logs.getvalue() - self.assertNotIn(REDACTED, logs) - self.assertIn('sekret', logs) - @mock.patch(M_PATH + 'readurl') def test_read_file_or_url_passes_params_to_readurl(self, m_readurl): """read_file_or_url passes all params through to readurl.""" diff --git a/cloudinit/url_helper.py b/cloudinit/url_helper.py index e6188ea..1496a47 100644 --- a/cloudinit/url_helper.py +++ b/cloudinit/url_helper.py @@ -8,7 +8,6 @@ # # This file is part of cloud-init. See LICENSE file for license information. -import copy import json import os import requests @@ -42,7 +41,6 @@ else: SSL_ENABLED = False CONFIG_ENABLED = False # This was added in 0.7 (but taken out in >=1.0) _REQ_VER = None -REDACTED = 'REDACTED' try: from distutils.version import LooseVersion import pkg_resources @@ -201,9 +199,9 @@ def _get_ssl_args(url, ssl_details): def readurl(url, data=None, timeout=None, retries=0, sec_between=1, - headers=None, headers_cb=None, headers_redact=None, - ssl_details=None, check_status=True, allow_redirects=True, - exception_cb=None, session=None, infinite=False, log_req_resp=True, + headers=None, headers_cb=None, ssl_details=None, + check_status=True, allow_redirects=True, exception_cb=None, + session=None, infinite=False, log_req_resp=True, request_method=None): """Wrapper around requests.Session to read the url and retry if necessary @@ -219,7 +217,6 @@ def readurl(url, data=None, timeout=None, retries=0, sec_between=1, :param headers: Optional dict of headers to send during request :param headers_cb: Optional callable returning a dict of values to send as headers during request - :param headers_redact: Optional list of header names to redact from the log :param ssl_details: Optional dict providing key_file, ca_certs, and cert_file keys for use on in ssl connections. :param check_status: Optional boolean set True to raise when HTTPError @@ -246,8 +243,6 @@ def readurl(url, data=None, timeout=None, retries=0, sec_between=1, req_args['method'] = request_method if timeout is not None: req_args['timeout'] = max(float(timeout), 0) - if headers_redact is None: - headers_redact = [] # It doesn't seem like config # was added in older library versions (or newer ones either), thus we # need to manually do the retries if it wasn't... @@ -291,14 +286,7 @@ def readurl(url, data=None, timeout=None, retries=0, sec_between=1, for (k, v) in req_args.items(): if k == 'data': continue - if k == 'headers' and headers_redact: - matched_headers = [k for k in headers_redact if v.get(k)] - if matched_headers: - filtered_req_args[k] = copy.deepcopy(v) - for key in matched_headers: - filtered_req_args[k][key] = REDACTED - else: - filtered_req_args[k] = v + filtered_req_args[k] = v try: if log_req_resp: @@ -351,8 +339,8 @@ def readurl(url, data=None, timeout=None, retries=0, sec_between=1, return None # Should throw before this... -def wait_for_url(urls, max_wait=None, timeout=None, status_cb=None, - headers_cb=None, headers_redact=None, sleep_time=1, +def wait_for_url(urls, max_wait=None, timeout=None, + status_cb=None, headers_cb=None, sleep_time=1, exception_cb=None, sleep_time_cb=None, request_method=None): """ urls: a list of urls to try @@ -364,7 +352,6 @@ def wait_for_url(urls, max_wait=None, timeout=None, status_cb=None, status_cb: call method with string message when a url is not available headers_cb: call method with single argument of url to get headers for request. - headers_redact: a list of header names to redact from the log exception_cb: call method with 2 arguments 'msg' (per status_cb) and 'exception', the exception that occurred. sleep_time_cb: call method with 2 arguments (response, loop_n) that @@ -428,9 +415,8 @@ def wait_for_url(urls, max_wait=None, timeout=None, status_cb=None, headers = {} response = readurl( - url, headers=headers, headers_redact=headers_redact, - timeout=timeout, check_status=False, - request_method=request_method) + url, headers=headers, timeout=timeout, + check_status=False, request_method=request_method) if not response.contents: reason = "empty response [%s]" % (response.code) url_exc = UrlError(ValueError(reason), code=response.code, diff --git a/doc/examples/cloud-config.txt b/doc/examples/cloud-config.txt index 0e82b83..eb84dcf 100644 --- a/doc/examples/cloud-config.txt +++ b/doc/examples/cloud-config.txt @@ -413,14 +413,10 @@ timezone: US/Eastern # if syslog_fix_perms is a list, it will iterate through and use the # first pair that does not raise error. # -# 'def_log_file' will be created with mode 'def_log_file_mode', which -# is specified as a numeric value and defaults to 0600. -# # the default values are '/var/log/cloud-init.log' and 'syslog:adm' # the value of 'def_log_file' should match what is configured in logging # if either is empty, then no change of ownership will be done def_log_file: /var/log/my-logging-file.log -def_log_file_mode: 0600 syslog_fix_perms: syslog:root # you can set passwords for a user or multiple users diff --git a/rhel/README.rhel b/rhel/README.rhel deleted file mode 100644 index aa29630..0000000 --- a/rhel/README.rhel +++ /dev/null @@ -1,5 +0,0 @@ -The following cloud-init modules are currently unsupported on this OS: - - apt_update_upgrade ('apt_update', 'apt_upgrade', 'apt_mirror', 'apt_preserve_sources_list', 'apt_old_mirror', 'apt_sources', 'debconf_selections', 'packages' options) - - byobu ('byobu_by_default' option) - - chef - - grub_dpkg diff --git a/rhel/cloud-init-tmpfiles.conf b/rhel/cloud-init-tmpfiles.conf deleted file mode 100644 index 0c6d2a3..0000000 --- a/rhel/cloud-init-tmpfiles.conf +++ /dev/null @@ -1 +0,0 @@ -d /run/cloud-init 0700 root root - - diff --git a/rhel/cloud.cfg b/rhel/cloud.cfg deleted file mode 100644 index 9ecba21..0000000 --- a/rhel/cloud.cfg +++ /dev/null @@ -1,69 +0,0 @@ -users: - - default - -disable_root: 1 -ssh_pwauth: 0 - -mount_default_fields: [~, ~, 'auto', 'defaults,nofail,x-systemd.requires=cloud-init.service', '0', '2'] -resize_rootfs_tmp: /dev -ssh_deletekeys: 1 -ssh_genkeytypes: ~ -syslog_fix_perms: ~ -disable_vmware_customization: false - -cloud_init_modules: - - disk_setup - - migrator - - bootcmd - - write-files - - growpart - - resizefs - - set_hostname - - update_hostname - - update_etc_hosts - - rsyslog - - users-groups - - ssh - -cloud_config_modules: - - mounts - - locale - - set-passwords - - rh_subscription - - yum-add-repo - - package-update-upgrade-install - - timezone - - puppet - - chef - - salt-minion - - mcollective - - disable-ec2-metadata - - runcmd - -cloud_final_modules: - - rightscale_userdata - - scripts-per-once - - scripts-per-boot - - scripts-per-instance - - scripts-user - - ssh-authkey-fingerprints - - keys-to-console - - phone-home - - final-message - - power-state-change - -system_info: - default_user: - name: cloud-user - lock_passwd: true - gecos: Cloud User - groups: [adm, systemd-journal] - sudo: ["ALL=(ALL) NOPASSWD:ALL"] - shell: /bin/bash - distro: rhel - paths: - cloud_dir: /var/lib/cloud - templates_dir: /etc/cloud/templates - ssh_svcname: sshd - -# vim:syntax=yaml diff --git a/rhel/systemd/cloud-config.service b/rhel/systemd/cloud-config.service deleted file mode 100644 index f3dcd4b..0000000 --- a/rhel/systemd/cloud-config.service +++ /dev/null @@ -1,18 +0,0 @@ -[Unit] -Description=Apply the settings specified in cloud-config -After=network-online.target cloud-config.target -Wants=network-online.target cloud-config.target -ConditionPathExists=!/etc/cloud/cloud-init.disabled -ConditionKernelCommandLine=!cloud-init=disabled - -[Service] -Type=oneshot -ExecStart=/usr/bin/cloud-init modules --mode=config -RemainAfterExit=yes -TimeoutSec=0 - -# Output needs to appear in instance console output -StandardOutput=journal+console - -[Install] -WantedBy=cloud-init.target diff --git a/rhel/systemd/cloud-config.target b/rhel/systemd/cloud-config.target deleted file mode 100644 index ae9b7d0..0000000 --- a/rhel/systemd/cloud-config.target +++ /dev/null @@ -1,11 +0,0 @@ -# cloud-init normally emits a "cloud-config" upstart event to inform third -# parties that cloud-config is available, which does us no good when we're -# using systemd. cloud-config.target serves as this synchronization point -# instead. Services that would "start on cloud-config" with upstart can -# instead use "After=cloud-config.target" and "Wants=cloud-config.target" -# as appropriate. - -[Unit] -Description=Cloud-config availability -Wants=cloud-init-local.service cloud-init.service -After=cloud-init-local.service cloud-init.service diff --git a/rhel/systemd/cloud-final.service b/rhel/systemd/cloud-final.service deleted file mode 100644 index f303483..0000000 --- a/rhel/systemd/cloud-final.service +++ /dev/null @@ -1,21 +0,0 @@ -[Unit] -Description=Execute cloud user/final scripts -After=network-online.target cloud-config.service rc-local.service -Wants=network-online.target cloud-config.service -ConditionPathExists=!/etc/cloud/cloud-init.disabled -ConditionKernelCommandLine=!cloud-init=disabled - -[Service] -Type=oneshot -ExecStart=/usr/bin/cloud-init modules --mode=final -RemainAfterExit=yes -TimeoutSec=0 -KillMode=process -ExecStartPost=/bin/echo "try restart NetworkManager.service" -ExecStartPost=/usr/bin/systemctl try-restart NetworkManager.service - -# Output needs to appear in instance console output -StandardOutput=journal+console - -[Install] -WantedBy=cloud-init.target diff --git a/rhel/systemd/cloud-init-local.service b/rhel/systemd/cloud-init-local.service deleted file mode 100644 index 8f9f6c9..0000000 --- a/rhel/systemd/cloud-init-local.service +++ /dev/null @@ -1,31 +0,0 @@ -[Unit] -Description=Initial cloud-init job (pre-networking) -DefaultDependencies=no -Wants=network-pre.target -After=systemd-remount-fs.service -Requires=dbus.socket -After=dbus.socket -Before=NetworkManager.service network.service -Before=network-pre.target -Before=shutdown.target -Before=firewalld.target -Conflicts=shutdown.target -RequiresMountsFor=/var/lib/cloud -ConditionPathExists=!/etc/cloud/cloud-init.disabled -ConditionKernelCommandLine=!cloud-init=disabled - -[Service] -Type=oneshot -ExecStartPre=/bin/mkdir -p /run/cloud-init -ExecStartPre=/sbin/restorecon /run/cloud-init -ExecStartPre=/usr/bin/touch /run/cloud-init/enabled -ExecStart=/usr/bin/cloud-init init --local -ExecStart=/bin/touch /run/cloud-init/network-config-ready -RemainAfterExit=yes -TimeoutSec=0 - -# Output needs to appear in instance console output -StandardOutput=journal+console - -[Install] -WantedBy=cloud-init.target diff --git a/rhel/systemd/cloud-init.service b/rhel/systemd/cloud-init.service deleted file mode 100644 index 0b3d796..0000000 --- a/rhel/systemd/cloud-init.service +++ /dev/null @@ -1,26 +0,0 @@ -[Unit] -Description=Initial cloud-init job (metadata service crawler) -Wants=cloud-init-local.service -Wants=sshd-keygen.service -Wants=sshd.service -After=cloud-init-local.service -After=NetworkManager.service network.service -After=NetworkManager-wait-online.service -Before=network-online.target -Before=sshd-keygen.service -Before=sshd.service -Before=systemd-user-sessions.service -ConditionPathExists=!/etc/cloud/cloud-init.disabled -ConditionKernelCommandLine=!cloud-init=disabled - -[Service] -Type=oneshot -ExecStart=/usr/bin/cloud-init init -RemainAfterExit=yes -TimeoutSec=0 - -# Output needs to appear in instance console output -StandardOutput=journal+console - -[Install] -WantedBy=cloud-init.target diff --git a/rhel/systemd/cloud-init.target b/rhel/systemd/cloud-init.target deleted file mode 100644 index 083c3b6..0000000 --- a/rhel/systemd/cloud-init.target +++ /dev/null @@ -1,7 +0,0 @@ -# cloud-init target is enabled by cloud-init-generator -# To disable it you can either: -# a.) boot with kernel cmdline of 'cloud-init=disabled' -# b.) touch a file /etc/cloud/cloud-init.disabled -[Unit] -Description=Cloud-init target -After=multi-user.target diff --git a/setup.py b/setup.py index b2ac9bb..01a67b9 100755 --- a/setup.py +++ b/setup.py @@ -139,6 +139,14 @@ INITSYS_FILES = { 'sysvinit_deb': [f for f in glob('sysvinit/debian/*') if is_f(f)], 'sysvinit_openrc': [f for f in glob('sysvinit/gentoo/*') if is_f(f)], 'sysvinit_suse': [f for f in glob('sysvinit/suse/*') if is_f(f)], + 'systemd': [render_tmpl(f) + for f in (glob('systemd/*.tmpl') + + glob('systemd/*.service') + + glob('systemd/*.target')) + if (is_f(f) and not is_generator(f))], + 'systemd.generators': [ + render_tmpl(f, mode=0o755) + for f in glob('systemd/*') if is_f(f) and is_generator(f)], 'upstart': [f for f in glob('upstart/*') if is_f(f)], } INITSYS_ROOTS = { @@ -147,6 +155,9 @@ INITSYS_ROOTS = { 'sysvinit_deb': 'etc/init.d', 'sysvinit_openrc': 'etc/init.d', 'sysvinit_suse': 'etc/init.d', + 'systemd': pkg_config_read('systemd', 'systemdsystemunitdir'), + 'systemd.generators': pkg_config_read('systemd', + 'systemdsystemgeneratordir'), 'upstart': 'etc/init/', } INITSYS_TYPES = sorted([f.partition(".")[0] for f in INITSYS_ROOTS.keys()]) @@ -197,6 +208,47 @@ class MyEggInfo(egg_info): return ret +# TODO: Is there a better way to do this?? +class InitsysInstallData(install): + init_system = None + user_options = install.user_options + [ + # This will magically show up in member variable 'init_sys' + ('init-system=', None, + ('init system(s) to configure (%s) [default: None]' % + (", ".join(INITSYS_TYPES)))), + ] + + def initialize_options(self): + install.initialize_options(self) + self.init_system = "" + + def finalize_options(self): + install.finalize_options(self) + + if self.init_system and isinstance(self.init_system, str): + self.init_system = self.init_system.split(",") + + if len(self.init_system) == 0: + self.init_system = ['systemd'] + + bad = [f for f in self.init_system if f not in INITSYS_TYPES] + if len(bad) != 0: + raise DistutilsArgError( + "Invalid --init-system: %s" % (','.join(bad))) + + for system in self.init_system: + # add data files for anything that starts with '.' + datakeys = [k for k in INITSYS_ROOTS + if k.partition(".")[0] == system] + for k in datakeys: + if not INITSYS_FILES[k]: + continue + self.distribution.data_files.append( + (INITSYS_ROOTS[k], INITSYS_FILES[k])) + # Force that command to reinitalize (with new file list) + self.distribution.reinitialize_command('install_data', True) + + if not in_virtualenv(): USR = "/" + USR ETC = "/" + ETC @@ -206,11 +258,14 @@ if not in_virtualenv(): INITSYS_ROOTS[k] = "/" + INITSYS_ROOTS[k] data_files = [ - (ETC + '/bash_completion.d', ['bash_completion/cloud-init']), + (ETC + '/cloud', [render_tmpl("config/cloud.cfg.tmpl")]), (ETC + '/cloud/cloud.cfg.d', glob('config/cloud.cfg.d/*')), (ETC + '/cloud/templates', glob('templates/*')), - (USR_LIB_EXEC + '/cloud-init', ['tools/uncloud-init', + (USR_LIB_EXEC + '/cloud-init', ['tools/ds-identify', + 'tools/uncloud-init', 'tools/write-ssh-key-fingerprints']), + (USR + '/share/bash-completion/completions', + ['bash_completion/cloud-init']), (USR + '/share/doc/cloud-init', [f for f in glob('doc/*') if is_f(f)]), (USR + '/share/doc/cloud-init/examples', [f for f in glob('doc/examples/*') if is_f(f)]), @@ -221,8 +276,15 @@ if os.uname()[0] != 'FreeBSD': data_files.extend([ (ETC + '/NetworkManager/dispatcher.d/', ['tools/hook-network-manager']), - ('/usr/lib/udev/rules.d', [f for f in glob('udev/*.rules')]) + (ETC + '/dhcp/dhclient-exit-hooks.d/', ['tools/hook-dhclient']), + (LIB + '/udev/rules.d', [f for f in glob('udev/*.rules')]) ]) +# Use a subclass for install that handles +# adding on the right init system configuration files +cmdclass = { + 'install': InitsysInstallData, + 'egg_info': MyEggInfo, +} requirements = read_requires() @@ -237,6 +299,8 @@ setuptools.setup( scripts=['tools/cloud-init-per'], license='Dual-licensed under GPLv3 or Apache 2.0', data_files=data_files, + install_requires=requirements, + cmdclass=cmdclass, entry_points={ 'console_scripts': [ 'cloud-init = cloudinit.cmd.main:main', diff --git a/systemd/cloud-init-generator.tmpl b/systemd/cloud-init-generator.tmpl index 0773356..45efa24 100755 --- a/systemd/cloud-init-generator.tmpl +++ b/systemd/cloud-init-generator.tmpl @@ -83,7 +83,7 @@ default() { check_for_datasource() { local ds_rc="" -{% if variant in ["rhel", "fedora", "centos"] %} +{% if variant in ["redhat", "fedora", "centos"] %} local dsidentify="/usr/libexec/cloud-init/ds-identify" {% else %} local dsidentify="/usr/lib/cloud-init/ds-identify" diff --git a/systemd/cloud-init.service.tmpl b/systemd/cloud-init.service.tmpl index af6d9a8..9ad3574 100644 --- a/systemd/cloud-init.service.tmpl +++ b/systemd/cloud-init.service.tmpl @@ -10,7 +10,7 @@ After=systemd-networkd-wait-online.service {% if variant in ["ubuntu", "unknown", "debian"] %} After=networking.service {% endif %} -{% if variant in ["centos", "fedora", "rhel"] %} +{% if variant in ["centos", "fedora", "redhat"] %} After=network.service After=NetworkManager.service {% endif %} diff --git a/tests/unittests/test_datasource/test_ec2.py b/tests/unittests/test_datasource/test_ec2.py index bd5bd4c..34a089f 100644 --- a/tests/unittests/test_datasource/test_ec2.py +++ b/tests/unittests/test_datasource/test_ec2.py @@ -429,23 +429,6 @@ class TestEc2(test_helpers.HttprettyTestCase): self.assertTrue(ds.get_data()) self.assertFalse(ds.is_classic_instance()) - def test_aws_token_redacted(self): - """Verify that aws tokens are redacted when logged.""" - ds = self._setup_ds( - platform_data=self.valid_platform_data, - sys_cfg={'datasource': {'Ec2': {'strict_id': False}}}, - md={'md': DEFAULT_METADATA}) - self.assertTrue(ds.get_data()) - all_logs = self.logs.getvalue().splitlines() - REDACT_TTL = "'X-aws-ec2-metadata-token-ttl-seconds': 'REDACTED'" - REDACT_TOK = "'X-aws-ec2-metadata-token': 'REDACTED'" - logs_with_redacted_ttl = [log for log in all_logs if REDACT_TTL in log] - logs_with_redacted = [log for log in all_logs if REDACT_TOK in log] - logs_with_token = [log for log in all_logs if 'API-TOKEN' in log] - self.assertEqual(1, len(logs_with_redacted_ttl)) - self.assertEqual(79, len(logs_with_redacted)) - self.assertEqual(0, len(logs_with_token)) - @mock.patch('cloudinit.net.dhcp.maybe_perform_dhcp_discovery') def test_valid_platform_with_strict_true(self, m_dhcp): """Valid platform data should return true with strict_id true.""" diff --git a/tests/unittests/test_net.py b/tests/unittests/test_net.py index a931a3e..01119e0 100644 --- a/tests/unittests/test_net.py +++ b/tests/unittests/test_net.py @@ -530,6 +530,7 @@ GATEWAY=172.19.3.254 HWADDR=fa:16:3e:ed:9a:59 IPADDR=172.19.1.34 NETMASK=255.255.252.0 +NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto TYPE=Ethernet @@ -635,6 +636,7 @@ IPADDR=172.19.1.34 IPADDR1=10.0.0.10 NETMASK=255.255.252.0 NETMASK1=255.255.255.0 +NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto TYPE=Ethernet @@ -770,6 +772,7 @@ IPV6ADDR_SECONDARIES="2001:DB9::10/64 2001:DB10::10/64" IPV6INIT=yes IPV6_DEFAULTGW=2001:DB8::1 NETMASK=255.255.252.0 +NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto TYPE=Ethernet @@ -886,6 +889,7 @@ NETWORK_CONFIGS = { BOOTPROTO=none DEVICE=eth1 HWADDR=cf:d6:af:48:e8:80 + NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto TYPE=Ethernet @@ -903,6 +907,7 @@ NETWORK_CONFIGS = { IPADDR=192.168.21.3 NETMASK=255.255.255.0 METRIC=10000 + NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto TYPE=Ethernet @@ -1017,6 +1022,7 @@ NETWORK_CONFIGS = { IPV6ADDR=2001:1::1/64 IPV6INIT=yes NETMASK=255.255.255.0 + NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto TYPE=Ethernet @@ -1485,6 +1491,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true DHCPV6C=yes IPV6INIT=yes MACADDR=aa:bb:cc:dd:ee:ff + NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto TYPE=Bond @@ -1493,6 +1500,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true BOOTPROTO=dhcp DEVICE=bond0.200 DHCLIENT_SET_DEFAULT_ROUTE=no + NM_CONTROLLED=no ONBOOT=yes PHYSDEV=bond0 STARTMODE=auto @@ -1511,6 +1519,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true IPV6_DEFAULTGW=2001:4800:78ff:1b::1 MACADDR=bb:bb:bb:bb:bb:aa NETMASK=255.255.255.0 + NM_CONTROLLED=no ONBOOT=yes PRIO=22 STARTMODE=auto @@ -1521,6 +1530,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true BOOTPROTO=none DEVICE=eth0 HWADDR=c0:d6:9f:2c:e8:80 + NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto TYPE=Ethernet @@ -1538,6 +1548,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true MTU=1500 NETMASK=255.255.255.0 NETMASK1=255.255.255.0 + NM_CONTROLLED=no ONBOOT=yes PHYSDEV=eth0 STARTMODE=auto @@ -1549,6 +1560,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true DEVICE=eth1 HWADDR=aa:d6:9f:2c:e8:80 MASTER=bond0 + NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto SLAVE=yes @@ -1559,6 +1571,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true DEVICE=eth2 HWADDR=c0:bb:9f:2c:e8:80 MASTER=bond0 + NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto SLAVE=yes @@ -1569,6 +1582,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true BRIDGE=br0 DEVICE=eth3 HWADDR=66:bb:9f:2c:e8:80 + NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto TYPE=Ethernet @@ -1578,6 +1592,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true BRIDGE=br0 DEVICE=eth4 HWADDR=98:bb:9f:2c:e8:80 + NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto TYPE=Ethernet @@ -1587,6 +1602,7 @@ pre-down route del -net 10.0.0.0/8 gw 11.0.0.1 metric 3 || true DEVICE=eth5 DHCLIENT_SET_DEFAULT_ROUTE=no HWADDR=98:bb:9f:2c:e8:8a + NM_CONTROLLED=no ONBOOT=no STARTMODE=manual TYPE=Ethernet @@ -2072,6 +2088,7 @@ iface bond0 inet6 static MTU=9000 NETMASK=255.255.255.0 NETMASK1=255.255.255.0 + NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto TYPE=Bond @@ -2082,6 +2099,7 @@ iface bond0 inet6 static DEVICE=bond0s0 HWADDR=aa:bb:cc:dd:e8:00 MASTER=bond0 + NM_CONTROLLED=no ONBOOT=yes SLAVE=yes STARTMODE=auto @@ -2104,6 +2122,7 @@ iface bond0 inet6 static DEVICE=bond0s1 HWADDR=aa:bb:cc:dd:e8:01 MASTER=bond0 + NM_CONTROLLED=no ONBOOT=yes SLAVE=yes STARTMODE=auto @@ -2142,6 +2161,7 @@ iface bond0 inet6 static BOOTPROTO=none DEVICE=en0 HWADDR=aa:bb:cc:dd:e8:00 + NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto TYPE=Ethernet @@ -2160,6 +2180,7 @@ iface bond0 inet6 static MTU=2222 NETMASK=255.255.255.0 NETMASK1=255.255.255.0 + NM_CONTROLLED=no ONBOOT=yes PHYSDEV=en0 STARTMODE=auto @@ -2201,6 +2222,7 @@ iface bond0 inet6 static DEVICE=br0 IPADDR=192.168.2.2 NETMASK=255.255.255.0 + NM_CONTROLLED=no ONBOOT=yes PRIO=22 STARTMODE=auto @@ -2216,6 +2238,7 @@ iface bond0 inet6 static IPADDR6=2001:1::100/96 IPV6ADDR=2001:1::100/96 IPV6INIT=yes + NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto TYPE=Ethernet @@ -2229,6 +2252,7 @@ iface bond0 inet6 static IPADDR6=2001:1::101/96 IPV6ADDR=2001:1::101/96 IPV6INIT=yes + NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto TYPE=Ethernet @@ -2303,6 +2327,7 @@ iface bond0 inet6 static HWADDR=52:54:00:12:34:00 IPADDR=192.168.1.2 NETMASK=255.255.255.0 + NM_CONTROLLED=no ONBOOT=no STARTMODE=manual TYPE=Ethernet @@ -2313,6 +2338,7 @@ iface bond0 inet6 static DEVICE=eth1 HWADDR=52:54:00:12:34:aa MTU=1480 + NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto TYPE=Ethernet @@ -2322,6 +2348,7 @@ iface bond0 inet6 static BOOTPROTO=none DEVICE=eth2 HWADDR=52:54:00:12:34:ff + NM_CONTROLLED=no ONBOOT=no STARTMODE=manual TYPE=Ethernet @@ -2739,6 +2766,7 @@ class TestRhelSysConfigRendering(CiTestCase): BOOTPROTO=dhcp DEVICE=eth1000 HWADDR=07-1c-c6-75-a4-be +NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto TYPE=Ethernet @@ -2860,6 +2888,7 @@ GATEWAY=10.0.2.2 HWADDR=52:54:00:12:34:00 IPADDR=10.0.2.15 NETMASK=255.255.255.0 +NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto TYPE=Ethernet @@ -2932,6 +2961,7 @@ USERCTL=no # BOOTPROTO=dhcp DEVICE=eth0 +NM_CONTROLLED=no ONBOOT=yes STARTMODE=auto TYPE=Ethernet diff --git a/tools/read-version b/tools/read-version index d43cc8f..6dca659 100755 --- a/tools/read-version +++ b/tools/read-version @@ -65,8 +65,32 @@ output_json = '--json' in sys.argv src_version = ci_version.version_string() version_long = None -version = src_version -version_long = None +if is_gitdir(_tdir) and which("git"): + flags = [] + if use_tags: + flags = ['--tags'] + cmd = ['git', 'describe', '--abbrev=8', '--match=[0-9]*'] + flags + + try: + version = tiny_p(cmd).strip() + except RuntimeError: + version = None + + if version is None or not version.startswith(src_version): + sys.stderr.write("git describe version (%s) differs from " + "cloudinit.version (%s)\n" % (version, src_version)) + sys.stderr.write( + "Please get the latest upstream tags.\n" + "As an example, this can be done with the following:\n" + "$ git remote add upstream https://git.launchpad.net/cloud-init\n" + "$ git fetch upstream --tags\n" + ) + sys.exit(1) + + version_long = tiny_p(cmd + ["--long"]).strip() +else: + version = src_version + version_long = None # version is X.Y.Z[+xxx.gHASH] # version_long is None or X.Y.Z-xxx-gHASH