Skip to content

Commit

Permalink
chore(exception): Replace errno with proper exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
holmanb committed Apr 30, 2024
1 parent bce5e4d commit c4bb864
Show file tree
Hide file tree
Showing 17 changed files with 53 additions and 100 deletions.
25 changes: 8 additions & 17 deletions cloudinit/config/cc_mcollective.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@

""" Mcollective: Install, configure and start mcollective"""

import errno
import io
import logging
from contextlib import suppress
from textwrap import dedent

# Used since this can maintain comments
Expand Down Expand Up @@ -100,15 +100,12 @@ def configure(
try:
old_contents = util.load_binary_file(server_cfg, quiet=False)
mcollective_config = ConfigObj(io.BytesIO(old_contents))
except OSError as e:
if e.errno != errno.ENOENT:
raise
else:
LOG.debug(
"Did not find file %s (starting with an empty config)",
server_cfg,
)
mcollective_config = ConfigObj()
except FileNotFoundError:
LOG.debug(
"Did not find file %s (starting with an empty config)",
server_cfg,
)
mcollective_config = ConfigObj()
for cfg_name, cfg in config.items():
if cfg_name == "public-cert":
util.write_file(pubcert_file, cfg, mode=0o644)
Expand All @@ -133,16 +130,10 @@ def configure(
# Otherwise just try to convert it to a string
mcollective_config[cfg_name] = str(cfg)

try:
with suppress(FileNotFoundError):
# We got all our config as wanted we'll copy
# the previous server.cfg and overwrite the old with our new one
util.copy(server_cfg, "%s.old" % (server_cfg))
except OSError as e:
if e.errno == errno.ENOENT:
# Doesn't exist to copy...
pass
else:
raise

# Now we got the whole (new) file, write to disk...
contents = io.BytesIO()
Expand Down
14 changes: 4 additions & 10 deletions cloudinit/config/cc_power_state_change.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

"""Power State Change: Change power state"""

import errno
import logging
import os
import re
Expand Down Expand Up @@ -229,8 +228,6 @@ def fatal(msg):
LOG.warning(msg)
doexit(EXIT_FAIL)

known_errnos = (errno.ENOENT, errno.ESRCH)

while True:
if time.time() > end_time:
msg = "timeout reached before %s ended" % pid
Expand All @@ -241,14 +238,11 @@ def fatal(msg):
if cmdline != pidcmdline:
msg = "cmdline changed for %s [now: %s]" % (pid, cmdline)
break

except OSError as ioerr:
if ioerr.errno in known_errnos:
msg = "pidfile gone [%d]" % ioerr.errno
else:
fatal("OSError during wait: %s" % ioerr)
except (ProcessLookupError, FileNotFoundError):
msg = "pidfile gone"
break

except OSError as ioerr:
fatal("OSError during wait: %s" % ioerr)
except Exception as e:
fatal("Unexpected Exception: %s" % e)

Expand Down
9 changes: 3 additions & 6 deletions cloudinit/config/cc_resizefs.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

"""Resizefs: cloud-config module which resizes the filesystem"""

import errno
import logging
import os
import re
Expand Down Expand Up @@ -233,19 +232,17 @@ def maybe_get_writable_device_path(devpath, info):

try:
statret = os.stat(devpath)
except OSError as exc:
if container and exc.errno == errno.ENOENT:
except FileNotFoundError:
if container:
LOG.debug(
"Device '%s' did not exist in container. cannot resize: %s",
devpath,
info,
)
elif exc.errno == errno.ENOENT:
else:
LOG.warning(
"Device '%s' did not exist. cannot resize: %s", devpath, info
)
else:
raise exc
return None

if not stat.S_ISBLK(statret.st_mode) and not stat.S_ISCHR(statret.st_mode):
Expand Down
15 changes: 6 additions & 9 deletions cloudinit/config/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from contextlib import suppress
from copy import deepcopy
from enum import Enum
from errno import EACCES
from functools import partial
from itertools import chain
from typing import (
Expand Down Expand Up @@ -1723,14 +1722,12 @@ def get_processed_or_fallback_path(

try:
paths = read_cfg_paths(fetch_existing_datasource="trust")
except OSError as e:
if e.errno == EACCES:
LOG.debug(
"Using default instance-data/user-data paths for non-root user"
)
paths = read_cfg_paths()
else:
raise
except PermissionError:
LOG.debug(
"Using default instance-data/user-data "
"paths with insufficient permissions"
)
paths = read_cfg_paths()
except DataSourceNotFoundException:
paths = read_cfg_paths()
LOG.warning(
Expand Down
4 changes: 3 additions & 1 deletion cloudinit/net/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,10 @@ def read_sys_net_safe(iface, field):
iface,
field,
)
except (FileNotFoundError, NotADirectoryError):
return False
except OSError as e:
if e.errno in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL):
if e.errno == errno.EINVAL:
return False
raise

Expand Down
11 changes: 4 additions & 7 deletions cloudinit/sources/DataSourceAltCloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
instance on RHEVm and vSphere.
"""

import errno
import logging
import os
import os.path
Expand Down Expand Up @@ -213,9 +212,8 @@ def user_data_rhevm(self):

try:
return_str = util.mount_cb(floppy_dev, read_user_data_callback)
except OSError as err:
if err.errno != errno.ENOENT:
raise
except FileNotFoundError:
pass
except util.MountFailedError:
util.logexc(
LOG,
Expand Down Expand Up @@ -253,9 +251,8 @@ def user_data_vsphere(self):
if return_str:
self.source = cdrom_dev
break
except OSError as err:
if err.errno != errno.ENOENT:
raise
except FileNotFoundError:
pass
except util.MountFailedError:
util.logexc(
LOG,
Expand Down
11 changes: 3 additions & 8 deletions cloudinit/sources/DataSourceBigstep.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
#
# This file is part of cloud-init. See LICENSE file for license information.

import errno
import json
import os

Expand Down Expand Up @@ -41,16 +40,12 @@ def _get_url_from_file(self):
self.paths.cloud_dir, "data", "seed", "bigstep", "url"
)
try:
content = util.load_text_file(url_file)
except OSError as e:
return util.load_text_file(url_file)
except FileNotFoundError:
# If the file doesn't exist, then the server probably isn't a
# Bigstep instance; otherwise, another problem exists which needs
# investigation
if e.errno == errno.ENOENT:
return None
else:
raise
return content
return None


# Used to match classes to dependencies
Expand Down
6 changes: 2 additions & 4 deletions cloudinit/sources/DataSourceNoCloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#
# This file is part of cloud-init. See LICENSE file for license information.

import errno
import logging
import os
from functools import partial
Expand Down Expand Up @@ -142,9 +141,8 @@ def _pp2d_callback(mp, data):
LOG.debug("Using data from %s", dev)
found.append(dev)
break
except OSError as e:
if e.errno != errno.ENOENT:
raise
except FileNotFoundError:
pass
except util.MountFailedError:
util.logexc(
LOG, "Failed to mount %s when looking for data", dev
Expand Down
6 changes: 2 additions & 4 deletions cloudinit/sources/DataSourceRbxCloud.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
This file contains code used to gather the user data passed to an
instance on rootbox / hyperone cloud platforms
"""
import errno
import logging
import os
import os.path
Expand Down Expand Up @@ -96,9 +95,8 @@ def get_md():
)
if rbx_data:
return rbx_data
except OSError as err:
if err.errno != errno.ENOENT:
raise
except FileNotFoundError:
pass
except util.MountFailedError:
util.logexc(
LOG, "Failed to mount %s when looking for user data", device
Expand Down
9 changes: 2 additions & 7 deletions cloudinit/sources/DataSourceSmartOS.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@

import base64
import binascii
import errno
import fcntl
import json
import logging
Expand Down Expand Up @@ -445,12 +444,8 @@ def as_ascii():
if byte == b"\n":
return as_ascii()
response.append(byte)
except OSError as exc:
if exc.errno == errno.EAGAIN:
raise JoyentMetadataTimeoutException(
msg % as_ascii()
) from exc
raise
except BlockingIOError as e:
raise JoyentMetadataTimeoutException(msg % as_ascii()) from e

def _write(self, msg):
self.fp.write(msg.encode("ascii"))
Expand Down
7 changes: 2 additions & 5 deletions cloudinit/temp_utils.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# This file is part of cloud-init. See LICENSE file for license information.

import contextlib
import errno
import logging
import os
import shutil
import tempfile
from contextlib import suppress

from cloudinit import util

Expand Down Expand Up @@ -71,11 +71,8 @@ def ExtendedTemporaryFile(**kwargs):
# file to unlink has been unlinked elsewhere..

def _unlink_if_exists(path):
try:
with suppress(FileNotFoundError):
os.unlink(path)
except OSError as e:
if e.errno != errno.ENOENT:
raise e

fh.unlink = _unlink_if_exists

Expand Down
7 changes: 3 additions & 4 deletions tests/unittests/cmd/test_query.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# This file is part of cloud-init. See LICENSE file for license information.

import errno
import gzip
import json
import os
Expand Down Expand Up @@ -167,16 +166,16 @@ def test_handle_args_error_when_no_read_permission_instance_data(
varname=None,
)
with mock.patch(M_PATH + "util.load_binary_file") as m_load:
m_load.side_effect = OSError(errno.EACCES, "Not allowed")
m_load.side_effect = PermissionError("Not allowed")
assert 1 == query.handle_args("anyname", args)
msg = "No read permission on '%s'. Try sudo" % noread_fn
assert msg in caplog.text

@pytest.mark.parametrize(
"exception",
[
(OSError(errno.EACCES, "Not allowed"),),
(OSError(errno.ENOENT, "Not allowed"),),
(PermissionError("Not allowed"),),
(FileNotFoundError("Not allowed"),),
(OSError,),
],
)
Expand Down
5 changes: 1 addition & 4 deletions tests/unittests/config/test_cc_growpart.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# This file is part of cloud-init. See LICENSE file for license information.
# pylint: disable=attribute-defined-outside-init

import errno
import logging
import os
import re
Expand Down Expand Up @@ -361,9 +360,7 @@ def mystat(path):
if path in devs:
return devstat_ret
if path in enoent:
e = OSError("%s: does not exist" % path)
e.errno = errno.ENOENT
raise e
raise FileNotFoundError("%s: does not exist" % path)
return real_stat(path)

opinfo = self.distro.device_part_info
Expand Down
10 changes: 5 additions & 5 deletions tests/unittests/config/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import unittest
from collections import namedtuple
from copy import deepcopy
from errno import EACCES
from pathlib import Path
from textwrap import dedent
from types import ModuleType
Expand Down Expand Up @@ -2589,8 +2588,11 @@ class TestHandleSchemaArgs:
"failure, expected_logs",
(
(
OSError("No permissions on /var/lib/cloud/instance"),
["Using default instance-data/user-data paths for non-root"],
PermissionError("No permissions on /var/lib/cloud/instance"),
[
"Using default instance-data/user-data paths with "
"insufficient permissions"
],
),
(
DataSourceNotFoundException("No cached datasource found yet"),
Expand All @@ -2609,8 +2611,6 @@ def test_handle_schema_unable_to_read_cfg_paths(
caplog,
tmpdir,
):
if isinstance(failure, OSError):
failure.errno = EACCES
read_cfg_paths.side_effect = [failure, paths]
user_data_fn = tmpdir.join("user-data")
with open(user_data_fn, "w") as f:
Expand Down
Loading

0 comments on commit c4bb864

Please sign in to comment.