# Copyright 2016-2021, Pulumi Corporation. # # 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 abc import ABC, abstractmethod from datetime import datetime from typing import Any, Callable, List, Mapping, Optional, Awaitable from ._cmd import PulumiCommand from ._config import ConfigMap, ConfigValue from ._output import OutputMap from ._project_settings import ProjectSettings from ._stack_settings import StackSettings from ._tag import TagMap PulumiFn = Callable[[], Optional[Awaitable[None]]] class StackSummary: """A summary of the status of a given stack.""" name: str current: bool update_in_progress: Optional[bool] last_update: Optional[datetime] resource_count: Optional[int] url: Optional[str] def __init__( self, name: str, current: bool, update_in_progress: Optional[bool] = None, last_update: Optional[datetime] = None, resource_count: Optional[int] = None, url: Optional[str] = None, ) -> None: self.name = name self.current = current self.update_in_progress = update_in_progress self.last_update = last_update self.resource_count = resource_count self.url = url class WhoAmIResult: """The currently logged-in Pulumi identity.""" user: str url: Optional[str] organizations: Optional[List[str]] def __init__( self, user: str, url: Optional[str] = None, organizations: Optional[List[str]] = None, ) -> None: self.user = user self.url = url self.organizations = organizations class PluginInfo: name: str kind: str size: int last_used_time: datetime install_time: Optional[datetime] version: Optional[str] def __init__( self, name: str, kind: str, size: int, last_used_time: datetime, install_time: Optional[datetime] = None, version: Optional[str] = None, ) -> None: self.name = name self.kind = kind self.size = size self.install_time = install_time self.last_used = last_used_time self.version = version class Deployment: version: Optional[int] deployment: Optional[Mapping[str, Any]] def __init__( self, version: Optional[int] = None, deployment: Optional[Mapping[str, Any]] = None, ) -> None: self.version = version self.deployment = deployment def __repr__(self): return f"Deployment(version={self.version!r}, deployment={self.deployment!r})" class Workspace(ABC): """ Workspace is the execution context containing a single Pulumi project, a program, and multiple stacks. Workspaces are used to manage the execution environment, providing various utilities such as plugin installation, environment configuration ($PULUMI_HOME), and creation, deletion, and listing of Stacks. """ work_dir: str """ The working directory to run Pulumi CLI commands """ pulumi_home: Optional[str] """ The directory override for CLI metadata if set. This customizes the location of $PULUMI_HOME where metadata is stored and plugins are installed. """ secrets_provider: Optional[str] """ The secrets provider to use for encryption and decryption of stack secrets. See: https://www.pulumi.com/docs/intro/concepts/secrets/#available-encryption-providers """ program: Optional[PulumiFn] """ The inline program `PulumiFn` to be used for Preview/Update operations if any. If none is specified, the stack will refer to ProjectSettings for this information. """ env_vars: Mapping[str, str] = {} """ Environment values scoped to the current workspace. These will be supplied to every Pulumi command. """ pulumi_version: str """ The version of the underlying Pulumi CLI/Engine. """ pulumi_command: PulumiCommand """ The underlying PulumiCommand instance that is used to execute CLI commands. """ @abstractmethod def project_settings(self) -> ProjectSettings: """ Returns the settings object for the current project if any. :returns: ProjectSettings """ @abstractmethod def save_project_settings(self, settings: ProjectSettings) -> None: """ Overwrites the settings object in the current project. There can only be a single project per workspace. Fails is new project name does not match old. :param settings: The project settings to save. """ @abstractmethod def stack_settings(self, stack_name: str) -> StackSettings: """ Returns the settings object for the stack matching the specified stack name if any. :param stack_name: The name of the stack. :return: StackSettings """ @abstractmethod def save_stack_settings(self, stack_name: str, settings: StackSettings) -> None: """ Overwrites the settings object for the stack matching the specified stack name. :param stack_name: The name of the stack. :param settings: The stack settings to save. """ @abstractmethod def serialize_args_for_op(self, stack_name: str) -> List[str]: """ A hook to provide additional args to CLI commands before they are executed. Provided with stack name, returns a list of args to append to an invoked command ["--config=...", ] LocalWorkspace does not utilize this extensibility point. :param stack_name: The name of the stack. """ @abstractmethod def post_command_callback(self, stack_name: str) -> None: """ A hook executed after every command. Called with the stack name. An extensibility point to perform workspace cleanup (CLI operations may create/modify a Pulumi.stack.yaml) LocalWorkspace does not utilize this extensibility point. :param stack_name: The name of the stack. """ @abstractmethod def add_environments(self, stack_name: str, *environment_names: str) -> None: """ Adds environments to the end of a stack's import list. Imported environments are merged in order per the ESC merge rules. The list of environments behaves as if it were the import list in an anonymous environment. :param stack_name: The name of the stack. :param environment_names: The names of the environment to add. """ @abstractmethod def list_environments(self, stack_name: str) -> List[str]: """ Returns the list of environments specified in a stack's configuration. :param stack_name: The name of the stack. :returns: List[str] """ @abstractmethod def remove_environment(self, stack_name: str, environment_name: str) -> None: """ Removes the specified environment from the stack configuration. :param stack_name: The name of the stack. :param environment_name: The name of the environment to remove. """ @abstractmethod def get_config( self, stack_name: str, key: str, *, path: bool = False ) -> ConfigValue: """ Returns the value associated with the specified stack name and key, scoped to the Workspace. :param stack_name: The name of the stack. :param key: The key for the config item to get. :param path: The key contains a path to a property in a map or list to get. :returns: ConfigValue """ @abstractmethod def get_all_config(self, stack_name: str) -> ConfigMap: """ Returns the config map for the specified stack name, scoped to the current Workspace. :param stack_name: The name of the stack. :returns: ConfigMap """ @abstractmethod def set_config( self, stack_name: str, key: str, value: ConfigValue, *, path: bool = False ) -> None: """ Sets the specified key-value pair on the provided stack name. :param stack_name: The name of the stack. :param key: The config key to add. :param value: The config value to add. :param path: The key contains a path to a property in a map or list to set. """ @abstractmethod def set_all_config( self, stack_name: str, config: ConfigMap, *, path: bool = False ) -> None: """ Sets all values in the provided config map for the specified stack name. :param stack_name: The name of the stack. :param config: A mapping of key to ConfigValue to set to config. :param path: The keys contain a path to a property in a map or list to set. """ @abstractmethod def remove_config(self, stack_name: str, key: str, *, path: bool = False) -> None: """ Removes the specified key-value pair on the provided stack name. :param stack_name: The name of the stack. :param key: The key to remove from config. :param path: The key contains a path to a property in a map or list to remove. """ @abstractmethod def remove_all_config( self, stack_name: str, keys: List[str], *, path: bool = False ) -> None: """ Removes all values in the provided key list for the specified stack name. :param stack_name: The name of the stack. :param keys: The keys to remove from config. :param path: The keys contain a path to a property in a map or list to remove. """ @abstractmethod def refresh_config(self, stack_name: str) -> None: """ Gets and sets the config map used with the last update for Stack matching stack name. :param stack_name: The name of the stack. """ @abstractmethod def get_tag(self, stack_name: str, key: str) -> str: """ Returns the value associated with the specified stack name and key, scoped to the Workspace. :param stack_name: The name of the stack. :param key: The key to use for the tag lookup. :returns: str """ @abstractmethod def set_tag(self, stack_name: str, key: str, value: str) -> None: """ Sets the specified key-value pair on the provided stack name. :param stack_name: The name of the stack. :param key: The tag key to set. :param value: The tag value to set. """ @abstractmethod def remove_tag(self, stack_name: str, key: str) -> None: """ Removes the specified key-value pair on the provided stack name. :param stack_name: The name of the stack. :param key: The tag key to remove. """ @abstractmethod def list_tags(self, stack_name: str) -> TagMap: """ Returns the tag map for the specified tag name, scoped to the Workspace. :param stack_name: The name of the stack. :returns: TagMap """ @abstractmethod def who_am_i(self) -> WhoAmIResult: """ Returns the currently authenticated user. :returns: WhoAmIResult """ @abstractmethod def stack(self) -> Optional[StackSummary]: """ Returns a summary of the currently selected stack, if any. :returns: Optional[StackSummary] """ @abstractmethod def create_stack(self, stack_name: str) -> None: """ Creates and sets a new stack with the stack name, failing if one already exists. :param str stack_name: The name of the stack to create :returns: None :raises CommandError Raised if a stack with the same name exists. """ @abstractmethod def select_stack(self, stack_name: str) -> None: """ Selects and sets an existing stack matching the stack stack_name, failing if none exists. :param stack_name: The name of the stack to select :returns: None :raises CommandError Raised if no matching stack exists. """ @abstractmethod def remove_stack( self, stack_name: str, force: Optional[bool] = None, preserve_config: Optional[bool] = None, ) -> None: """ Deletes the stack and all associated configuration and history. :param stack_name: The name of the stack to remove """ @abstractmethod def list_stacks(self, include_all: Optional[bool] = None) -> List[StackSummary]: """ Returns all Stacks created under the current Project. This queries underlying backend and may return stacks not present in the Workspace (as Pulumi..yaml files). :param include_all: List all stacks instead of just stacks for the current project :returns: List[StackSummary] """ @abstractmethod def install_plugin(self, name: str, version: str, kind: str = "resource") -> None: """ Installs a plugin in the Workspace, for example to use cloud providers like AWS or GCP. :param name: The name of the plugin to install. :param version: The version to install. :param kind: The kind of plugin. """ @abstractmethod def install_plugin_from_server(self, name: str, version: str, server: str) -> None: """ Installs a plugin in the Workspace from a remote server, for example a third party plugin. :param name: The name of the plugin to install. :param version: The version to install. :param server: The server to install from. """ @abstractmethod def remove_plugin( self, name: Optional[str] = None, version_range: Optional[str] = None, kind: str = "resource", ) -> None: """ Removes a plugin from the Workspace matching the specified name and version. :param name: The name of the plugin to remove. :param version_range: The version range to remove. :param kind: The kind of plugin. """ @abstractmethod def list_plugins(self) -> List[PluginInfo]: """ Returns a list of all plugins installed in the Workspace. :returns: List[PluginInfo] """ @abstractmethod def export_stack(self, stack_name: str) -> Deployment: """ ExportStack exports the deployment state of the stack matching the given name. This can be combined with ImportStack to edit a stack's state (such as recovery from failed deployments). :param stack_name: The name of the stack to export. :returns: Deployment """ @abstractmethod def import_stack(self, stack_name: str, state: Deployment) -> None: """ ImportStack imports the specified deployment state into a pre-existing stack. This can be combined with ExportStack to edit a stack's state (such as recovery from failed deployments). :param stack_name: The name of the stack to import. :param state: The deployment state to import. """ @abstractmethod def stack_outputs(self, stack_name: str) -> OutputMap: """ Gets the current set of Stack outputs from the last Stack.up(). :param stack_name: The name of the stack. :returns: OutputMap """