Skip to content

Commit

Permalink
Add fix, enhancements and pytests for CLI (#1498)
Browse files Browse the repository at this point in the history
* Add fix, enhancements and pytests for CLI

* No zero-padded month for CalVer release branches

* Update cli test

* Simplify test.yaml
  • Loading branch information
iameskild authored Oct 27, 2022
1 parent 734c27e commit 72d855a
Show file tree
Hide file tree
Showing 9 changed files with 126 additions and 26 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/kubernetes_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ on:
push:
branches:
- main
- release/\d{4}.\d{2}.\d{1,2}
- release/\d{4}.\d{1,2}.\d{1,2}
paths:
- ".github/workflows/kubernetes_test.yaml"
- "tests/**"
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/run-pre-commit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
push:
branches:
- main
- release/\d{4}.\d{2}.\d{1,2}
- release/\d{4}.\d{1,2}.\d{1,2}
pull_request:

jobs:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test-provider.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ on:
push:
branches:
- main
- release/\d{4}.\d{2}.\d{1,2}
- release/\d{4}.\d{1,2}.\d{1,2}
paths:
- ".github/workflows/test-provider.yaml"
- "tests/**"
Expand Down
13 changes: 2 additions & 11 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ on:
push:
branches:
- main
- release/\d{4}.\d{2}.\d{1,2}
- release/\d{4}.\d{1,2}.\d{1,2}
paths:
- ".github/workflows/test.yaml"
- "tests/**"
Expand All @@ -27,7 +27,7 @@ on:

jobs:
test-general:
name: 'Test Package'
name: 'Pytest'
runs-on: ubuntu-latest
strategy:
matrix:
Expand All @@ -48,15 +48,6 @@ jobs:
- name: Install Nebari
run: |
pip install .[dev]
- name: Black Formatting
run: |
black --version
black nebari --diff --exclude "nebari/_version.py"
black --check nebari --exclude "nebari/_version.py"
- name: Flake8 Formatting
run: |
flake8 --version
flake8
- name: Test Nebari
run: |
pytest --version
Expand Down
17 changes: 17 additions & 0 deletions nebari/cli/_init.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import os
import re
from pathlib import Path

import questionary
import rich
Expand Down Expand Up @@ -263,13 +265,25 @@ def check_project_name(ctx: typer.Context, project_name: str):
return project_name


def check_ssl_cert_email(ctx: typer.Context, ssl_cert_email: str):
if ssl_cert_email and not re.match("^[^ @]+@[^ @]+\\.[^ @]+$", ssl_cert_email):
raise ValueError("ssl-cert-email should be a valid email address")

return ssl_cert_email


def guided_init_wizard(ctx: typer.Context, guided_init: str):
"""
Guided Init Wizard is a user-friendly questionnaire used to help generate the `nebari-config.yaml`.
"""
qmark = " "
disable_checks = os.environ.get("NEBARI_DISABLE_INIT_CHECKS", False)

if Path("nebari-config.yaml").exists():
raise ValueError(
"A nebari-config.yaml file already exists. Please move or delete it and try again."
)

if not guided_init:
return guided_init

Expand Down Expand Up @@ -459,6 +473,9 @@ def guided_init_wizard(ctx: typer.Context, guided_init: str):
qmark=qmark,
).unsafe_ask()

if not disable_checks:
check_ssl_cert_email(ctx, ssl_cert_email=inputs.ssl_cert_email)

# ADVANCED FEATURES
rich.print(
(
Expand Down
34 changes: 26 additions & 8 deletions nebari/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
check_auth_provider_creds,
check_cloud_provider_creds,
check_project_name,
check_ssl_cert_email,
enum_to_list,
guided_init_wizard,
handle_init,
Expand Down Expand Up @@ -139,6 +140,7 @@ def init(
),
ssl_cert_email: str = typer.Option(
None,
callback=check_ssl_cert_email,
),
disable_prompt: bool = typer.Option(
False,
Expand Down Expand Up @@ -271,7 +273,7 @@ def deploy(
dns_auto_provision: bool = typer.Option(
False,
"--dns-auto-provision",
help="Attempt to automatically provision DNS. For Auth0 is requires environment variables AUTH0_DOMAIN, AUTH0_CLIENTID, AUTH0_CLIENT_SECRET",
help="Attempt to automatically provision DNS, currently only available for `cloudflare`",
),
disable_prompt: bool = typer.Option(
False,
Expand All @@ -283,6 +285,16 @@ def deploy(
"--disable-render",
help="Disable auto-rendering in deploy stage",
),
disable_checks: bool = typer.Option(
False,
"--disable-checks",
help="Disable the checks performed after each stage",
),
skip_remote_state_provision: bool = typer.Option(
True,
"--skip-remote-state-provision",
help="Skip terraform state deployment which is often required in CI once the terraform remote state bootstrapping phase is complete",
),
):
"""
Deploy the Nebari cluster from your [purple]nebari-config.yaml[/purple] file.
Expand All @@ -306,8 +318,8 @@ def deploy(
dns_provider=dns_provider,
dns_auto_provision=dns_auto_provision,
disable_prompt=disable_prompt,
disable_checks=False,
skip_remote_state_provision=False,
disable_checks=disable_checks,
skip_remote_state_provision=skip_remote_state_provision,
)


Expand All @@ -317,7 +329,8 @@ def destroy(
..., "-c", "--config", help="nebari configuration file path"
),
output: str = typer.Option(
"./" "-o",
"./",
"-o",
"--output",
help="output directory",
),
Expand All @@ -335,10 +348,8 @@ def destroy(
"""
Destroy the Nebari cluster from your [purple]nebari-config.yaml[/purple] file.
"""
if not disable_prompt:
if typer.confirm("Are you sure you want to destroy your Nebari cluster?"):
raise typer.Abort()
else:

def _run_destroy(config=config, disable_render=disable_render):
config_filename = Path(config)
if not config_filename.is_file():
raise ValueError(
Expand All @@ -354,6 +365,13 @@ def destroy(

destroy_configuration(config_yaml)

if disable_prompt:
_run_destroy()
elif typer.confirm("Are you sure you want to destroy your Nebari cluster?"):
_run_destroy()
else:
raise typer.Abort()


@app.command(rich_help_panel=SECOND_COMMAND_GROUP_NAME)
def cost(
Expand Down
2 changes: 0 additions & 2 deletions nebari/initialize.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,8 +427,6 @@ def render_config(
config["environments"] = default_environments().copy()

if ssl_cert_email is not None:
if not re.match("^[^ @]+@[^ @]+\\.[^ @]+$", ssl_cert_email):
raise ValueError("ssl-cert-email should be a valid email address")
config["certificate"] = {
"type": "lets-encrypt",
"acme_email": ssl_cert_email,
Expand Down
3 changes: 1 addition & 2 deletions nebari/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,6 @@ def project_name_convention(value: typing.Any, values):
return letter_dash_underscore_pydantic


# CLEAN UP
class InitInputs(Base):
cloud_provider: typing.Type[ProviderEnum] = "local"
project_name: str = ""
Expand All @@ -539,7 +538,7 @@ class InitInputs(Base):
repository: typing.Union[str, None] = None
repository_auto_provision: bool = False
ci_provider: typing.Optional[CiEnum] = None
terraform_state: typing.Optional[TerraformStateEnum] = None
terraform_state: typing.Optional[TerraformStateEnum] = "remote"
kubernetes_version: typing.Union[str, None] = None
ssl_cert_email: typing.Union[str, None] = None
disable_prompt: bool = False
Expand Down
77 changes: 77 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import os
import subprocess
import typing
from pathlib import Path

import pytest

from nebari.schema import InitInputs
from nebari.utils import load_yaml

PROJECT_NAME = "clitest"
DOMAIN_NAME = "clitest.dev"


def run_cli_cmd(command: str, working_dir: typing.Union[str, Path]):
"""Run the provided CLI command using subprocess."""

try:
os.chdir(working_dir)
subprocess.call(command.split())
except subprocess.CalledProcessError:
return False

return True


@pytest.mark.parametrize(
"namespace, auth_provider, ci_provider, ssl_cert_email",
(
[None, None, None, None],
["prod", "github", "github-actions", "it@acme.org"],
),
)
def test_nebari_init(tmp_path, namespace, auth_provider, ci_provider, ssl_cert_email):
"""Test `nebari init` CLI command."""

command = f"nebari init local --project {PROJECT_NAME} --domain {DOMAIN_NAME} --disable-prompt"

default_values = InitInputs()

if namespace:
command += f" --namespace {namespace}"
else:
namespace = default_values.namespace
if auth_provider:
command += f" --auth-provider {auth_provider}"
else:
auth_provider = default_values.auth_provider
if ci_provider:
command += f" --ci-provider {ci_provider}"
else:
ci_provider = default_values.ci_provider
if ssl_cert_email:
command += f" --ssl-cert-email {ssl_cert_email}"
else:
ssl_cert_email = default_values.ssl_cert_email

assert run_cli_cmd(command, tmp_path)

config = load_yaml(tmp_path / "nebari-config.yaml")

assert config.get("namespace") == namespace
assert (
config.get("security", {}).get("authentication", {}).get("type").lower()
== auth_provider
)
ci_cd = config.get("ci_cd", None)
if ci_cd:
assert ci_cd.get("type", {}) == ci_provider
else:
assert ci_cd == ci_provider
ci_cd = config.get("ci_cd", None)
acme_email = config.get("certificate", None)
if acme_email:
assert acme_email.get("acme_email") == ssl_cert_email
else:
assert acme_email == ssl_cert_email

0 comments on commit 72d855a

Please sign in to comment.