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

[WIP] Change logic for generating/loading stack to avoid mismatching key errors #2282

Closed
Closed
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
2 changes: 2 additions & 0 deletions data_safe_haven/commands/sre.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ def deploy(
pulumi_config = DSHPulumiConfig.from_remote_or_create(
context, encrypted_key=None, projects={}
)

sre_config = SREConfig.from_remote_by_name(context, name)

# Check whether current IP address is authorised to take administrator actions
Expand All @@ -68,6 +69,7 @@ def deploy(
pulumi_config=pulumi_config,
create_project=True,
)

# Set Azure options
stack.add_option(
"azure-native:location", sre_config.azure.location, replace=False
Expand Down
50 changes: 29 additions & 21 deletions data_safe_haven/infrastructure/project_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,27 +119,45 @@ def stack(self) -> automation.Stack:
"""Load the Pulumi stack, creating if needed."""
if not self._stack:
self.logger.debug(f"Creating/loading stack [green]{self.stack_name}[/].")
# Note: `create_or_select_stack` is not used here because we need to know whether the stack exists or not.
# There is no way to check if a stack exists other than trying to `create_stack` or `select_stack` and catching the error.
# `create_or_select_stack` never generates an error, and doesn't tell us whether the stack was created or selected.
# When creating a stack, it generates a new encryption key rather than using the project's key, so we need to set the key
# manually after creating the stack.
try:
self._stack = automation.create_or_select_stack(
self._stack = automation.select_stack(
opts=automation.LocalWorkspaceOptions(
env_vars=self.account.env,
project_settings=self.project_settings,
secrets_provider=self.context.pulumi_secrets_provider_url,
stack_settings={self.stack_name: self.stack_settings},
secrets_provider=self.context.pulumi_secrets_provider_url,
),
program=self.program,
project_name=self.project_name,
stack_name=self.stack_name,
)
self.logger.info(f"Loaded stack [green]{self.stack_name}[/].")
# Ensure encrypted key is stored in the Pulumi configuration
self.update_dsh_pulumi_encrypted_key(self._stack.workspace)
# Ensure workspace plugins are installed
self.install_plugins(self._stack.workspace)
except automation.CommandError as exc:
self.log_exception(exc)
msg = f"Could not load Pulumi stack {self.stack_name}."
raise DataSafeHavenPulumiError(msg) from exc
except automation.CommandError:
try:
self._stack = automation.create_stack(
opts=automation.LocalWorkspaceOptions(
env_vars=self.account.env,
project_settings=self.project_settings,
secrets_provider=self.context.pulumi_secrets_provider_url,
),
program=self.program,
project_name=self.project_name,
stack_name=self.stack_name,
)
self._stack.workspace.save_stack_settings(
self.stack_name, self.stack_settings
)
except automation.CommandError as exc:
self.log_exception(exc)
msg = f"Could not create Pulumi stack {self.stack_name}."
raise DataSafeHavenPulumiError(msg) from exc
self.logger.info(f"Loaded stack [green]{self.stack_name}[/].")
# Ensure workspace plugins are installed
self.install_plugins(self._stack.workspace)
return self._stack

def add_option(self, name: str, value: str, *, replace: bool) -> None:
Expand Down Expand Up @@ -425,16 +443,6 @@ def update_dsh_pulumi_project(self) -> None:
}
self.pulumi_project.stack_config = all_config_dict

def update_dsh_pulumi_encrypted_key(self, workspace: automation.Workspace) -> None:
"""Update encrypted key in the DSHPulumiProject object"""
stack_key = workspace.stack_settings(stack_name=self.stack_name).encrypted_key

if not self.pulumi_config.encrypted_key:
self.pulumi_config.encrypted_key = stack_key
elif self.pulumi_config.encrypted_key != stack_key:
msg = "Stack encrypted key does not match project encrypted key"
raise DataSafeHavenPulumiError(msg)


class SREProjectManager(ProjectManager):
"""Interact with an SRE using Pulumi"""
Expand Down
Loading