[automation-api/python] - Support recovery workflow (#6037)
This commit is contained in:
parent
059402483b
commit
89b1d0d2c7
|
@ -32,6 +32,12 @@ CHANGELOG
|
|||
- [sdk/dotnet] Fix looking up empty version in `ResourcePackages.TryGetResourceType`.
|
||||
[#6084](https://github.com/pulumi/pulumi/pull/6084)
|
||||
|
||||
- Python Automation API.
|
||||
[#5979](https://github.com/pulumi/pulumi/pull/5979)
|
||||
|
||||
- Support recovery workflow (import/export/cancel) in Python Automation API.
|
||||
[#6037](https://github.com/pulumi/pulumi/pull/6037)
|
||||
|
||||
## 2.17.0 (2021-01-06)
|
||||
|
||||
- Respect the `version` resource option for provider resources.
|
||||
|
@ -48,9 +54,6 @@ CHANGELOG
|
|||
|
||||
- [CLI] Add a confirmation prompt when using `pulumi policy rm`
|
||||
[#6034](https://github.com/pulumi/pulumi/pull/6034)
|
||||
|
||||
- Python Automation API.
|
||||
[#5979](https://github.com/pulumi/pulumi/pull/5979)
|
||||
|
||||
- [CLI] Ensure errors with the Pulumi credentials file
|
||||
give the user some information on how to resolve the problem
|
||||
|
|
|
@ -449,7 +449,7 @@ func (l *LocalWorkspace) ImportStack(ctx context.Context, stackName string, stat
|
|||
|
||||
f, err := ioutil.TempFile(os.TempDir(), "")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not import stack. failed to get allocate temp file.")
|
||||
return errors.Wrap(err, "could not import stack. failed to allocate temp file.")
|
||||
}
|
||||
defer func() { contract.IgnoreError(os.Remove(f.Name())) }()
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ from typing import Optional, List, Mapping, Callable
|
|||
from .config import ConfigMap, ConfigValue
|
||||
from .project_settings import ProjectSettings
|
||||
from .stack_settings import StackSettings
|
||||
from .workspace import Workspace, PluginInfo, StackSummary, WhoAmIResult, PulumiFn
|
||||
from .workspace import Workspace, PluginInfo, StackSummary, WhoAmIResult, PulumiFn, Deployment
|
||||
from .stack import _DATETIME_FORMAT, Stack
|
||||
from .cmd import _run_pulumi_cmd, CommandResult, OnOutput
|
||||
|
||||
|
@ -256,6 +256,20 @@ class LocalWorkspace(Workspace):
|
|||
plugin_list.append(plugin)
|
||||
return plugin_list
|
||||
|
||||
def export_stack(self, stack_name: str) -> Deployment:
|
||||
self.select_stack(stack_name)
|
||||
result = self._run_pulumi_cmd_sync(["stack", "export", "--show-secrets"])
|
||||
state_json = json.loads(result.stdout)
|
||||
return Deployment(**state_json)
|
||||
|
||||
def import_stack(self, stack_name: str, state: Deployment) -> None:
|
||||
self.select_stack(stack_name)
|
||||
file = tempfile.NamedTemporaryFile(mode="w", delete=False)
|
||||
json.dump(state.__dict__, file, indent=4)
|
||||
file.close()
|
||||
self._run_pulumi_cmd_sync(["stack", "import", "--file", file.name])
|
||||
os.remove(file.name)
|
||||
|
||||
def _run_pulumi_cmd_sync(self, args: List[str], on_output: Optional[OnOutput] = None) -> CommandResult:
|
||||
envs = {"PULUMI_HOME": self.pulumi_home} if self.pulumi_home else {}
|
||||
envs = {**envs, **self.env_vars}
|
||||
|
|
|
@ -23,9 +23,9 @@ from typing import List, Any, Mapping, MutableMapping, Optional
|
|||
|
||||
from .cmd import CommandResult, _run_pulumi_cmd, OnOutput
|
||||
from .config import ConfigValue, ConfigMap, _SECRET_SENTINEL
|
||||
from .errors import StackAlreadyExistsError, CommandError
|
||||
from .errors import StackAlreadyExistsError
|
||||
from .server import LanguageServer
|
||||
from .workspace import Workspace, PulumiFn
|
||||
from .workspace import Workspace, PulumiFn, Deployment
|
||||
from ...runtime.settings import _GRPC_CHANNEL_OPTIONS
|
||||
from ...runtime.proto import language_pb2_grpc
|
||||
|
||||
|
@ -329,10 +329,9 @@ class Stack:
|
|||
summary = self.info()
|
||||
assert (summary is not None)
|
||||
return PreviewResult(stdout=preview_result.stdout, stderr=preview_result.stderr, summary=summary)
|
||||
except CommandError as exn:
|
||||
finally:
|
||||
if on_exit is not None:
|
||||
on_exit()
|
||||
raise
|
||||
|
||||
def refresh(self,
|
||||
parallel: Optional[int] = None,
|
||||
|
@ -497,6 +496,34 @@ class Stack:
|
|||
return None
|
||||
return history[0]
|
||||
|
||||
def cancel(self) -> None:
|
||||
"""
|
||||
Cancel stops a stack's currently running update. It returns an error if no update is currently running.
|
||||
Note that this operation is _very dangerous_, and may leave the stack in an inconsistent state
|
||||
if a resource operation was pending when the update was canceled.
|
||||
This command is not supported for local backends.
|
||||
"""
|
||||
self.workspace.select_stack(self.name)
|
||||
self._run_pulumi_cmd_sync(["cancel", "--yes"])
|
||||
|
||||
def export_stack(self) -> Deployment:
|
||||
"""
|
||||
export_stack exports the deployment state of the stack.
|
||||
This can be combined with Stack.import_state to edit a stack's state (such as recovery from failed deployments).
|
||||
|
||||
:returns: Deployment
|
||||
"""
|
||||
return self.workspace.export_stack(self.name)
|
||||
|
||||
def import_stack(self, state: Deployment) -> None:
|
||||
"""
|
||||
import_stack imports the specified deployment state into a pre-existing stack.
|
||||
This can be combined with Stack.export_state to edit a stack's state (such as recovery from failed deployments).
|
||||
|
||||
:param state: The deployment state to import.
|
||||
"""
|
||||
return self.workspace.import_stack(self.name, state)
|
||||
|
||||
def _run_pulumi_cmd_sync(self,
|
||||
args: List[str],
|
||||
on_output: Optional[OnOutput] = None) -> CommandResult:
|
||||
|
|
|
@ -85,6 +85,18 @@ class PluginInfo:
|
|||
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.
|
||||
|
@ -346,3 +358,25 @@ class Workspace(ABC):
|
|||
:returns: List[PluginInfo]
|
||||
"""
|
||||
pass
|
||||
|
||||
@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
|
||||
"""
|
||||
pass
|
||||
|
||||
@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.
|
||||
"""
|
||||
pass
|
||||
|
|
Loading…
Reference in a new issue