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 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 CanDeploy() { WorkspaceStack stack = null; try { // Arrange stack = await InitializeStack(() => { var args = new StandardVpcArgs { CidrBlockSegment = 1 }; var vpc = new StandardVpc("test-vpc", args); return(new Dictionary <string, object> { { "VpcId", vpc.Vpc.Apply(v => v.Id) } }); }); // Act var upResult = await stack.UpAsync(new UpOptions { OnStandardOutput = s => Console.WriteLine($"stdout:{s}"), OnStandardError = s => Console.WriteLine($"stderr:{s}"), }); // Assert var expectedVpcId = (string)upResult.Outputs["VpcId"].Value; var describeVpcsResponse = await _ec2Client.DescribeVpcsAsync(); describeVpcsResponse.Vpcs.Any(v => v.VpcId == expectedVpcId).ShouldBeTrue(); } finally { if (stack != null) { // Cleanup var destroyResult = await stack.DestroyAsync(); Console.WriteLine(destroyResult.StandardOutput); } } }
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 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); }
public static Task SetJsonConfig(this WorkspaceStack stack, string key, object config, bool secure = false) => stack.SetConfigAsync(key, new ConfigValue(JsonSerializer.Serialize(config), secure));