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

feat: add ui support #44

Merged
merged 1 commit into from
May 29, 2024
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
19 changes: 19 additions & 0 deletions rockcraft.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,25 @@ services:
override: replace
startup: enabled

package-repositories:
- type: apt
url: https://deb.nodesource.com/node_20.x
components: [main]
suites: [focal]
key-id: 9FD3B784BC1C6FC31A8A0A1C1655A0AB68576280
- type: apt
url: https://dl.yarnpkg.com/debian/
components: [main]
suites: [stable]
key-id: 72ECF46A56B4AD39C907BBB71646B01B86E50310

parts:

vault:
plugin: go
go-buildtags:
- vault
- ui
source: https://github.com/hashicorp/vault.git
source-tag: v1.15.6
source-type: git
Expand All @@ -28,7 +43,11 @@ parts:
- bin/vault
build-snaps:
- go/1.21/stable
build-packages:
- nodejs
- yarn
override-build: |
make static-dist
craftctl default
strip -s $CRAFT_PART_INSTALL/bin/*

Expand Down
67 changes: 27 additions & 40 deletions tests/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,51 +1,38 @@
# Testing tools configuration
[tool.coverage.run]
branch = true

[tool.coverage.report]
show_missing = true

[tool.black]
line-length = 99
target-version = ["py38"]
[tool.pytest.ini_options]
minversion = "6.0"
log_cli_level = "INFO"

[tool.isort]
profile = "black"
# Linting tools configuration
[tool.ruff]
line-length = 99

[tool.flake8]
max-line-length = 99
max-doc-length = 99
[tool.ruff.lint]
select = ["E", "W", "F", "C", "N", "D", "I001"]
extend-ignore = [
"D203",
"D204",
"D213",
"D215",
"D400",
"D404",
"D406",
"D407",
"D408",
"D409",
"D413",
]
ignore = ["E501", "D107"]

[tool.ruff.lint.mccabe]
max-complexity = 10
exclude = [".git", "__pycache__", ".tox", "build", "dist", "*.egg_info", "venv"]
select = ["E", "W", "F", "C", "N", "R", "D", "H"]
per-file-ignores = ["tests/*:D100,D101,D102,D103,D107"]
docstring-convention = "google"
copyright-check = "True"
copyright-author = "Canonical Ltd."
copyright-regexp = "Copyright\\s\\d{4}([-,]\\d{4})*\\s+%(author)s"

[tool.mypy]
pretty = true
python_version = 3.8
follow_imports = "normal"
warn_redundant_casts = true
warn_unused_ignores = true
warn_unused_configs = true
show_traceback = true
show_error_codes = true
namespace_packages = true
explicit_package_bases = true
check_untyped_defs = true
allow_redefinition = true
[tool.codespell]
skip = "build,lib,venv,icon.svg,.tox,.git,.mypy_cache,.ruff_cache,.coverage"

# Ignore libraries that do not have type hint nor stubs
[[tool.mypy.overrides]]
module = ["flatten_json.*", "git.*"]
ignore_missing_imports = true

[[tool.mypy.overrides]]
module = ["charms.*"]
follow_imports = "silent"

[tool.pytest.ini_options]
minversion = "6.0"
log_cli_level = "INFO"
3 changes: 3 additions & 0 deletions tests/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
hvac
requests
ruff
pyright
pytest
53 changes: 32 additions & 21 deletions tests/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,49 +7,60 @@
import logging
import subprocess
import time
import unittest

import pytest
import requests

from vault import Vault

logger = logging.getLogger(__name__)


def wait_for_vault_to_be_available(timeout: int = 30):
def wait_for_vault_to_be_available(timeout: int = 30) -> None:
"""Wait for Vault to be available."""
initial_time = time.time()
vault = Vault("http://localhost:8200")
while time.time() - initial_time < timeout:
try:
if vault.is_api_available():
logger.info("Vault API is available")
return True
return
except Exception:
pass
time.sleep(1)
raise TimeoutError("Vault is not available after {} seconds".format(timeout))


class TestVaultRock(unittest.TestCase):
"""Integration tests to validate that the Vault ROCK works as expected."""
@pytest.fixture(scope="module")
def run_container():
"""Start a Vault container."""
subprocess.check_call(
"docker run -d -p 8200:8200 vault-rock:test",
shell=True,
)


def test_given_vault_container_running_when_ui_is_enabled_then_ui_is_available(run_container):
"""Validate that UI is available."""
wait_for_vault_to_be_available()
response = requests.get("http://localhost:8200/ui/vault/init")

def setUp(self):
"""Starts a Vault container."""
subprocess.check_call(
"docker run -d -p 8200:8200 vault-rock:test ",
shell=True,
)
assert response.status_code == 200
assert "Vault UI is not available in this binary." not in response.text # This is the message when UI is disabled # noqa: E501
assert "vault/config/environment" in response.text # This is a common element in the UI

def test_given_vault_container_running_when_initialize_then_properly_responds_to_commands(
self,
):
"""Runs basic CLI commands to initialize and unseal Vault."""
vault = Vault("http://localhost:8200")

wait_for_vault_to_be_available()
def test_given_vault_container_running_when_initialize_then_properly_responds_to_commands(
run_container
):
"""Runs basic CLI commands to initialize and unseal Vault."""
vault = Vault("http://localhost:8200")

wait_for_vault_to_be_available()

root_token, unseal_keys = vault.initialize()
_, unseal_keys = vault.initialize()

vault.unseal(unseal_keys)
vault.unseal(unseal_keys)

self.assertEqual(vault.is_initialized(), True)
self.assertEqual(vault.is_sealed(), False)
assert vault.is_initialized()
assert not vault.is_sealed()
36 changes: 5 additions & 31 deletions tests/tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -9,55 +9,29 @@ envlist = integration, lint, fmt, static

[testenv]
deps =
pytest
pytest-operator
-r{toxinidir}/requirements.txt
setenv =
PYTHONPATH = {toxinidir}
PYTHONBREAKPOINT=ipdb.set_trace

[testenv:fmt]
description = Apply coding style standards to code
deps =
black
isort
commands =
isort {toxinidir}
black {toxinidir}
ruff check --fix {[vars]all_path}

[testenv:lint]
description = Check code against coding style standards
deps =
black
flake8
flake8-docstrings
flake8-copyright
flake8-builtins
pyproject-flake8
pep8-naming
isort
commands =
pflake8 {toxinidir}
isort --check-only --diff {toxinidir}
black --check --diff {toxinidir}
ruff check {toxinidir}

[testenv:static]
description = Run static analysis checks
deps =
-r{toxinidir}/requirements.txt
mypy
types-PyYAML
pytest
types-setuptools
types-toml
commands =
mypy {toxinidir} {posargs}
pyright {toxinidir}
setenv =
PYTHONPATH = ""

[testenv:integration]
description = Run integration tests
deps =
pytest
-r{toxinidir}/requirements.txt
commands =
pytest -v --tb native --log-cli-level=INFO -s {posargs} {toxinidir}
pytest -v --tb native --log-cli-level=INFO -s {posargs} {toxinidir}
8 changes: 4 additions & 4 deletions tests/vault.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ def initialize(
return initialize_response["root_token"], initialize_response["keys"]

def is_initialized(self) -> bool:
"""Returns whether Vault is initialized."""
"""Return whether Vault is initialized."""
return self._client.sys.is_initialized()

def is_sealed(self) -> bool:
"""Returns whether Vault is sealed."""
"""Return whether Vault is sealed."""
return self._client.sys.is_sealed()

def unseal(self, unseal_keys: List[str]) -> None:
Expand All @@ -49,7 +49,7 @@ def unseal(self, unseal_keys: List[str]) -> None:
logger.info("Vault is unsealed")

def is_api_available(self) -> bool:
"""Returns whether Vault is available."""
"""Return whether Vault is available."""
self._client.sys.read_health_status()
try:
self._client.sys.read_health_status()
Expand All @@ -58,5 +58,5 @@ def is_api_available(self) -> bool:
return True

def set_token(self, token: str) -> None:
"""Sets the Vault token for authentication."""
"""Set the Vault token for authentication."""
self._client.token = token
Loading