Example #1
0
        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);
        }
Example #2
0
        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");
        }
Example #3
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);
            }
        }
Example #4
0
        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);
        }
Example #5
0
        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);
            }
        }
Example #6
0
        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);
        }
Example #7
0
        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);
        }
Example #8
0
        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);
        }
Example #9
0
        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);
                }
            }
Example #10
0
        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);
            }
        }
Example #11
0
        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);
        }
Example #12
0
        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);
        }
Example #13
0
        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);
            }
        }
Example #14
0
        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);
        }