diff options
author | Alberto Contreras <alberto.contreras@canonical.com> | 2022-08-05 05:01:19 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-08-04 21:01:19 -0600 |
commit | 8e26b2f8a9ce8c1186a6e5f2e9bd90a984fde52a (patch) | |
tree | a292222254702d788ed071bacca6908c750bf035 /cloudinit/cmd | |
parent | 95a3e798a673c8d42147d9c6c82e2053ab8fcdd4 (diff) | |
download | cloud-init-git-8e26b2f8a9ce8c1186a6e5f2e9bd90a984fde52a.tar.gz |
main: avoid downloading full contents cmdline urls (#1606)
In the case that the url content does not start with
`#cloud-config`, avoid downloading the full content.
Add deprecated logs to prefer `cloud-config-url` over
`url` on the kernel command line.
Restructure and link kernel command line docs to
instance-data docs.
Add some typing.
LP: #1937319
Diffstat (limited to 'cloudinit/cmd')
-rwxr-xr-x | cloudinit/cmd/main.py | 32 |
1 files changed, 27 insertions, 5 deletions
diff --git a/cloudinit/cmd/main.py b/cloudinit/cmd/main.py index a6fb7088..2860126a 100755 --- a/cloudinit/cmd/main.py +++ b/cloudinit/cmd/main.py @@ -21,6 +21,7 @@ import os import sys import time import traceback +from typing import Tuple from cloudinit import patcher from cloudinit.config.modules import Modules @@ -143,7 +144,7 @@ def parse_cmdline_url(cmdline, names=("cloud-config-url", "url")): raise KeyError("No keys (%s) found in string '%s'" % (cmdline, names)) -def attempt_cmdline_url(path, network=True, cmdline=None): +def attempt_cmdline_url(path, network=True, cmdline=None) -> Tuple[int, str]: """Write data from url referenced in command line to path. path: a file to write content to if downloaded. @@ -190,7 +191,7 @@ def attempt_cmdline_url(path, network=True, cmdline=None): return (level, m) - kwargs = {"url": url, "timeout": 10, "retries": 2} + kwargs = {"url": url, "timeout": 10, "retries": 2, "stream": True} if network or path_is_local: level = logging.WARN kwargs["sec_between"] = 1 @@ -202,22 +203,43 @@ def attempt_cmdline_url(path, network=True, cmdline=None): header = b"#cloud-config" try: resp = url_helper.read_file_or_url(**kwargs) + sniffed_content = b"" if resp.ok(): - data = resp.contents - if not resp.contents.startswith(header): + is_cloud_cfg = True + if isinstance(resp, url_helper.UrlResponse): + try: + sniffed_content += next( + resp.iter_content(chunk_size=len(header)) + ) + except StopIteration: + pass + if not sniffed_content.startswith(header): + is_cloud_cfg = False + elif not resp.contents.startswith(header): + is_cloud_cfg = False + if is_cloud_cfg: + if cmdline_name == "url": + LOG.warning( + "DEPRECATED: `url` kernel command line key is" + " deprecated for providing cloud-config via URL." + " Please use `cloud-config-url` kernel command line" + " parameter instead" + ) + else: if cmdline_name == "cloud-config-url": level = logging.WARN else: level = logging.INFO return ( level, - "contents of '%s' did not start with %s" % (url, header), + f"contents of '{url}' did not start with {str(header)}", ) else: return ( level, "url '%s' returned code %s. Ignoring." % (url, resp.code), ) + data = sniffed_content + resp.contents except url_helper.UrlError as e: return (level, "retrieving url '%s' failed: %s" % (url, e)) |