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

Move pulumi context settings and persistent data #1820

Merged
merged 97 commits into from
May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
d78d1d8
Move Pulumi storage account and key to context
JimMadge Apr 17, 2024
a63fa28
Add test for pulumi_backend_url
JimMadge Apr 17, 2024
9f38457
Add test for pulumi_secrets_provider_url
JimMadge Apr 17, 2024
325acaf
Add tests for context properties
JimMadge Apr 17, 2024
cb9fa78
Add basic pulumi configuration class
JimMadge Apr 17, 2024
7315aeb
Run lint:fmt
JimMadge Apr 17, 2024
9523e9c
Add example class test for UniqueList
JimMadge Apr 18, 2024
2688987
Add model_dump test
JimMadge Apr 18, 2024
d94b1c9
Use UniqueList for pulumi stacks
JimMadge Apr 18, 2024
dc2b073
Add getitem method for PulumiConfig
JimMadge Apr 18, 2024
6e7ef72
Run lint:fmt
JimMadge Apr 18, 2024
0a4de3c
Add stack_names method
JimMadge Apr 18, 2024
186a3f1
Add to_yaml method
JimMadge Apr 18, 2024
642ea88
Add delitem method
JimMadge Apr 18, 2024
7ec97e4
Add extra delitem tests
JimMadge Apr 18, 2024
5a38b8f
Add setitem method
JimMadge Apr 18, 2024
caeadc7
Fix typing
JimMadge Apr 18, 2024
fad3e03
Add eq tests
JimMadge Apr 18, 2024
d8a2f92
Add docstrings
JimMadge Apr 18, 2024
12c66d0
Add write_config method
JimMadge Apr 18, 2024
c9c7e1a
Add from_yaml classmethod
JimMadge Apr 19, 2024
5e7235c
Add upload method
JimMadge Apr 19, 2024
6826769
Add from_remote classmethod
JimMadge Apr 19, 2024
f0f9776
Remove Pulumi persistent data from Config class
JimMadge Apr 19, 2024
b1cb061
Revert "Remove Pulumi persistent data from Config class"
JimMadge Apr 22, 2024
368a2b3
Run lint:fmt
JimMadge Apr 22, 2024
0a0d801
Add ConfigClass
JimMadge Apr 22, 2024
7938cbc
Restructure pulumi config to use ConfigClass
JimMadge Apr 22, 2024
1693bae
Use ConfigClass for Config
JimMadge Apr 23, 2024
96f490e
Restructure pulumi config classes
JimMadge Apr 23, 2024
fd43fcf
Add stack_config_dict method
JimMadge Apr 23, 2024
77cb51c
Remove ConfigSectionPulumi and methods
JimMadge Apr 23, 2024
fd8ad8e
Remove old tests, move fixtures
JimMadge Apr 24, 2024
10766c5
Move more fixtures
JimMadge Apr 24, 2024
ca9a932
Move sanitite sre name function
JimMadge Apr 24, 2024
0c90325
Add basic tests for StackManager/SHMStackManager
JimMadge Apr 24, 2024
3be7f58
Restructure DSHPulumiProject class
JimMadge Apr 25, 2024
41b6eb2
Update create_or_select_stack
JimMadge Apr 25, 2024
65a6b9e
Add stack_all_config property
JimMadge Apr 25, 2024
a0b475c
Add udpate_dsh_pulumi_project method
JimMadge Apr 25, 2024
4573f8e
Add create_or_select_project method
JimMadge Apr 25, 2024
dcfbf0c
Propagate Pulumi config changes to infra/commands
JimMadge Apr 25, 2024
1118d06
Merge remote-tracking branch 'origin/develop' into pulumi_storage
JimMadge Apr 25, 2024
46e10d2
Remove unnecessary type hints
JimMadge Apr 25, 2024
72e055c
WIP rearrange module structure
JimMadge Apr 25, 2024
2012ff6
Update imports
JimMadge Apr 25, 2024
83babaf
Update data_safe_haven/functions/__init__.py
JimMadge Apr 25, 2024
f74e45e
Enforce local Pulumi account for tests
JimMadge Apr 25, 2024
5496d01
Add check keyword arg to subprocess run
JimMadge Apr 26, 2024
4511a05
Add blob_exists method
JimMadge Apr 26, 2024
27e0303
Add from_remote_or_create method
JimMadge Apr 26, 2024
cd15fbe
Create DSHPulumiConfig on SHM deploy if needed
JimMadge Apr 26, 2024
e985083
Correct blob_exists method
JimMadge Apr 26, 2024
fadc117
Use no secrets provider for some tests
JimMadge Apr 26, 2024
23c8b3e
Try None instead of lambda: None
JimMadge Apr 26, 2024
af8e4e0
Add CONFIG_PASSPHRASE env var for tests
JimMadge Apr 26, 2024
7a8cc97
Rename ConfigClass to SerialisableConfig
JimMadge Apr 26, 2024
1ed85de
Move test file structure consistent with project
JimMadge Apr 26, 2024
0d97fb4
Add clearer error for context show when no context present
craddm Apr 26, 2024
d6e181c
Add wait between creating keyvault and adding key
craddm Apr 26, 2024
f881aaa
add link to list of azure vm SKUs to config template
craddm Apr 26, 2024
0ec5b4a
Add index field to sre config template
craddm Apr 26, 2024
de9e82c
Ensure upload of Pulumi config when deploying shm
craddm Apr 26, 2024
f3721d1
Adding encrypted key to pulumi yaml
craddm Apr 26, 2024
0a0b9a2
:sparkles: Add a YAML-serialisable model
jemrobinson Apr 26, 2024
a3cf0a8
:truck: Move SerialisableConfig to AzureSerialisableModel
jemrobinson Apr 26, 2024
1868cef
:recycle: Make ContextSettings inherit from YAMLSerialisableModel
jemrobinson Apr 26, 2024
6498f4c
:loud_sound: Improve ContextSettings docstring
jemrobinson Apr 26, 2024
016bcb4
:loud_sound: Add file-level docstring
jemrobinson Apr 26, 2024
5a00033
Run tests and linting on all PRs
JimMadge Apr 29, 2024
7a7d28b
Run tests and linting on all PRs
JimMadge Apr 29, 2024
7808fe3
:bug: Fixed import structure to avoid circular imports
jemrobinson Apr 29, 2024
7bced0e
:truck: Moved tests for SerialisableConfig into tests for AzureSerial…
jemrobinson Apr 29, 2024
96be609
:bug: Fix some outdated test strings
jemrobinson Apr 29, 2024
59e417e
:bug: Fix YAML dump settings
jemrobinson Apr 29, 2024
cb60079
:sparkles: Add new test for YAMLSerialisableModel
jemrobinson Apr 29, 2024
a6b35b7
:rotating_light: Apply linting changes
jemrobinson Apr 29, 2024
2e02625
:bug: Added missing config_type for ContextSettings class
jemrobinson Apr 29, 2024
51e6471
:white_check_mark: Add tests for to_filepath and from_filepath
jemrobinson Apr 29, 2024
9607426
Use fixture in to_filepath test
JimMadge Apr 30, 2024
6097b57
Merge pull request #1840 from alan-turing-institute/separate-config-c…
jemrobinson Apr 30, 2024
82f330d
Merge branch 'pulumi_storage' into pulumi_storage_fixes
JimMadge Apr 30, 2024
a3d9eba
Add test for no context file
JimMadge Apr 30, 2024
fb280b9
Improve message and exit code
JimMadge Apr 30, 2024
1f0b05a
Fix DSHPulumiProject fixtures
JimMadge Apr 30, 2024
42a11c0
Update tests
JimMadge Apr 30, 2024
9f114a4
Fix linting
JimMadge Apr 30, 2024
a1e1e37
Ensure pulumi configuration is uploaded for sre
JimMadge Apr 30, 2024
db1fc3d
Add test ensuring upload is called
JimMadge May 1, 2024
1343280
Replace unittest.mock with mocker
JimMadge May 1, 2024
b66600c
Run lint:fmt
JimMadge May 1, 2024
b8410b8
Merge pull request #1839 from craddm/pulumi_storage_fixes
JimMadge May 1, 2024
f68a127
Add missing test file
JimMadge May 1, 2024
18731b9
Correct arguments to create_or_select_stack
JimMadge May 1, 2024
5e7c772
Add fixture to fix stack manager tests
JimMadge May 1, 2024
4e46044
Add tests for project and stack settings
JimMadge May 1, 2024
e3da88a
Run lint:fmt
JimMadge May 1, 2024
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: 0 additions & 1 deletion .github/workflows/build_documentation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ on: # yamllint disable-line rule:truthy
push:
branches: [develop, latest]
pull_request:
branches: [develop, latest]

jobs:
build:
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/lint_code.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ on: # yamllint disable-line rule:truthy
push:
branches: [develop, latest]
pull_request:
branches: [develop, latest]

jobs:
lint_json:
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/test_code.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ on: # yamllint disable-line rule:truthy
push:
branches: [develop, latest]
pull_request:
branches: [develop, latest]

jobs:
test_python:
Expand Down
19 changes: 14 additions & 5 deletions data_safe_haven/administration/users/guacamole_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,28 @@
from collections.abc import Sequence
from typing import Any

from data_safe_haven.config import Config
from data_safe_haven.config import Config, DSHPulumiProject
from data_safe_haven.context import Context
from data_safe_haven.external import AzureApi, AzurePostgreSQLDatabase
from data_safe_haven.infrastructure import SREStackManager

from .research_user import ResearchUser


class GuacamoleUsers:
def __init__(self, config: Config, sre_name: str, *args: Any, **kwargs: Any):
def __init__(
self,
context: Context,
config: Config,
pulumi_project: DSHPulumiProject,
sre_name: str,
*args: Any,
**kwargs: Any,
):
super().__init__(*args, **kwargs)
sre_stack = SREStackManager(config, sre_name)
sre_stack = SREStackManager(context, config, pulumi_project, sre_name)
# Read the SRE database secret from key vault
azure_api = AzureApi(config.context.subscription_name)
azure_api = AzureApi(context.subscription_name)
connection_db_server_password = azure_api.get_keyvault_secret(
sre_stack.output("data")["key_vault_name"],
sre_stack.output("data")["password_user_database_admin_secret"],
Expand All @@ -24,7 +33,7 @@ def __init__(self, config: Config, sre_name: str, *args: Any, **kwargs: Any):
connection_db_server_password,
sre_stack.output("remote_desktop")["connection_db_server_name"],
sre_stack.output("remote_desktop")["resource_group_name"],
config.context.subscription_name,
context.subscription_name,
)
self.users_: Sequence[ResearchUser] | None = None
self.postgres_script_path: pathlib.Path = (
Expand Down
18 changes: 14 additions & 4 deletions data_safe_haven/administration/users/user_handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
import pathlib
from collections.abc import Sequence

from data_safe_haven.config import Config
from data_safe_haven.config import Config, DSHPulumiConfig, DSHPulumiProject
from data_safe_haven.context import Context
from data_safe_haven.exceptions import DataSafeHavenUserHandlingError
from data_safe_haven.external import GraphApi
from data_safe_haven.utility import LoggingSingleton
Expand All @@ -15,11 +16,15 @@
class UserHandler:
def __init__(
self,
context: Context,
config: Config,
pulumi_config: DSHPulumiConfig,
graph_api: GraphApi,
):
self.azure_ad_users = AzureADUsers(graph_api)
self.context = context
self.config = config
self.pulumi_config = pulumi_config
self.logger = LoggingSingleton()
self.sre_guacamole_users_: dict[str, GuacamoleUsers] = {}

Expand Down Expand Up @@ -72,19 +77,24 @@ def get_usernames(self) -> dict[str, list[str]]:
usernames = {}
usernames["Azure AD"] = self.get_usernames_azure_ad()
for sre_name in self.config.sre_names:
usernames[f"SRE {sre_name}"] = self.get_usernames_guacamole(sre_name)
usernames[f"SRE {sre_name}"] = self.get_usernames_guacamole(
sre_name,
self.pulumi_config[sre_name],
)
return usernames

def get_usernames_azure_ad(self) -> list[str]:
"""Load usernames from Azure AD"""
return [user.username for user in self.azure_ad_users.list()]

def get_usernames_guacamole(self, sre_name: str) -> list[str]:
def get_usernames_guacamole(
self, sre_name: str, sre_pulumi_project: DSHPulumiProject
) -> list[str]:
"""Lazy-load usernames from Guacamole"""
try:
if sre_name not in self.sre_guacamole_users_.keys():
self.sre_guacamole_users_[sre_name] = GuacamoleUsers(
self.config, sre_name
self.context, self.config, sre_pulumi_project, sre_name
)
return [
user.username for user in self.sre_guacamole_users_[sre_name].list()
Expand Down
6 changes: 4 additions & 2 deletions data_safe_haven/commands/admin_add_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import pathlib

from data_safe_haven.administration.users import UserHandler
from data_safe_haven.config import Config, ContextSettings
from data_safe_haven.config import Config, DSHPulumiConfig
from data_safe_haven.context import ContextSettings
from data_safe_haven.exceptions import DataSafeHavenError
from data_safe_haven.external import GraphApi

Expand All @@ -12,6 +13,7 @@ def admin_add_users(csv_path: pathlib.Path) -> None:
"""Add users to a deployed Data Safe Haven"""
context = ContextSettings.from_file().assert_context()
config = Config.from_remote(context)
pulumi_config = DSHPulumiConfig.from_remote(context)

shm_name = context.shm_name

Expand All @@ -27,7 +29,7 @@ def admin_add_users(csv_path: pathlib.Path) -> None:
)

# Add users to SHM
users = UserHandler(config, graph_api)
users = UserHandler(context, config, pulumi_config, graph_api)
users.add(csv_path)
except DataSafeHavenError as exc:
msg = f"Could not add users to Data Safe Haven '{shm_name}'.\n{exc}"
Expand Down
6 changes: 4 additions & 2 deletions data_safe_haven/commands/admin_list_users.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""List users from a deployed Data Safe Haven"""

from data_safe_haven.administration.users import UserHandler
from data_safe_haven.config import Config, ContextSettings
from data_safe_haven.config import Config, DSHPulumiConfig
from data_safe_haven.context import ContextSettings
from data_safe_haven.exceptions import DataSafeHavenError
from data_safe_haven.external import GraphApi

Expand All @@ -10,6 +11,7 @@ def admin_list_users() -> None:
"""List users from a deployed Data Safe Haven"""
context = ContextSettings.from_file().assert_context()
config = Config.from_remote(context)
pulumi_config = DSHPulumiConfig.from_remote(context)

shm_name = context.shm_name

Expand All @@ -21,7 +23,7 @@ def admin_list_users() -> None:
)

# List users from all sources
users = UserHandler(config, graph_api)
users = UserHandler(context, config, pulumi_config, graph_api)
users.list()
except DataSafeHavenError as exc:
msg = f"Could not list users for Data Safe Haven '{shm_name}'.\n{exc}"
Expand Down
9 changes: 6 additions & 3 deletions data_safe_haven/commands/admin_register_users.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
"""Register existing users with a deployed SRE"""

from data_safe_haven.administration.users import UserHandler
from data_safe_haven.config import Config, ContextSettings
from data_safe_haven.config import Config, DSHPulumiConfig
from data_safe_haven.context import ContextSettings
from data_safe_haven.exceptions import DataSafeHavenError
from data_safe_haven.external import GraphApi
from data_safe_haven.functions import sanitise_sre_name
from data_safe_haven.utility import LoggingSingleton


Expand All @@ -14,10 +16,11 @@ def admin_register_users(
"""Register existing users with a deployed SRE"""
context = ContextSettings.from_file().assert_context()
config = Config.from_remote(context)
pulumi_config = DSHPulumiConfig.from_remote(context)

shm_name = context.shm_name
# Use a JSON-safe SRE name
sre_name = config.sanitise_sre_name(sre)
sre_name = sanitise_sre_name(sre)

try:
# Check that SRE option has been provided
Expand All @@ -35,7 +38,7 @@ def admin_register_users(
)

# List users
users = UserHandler(config, graph_api)
users = UserHandler(context, config, pulumi_config, graph_api)
available_usernames = users.get_usernames_azure_ad()
usernames_to_register = []
for username in usernames:
Expand Down
6 changes: 4 additions & 2 deletions data_safe_haven/commands/admin_remove_users.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
"""Remove existing users from a deployed Data Safe Haven"""

from data_safe_haven.administration.users import UserHandler
from data_safe_haven.config import Config, ContextSettings
from data_safe_haven.config import Config, DSHPulumiConfig
from data_safe_haven.context import ContextSettings
from data_safe_haven.exceptions import DataSafeHavenError
from data_safe_haven.external import GraphApi

Expand All @@ -12,6 +13,7 @@ def admin_remove_users(
"""Remove existing users from a deployed Data Safe Haven"""
context = ContextSettings.from_file().assert_context()
config = Config.from_remote(context)
pulumi_config = DSHPulumiConfig.from_remote(context)

shm_name = context.shm_name

Expand All @@ -24,7 +26,7 @@ def admin_remove_users(

# Remove users from SHM
if usernames:
users = UserHandler(config, graph_api)
users = UserHandler(context, config, pulumi_config, graph_api)
users.remove(usernames)
except DataSafeHavenError as exc:
msg = f"Could not remove users from Data Safe Haven '{shm_name}'.\n{exc}"
Expand Down
11 changes: 8 additions & 3 deletions data_safe_haven/commands/admin_unregister_users.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
"""Unregister existing users from a deployed SRE"""

from data_safe_haven.administration.users import UserHandler
from data_safe_haven.config import Config, ContextSettings
from data_safe_haven.config import Config, DSHPulumiConfig
from data_safe_haven.context import ContextSettings
from data_safe_haven.exceptions import DataSafeHavenError
from data_safe_haven.external import GraphApi
from data_safe_haven.functions import sanitise_sre_name
from data_safe_haven.utility import LoggingSingleton


Expand All @@ -14,9 +16,12 @@ def admin_unregister_users(
"""Unregister existing users from a deployed SRE"""
context = ContextSettings.from_file().assert_context()
config = Config.from_remote(context)
pulumi_config = DSHPulumiConfig.from_remote(context)

shm_name = context.shm_name
sre_name = config.sanitise_sre_name(sre)
sre_name = sanitise_sre_name(sre)

# sre_pulumi_project = pulumi_config.create_or_select_project(sre_name)

try:
# Check that SRE option has been provided
Expand All @@ -34,7 +39,7 @@ def admin_unregister_users(
)

# List users
users = UserHandler(config, graph_api)
users = UserHandler(context, config, pulumi_config, graph_api)
available_usernames = users.get_usernames_azure_ad()
usernames_to_unregister = []
for username in usernames:
Expand Down
10 changes: 5 additions & 5 deletions data_safe_haven/commands/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
import typer
from rich import print

from data_safe_haven.config import Config, ContextSettings
from data_safe_haven.config import Config
from data_safe_haven.context import ContextSettings

config_command_group = typer.Typer()

Expand All @@ -19,8 +20,7 @@ def template(
] = None
) -> None:
"""Write a template Data Safe Haven configuration."""
context = ContextSettings.from_file().assert_context()
config = Config.template(context)
config = Config.template()
if file:
with open(file, "w") as outfile:
outfile.write(config.to_yaml())
Expand All @@ -36,8 +36,8 @@ def upload(
context = ContextSettings.from_file().assert_context()
with open(file) as config_file:
config_yaml = config_file.read()
config = Config.from_yaml(context, config_yaml)
config.upload()
config = Config.from_yaml(config_yaml)
config.upload(context)


@config_command_group.command()
Expand Down
17 changes: 12 additions & 5 deletions data_safe_haven/commands/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
import typer
from rich import print

from data_safe_haven.config import ContextSettings
from data_safe_haven.config.context_settings import Context, default_config_file_path
from data_safe_haven.context import ContextInfra
from data_safe_haven.context import (
Context,
ContextInfra,
ContextSettings,
)
from data_safe_haven.exceptions import DataSafeHavenConfigError
from data_safe_haven.functions.typer_validators import typer_validate_aad_guid

context_command_group = typer.Typer()
Expand All @@ -16,7 +19,11 @@
@context_command_group.command()
def show() -> None:
"""Show information about the selected context."""
settings = ContextSettings.from_file()
try:
settings = ContextSettings.from_file()
except DataSafeHavenConfigError as exc:
print("No context configuration file.")
raise typer.Exit(code=1) from exc

current_context_key = settings.selected
current_context = settings.context
Expand Down Expand Up @@ -84,7 +91,7 @@ def add(
],
) -> None:
"""Add a new context to the context list."""
if default_config_file_path().exists():
if ContextSettings.default_config_file_path().exists():
settings = ContextSettings.from_file()
settings.add(
key=key,
Expand Down
Loading