Skip to content

Commit

Permalink
Make AzureCli class a singleton
Browse files Browse the repository at this point in the history
  • Loading branch information
JimMadge committed Oct 24, 2023
1 parent 7cd5bc6 commit 1c87532
Show file tree
Hide file tree
Showing 5 changed files with 15 additions and 9 deletions.
4 changes: 2 additions & 2 deletions data_safe_haven/external/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .api.azure_api import AzureApi
from .api.azure_cli import AzureCli
from .api.azure_cli import AzureCliSingleton
from .api.graph_api import GraphApi
from .interface.azure_container_instance import AzureContainerInstance
from .interface.azure_fileshare import AzureFileShare
Expand All @@ -8,7 +8,7 @@

__all__ = [
"AzureApi",
"AzureCli",
"AzureCliSingleton",
"AzureContainerInstance",
"AzureFileShare",
"AzureIPv4Range",
Expand Down
10 changes: 8 additions & 2 deletions data_safe_haven/external/api/azure_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import typer

from data_safe_haven.exceptions import DataSafeHavenAzureError
from data_safe_haven.utility import LoggingSingleton
from data_safe_haven.utility import LoggingSingleton, Singleton


@dataclass
Expand All @@ -19,7 +19,7 @@ class AzureCliAccount:
tenant_id: str


class AzureCli:
class AzureCliSingleton(metaclass=Singleton):
"""Interface to the Azure CLI"""

def __init__(self) -> None:
Expand All @@ -32,6 +32,7 @@ def __init__(self) -> None:
self.path = path

self._account: AzureCliAccount | None = None
self._confirmed = False

@property
def account(self) -> AzureCliAccount:
Expand Down Expand Up @@ -62,6 +63,9 @@ def account(self) -> AzureCliAccount:

def confirm(self) -> None:
"""Prompt user to confirm the Azure CLI account is correct"""
if self._confirmed:
return None

account = self.account
self.logger.info(
f"name: {account.name} (id: {account.id_}\ntenant: {account.tenant_id})"
Expand All @@ -71,3 +75,5 @@ def confirm(self) -> None:
"Please use `az login` to connect to the correct Azure CLI account"
)
raise typer.Exit(1)

self._confirmed = True
4 changes: 2 additions & 2 deletions data_safe_haven/infrastructure/stack_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

from data_safe_haven.config import Config
from data_safe_haven.exceptions import DataSafeHavenAzureError, DataSafeHavenPulumiError
from data_safe_haven.external import AzureApi, AzureCli
from data_safe_haven.external import AzureApi, AzureCliSingleton
from data_safe_haven.functions import replace_separators
from data_safe_haven.infrastructure.stacks import DeclarativeSHM, DeclarativeSRE
from data_safe_haven.utility import LoggingSingleton
Expand All @@ -31,7 +31,7 @@ def __init__(self, config: Config):

# Ensure Azure CLI account is correct
# This will be needed to populate env
AzureCli().confirm()
AzureCliSingleton().confirm()

@property
def env(self) -> dict[str, Any]:
Expand Down
2 changes: 2 additions & 0 deletions data_safe_haven/utility/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from .enums import DatabaseSystem, SoftwarePackageCategory
from .file_reader import FileReader
from .logger import LoggingSingleton, NonLoggingSingleton
from .singleton import Singleton
from .types import PathType

__all__ = [
Expand All @@ -9,5 +10,6 @@
"LoggingSingleton",
"NonLoggingSingleton",
"PathType",
"Singleton",
"SoftwarePackageCategory",
]
4 changes: 1 addition & 3 deletions data_safe_haven/utility/logger.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Standalone logging class implemented as a singleton"""
import io
import logging
from typing import Any, ClassVar, Optional
from typing import Any, ClassVar

from rich.console import Console
from rich.highlighter import RegexHighlighter
Expand Down Expand Up @@ -98,8 +98,6 @@ class LoggingSingleton(logging.Logger, metaclass=Singleton):

date_fmt = r"%Y-%m-%d %H:%M:%S"
rich_format = r"[log.time]%(asctime)s[/] [%(levelname)8s] %(message)s"
# Due to https://bugs.python.org/issue45857 we must use `Optional`
_instance: Optional["LoggingSingleton"] = None

def __init__(self) -> None:
super().__init__(name="data_safe_haven", level=logging.INFO)
Expand Down

0 comments on commit 1c87532

Please sign in to comment.