Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

App Config Schema #213

Merged
merged 5 commits into from
Jan 26, 2024
Merged

App Config Schema #213

merged 5 commits into from
Jan 26, 2024

Conversation

snaselj
Copy link
Contributor

@snaselj snaselj commented Jan 17, 2024

Closes: NaN

What's Changed

  • Added invoke generate-app-config-schema command to generate a JSON schema for the App config.
  • Added invoke validate-app-config command to validate the App config against the schema.
  • Added App config JSON schema.
  • Merged pylint, check-migrations and validate-app-config to single CI Job check-in-docker.

@snaselj snaselj marked this pull request as ready for review January 17, 2024 11:57
Comment on lines 10 to 18
"cisco_ios": {
"type": "string",
"default": {}
},
"arista_eos": {
"type": "string",
"default": {}
}
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an example and not the schema, this setting is only {} be default

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

tasks.py Outdated
Comment on lines 826 to 837
@task
def generate_app_config_schema(context):
"""Generate the app config schema based on the app config."""
start(context, service="nautobot")
nbshell(context, file="development/app_config_schema.py", env={"APP_CONFIG_SCHEMA_COMMAND": "generate"})


@task
def validate_app_config(context):
"""Validate the app config based on the app config schema."""
start(context, service="nautobot")
nbshell(context, plain=True, file="development/app_config_schema.py", env={"APP_CONFIG_SCHEMA_COMMAND": "validate"})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this have to run via nbshell since it's importing the app config?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lampwins I think there may be efforts to explore adding this to startup and being done by core right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To import the App config class, it's necessary to do it in initialized Nautobot / Django environment. It is possible to use AST parser instead, but this seems to be a more simple solution.

Another step is to deprecate default_settings and required_settings config class properties, and replace it with JSON schema. For Nautobot 2.x, it can work the way, that when the schema file is present, it will be used and deprecation message will be logged out. In Nautobot 3.x, we can remove these properties.

Another improvement I suggest, is to store the App configuration as a property of it's config class, e.g. NautobotAppConfig.settings. All apps code then can use this, instead of accessing django.PLUGINS_CONFIG.

WDYT @whitej6 @lampwins ?

Comment on lines +14 to +23
def _enrich_object_schema(schema, defaults, required):
schema["additionalProperties"] = False
for key, value in schema["properties"].items():
if required and key in required:
value["required"] = True
default_value = defaults and defaults.get(key, None)
if value["type"] == "object" and "properties" in value:
_enrich_object_schema(value, default_value, None)
elif default_value is not None:
value["default"] = default_value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lampwins FYI apps is looking into providing as part of the dev env the ability to dynamically generate the json schema based on the required and default settings in the app config. The schema is held in the root of the package app-config-schema.json.

Also in going through this I have a suspicion that our heavy use of parsing the app config in a constance.py breaks lazy loading. For MOST scenarios this is not problematic but it breaks some out of the box behaviors for django when using the override setting decorator.

Comment on lines -139 to +140
check-migrations:
needs:
- "bandit"
- "ruff"
- "flake8"
- "poetry"
- "yamllint"
- "black"
runs-on: "ubuntu-22.04"
strategy:
fail-fast: true
matrix:
python-version: ["3.11"]
nautobot-version: ["2.0.0"]
env:
INVOKE_NAUTOBOT_FIREWALL_MODELS_PYTHON_VER: "${{ matrix.python-version }}"
INVOKE_NAUTOBOT_FIREWALL_MODELS_NAUTOBOT_VER: "${{ matrix.nautobot-version }}"
steps:
- name: "Check out repository code"
uses: "actions/checkout@v4"
- name: "Setup environment"
uses: "networktocode/gh-action-setup-poetry-environment@v4"
- name: "Set up Docker Buildx"
id: "buildx"
uses: "docker/setup-buildx-action@v3"
- name: "Build"
uses: "docker/build-push-action@v5"
with:
builder: "${{ steps.buildx.outputs.name }}"
context: "./"
push: false
load: true
tags: "${{ env.APP_NAME }}/nautobot:${{ matrix.nautobot-version }}-py${{ matrix.python-version }}"
file: "./development/Dockerfile"
cache-from: "type=gha,scope=${{ matrix.nautobot-version }}-py${{ matrix.python-version }}"
cache-to: "type=gha,scope=${{ matrix.nautobot-version }}-py${{ matrix.python-version }}"
build-args: |
NAUTOBOT_VER=${{ matrix.nautobot-version }}
PYTHON_VER=${{ matrix.python-version }}
- name: "Copy credentials"
run: "cp development/creds.example.env development/creds.env"
- name: "Checking: App Config"
run: "poetry run invoke validate-app-config"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change should defer to dev standards. I understand why but we lose some high level visibility when combining 3 tests into one CI task

"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": f"https://raw.githubusercontent.com/{owner}/{repository}/develop/{package_name}/app-config-schema.json",
"$comment": "TBD: Update $id, replace `develop` with the future release tag",
**SchemaBuilder().to_json_schema(app_config), # type: ignore
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we're generating the schema based on the example provided in development/nautobot_config.py? That seems fragile to me - depending on the app I'd think that the development config often may not match the full configuration possible for the app.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct, this invoke task is just a helper to quickly get something from the current configuration. Needs to be updated by the user.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make sure that's documented very clearly then. :-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added warning statement to invoke task docstring and stdout.

@itdependsnetworks
Copy link
Contributor

I think it would be good to get the testing structure in place so as the schema get's more complicated, we can just provide mock valid and mock invalid configs for regression testings.

@snaselj
Copy link
Contributor Author

snaselj commented Jan 19, 2024

I think it would be good to get the testing structure in place so as the schema get's more complicated, we can just provide mock valid and mock invalid configs for regression testings.

Agreed, I would postpone to create such test to the stage when the validation will be done in the app, and implement that in unittest. Currently, we are preparing JSON schemas only, without real usage in app and validation is in invoke task only.

@itdependsnetworks
Copy link
Contributor

Seems fair

@snaselj snaselj requested a review from whitej6 January 26, 2024 04:32
@snaselj snaselj merged commit fbb7c77 into develop Jan 26, 2024
15 checks passed
@snaselj snaselj deleted the u/snaselj-config-schema branch January 26, 2024 15:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants