summaryrefslogtreecommitdiff
path: root/cloudinit/config/cc_ubuntu_advantage.py
diff options
context:
space:
mode:
Diffstat (limited to 'cloudinit/config/cc_ubuntu_advantage.py')
-rw-r--r--cloudinit/config/cc_ubuntu_advantage.py108
1 files changed, 106 insertions, 2 deletions
diff --git a/cloudinit/config/cc_ubuntu_advantage.py b/cloudinit/config/cc_ubuntu_advantage.py
index 900db695..c05d6297 100644
--- a/cloudinit/config/cc_ubuntu_advantage.py
+++ b/cloudinit/config/cc_ubuntu_advantage.py
@@ -2,7 +2,9 @@
"""ubuntu_advantage: Configure Ubuntu Advantage support services"""
+import re
from textwrap import dedent
+from urllib.parse import urlparse
from cloudinit import log as logging
from cloudinit import subp, util
@@ -69,8 +71,26 @@ meta: MetaSchema = {
- fips
"""
),
+ dedent(
+ """\
+ # Set a http(s) proxy before attaching the machine to an
+ # Ubuntu Advantage support contract and enabling the FIPS service.
+ ubuntu_advantage:
+ token: <ua_contract_token>
+ config:
+ http_proxy: 'http://some-proxy:8088'
+ https_proxy: 'https://some-proxy:8088'
+ global_apt_https_proxy: 'http://some-global-apt-proxy:8088/'
+ global_apt_http_proxy: 'https://some-global-apt-proxy:8088/'
+ ua_apt_http_proxy: 'http://10.0.10.10:3128'
+ ua_apt_https_proxy: 'https://10.0.10.10:3128'
+ enable:
+ - fips
+ """
+ ),
],
"frequency": PER_INSTANCE,
+ "activate_by_schema_keys": ["ubuntu_advantage", "ubuntu-advantage"],
}
__doc__ = get_meta_doc(meta)
@@ -78,7 +98,46 @@ __doc__ = get_meta_doc(meta)
LOG = logging.getLogger(__name__)
-def configure_ua(token=None, enable=None):
+def supplemental_schema_validation(ua_config):
+ """Validate user-provided ua:config option values.
+
+ This function supplements flexible jsonschema validation with specific
+ value checks to aid in triage of invalid user-provided configuration.
+
+ @param ua_config: Dictionary of config value under 'ubuntu_advantage'.
+
+ @raises: ValueError describing invalid values provided.
+ """
+ errors = []
+ nl = "\n"
+ for key, value in sorted(ua_config.items()):
+ if key in (
+ "http_proxy",
+ "https_proxy",
+ "global_apt_http_proxy",
+ "global_apt_https_proxy",
+ "ua_apt_http_proxy",
+ "ua_apt_https_proxy",
+ ):
+ try:
+ parsed_url = urlparse(value)
+ if parsed_url.scheme not in ("http", "https"):
+ errors.append(
+ f"Expected URL scheme http/https for ua:config:{key}."
+ f" Found: {value}"
+ )
+ except (AttributeError, ValueError):
+ errors.append(
+ f"Expected a URL for ua:config:{key}. Found: {value}"
+ )
+
+ if errors:
+ raise ValueError(
+ f"Invalid ubuntu_advantage configuration:{nl}{nl.join(errors)}"
+ )
+
+
+def configure_ua(token=None, enable=None, config=None):
"""Call ua commandline client to attach or enable services."""
error = None
if not token:
@@ -102,6 +161,44 @@ def configure_ua(token=None, enable=None):
)
enable = []
+ if config is None:
+ config = dict()
+ elif not isinstance(config, dict):
+ LOG.warning(
+ "ubuntu_advantage: config should be a dict, not"
+ " a %s; skipping enabling config parameters",
+ type(config).__name__,
+ )
+ config = dict()
+
+ enable_errors = []
+
+ # UA Config
+ for key, value in sorted(config.items()):
+ if value is None:
+ LOG.debug("Unsetting UA config for %s", key)
+ config_cmd = ["ua", "config", "unset", key]
+ else:
+ LOG.debug("Setting UA config %s=%s", key, value)
+ if re.search(r"\s", value):
+ key_value = f"{key}={re.escape(value)}"
+ else:
+ key_value = f"{key}={value}"
+ config_cmd = ["ua", "config", "set", key_value]
+
+ try:
+ subp.subp(config_cmd)
+ except subp.ProcessExecutionError as e:
+ enable_errors.append((key, e))
+
+ if enable_errors:
+ for param, error in enable_errors:
+ LOG.warning('Failure enabling "%s":\n%s', param, error)
+ raise RuntimeError(
+ "Failure enabling Ubuntu Advantage config(s): {}".format(
+ ", ".join('"{}"'.format(param) for param, _ in enable_errors)
+ )
+ )
attach_cmd = ["ua", "attach", token]
LOG.debug("Attaching to Ubuntu Advantage. %s", " ".join(attach_cmd))
try:
@@ -176,9 +273,16 @@ def handle(name, cfg, cloud, log, args):
LOG.error(msg)
raise RuntimeError(msg)
+ config = ua_section.get("config")
+
+ if config is not None:
+ supplemental_schema_validation(config)
+
maybe_install_ua_tools(cloud)
configure_ua(
- token=ua_section.get("token"), enable=ua_section.get("enable")
+ token=ua_section.get("token"),
+ enable=ua_section.get("enable"),
+ config=config,
)