add option to exclude config overrides from file

This commit is contained in:
Robert Kaussow 2020-03-08 15:39:22 +01:00
parent 5bbb016119
commit 16c32caec8
4 changed files with 39 additions and 18 deletions

3
.gitignore vendored
View File

@ -106,3 +106,6 @@ pip-wheel-metadata
docs/themes/ docs/themes/
docs/public/ docs/public/
resources/_gen/ resources/_gen/
# Misc
.dockertidy*

View File

@ -31,6 +31,7 @@ class DockerTidy:
parser.add_argument( parser.add_argument(
"--dry-run", "--dry-run",
action="store_true", action="store_true",
default=None,
dest="dry_run", dest="dry_run",
help="Only log actions, don't stop anything." help="Only log actions, don't stop anything."
) )
@ -52,7 +53,7 @@ class DockerTidy:
"--version", action="version", version="%(prog)s {}".format(__version__) "--version", action="version", version="%(prog)s {}".format(__version__)
) )
subparsers = parser.add_subparsers(help="sub-command help") subparsers = parser.add_subparsers(dest="command", help="sub-command help")
parser_gc = subparsers.add_parser("gc", help="Run docker garbage collector.") parser_gc = subparsers.add_parser("gc", help="Run docker garbage collector.")
parser_gc.add_argument( parser_gc.add_argument(

View File

@ -14,6 +14,7 @@ import dockertidy.Exception
import dockertidy.Parser import dockertidy.Parser
from dockertidy.Parser import env from dockertidy.Parser import env
from dockertidy.Utils import Singleton from dockertidy.Utils import Singleton
from dockertidy.Utils import dict_intersect
config_dir = AppDirs("docker-tidy").user_config_dir config_dir = AppDirs("docker-tidy").user_config_dir
default_config_file = os.path.join(config_dir, "config.yml") default_config_file = os.path.join(config_dir, "config.yml")
@ -29,6 +30,9 @@ class Config():
""" """
SETTINGS = { SETTINGS = {
"command": {
"default": "",
},
"config_file": { "config_file": {
"default": "", "default": "",
"env": "CONFIG_FILE", "env": "CONFIG_FILE",
@ -134,9 +138,12 @@ class Config():
return normalized return normalized
def _get_defaults(self): def _get_defaults(self, files=False):
normalized = {} normalized = {}
for key, item in self.SETTINGS.items(): for key, item in self.SETTINGS.items():
if files and not item.get("file"):
continue
normalized = self._add_dict_branch(normalized, key.split("."), item["default"]) normalized = self._add_dict_branch(normalized, key.split("."), item["default"])
self.schema = anyconfig.gen_schema(normalized) self.schema = anyconfig.gen_schema(normalized)
@ -165,6 +172,7 @@ class Config():
args = self._get_args(self._args) args = self._get_args(self._args)
envs = self._get_envs() envs = self._get_envs()
defaults = self._get_defaults() defaults = self._get_defaults()
files_raw = self._get_defaults(files=True)
# preset config file path # preset config file path
if envs.get("config_file"): if envs.get("config_file"):
@ -179,23 +187,25 @@ class Config():
source_files.append(os.path.join(os.getcwd(), ".dockertidy.yml")) source_files.append(os.path.join(os.getcwd(), ".dockertidy.yml"))
source_files.append(os.path.join(os.getcwd(), ".dockertidy.yaml")) source_files.append(os.path.join(os.getcwd(), ".dockertidy.yaml"))
for config in source_files: for config in [i for i in source_files if os.path.exists(i)]:
if config and os.path.exists(config):
with open(config, "r", encoding="utf8") as stream: with open(config, "r", encoding="utf8") as stream:
s = stream.read() s = stream.read()
try: try:
file_dict = ruamel.yaml.safe_load(s) normalized = ruamel.yaml.safe_load(s)
except ( except (ruamel.yaml.composer.ComposerError, ruamel.yaml.scanner.ScannerError) as e:
ruamel.yaml.composer.ComposerError, ruamel.yaml.scanner.ScannerError
) as e:
message = "{} {}".format(e.context, e.problem) message = "{} {}".format(e.context, e.problem)
raise dockertidy.Exception.ConfigError( raise dockertidy.Exception.ConfigError(
"Unable to read config file {}".format(config), message "Unable to read config file {}".format(config), message
) )
if self._validate(file_dict): if self._validate(normalized):
anyconfig.merge(defaults, file_dict, ac_merge=anyconfig.MS_DICTS) anyconfig.merge(files_raw, normalized, ac_merge=anyconfig.MS_DICTS)
defaults["logging"]["level"] = defaults["logging"]["level"].upper() files_raw["logging"]["level"] = files_raw["logging"]["level"].upper()
files = dict_intersect(files_raw, self._get_defaults(files=True))
if self._validate(files):
anyconfig.merge(defaults, files, ac_merge=anyconfig.MS_DICTS)
if self._validate(envs): if self._validate(envs):
anyconfig.merge(defaults, envs, ac_merge=anyconfig.MS_DICTS) anyconfig.merge(defaults, envs, ac_merge=anyconfig.MS_DICTS)

View File

@ -8,6 +8,13 @@ def to_bool(string):
return bool(strtobool(str(string))) return bool(strtobool(str(string)))
def dict_intersect(d1, d2):
return {
k: dict_intersect(d1[k], d2[k]) if isinstance(d1[k], dict) else d1[k]
for k in d1.keys() & d2.keys()
}
class Singleton(type): class Singleton(type):
"""Singleton metaclass.""" """Singleton metaclass."""