Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 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
1 change: 1 addition & 0 deletions index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ testcontainers-python facilitates the use of Docker containers for functional an
modules/redis/README
modules/registry/README
modules/selenium/README
modules/vault/README
modules/weaviate/README

Getting Started
Expand Down
2 changes: 2 additions & 0 deletions modules/vault/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.. autoclass:: testcontainers.vault.VaultContainer
.. title:: testcontainers.vault.VaultContainer
64 changes: 64 additions & 0 deletions modules/vault/testcontainers/vault/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

from urllib.request import urlopen
from http.client import HTTPException
from testcontainers.core.container import DockerContainer
from testcontainers.core.utils import raise_for_deprecated_parameter
from testcontainers.core.waiting_utils import wait_container_is_ready


class VaultContainer(DockerContainer):
"""
Vault container.

Example:

.. doctest::

>>> from testcontainers.vault import VaultContainer

>>> with VaultContainer("hashicorp/vault:1.16.1") as vault_container:
... connection_url = vault_container.get_connection_url()
... root_token = vault_container.root_token
"""
def __init__(self, image: str = "hashicorp/vault:latest", port: int = 8200,
root_token: str = "toor", **kwargs) -> None:
super(VaultContainer, self).__init__(image, **kwargs)
self.port = port
self.root_token = root_token
self.with_exposed_ports(self.port)
self.with_env("VAULT_DEV_ROOT_TOKEN_ID", self.root_token)

def get_connection_url(self) -> str:
"""
Get the connection URL used to connect to the Vault container.

Returns:
str: The address to connect to.
"""
host_ip = self.get_container_host_ip()
exposed_port = self.get_exposed_port(self.port)
return f"http://{host_ip}:{exposed_port}"

@wait_container_is_ready(HTTPException)
def _healthcheck(self) -> None:
url = f"{self.get_connection_url()}/v1/sys/health"
with urlopen(url) as res:
if res.status > 299:
raise HTTPException()

def start(self) -> "VaultContainer":
super().start()
self._healthcheck()
return self
41 changes: 41 additions & 0 deletions modules/vault/tests/test_vault.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import hvac
from testcontainers.vault import VaultContainer


def test_docker_run_vault():
config = VaultContainer("hashicorp/vault:1.16.1")
with config as vault:
url = vault.get_connection_url()
client = hvac.Client(url=url)
status = client.sys.read_health_status()
assert status.status_code == 200


def test_docker_run_vault_act_as_root():
config = VaultContainer("hashicorp/vault:1.16.1")
with config as vault:
url = vault.get_connection_url()
client = hvac.Client(url=url, token=vault.root_token)
assert client.is_authenticated()
assert client.sys.is_initialized()
assert not client.sys.is_sealed()

client.sys.enable_secrets_engine(
backend_type="kv",
path="secrets",
config={
"version": "2",
},
)
client.secrets.kv.v2.create_or_update_secret(
path="my-secret",
mount_point="secrets",
secret={
"pssst": "this is secret",
},
)
resp = client.secrets.kv.v2.read_secret(
path="my-secret",
mount_point="secrets",
)
assert resp["data"]["data"]["pssst"] == "this is secret"
19 changes: 18 additions & 1 deletion poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ packages = [
{ include = "testcontainers", from = "modules/redis" },
{ include = "testcontainers", from = "modules/registry" },
{ include = "testcontainers", from = "modules/selenium" },
{ include = "testcontainers", from = "modules/vault" },
{ include = "testcontainers", from = "modules/weaviate" }
]

Expand Down Expand Up @@ -144,6 +145,7 @@ psycopg = "*"
cassandra-driver = "*"
pytest-asyncio = "0.23.5"
kafka-python-ng = "^2.2.0"
hvac = "*"

[[tool.poetry.source]]
name = "PyPI"
Expand Down Expand Up @@ -262,6 +264,7 @@ mypy_path = [
# "modules/rabbitmq",
# "modules/redis",
# "modules/selenium"
# "modules/vault"
# "modules/weaviate"
]
enable_error_code = [
Expand Down