Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion cloudinit/cmd/devel/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import logging

from cloudinit import log
from cloudinit.helpers import Paths
from cloudinit.stages import Init


Expand All @@ -16,7 +17,7 @@ def addLogHandlerCLI(logger, log_level):
return logger


def read_cfg_paths():
def read_cfg_paths() -> Paths:
"""Return a Paths object based on the system configuration on disk."""
init = Init(ds_deps=[])
init.read_cfg()
Expand Down
19 changes: 8 additions & 11 deletions cloudinit/cmd/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
import os
import sys
from time import gmtime, sleep, strftime
from typing import Tuple

from cloudinit.cmd.devel import read_cfg_paths
from cloudinit.distros import uses_systemd
from cloudinit.stages import Init
from cloudinit.util import get_cmdline, load_file, load_json

CLOUDINIT_DISABLED_FILE = "/etc/cloud/cloud-init.disabled"
Expand Down Expand Up @@ -64,17 +65,16 @@ def get_parser(parser=None):
return parser


def handle_status_args(name, args):
def handle_status_args(name, args) -> int:
Comment thread
blackboxsw marked this conversation as resolved.
"""Handle calls to 'cloud-init status' as a subcommand."""
# Read configured paths
init = Init(ds_deps=[])
init.read_cfg()
status, status_detail, time = get_status_details(init.paths)
paths = read_cfg_paths()
status, status_detail, time = get_status_details(paths)
if args.wait:
while status in (UXAppStatus.NOT_RUN, UXAppStatus.RUNNING):
sys.stdout.write(".")
sys.stdout.flush()
status, status_detail, time = get_status_details(init.paths)
status, status_detail, time = get_status_details(paths)
sleep(0.25)
sys.stdout.write("\n")
print("status: {0}".format(status.value))
Expand Down Expand Up @@ -115,17 +115,14 @@ def _is_cloudinit_disabled(disable_file, paths):
return (is_disabled, reason)


def get_status_details(paths=None):
def get_status_details(paths=None) -> Tuple[UXAppStatus, str, str]:
"""Return a 3-tuple of status, status_details and time of last event.

@param paths: An initialized cloudinit.helpers.paths object.

Values are obtained from parsing paths.run_dir/status.json.
"""
if not paths:
init = Init(ds_deps=[])
init.read_cfg()
paths = init.paths
paths = paths or read_cfg_paths()

status = UXAppStatus.NOT_RUN
status_detail = ""
Expand Down
13 changes: 7 additions & 6 deletions cloudinit/stages.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import pickle
import sys
from collections import namedtuple
from typing import Dict, List, Optional, Set
from typing import Dict, Iterable, List, Optional, Set

from cloudinit import cloud, distros, handlers, helpers, importer
from cloudinit import log as logging
Expand Down Expand Up @@ -58,12 +58,12 @@ def update_event_enabled(
case, we only have the data source's `default_update_events`,
so an event that should be enabled in userdata may be denied.
"""
default_events = (
datasource.default_update_events
) # type: Dict[EventScope, Set[EventType]]
user_events = userdata_to_events(
default_events: Dict[
EventScope, Set[EventType]
] = datasource.default_update_events
user_events: Dict[EventScope, Set[EventType]] = userdata_to_events(
cfg.get("updates", {})
) # type: Dict[EventScope, Set[EventType]]
)
# A value in the first will override a value in the second
allowed = util.mergemanydict(
[
Expand All @@ -73,6 +73,7 @@ def update_event_enabled(
)
LOG.debug("Allowed events: %s", allowed)

scopes: Iterable[EventScope]
if not scope:
scopes = allowed.keys()
else:
Expand Down
32 changes: 24 additions & 8 deletions cloudinit/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
import sys
import time
from base64 import b64decode, b64encode
from errno import ENOENT
from collections import deque
from errno import EACCES, ENOENT
from functools import lru_cache
from typing import List
from urllib import parse
Expand Down Expand Up @@ -998,6 +999,7 @@ def read_seeded(base="", ext="", timeout=5, retries=10, file_retries=0):


def read_conf_d(confd):
"""Read configuration directory."""
# Get reverse sorted list (later trumps newer)
confs = sorted(os.listdir(confd), reverse=True)

Expand All @@ -1010,13 +1012,27 @@ def read_conf_d(confd):
# Load them all so that they can be merged
cfgs = []
for fn in confs:
cfgs.append(read_conf(os.path.join(confd, fn)))
try:
cfgs.append(read_conf(os.path.join(confd, fn)))
except OSError as e:
if e.errno == EACCES:
LOG.warning(
"REDACTED config part %s/%s for non-root user", confd, fn
)

return mergemanydict(cfgs)


def read_conf_with_confd(cfgfile):
cfg = read_conf(cfgfile)
cfgs = deque()
cfg: dict = {}
try:
cfg = read_conf(cfgfile)
except OSError as e:
if e.errno == EACCES:
LOG.warning("REDACTED config part %s for non-root user", cfgfile)
else:
cfgs.append(cfg)

confd = False
if "conf_d" in cfg:
Expand All @@ -1032,12 +1048,12 @@ def read_conf_with_confd(cfgfile):
elif os.path.isdir("%s.d" % cfgfile):
confd = "%s.d" % cfgfile

if not confd or not os.path.isdir(confd):
return cfg
if confd and os.path.isdir(confd):
# Conf.d settings override input configuration
confd_cfg = read_conf_d(confd)
cfgs.appendleft(confd_cfg)

# Conf.d settings override input configuration
confd_cfg = read_conf_d(confd)
return mergemanydict([confd_cfg, cfg])
return mergemanydict(cfgs)


def read_conf_from_cmdline(cmdline=None):
Expand Down
5 changes: 0 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ exclude=[
'^cloudinit/sources/DataSourceVMware\.py$',
'^cloudinit/sources/__init__\.py$',
'^cloudinit/sources/helpers/vmware/imc/config_file\.py$',
'^cloudinit/stages\.py$',
'^cloudinit/templater\.py$',
'^cloudinit/url_helper\.py$',
'^conftest\.py$',
Expand All @@ -56,12 +55,9 @@ exclude=[
'^tests/integration_tests/modules/test_growpart\.py$',
'^tests/integration_tests/modules/test_ssh_keysfile\.py$',
'^tests/unittests/__init__\.py$',
'^tests/unittests/cmd/devel/test_render\.py$',
'^tests/unittests/cmd/test_clean\.py$',
'^tests/unittests/cmd/test_cloud_id\.py$',
'^tests/unittests/cmd/test_main\.py$',
'^tests/unittests/cmd/test_query\.py$',
'^tests/unittests/cmd/test_status\.py$',
'^tests/unittests/config/test_cc_chef\.py$',
'^tests/unittests/config/test_cc_landscape\.py$',
'^tests/unittests/config/test_cc_locale\.py$',
Expand Down Expand Up @@ -96,7 +92,6 @@ exclude=[
'^tests/unittests/test_subp\.py$',
'^tests/unittests/test_templating\.py$',
'^tests/unittests/test_url_helper\.py$',
'^tests/unittests/test_util\.py$',
'^tools/mock-meta\.py$',
]

Expand Down
Loading