Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e0c6725
schema: perform validate_cloudcfg_schema once in early boot
blackboxsw Jan 5, 2022
feb5c5e
schema: deliver single JSON schema file and Paths.schema_dir
blackboxsw Jan 7, 2022
5c66261
schema: support legacy module schema and compisite global schema
blackboxsw Jan 7, 2022
12b9504
schema: define schema meta for cc_apt_pipelining
blackboxsw Jan 7, 2022
b1cf0aa
schema: annotation fixes for lists and empty schema
blackboxsw Jan 7, 2022
cfaf67b
schema: clarify schema warning message
blackboxsw Jan 8, 2022
5e8ff02
integration test
blackboxsw Jan 8, 2022
2ea7fce
schema: warn when multiple schema files present, but use the first one
blackboxsw Jan 12, 2022
cf10af4
tests
blackboxsw Jan 12, 2022
dd7e363
tests: apt_pipelining schema tests
blackboxsw Jan 12, 2022
1710170
tests: apt_pipelining spelling
blackboxsw Jan 12, 2022
3bf0220
schema: migrate cc_apk_configure and add schema tests
blackboxsw Jan 12, 2022
2b43a2e
schema: allow CLOUD_INIT_SCHEMA_DIR env override for Paths.schema_dir
blackboxsw Jan 13, 2022
392db85
rebase includes keyboard legacy schema
blackboxsw Jan 13, 2022
8c40933
tox: use setenv in tox so tox -e doc includes defines schema docs
blackboxsw Jan 14, 2022
3473609
schema: deliver cloud-init-schema.json with python modules. Drop path…
blackboxsw Jan 14, 2022
d47ebc3
schema: do not version cloud-init-schema.json yet
blackboxsw Jan 14, 2022
bbbbc43
drop now-irrelevant paths.schema_dir from tests
blackboxsw Jan 14, 2022
a77e879
setup.py: include schema json data file in packaging
blackboxsw Jan 14, 2022
4ff1b3c
testing: no longer mkdir schema_dir
blackboxsw Jan 18, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions cloudinit/cmd/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

patcher.patch_logging()

from cloudinit.config.schema import validate_cloudconfig_schema
from cloudinit import log as logging
from cloudinit import netinfo
from cloudinit import signal_handler
Expand Down Expand Up @@ -474,6 +475,12 @@ def main_init(name, args):
util.logexc(LOG, "Consuming user data failed!")
return (init.datasource, ["Consuming user data failed!"])

# Validate user-data adheres to schema definition
if os.path.exists(init.paths.get_ipath_cur("userdata_raw")):
validate_cloudconfig_schema(config=init.cfg, strict=False)
else:
LOG.debug("Skipping user-data validation. No user-data found.")

apply_reporting_cfg(init.cfg)

# Stage 8 - re-read and apply relevant cloud-config to include user-data
Expand Down
103 changes: 2 additions & 101 deletions cloudinit/config/cc_apk_configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from cloudinit import log as logging
from cloudinit import temp_utils, templater, util
from cloudinit.config.schema import get_meta_doc, validate_cloudconfig_schema
from cloudinit.config.schema import get_meta_doc
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Migrated schema modules will no longer define "schema" attribute or run validate_cloudconfig_schema since we run schema validation one-time against the full schema after the user-data is processed in main.py:480

from cloudinit.settings import PER_INSTANCE

LOG = logging.getLogger(__name__)
Expand Down Expand Up @@ -102,104 +102,7 @@
"frequency": frequency,
}

schema = {
"type": "object",
"properties": {
"apk_repos": {
"type": "object",
"properties": {
"preserve_repositories": {
"type": "boolean",
"default": False,
"description": dedent(
"""\
By default, cloud-init will generate a new repositories
file ``/etc/apk/repositories`` based on any valid
configuration settings specified within a apk_repos
section of cloud config. To disable this behavior and
preserve the repositories file from the pristine image,
set ``preserve_repositories`` to ``true``.

The ``preserve_repositories`` option overrides
all other config keys that would alter
``/etc/apk/repositories``.
"""
),
},
"alpine_repo": {
"type": ["object", "null"],
"properties": {
"base_url": {
"type": "string",
"default": DEFAULT_MIRROR,
"description": dedent(
"""\
The base URL of an Alpine repository, or
mirror, to download official packages from.
If not specified then it defaults to ``{}``
""".format(
DEFAULT_MIRROR
)
),
},
"community_enabled": {
"type": "boolean",
"default": False,
"description": dedent(
"""\
Whether to add the Community repo to the
repositories file. By default the Community
repo is not included.
"""
),
},
"testing_enabled": {
"type": "boolean",
"default": False,
"description": dedent(
"""\
Whether to add the Testing repo to the
repositories file. By default the Testing
repo is not included. It is only recommended
to use the Testing repo on a machine running
the ``Edge`` version of Alpine as packages
installed from Testing may have dependancies
that conflict with those in non-Edge Main or
Community repos."
"""
),
},
"version": {
"type": "string",
"description": dedent(
"""\
The Alpine version to use (e.g. ``v3.12`` or
``edge``)
"""
),
},
},
"required": ["version"],
"minProperties": 1,
"additionalProperties": False,
},
"local_repo_base_url": {
"type": "string",
"description": dedent(
"""\
The base URL of an Alpine repository containing
unofficial packages
"""
),
},
},
"minProperties": 1, # Either preserve_repositories or alpine_repo
"additionalProperties": False,
}
},
}

__doc__ = get_meta_doc(meta, schema)
__doc__ = get_meta_doc(meta)
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.



def handle(name, cfg, cloud, log, _args):
Expand All @@ -222,8 +125,6 @@ def handle(name, cfg, cloud, log, _args):
)
return

validate_cloudconfig_schema(cfg, schema)

# If "preserve_repositories" is explicitly set to True in
# the configuration do nothing.
if util.get_cfg_option_bool(apk_section, "preserve_repositories", False):
Expand Down
63 changes: 34 additions & 29 deletions cloudinit/config/cc_apt_pipelining.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,59 @@
#
# This file is part of cloud-init. See LICENSE file for license information.

"""
Apt Pipelining
--------------
**Summary:** configure apt pipelining
"""Apt Pipelining: configure apt pipelining."""

This module configures apt's ``Acquite::http::Pipeline-Depth`` option, which
controls how apt handles HTTP pipelining. It may be useful for pipelining to be
disabled, because some web servers, such as S3 do not pipeline properly (LP:
#948461). The ``apt_pipelining`` config key may be set to ``false`` to disable
pipelining altogether. This is the default behavior. If it is set to ``none``,
``unchanged``, or ``os``, no change will be made to apt configuration and the
default setting for the distro will be used. The pipeline depth can also be
manually specified by setting ``apt_pipelining`` to a number. However, this is
not recommended.

**Internal name:** ``cc_apt_pipelining``

**Module frequency:** per instance

**Supported distros:** ubuntu, debian

**Config keys**::
apt_pipelining: <false/none/unchanged/os/number>
"""
from textwrap import dedent

from cloudinit import util
from cloudinit.config.schema import get_meta_doc
from cloudinit.settings import PER_INSTANCE

frequency = PER_INSTANCE

distros = ["ubuntu", "debian"]

DEFAULT_FILE = "/etc/apt/apt.conf.d/90cloud-init-pipelining"

APT_PIPE_TPL = (
"//Written by cloud-init per 'apt_pipelining'\n"
'Acquire::http::Pipeline-Depth "%s";\n'
)

# Acquire::http::Pipeline-Depth can be a value
# from 0 to 5 indicating how many outstanding requests APT should send.
# A value of zero MUST be specified if the remote host does not properly linger
# on TCP connections - otherwise data corruption will occur.

meta = {
"id": "cc_apt_pipelining",
"name": "Apt Pipelining",
"title": "Configure apt pipelining",
"description": dedent(
"""\
This module configures apt's ``Acquite::http::Pipeline-Depth`` option,
which controls how apt handles HTTP pipelining. It may be useful for
pipelining to be disabled, because some web servers, such as S3 do not
pipeline properly (LP: #948461).

Value configuration options for this module are:

* ``false`` (Default): disable pipelining altogether
* ``none``, ``unchanged``, or ``os``: use distro default
* ``<number>``: Manually specify pipeline depth. This is not recommended.""" # noqa: E501
),
"distros": distros,
"frequency": frequency,
"examples": [
"apt_pipelining: false",
"apt_pipelining: none",
"apt_pipelining: unchanged",
"apt_pipelining: os",
"apt_pipelining: 3",
],
}

__doc__ = get_meta_doc(meta)

def handle(_name, cfg, _cloud, log, _args):

apt_pipe_value = util.get_cfg_option_str(cfg, "apt_pipelining", "os")
def handle(_name, cfg, _cloud, log, _args):
apt_pipe_value = cfg.get("apt_pipelining", "os")
Comment thread
blackboxsw marked this conversation as resolved.
apt_pipe_value_s = str(apt_pipe_value).lower().strip()

if apt_pipe_value_s == "false":
Expand Down
69 changes: 69 additions & 0 deletions cloudinit/config/cloud-init-schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$defs": {
"cc_apk_configure": {
"type": "object",
"properties": {
"apk_repos": {
"type": "object",
"properties": {
"preserve_repositories": {
"type": "boolean",
"default": false,
"description": "By default, cloud-init will generate a new repositories file ``/etc/apk/repositories`` based on any valid configuration settings specified within a apk_repos section of cloud config. To disable this behavior and preserve the repositories file from the pristine image, set ``preserve_repositories`` to ``true``.\n\n The ``preserve_repositories`` option overrides all other config keys that would alter ``/etc/apk/repositories``."
},
"alpine_repo": {
"type": ["object", "null"],
"properties": {
"base_url": {
"type": "string",
"default": "https://alpine.global.ssl.fastly.net/alpine",
"description": "The base URL of an Alpine repository, or mirror, to download official packages from. If not specified then it defaults to ``https://alpine.global.ssl.fastly.net/alpine``"
},
"community_enabled": {
"type": "boolean",
"default": false,
"description": "Whether to add the Community repo to the repositories file. By default the Community repo is not included."
},
"testing_enabled": {
"type": "boolean",
"default": false,
"description": "Whether to add the Testing repo to the repositories file. By default the Testing repo is not included. It is only recommended to use the Testing repo on a machine running the ``Edge`` version of Alpine as packages installed from Testing may have dependancies that conflict with those in non-Edge Main or Community repos."
},
"version": {
"type": "string",
"description": "The Alpine version to use (e.g. ``v3.12`` or ``edge``)"
}
},
"required": ["version"],
"minProperties": 1,
"additionalProperties": false
},
"local_repo_base_url": {
"type": "string",
"description": "The base URL of an Alpine repository containing unofficial packages"
}
},
"minProperties": 1,
"additionalProperties": false
}
}
},
"cc_apt_pipelining": {
"type": "object",
"properties": {
"apt_pipelining": {
"oneOf": [
{"type": "integer"},
{"type": "boolean"},
{"type": "string", "enum": ["none", "unchanged", "os"]}
]
}
}
}
},
"allOf": [
{ "$ref": "#/$defs/cc_apk_configure" },
{ "$ref": "#/$defs/cc_apt_pipelining" }
]
}
Loading