static async Task <int> DestroyStack(string stack) { var projectName = Env.ProjectName; var currentDir = Directory.GetCurrentDirectory(); using var workspace = await LocalWorkspace.CreateAsync( new LocalWorkspaceOptions { Program = PulumiFn.Create <DefaultStack>(), ProjectSettings = new ProjectSettings(projectName, ProjectRuntimeName.Dotnet), WorkDir = currentDir } ); var appStack = await WorkspaceStack.SelectAsync(stack, workspace); Information("Destroying {Stack}", stack); var result = await appStack.DestroyAsync( new DestroyOptions { OnStandardOutput = Information, OnStandardError = Error } ); return(result.Summary.Result == UpdateState.Succeeded ? 0 : -1); }
public async Task AddRemoveListPlugins() { using var workspace = await LocalWorkspace.CreateAsync(); var plugins = await workspace.ListPluginsAsync(); if (plugins.Any(p => p.Name == "aws" && p.Version == "3.0.0")) { await workspace.RemovePluginAsync("aws", "3.0.0"); plugins = await workspace.ListPluginsAsync(); Assert.DoesNotContain(plugins, p => p.Name == "aws" && p.Version == "3.0.0"); } await workspace.InstallPluginAsync("aws", "v3.0.0"); plugins = await workspace.ListPluginsAsync(); var aws = plugins.FirstOrDefault(p => p.Name == "aws" && p.Version == "3.0.0"); Assert.NotNull(aws); await workspace.RemovePluginAsync("aws", "3.0.0"); plugins = await workspace.ListPluginsAsync(); Assert.DoesNotContain(plugins, p => p.Name == "aws" && p.Version == "3.0.0"); }
public async Task StackAlreadyExistsExceptionIsThrown() { var projectSettings = new ProjectSettings("command_exception_test", ProjectRuntimeName.NodeJS); using var workspace = await LocalWorkspace.CreateAsync(new LocalWorkspaceOptions { ProjectSettings = projectSettings, EnvironmentVariables = new Dictionary <string, string?>() { ["PULUMI_CONFIG_PASSPHRASE"] = "test" } }); var stackName = $"already_existing_stack{GetTestSuffix()}"; await workspace.CreateStackAsync(stackName); try { var createTask = workspace.CreateStackAsync(stackName); await Assert.ThrowsAsync <StackAlreadyExistsException>( () => createTask); } finally { await workspace.RemoveStackAsync(stackName); } }
public async Task ManipulateConfig() { var projectName = "node_test"; var projectSettings = new ProjectSettings(projectName, ProjectRuntimeName.NodeJS); using var workspace = await LocalWorkspace.CreateAsync(new LocalWorkspaceOptions { ProjectSettings = projectSettings, EnvironmentVariables = new Dictionary <string, string>() { ["PULUMI_CONFIG_PASSPHRASE"] = "test", } }); var stackName = $"int_test{GetTestSuffix()}"; var stack = await WorkspaceStack.CreateAsync(stackName, workspace); var config = new Dictionary <string, ConfigValue>() { ["plain"] = new ConfigValue("abc"), ["secret"] = new ConfigValue("def", isSecret: true), }; var plainKey = NormalizeConfigKey("plain", projectName); var secretKey = NormalizeConfigKey("secret", projectName); await Assert.ThrowsAsync <CommandException>( () => stack.GetConfigValueAsync(plainKey)); var values = await stack.GetConfigAsync(); Assert.Empty(values); await stack.SetConfigAsync(config); values = await stack.GetConfigAsync(); Assert.True(values.TryGetValue(plainKey, out var plainValue)); Assert.Equal("abc", plainValue !.Value); Assert.False(plainValue.IsSecret); Assert.True(values.TryGetValue(secretKey, out var secretValue)); Assert.Equal("def", secretValue !.Value); Assert.True(secretValue.IsSecret); await stack.RemoveConfigValueAsync("plain"); values = await stack.GetConfigAsync(); Assert.Single(values); await stack.SetConfigValueAsync("foo", new ConfigValue("bar")); values = await stack.GetConfigAsync(); Assert.Equal(2, values.Count); await workspace.RemoveStackAsync(stackName); }
public async Task ImportExportStack() { var workingDir = ResourcePath(Path.Combine("Data", "testproj")); var projectSettings = new ProjectSettings("testproj", ProjectRuntimeName.Go) { Description = "A minimal Go Pulumi program" }; using var workspace = await LocalWorkspace.CreateAsync(new LocalWorkspaceOptions { WorkDir = workingDir, ProjectSettings = projectSettings }); StackDeployment deployment; var stackName = $"{RandomStackName()}"; try { var stack = await WorkspaceStack.CreateAsync(stackName, workspace); var upResult = await stack.UpAsync(); Assert.Equal(UpdateKind.Update, upResult.Summary.Kind); Assert.Equal(UpdateState.Succeeded, upResult.Summary.Result); Assert.Equal(3, upResult.Outputs.Count); deployment = await workspace.ExportStackAsync(stackName); Assert.True(deployment.Version > 0); var previewBeforeDestroy = await stack.PreviewAsync(); Assert.Equal(1, previewBeforeDestroy.ChangeSummary[OperationType.Same]); await stack.DestroyAsync(); var previewAfterDestroy = await stack.PreviewAsync(); Assert.Equal(1, previewAfterDestroy.ChangeSummary[OperationType.Create]); await workspace.ImportStackAsync(stackName, deployment); // After we imported before-destroy deployment, // preview is back to reporting the before-destroy // state. var previewAfterImport = await stack.PreviewAsync(); Assert.Equal(1, previewAfterImport.ChangeSummary[OperationType.Same]); } finally { await workspace.RemoveStackAsync(stackName); } }
public async Task StackNotFoundExceptionIsThrown() { var projectSettings = new ProjectSettings("command_exception_test", ProjectRuntimeName.NodeJS); using var workspace = await LocalWorkspace.CreateAsync(new LocalWorkspaceOptions { ProjectSettings = projectSettings, }); var stackName = $"non_existent_stack{GetTestSuffix()}"; var selectTask = workspace.SelectStackAsync(stackName); await Assert.ThrowsAsync <StackNotFoundException>( () => selectTask); }
public async Task GetProjectSettings(string extension) { var workingDir = ResourcePath(Path.Combine("Data", extension)); using var workspace = await LocalWorkspace.CreateAsync(new LocalWorkspaceOptions { WorkDir = workingDir, }); var settings = await workspace.GetProjectSettingsAsync(); Assert.NotNull(settings); Assert.Equal("testproj", settings !.Name); Assert.Equal(ProjectRuntimeName.Go, settings.Runtime.Name); Assert.Equal("A minimal Go Pulumi program", settings.Description); }
public async Task CreateSelectRemoveStack() { var projectSettings = new ProjectSettings("create_select_remove_stack_test", ProjectRuntimeName.NodeJS); using var workspace = await LocalWorkspace.CreateAsync(new LocalWorkspaceOptions { ProjectSettings = projectSettings, EnvironmentVariables = new Dictionary <string, string?>() { ["PULUMI_CONFIG_PASSPHRASE"] = "test", } }); var stackName = $"{RandomStackName()}"; var stacks = await workspace.ListStacksAsync(); if (stacks.Any(s => s.Name == stackName)) { await workspace.RemoveStackAsync(stackName); stacks = await workspace.ListStacksAsync(); Assert.DoesNotContain(stacks, s => s.Name == stackName); } await workspace.CreateStackAsync(stackName); stacks = await workspace.ListStacksAsync(); var newStack = stacks.FirstOrDefault(s => s.Name == stackName); Assert.NotNull(newStack); Assert.True(newStack.IsCurrent); await workspace.SelectStackAsync(stackName); await workspace.RemoveStackAsync(stackName); stacks = await workspace.ListStacksAsync(); Assert.DoesNotContain(stacks, s => s.Name == stackName); }
public async Task ListStackAndCurrentlySelected() { var projectSettings = new ProjectSettings( $"node_list_test{GetTestSuffix()}", ProjectRuntimeName.NodeJS); using var workspace = await LocalWorkspace.CreateAsync(new LocalWorkspaceOptions { ProjectSettings = projectSettings, EnvironmentVariables = new Dictionary <string, string?>() { ["PULUMI_CONFIG_PASSPHRASE"] = "test", } }); var stackNames = new List <string>(); try { for (var i = 0; i < 2; i++) { var stackName = GetStackName(); await WorkspaceStack.CreateAsync(stackName, workspace); stackNames.Add(stackName); var summary = await workspace.GetStackAsync(); Assert.NotNull(summary); Assert.True(summary !.IsCurrent); var stacks = await workspace.ListStacksAsync(); Assert.Equal(i + 1, stacks.Count); } } finally { foreach (var name in stackNames) { await workspace.RemoveStackAsync(name); } }
public async Task StackAlreadyExistsExceptionIsThrown() { var projectSettings = new ProjectSettings("command_exception_test", ProjectRuntimeName.NodeJS); using var workspace = await LocalWorkspace.CreateAsync(new LocalWorkspaceOptions { ProjectSettings = projectSettings, }); var stackName = $"already_existing_stack{GetTestSuffix()}"; await workspace.CreateStackAsync(stackName); try { var createTask = workspace.CreateStackAsync(stackName); await Assert.ThrowsAsync <StackAlreadyExistsException>( () => createTask); } finally { await workspace.RemoveStackAsync(stackName); } }
public async Task GetStackSettings(string extension) { var workingDir = ResourcePath(Path.Combine("Data", extension)); using var workspace = await LocalWorkspace.CreateAsync(new LocalWorkspaceOptions { WorkDir = workingDir, }); var settings = await workspace.GetStackSettingsAsync("dev"); Assert.NotNull(settings); Assert.Equal("abc", settings !.SecretsProvider); Assert.NotNull(settings.Config); Assert.True(settings.Config !.TryGetValue("plain", out var plainValue)); Assert.Equal("plain", plainValue !.Value); Assert.False(plainValue.IsSecure); Assert.True(settings.Config.TryGetValue("secure", out var secureValue)); Assert.Equal("secret", secureValue !.Value); Assert.True(secureValue.IsSecure); }
public async Task CreateSelectRemoveStack() { var projectSettings = new ProjectSettings("node_test", ProjectRuntimeName.NodeJS); using var workspace = await LocalWorkspace.CreateAsync(new LocalWorkspaceOptions { ProjectSettings = projectSettings, EnvironmentVariables = new Dictionary <string, string>() { ["PULUMI_CONFIG_PASSPHRASE"] = "test", } }); var stackName = $"int_test{GetTestSuffix()}"; var stacks = await workspace.ListStacksAsync(); Assert.Empty(stacks); await workspace.CreateStackAsync(stackName); stacks = await workspace.ListStacksAsync(); var newStack = stacks.FirstOrDefault(s => s.Name == stackName); Assert.NotNull(newStack); Assert.True(newStack.IsCurrent); await workspace.SelectStackAsync(stackName); await workspace.RemoveStackAsync(stackName); stacks = await workspace.ListStacksAsync(); Assert.Empty(stacks); }
public async Task ConcurrentUpdateExceptionIsThrown() { var projectSettings = new ProjectSettings("command_exception_test", ProjectRuntimeName.NodeJS); using var workspace = await LocalWorkspace.CreateAsync(new LocalWorkspaceOptions { ProjectSettings = projectSettings, }); var stackName = $"concurrent_update_stack{GetTestSuffix()}"; await workspace.CreateStackAsync(stackName); try { var stack = await WorkspaceStack.SelectAsync(stackName, workspace); var hitSemaphore = false; using var semaphore = new SemaphoreSlim(0, 1); var program = PulumiFn.Create(() => { hitSemaphore = true; // ReSharper disable once AccessToDisposedClosure semaphore.Wait(); return(new Dictionary <string, object?> { ["test"] = "doesnt matter", }); }); var upTask = stack.UpAsync(new UpOptions { Program = program, }); // wait until we hit semaphore while (!hitSemaphore) { await Task.Delay(TimeSpan.FromSeconds(2)); if (upTask.IsFaulted) { throw upTask.Exception !; } else if (upTask.IsCompleted) { throw new Exception("never hit semaphore in first UP task"); } } // before releasing the semaphore, ensure another up throws var concurrentTask = stack.UpAsync(new UpOptions { Program = program, // should never make it into this }); await Assert.ThrowsAsync <ConcurrentUpdateException>( () => concurrentTask); // finish first up call semaphore.Release(); await upTask; } finally { await workspace.RemoveStackAsync(stackName); } }
static async Task <int> DeployStack( string stack, string name, string tier, string track, string version, string image, int percentage ) { var currentDir = Directory.GetCurrentDirectory(); Information("Starting with {Name} {Stack} in {CurrentDir}", name, stack, currentDir); var customStackPath = Path.Combine(currentDir, "deploy"); var usingCustomStack = Directory.Exists(customStackPath); if (usingCustomStack) { Information("Using the custom stack in {Directory}", customStackPath); } LocalWorkspaceOptions stackArgs = usingCustomStack ? new LocalProgramArgs(stack, customStackPath) : new InlineProgramArgs(name, stack, PulumiFn.Create <DefaultStack>()); using var workspace = await LocalWorkspace.CreateAsync(stackArgs); var appStack = await WorkspaceStack.CreateOrSelectAsync(stack, workspace); await appStack.RefreshAsync(); Information("Configuring stack {Stack}", stack); var appSettings = new AutoDevOpsSettings.AppSettings(name, tier, track, version); var deploymentSettings = await Settings.GetDeploymentSettings(); await appStack.SetJsonConfig("gitlab", Settings.GitLabSettings()); await appStack.SetJsonConfig("registry", Settings.RegistrySettings(), true); await appStack.SetJsonConfig("app", appSettings); await appStack.SetJsonConfig("deploy", Settings.DeploySettings(image, percentage)); await appStack.SetJsonConfig("service", deploymentSettings.Service); await appStack.SetJsonConfig("ingress", deploymentSettings.Ingress); await appStack.SetJsonConfig("prometheus", deploymentSettings.Prometheus); Information("Installing plugins"); await appStack.Workspace.InstallPluginAsync("kubernetes", "v3.3.0"); Information("Deploying stack {Stack}", stack); var result = await appStack.UpAsync( new UpOptions { OnStandardOutput = Information, OnStandardError = Error } ); Information("Deployment result: {Result}", result.Summary.Message); if (!Env.EnvironmentUrl.IsEmpty()) { Information("Environment URL: {EnvironmentUrl}", Env.EnvironmentUrl); } return(result.Summary.Result == UpdateState.Succeeded ? 0 : -1); }