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
24 changes: 24 additions & 0 deletions ceph_devstack/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ def parse_args(args: List[str]) -> argparse.Namespace:
parser_config_set = subparsers_config.add_parser("set")
parser_config_set.add_argument("name")
parser_config_set.add_argument("value")
parser_config_unset = subparsers_config.add_parser("unset")
parser_config_unset.add_argument("name")
parser_doc = subparsers.add_parser(
"doctor", help="Check that the system meets requirements"
)
Expand Down Expand Up @@ -129,6 +131,8 @@ class Config(dict):
__slots__ = ["user_obj", "user_path"]

def load(self, config_path: Path | None = None):
args = self.get("args")
self.clear()
parsed = tomlkit.parse((Path(__file__).parent / "config.toml").read_text())
self.update(parsed)
if config_path:
Expand All @@ -140,6 +144,8 @@ def load(self, config_path: Path | None = None):
raise OSError(f"Config file at {self.user_path} not found!")
else:
self.user_obj = {}
if args:
self["args"] = args

def dump(self):
return tomlkit.dumps(self)
Expand Down Expand Up @@ -182,6 +188,24 @@ def set_value(self, name: str, value: str) -> None:
self.user_path.write_text(tomlkit.dumps(self.user_obj).strip())
i += 1

def unset_value(self, name: str) -> None:
path = name.split(".")
obj = self.user_obj
i = 0
last_index = len(path) - 1
while i <= last_index:
if i < last_index:
if path[i] not in obj:
break
obj = obj[path[i]]
elif i == last_index:
obj.pop(path[i])
self.update(self.user_obj)
self.user_path.parent.mkdir(exist_ok=True)
self.user_path.write_text(tomlkit.dumps(self.user_obj).strip())
i += 1
self.load(self.user_path)


config = Config()
config.load()
1 change: 1 addition & 0 deletions ceph_devstack/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"dump": lambda config, args: print(config.dump()),
"get": lambda config, args: print(config.get_value(args.name)),
"set": lambda config, args: print(config.set_value(args.name, args.value)),
"unset": lambda config, args: config.unset_value(args.name),
}

COMMAND_HANDLERS = {
Expand Down
49 changes: 24 additions & 25 deletions tests/test_config.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
import pytest
import tomlkit

from ceph_devstack import config, Config


@pytest.fixture(scope="function")
def test_config(tmp_path) -> Config:
test_config = Config()
config_file = tmp_path / "test_config.toml"
config_file.write_text("")
test_config.load(config_file)
return test_config


class TestConfigDump:
def test_config_dump_returns_string(self):
result = config.dump()
Expand Down Expand Up @@ -54,50 +64,39 @@ def test_get_value_returns_string_for_int(self):


class TestConfigSet:
def test_set_value_simple_key(self, tmp_path):
test_config = Config()
config_file = tmp_path / "test_config.toml"
config_file.write_text("")
test_config.load(config_file)
def test_set_value_simple_key(self, test_config):
test_config.set_value("test_key", "test_value")
assert test_config["test_key"] == "test_value"

def test_set_value_nested_key(self, tmp_path):
test_config = Config()
config_file = tmp_path / "test_config.toml"
config_file.write_text("")
test_config.load(config_file)
def test_set_value_nested_key(self, test_config):
test_config.set_value("test_section.test_key", "test_value")
assert test_config["test_section"]["test_key"] == "test_value"

def test_set_value_updates_user_obj(self, tmp_path):
test_config = Config()
config_file = tmp_path / "test_config.toml"
config_file.write_text("")
test_config.load(config_file)
def test_set_value_updates_user_obj(self, test_config):
test_config.set_value("new_key", "new_value")
assert "new_key" in test_config.user_obj

def test_set_value_creates_intermediate_sections(self, tmp_path):
test_config = Config()
config_file = tmp_path / "test_config.toml"
config_file.write_text("")
test_config.load(config_file)
def test_set_value_creates_intermediate_sections(self, test_config):
test_config.set_value("deep.nested.key", "value")
assert test_config.user_obj["deep"]["nested"]["key"] == "value"

def test_set_value_overrides_existing(self, tmp_path):
test_config = Config()
config_file = tmp_path / "test_config.toml"
config_file.write_text("")
test_config.load(config_file)
def test_set_value_overrides_existing(self, test_config):
original_count = test_config["containers"]["testnode"]["count"]
new_count = original_count + 2
test_config.set_value("containers.testnode.count", str(new_count))
assert test_config["containers"]["testnode"]["count"] != original_count
assert test_config["containers"]["testnode"]["count"] == new_count


class TestConfigUnset:
def test_unset_value_simple_key(self, test_config):
test_config.set_value("test_key", "test_value")
assert "test_key" in test_config
assert test_config["test_key"] == "test_value"
test_config.unset_value("test_key")
assert "test_key" not in test_config


class TestConfigDefaults:
def test_config_defaults(self):
assert config == {
Expand Down
Loading