Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[auto] Add support for the path option for config operations #191

Merged
merged 1 commit into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions CHANGELOG_PENDING.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
### Improvements

- [sdk/automation-api] Add support for the path option for config operations.
[#191](https://github.com/pulumi/pulumi-dotnet/pull/191)

### Bug Fixes
- [sdk] Register and await tasks created from `Apply` that don't return anything.

- [sdk] Register and await tasks created from `Apply` that don't return anything.
110 changes: 110 additions & 0 deletions sdk/Pulumi.Automation.Tests/LocalWorkspaceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,116 @@ await Assert.ThrowsAsync<CommandException>(
}
}

[Fact]
public async Task ManipulateConfigPath()
{
var projectName = "manipulate_config_path_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 = $"{RandomStackName()}";
var stack = await WorkspaceStack.CreateAsync(stackName, workspace);

try
{
// test backward compatibility
await stack.SetConfigAsync("key1", new ConfigValue("value1"));
// test new flag without subPath
await stack.SetConfigAsync("key2", new ConfigValue("value2"), path: false);
// test new flag with subPath
await stack.SetConfigAsync("key3.subKey1", new ConfigValue("value3"), path: true);
// test secret
await stack.SetConfigAsync("key4", new ConfigValue("value4", isSecret: true));
// test subPath and key as secret
await stack.SetConfigAsync("key5.subKey1", new ConfigValue("value5", isSecret: true), path: true);
// test string with dots
await stack.SetConfigAsync("key6.subKey1", new ConfigValue("value6", isSecret: true));
// test string with dots
await stack.SetConfigAsync("key7.subKey1", new ConfigValue("value7", isSecret: true), path: false);
// test subPath
await stack.SetConfigAsync("key7.subKey2", new ConfigValue("value8"), path: true);
// test subPath
await stack.SetConfigAsync("key7.subKey3", new ConfigValue("value9"), path: true);

// test backward compatibility
var cv1 = await stack.GetConfigAsync("key1");
Assert.NotNull(cv1);
Assert.Equal("value1", cv1.Value);
Assert.False(cv1.IsSecret);

// test new flag without subPath
var cv2 = await stack.GetConfigAsync("key2", path: false);
Assert.NotNull(cv2);
Assert.Equal("value2", cv2.Value);
Assert.False(cv2.IsSecret);

// test new flag with subPath
var cv3 = await stack.GetConfigAsync("key3.subKey1", path: true);
Assert.NotNull(cv3);
Assert.Equal("value3", cv3.Value);
Assert.False(cv3.IsSecret);

// test secret
var cv4 = await stack.GetConfigAsync("key4");
Assert.NotNull(cv4);
Assert.Equal("value4", cv4.Value);
Assert.True(cv4.IsSecret);

// test subPath and key as secret
var cv5 = await stack.GetConfigAsync("key5.subKey1", true);
Assert.NotNull(cv5);
Assert.Equal("value5", cv5.Value);
Assert.True(cv5.IsSecret);

// test string with dots
var cv6 = await stack.GetConfigAsync("key6.subKey1");
Assert.NotNull(cv6);
Assert.Equal("value6", cv6.Value);
Assert.True(cv6.IsSecret);

// test string with dots
var cv7 = await stack.GetConfigAsync("key7.subKey1", false);
Assert.NotNull(cv7);
Assert.Equal("value7", cv7.Value);
Assert.True(cv7.IsSecret);

// test string with dots
var cv8 = await stack.GetConfigAsync("key7.subKey2", true);
Assert.NotNull(cv8);
Assert.Equal("value8", cv8.Value);
Assert.False(cv8.IsSecret);

// test string with dots
var cv9 = await stack.GetConfigAsync("key7.subKey3", true);
Assert.NotNull(cv9);
Assert.Equal("value9", cv9.Value);
Assert.False(cv9.IsSecret);

await stack.RemoveConfigAsync("key1");
await stack.RemoveConfigAsync("key2", path: false);
await stack.RemoveConfigAsync("key3", path: false);
await stack.RemoveConfigAsync("key4", path: false);
await stack.RemoveConfigAsync("key5", path: false);
await stack.RemoveConfigAsync("key6.subKey1", path: false);
await stack.RemoveConfigAsync("key7.subKey1", path: false);

var cfg = await stack.GetAllConfigAsync();
Assert.Equal("{\"subKey2\":\"value8\",\"subKey3\":\"value9\"}", cfg[$"{projectName}:key7"].Value);
}
finally
{
await workspace.RemoveStackAsync(stackName);
}
}

[Fact]
public async Task SupportConfigFlagLike()
{
Expand Down
63 changes: 55 additions & 8 deletions sdk/Pulumi.Automation/LocalWorkspace.cs
Original file line number Diff line number Diff line change
Expand Up @@ -567,9 +567,19 @@ public override async Task<Dictionary<string, string>> ListTagsAsync(string stac
}

/// <inheritdoc/>
public override async Task<ConfigValue> GetConfigAsync(string stackName, string key, CancellationToken cancellationToken = default)
public override Task<ConfigValue> GetConfigAsync(string stackName, string key, CancellationToken cancellationToken = default)
=> GetConfigAsync(stackName, key, false, cancellationToken);

/// <inheritdoc/>
public override async Task<ConfigValue> GetConfigAsync(string stackName, string key, bool path, CancellationToken cancellationToken = default)
{
var result = await this.RunCommandAsync(new[] { "config", "get", key, "--json", "--stack", stackName }, cancellationToken).ConfigureAwait(false);
var args = new List<string> { "config", "get" };
if (path)
{
args.Add("--path");
}
args.AddRange(new[] { key, "--json", "--stack", stackName });
var result = await this.RunCommandAsync(args, cancellationToken).ConfigureAwait(false);
return this._serializer.DeserializeJson<ConfigValue>(result.StandardOutput);
}

Expand All @@ -585,16 +595,34 @@ public override async Task<ImmutableDictionary<string, ConfigValue>> GetAllConfi
}

/// <inheritdoc/>
public override async Task SetConfigAsync(string stackName, string key, ConfigValue value, CancellationToken cancellationToken = default)
public override Task SetConfigAsync(string stackName, string key, ConfigValue value, CancellationToken cancellationToken = default)
=> SetConfigAsync(stackName, key, value, false, cancellationToken);

/// <inheritdoc/>
public override async Task SetConfigAsync(string stackName, string key, ConfigValue value, bool path, CancellationToken cancellationToken = default)
{
var args = new List<string> { "config", "set" };
if (path)
{
args.Add("--path");
}
var secretArg = value.IsSecret ? "--secret" : "--plaintext";
await this.RunCommandAsync(new[] { "config", "set", key, secretArg, "--stack", stackName, "--non-interactive", "--", value.Value }, cancellationToken).ConfigureAwait(false);
args.AddRange(new[] { key, secretArg, "--stack", stackName, "--non-interactive", "--", value.Value });
await this.RunCommandAsync(args, cancellationToken).ConfigureAwait(false);
}

/// <inheritdoc/>
public override async Task SetAllConfigAsync(string stackName, IDictionary<string, ConfigValue> configMap, CancellationToken cancellationToken = default)
public override Task SetAllConfigAsync(string stackName, IDictionary<string, ConfigValue> configMap, CancellationToken cancellationToken = default)
=> SetAllConfigAsync(stackName, configMap, false, cancellationToken);

/// <inheritdoc/>
public override async Task SetAllConfigAsync(string stackName, IDictionary<string, ConfigValue> configMap, bool path, CancellationToken cancellationToken = default)
{
var args = new List<string> { "config", "set-all", "--stack", stackName };
if (path)
{
args.Add("--path");
}
foreach (var (key, value) in configMap)
{
var secretArg = value.IsSecret ? "--secret" : "--plaintext";
Expand All @@ -605,13 +633,32 @@ public override async Task SetAllConfigAsync(string stackName, IDictionary<strin
}

/// <inheritdoc/>
public override async Task RemoveConfigAsync(string stackName, string key, CancellationToken cancellationToken = default)
=> await this.RunCommandAsync(new[] { "config", "rm", key, "--stack", stackName }, cancellationToken).ConfigureAwait(false);
public override Task RemoveConfigAsync(string stackName, string key, CancellationToken cancellationToken = default)
=> RemoveConfigAsync(stackName, key, false, cancellationToken);

/// <inheritdoc/>
public override async Task RemoveConfigAsync(string stackName, string key, bool path, CancellationToken cancellationToken = default)
{
var args = new List<string> { "config", "rm", key, "--stack", stackName };
if (path)
{
args.Add("--path");
}
await this.RunCommandAsync(args, cancellationToken).ConfigureAwait(false);
}

/// <inheritdoc/>
public override Task RemoveAllConfigAsync(string stackName, IEnumerable<string> keys, CancellationToken cancellationToken = default)
=> RemoveAllConfigAsync(stackName, keys, false, cancellationToken);

/// <inheritdoc/>
public override async Task RemoveAllConfigAsync(string stackName, IEnumerable<string> keys, CancellationToken cancellationToken = default)
public override async Task RemoveAllConfigAsync(string stackName, IEnumerable<string> keys, bool path, CancellationToken cancellationToken = default)
{
var args = new List<string> { "config", "rm-all", "--stack", stackName };
if (path)
{
args.Add("--path");
}
args.AddRange(keys);
await this.RunCommandAsync(args, cancellationToken).ConfigureAwait(false);
}
Expand Down
Loading
Loading