Skip to content

Commit

Permalink
getting project config from server works
Browse files Browse the repository at this point in the history
  • Loading branch information
holtgrewe committed Nov 3, 2023
1 parent 1ef0cf1 commit 5b81cca
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 47 deletions.
2 changes: 1 addition & 1 deletion requirements/base.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ python-dateutil >=2.8.1,<3.0
# pydantic: typed models and validation
pydantic >=2,<3

# toml parsing if python <3.11
# toml parsing and writing
toml >=0.10.2,<0.11

# typer: typed command line interfaces.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[[projects]]
uuid = "16251f30-1168-41c9-8af6-07c8f40f6860"
import_data_protocol = "http"
import_data_host = "http-host.example.com"
import_data_path = "http-prefix/"
import_data_user = "http-user"
import_data_password = "http-password"

[global]
varfish_server_url = "http://varfish.example.com:8080"
varfish_api_token = "faKeTOKeN"
28 changes: 22 additions & 6 deletions tests/cli/test_projects.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Test CLI for projects API."""

import json
import types
import typing
import uuid

Expand All @@ -12,6 +13,8 @@

from tests.conftest import FakeFs
from varfish_cli.cli import app
from varfish_cli.cli.projects import cli_project_load_config
from varfish_cli.config import CommonOptions


@pytest.fixture
Expand Down Expand Up @@ -112,17 +115,17 @@ def test_project_retrieve(
snapshot.assert_match(result.output, "result_output")


def test_project_load_config(
runner: CliRunner,
def test_project_load_config_raw_func_call(
fake_fs_configured: FakeFs,
requests_mock: RequestsMocker,
fake_conn: typing.Tuple[str, str],
project_retrieve_result,
snapshot: Snapshot,
mocker: MockerFixture,
):
mocker.patch("varfish_cli.config.open", fake_fs_configured.open_, create=True)
mocker.patch("varfish_cli.config.os", fake_fs_configured.os)
mocker.patch("varfish_cli.cli.projects.open", fake_fs_configured.open_, create=True)
mocker.patch("varfish_cli.cli.projects.os", fake_fs_configured.os, create=True)

responses = {
"import_data_host": ("STRING", "http-host.example.com"),
Expand All @@ -133,7 +136,7 @@ def test_project_load_config(
"import_data_user": ("STRING", "http-user"),
}

project_uuid = str(uuid.uuid4())
project_uuid = "16251f30-1168-41c9-8af6-07c8f40f6860"
host, token = fake_conn
req_mocks = []
for setting_name, (setting_type, setting_value) in responses.items():
Expand All @@ -155,7 +158,21 @@ def test_project_load_config(
},
)
)
result = runner.invoke(app, ["--verbose", "projects", "project-load-config", project_uuid])

ctx = types.SimpleNamespace(
obj=CommonOptions(
verbose=True,
verify_ssl=False,
config=None,
varfish_server_url=host,
varfish_api_token=token,
)
)
cli_project_load_config(
ctx,
project_uuid=project_uuid,
config_path=fake_fs_configured.os.path.expanduser("~/.varfishrc.toml"),
)

rc_path = fake_fs_configured.os.path.expanduser("~/.varfishrc.toml")
with fake_fs_configured.open_(rc_path, "rt") as inputf:
Expand All @@ -166,5 +183,4 @@ def test_project_load_config(
for req_mock in req_mocks:
assert req_mock.called_once, req_mock._netloc

assert result.exit_code == 0, result.output
snapshot.assert_match(fcontents, "result_output")
1 change: 0 additions & 1 deletion tests/test_config.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import json

import pydantic
from pytest_snapshot.plugin import Snapshot

from varfish_cli import config
Expand Down
6 changes: 4 additions & 2 deletions varfish_cli/api/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def project_settings_retrieve(
app_name: typing.Optional[str],
setting_name: typing.Optional[str],
verify_ssl: bool = True,
) -> SettingsEntry:
) -> SettingsEntry:
server_url = strip_trailing_slash(server_url)
queries = []
if app_name:
Expand All @@ -69,7 +69,9 @@ def project_settings_retrieve(
query = "&".join(queries)
if query:
query = f"?{query}"
endpoint = f"{server_url}{ENDPOINT_PROJECT_SETTING_RETRIEVE}{query}".format(project_uuid=project_uuid)
endpoint = f"{server_url}{ENDPOINT_PROJECT_SETTING_RETRIEVE}{query}".format(
project_uuid=project_uuid
)
logger.debug("Sending GET request to end point %s", endpoint)
headers = {"Authorization": "Token %s" % api_token}
result = requests.get(endpoint, headers=headers, verify=verify_ssl)
Expand Down
4 changes: 1 addition & 3 deletions varfish_cli/cli/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,10 @@

from varfish_cli import __version__
from varfish_cli.cli import cases, importer, projects, varannos
from varfish_cli.cli.common import DEFAULT_PATH_VARFISHRC
from varfish_cli.config import CommonOptions, load_config
from varfish_cli.exceptions import InvalidConfiguration

#: Paths to search the global configuration in.
DEFAULT_PATH_VARFISHRC = "~/.varfishrc.toml"


def version_callback(value: bool):
"""Callback when called with 'version' or '--version'"""
Expand Down
4 changes: 4 additions & 0 deletions varfish_cli/cli/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
from varfish_cli.common import OutputFormat
from varfish_cli.exceptions import RestApiCallException

#: Paths to search the global configuration in.
DEFAULT_PATH_VARFISHRC = "~/.varfishrc.toml"


#: Type to use for model in the helper classes below.
ModelType = typing.TypeVar("ModelType", bound=pydantic.BaseModel)

Expand Down
43 changes: 21 additions & 22 deletions varfish_cli/cli/projects.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,17 @@
"""Implementation of varfish-cli subcommand "projects *"."""

import os

try:
import tomllib
from tomllib import TOMLDecodeError
except ImportError:
import toml as tomllib
from toml import TomlDecodeError as TOMLDecodeError

import typing
import uuid

from logzero import logger
import toml
import typer

from varfish_cli import api, common
from varfish_cli.cli import DEFAULT_PATH_VARFISHRC
from varfish_cli.cli.common import ListObjects, RetrieveObject
from varfish_cli.cli.common import DEFAULT_PATH_VARFISHRC, ListObjects, RetrieveObject
from varfish_cli.common import OutputFormat
from varfish_cli.config import CommonOptions
from varfish_cli.config import ProjectConfig

#: Default fields for projects.
DEFAULT_FIELDS_PROJECT: typing.Dict[OutputFormat, typing.Optional[typing.Tuple[str, ...]]] = {
Expand Down Expand Up @@ -100,9 +92,6 @@ def cli_project_load_config(
str,
typer.Option("--config-path", help="Path to configuration file", envvar="VARFISH_RC_PATH"),
] = DEFAULT_PATH_VARFISHRC,
output_file: typing.Annotated[
str, typer.Option("--output-file", help="Path to file to write to")
] = "-",
):
"""Load project configuration for import and store in ~/.varfishrc.toml"""
common_options: common.CommonOptions = ctx.obj
Expand All @@ -117,7 +106,7 @@ def cli_project_load_config(
"import_data_user": str,
}

kwargs = {}
kwargs = {"uuid": project_uuid}
for field_name, field_type in fields_types.items():
logger.debug(" - retrieving %s", field_name)
setting_entry = api.project_settings_retrieve(
Expand All @@ -128,23 +117,33 @@ def cli_project_load_config(
setting_name=field_name,
verify_ssl=common_options.verify_ssl,
)
print(setting_entry)
if setting_entry.value:
kwargs[field_name] = field_type(setting_entry.value)
print(kwargs)
project_config = ProjectConfig(**kwargs).model_dump(mode="json")

logger.info("... all data retrieved, updating config...")
logger.debug(" - project_config: %s", project_config)

if not os.path.exists(config_path):
if os.path.exists(config_path):
with open(config_path, "rt") as tomlf:
try:
config_toml = tomllib.loads(tomlf.read())
except TOMLDecodeError as e:
config_toml = toml.loads(tomlf.read())
except toml.TomlDecodeError as e:
logger.error("could not parse configuration file %s: %s", config_path, e)
raise typer.Exit(1)
else:
config_toml = {}

config_toml.setdefault("paths", [])
config_toml.setdefault("projects", [])
match_idx = None
for idx, project in enumerate(config_toml["projects"]):
if project["project"] == str(project_config["uuid"]):
match_idx = idx
break
else:
config_toml["projects"].append(project_config)
if match_idx is not None:
config_toml["projects"][match_idx] = project_config

print(kwargs)
with open(config_path, "wt") as outputf:
outputf.write(toml.dumps(config_toml))
17 changes: 5 additions & 12 deletions varfish_cli/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,12 @@

import enum
import os
import uuid

try:
import tomllib
from tomllib import TOMLDecodeError
except ImportError:
import toml as tomllib
from toml import TomlDecodeError as TOMLDecodeError

import typing
import uuid

from logzero import logger
import pydantic
import toml
import typer


Expand Down Expand Up @@ -49,8 +42,8 @@ def load_config(config_path: str) -> typing.Tuple[typing.Optional[str], typing.O
logger.debug("loading configuration from %s", config_path)
with open(config_path, "rt") as tomlf:
try:
config_toml = tomllib.loads(tomlf.read())
except TOMLDecodeError as e:
config_toml = toml.loads(tomlf.read())
except toml.TomlDecodeError as e:
logger.error("could not parse configuration file %s: %s", config_path, e)
raise typer.Exit(1)
toml_varfish_server_url = config_toml.get("global", {}).get("varfish_server_url")
Expand Down Expand Up @@ -108,7 +101,7 @@ def load_projects(config_path: str) -> typing.Dict[uuid.UUID, ProjectConfig]:

with open(config_path, "rt") as inputf:
fcontents = inputf.read()
toml_dict = tomllib.loads(fcontents)
toml_dict = toml.loads(fcontents)

projects = list(map(ProjectConfig.model_validate, toml_dict.get("projects", [])))
return {p.uuid: p for p in projects}

0 comments on commit 5b81cca

Please sign in to comment.