[automation] - Consume config set-all and rm-all commands (#6388)

This commit is contained in:
Komal 2021-02-19 22:59:18 -08:00 committed by GitHub
parent 4882c9fec5
commit 5f4e687a1d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 251 additions and 35 deletions

View file

@ -21,6 +21,8 @@ CHANGELOG
- [cli] Added commands `config set-all` and `config rm-all` to set and remove multiple configuration keys.
[#6373](https://github.com/pulumi/pulumi/pulls/6373)
- [automation/*] Consume `config set-all` and `config rm-all` from automation API.
[#6388](https://github.com/pulumi/pulumi/pulls/6388)
### Bug Fixes

View file

@ -464,11 +464,14 @@ namespace Pulumi.Automation
/// <inheritdoc/>
public override async Task SetConfigAsync(string stackName, IDictionary<string, ConfigValue> configMap, CancellationToken cancellationToken = default)
{
// TODO: do this in parallel after this is fixed https://github.com/pulumi/pulumi/issues/3877
await this.SelectStackAsync(stackName, cancellationToken).ConfigureAwait(false);
foreach (var (key, value) in configMap)
await this.SetConfigValueAsync(key, value, cancellationToken).ConfigureAwait(false);
var args = new List<string>{"config", "set-all", "--stack", stackName};
foreach (var (key, value) in configMap)
{
var secretArg = value.IsSecret ? "--secret" : "--plaintext";
args.Add(secretArg);
args.Add($"{key}={value.Value}");
}
await this.RunCommandAsync(args, cancellationToken).ConfigureAwait(false);
}
private async Task SetConfigValueAsync(string key, ConfigValue value, CancellationToken cancellationToken)
@ -487,11 +490,9 @@ namespace Pulumi.Automation
/// <inheritdoc/>
public override async Task RemoveConfigAsync(string stackName, IEnumerable<string> keys, CancellationToken cancellationToken = default)
{
// TODO: do this in parallel after this is fixed https://github.com/pulumi/pulumi/issues/3877
await this.SelectStackAsync(stackName, cancellationToken).ConfigureAwait(false);
foreach (var key in keys)
await this.RunCommandAsync(new[] { "config", "rm", key }, cancellationToken).ConfigureAwait(false);
var args = new List<string>{"config", "rm-all", "--stack", stackName};
args.AddRange(keys);
await this.RunCommandAsync(args, cancellationToken).ConfigureAwait(false);
}
/// <inheritdoc/>

View file

@ -186,11 +186,19 @@ func (l *LocalWorkspace) SetConfig(ctx context.Context, stackName string, key st
// SetAllConfig sets all values in the provided config map for the specified stack name.
// LocalWorkspace writes the config to the matching Pulumi.<stack>.yaml file in Workspace.WorkDir().
func (l *LocalWorkspace) SetAllConfig(ctx context.Context, stackName string, config ConfigMap) error {
args := []string{"config", "set-all", "--stack", stackName}
for k, v := range config {
err := l.SetConfig(ctx, stackName, k, v)
if err != nil {
return err
secretArg := "--plaintext"
if v.Secret {
secretArg = "--secret"
}
args = append(args, secretArg, fmt.Sprintf("%s=%s", k, v.Value))
}
stdout, stderr, errCode, err := l.runPulumiCmdSync(ctx, args...)
if err != nil {
return newAutoError(errors.Wrap(err, "unable to set config"), stdout, stderr, errCode)
}
return nil
}
@ -213,11 +221,11 @@ func (l *LocalWorkspace) RemoveConfig(ctx context.Context, stackName string, key
// RemoveAllConfig removes all values in the provided key list for the specified stack name
// It will remove any matching values in the Pulumi.<stack>.yaml file in Workspace.WorkDir().
func (l *LocalWorkspace) RemoveAllConfig(ctx context.Context, stackName string, keys []string) error {
for _, k := range keys {
err := l.RemoveConfig(ctx, stackName, k)
if err != nil {
return err
}
args := []string{"config", "rm-all", "--stack", stackName}
args = append(args, keys...)
stdout, stderr, errCode, err := l.runPulumiCmdSync(ctx, args...)
if err != nil {
return newAutoError(errors.Wrap(err, "unable to set config"), stdout, stderr, errCode)
}
return nil
}

View file

@ -1132,6 +1132,207 @@ func TestNestedConfig(t *testing.T) {
assert.JSONEq(t, "[\"one\",\"two\",\"three\"]", list.Value)
}
func BenchmarkBulkSetConfigMixed(b *testing.B) {
ctx := context.Background()
stackName := FullyQualifiedStackName(pulumiOrg, "set_config_mixed", "dev")
// initialize
s, err := NewStackInlineSource(ctx, stackName, "set_config_mixed", func(ctx *pulumi.Context) error { return nil })
if err != nil {
b.Errorf("failed to initialize stack, err: %v", err)
b.FailNow()
}
cfg := ConfigMap{
"one": ConfigValue{Value: "one", Secret: true},
"two": ConfigValue{Value: "two"},
"three": ConfigValue{Value: "three", Secret: true},
"four": ConfigValue{Value: "four"},
"five": ConfigValue{Value: "five", Secret: true},
"six": ConfigValue{Value: "six"},
"seven": ConfigValue{Value: "seven", Secret: true},
"eight": ConfigValue{Value: "eight"},
"nine": ConfigValue{Value: "nine", Secret: true},
"ten": ConfigValue{Value: "ten"},
"eleven": ConfigValue{Value: "one", Secret: true},
"twelve": ConfigValue{Value: "two"},
"thirteen": ConfigValue{Value: "three", Secret: true},
"fourteen": ConfigValue{Value: "four"},
"fifteen": ConfigValue{Value: "five", Secret: true},
"sixteen": ConfigValue{Value: "six"},
"seventeen": ConfigValue{Value: "seven", Secret: true},
"eighteen": ConfigValue{Value: "eight"},
"nineteen": ConfigValue{Value: "nine", Secret: true},
"twenty": ConfigValue{Value: "ten"},
"one1": ConfigValue{Value: "one", Secret: true},
"two1": ConfigValue{Value: "two"},
"three1": ConfigValue{Value: "three", Secret: true},
"four1": ConfigValue{Value: "four"},
"five1": ConfigValue{Value: "five", Secret: true},
"six1": ConfigValue{Value: "six"},
"seven1": ConfigValue{Value: "seven", Secret: true},
"eight1": ConfigValue{Value: "eight"},
"nine1": ConfigValue{Value: "nine", Secret: true},
"ten1": ConfigValue{Value: "ten"},
"eleven1": ConfigValue{Value: "one", Secret: true},
"twelve1": ConfigValue{Value: "two"},
"thirteen1": ConfigValue{Value: "three", Secret: true},
"fourteen1": ConfigValue{Value: "four"},
"fifteen1": ConfigValue{Value: "five", Secret: true},
"sixteen1": ConfigValue{Value: "six"},
"seventeen1": ConfigValue{Value: "seven", Secret: true},
"eighteen1": ConfigValue{Value: "eight"},
"nineteen1": ConfigValue{Value: "nine", Secret: true},
"twenty1": ConfigValue{Value: "ten"},
}
err = s.SetAllConfig(ctx, cfg)
if err != nil {
b.Errorf("failed to set config, err: %v", err)
b.FailNow()
}
defer func() {
// -- pulumi stack rm --
err = s.Workspace().RemoveStack(ctx, s.Name())
assert.Nil(b, err, "failed to remove stack. Resources have leaked.")
}()
}
func BenchmarkBulkSetConfigPlain(b *testing.B) {
ctx := context.Background()
stackName := FullyQualifiedStackName(pulumiOrg, "set_config_plain", "dev")
// initialize
s, err := NewStackInlineSource(ctx, stackName, "set_config_plain", func(ctx *pulumi.Context) error { return nil })
if err != nil {
b.Errorf("failed to initialize stack, err: %v", err)
b.FailNow()
}
cfg := ConfigMap{
"one": ConfigValue{Value: "one"},
"two": ConfigValue{Value: "two"},
"three": ConfigValue{Value: "three"},
"four": ConfigValue{Value: "four"},
"five": ConfigValue{Value: "five"},
"six": ConfigValue{Value: "six"},
"seven": ConfigValue{Value: "seven"},
"eight": ConfigValue{Value: "eight"},
"nine": ConfigValue{Value: "nine"},
"ten": ConfigValue{Value: "ten"},
"eleven": ConfigValue{Value: "one"},
"twelve": ConfigValue{Value: "two"},
"thirteen": ConfigValue{Value: "three"},
"fourteen": ConfigValue{Value: "four"},
"fifteen": ConfigValue{Value: "five"},
"sixteen": ConfigValue{Value: "six"},
"seventeen": ConfigValue{Value: "seven"},
"eighteen": ConfigValue{Value: "eight"},
"nineteen": ConfigValue{Value: "nine"},
"twenty": ConfigValue{Value: "ten"},
"one1": ConfigValue{Value: "one"},
"two1": ConfigValue{Value: "two"},
"three1": ConfigValue{Value: "three"},
"four1": ConfigValue{Value: "four"},
"five1": ConfigValue{Value: "five"},
"six1": ConfigValue{Value: "six"},
"seven1": ConfigValue{Value: "seven"},
"eight1": ConfigValue{Value: "eight"},
"nine1": ConfigValue{Value: "nine"},
"ten1": ConfigValue{Value: "ten"},
"eleven1": ConfigValue{Value: "one"},
"twelve1": ConfigValue{Value: "two"},
"thirteen1": ConfigValue{Value: "three"},
"fourteen1": ConfigValue{Value: "four"},
"fifteen1": ConfigValue{Value: "five"},
"sixteen1": ConfigValue{Value: "six"},
"seventeen1": ConfigValue{Value: "seven"},
"eighteen1": ConfigValue{Value: "eight"},
"nineteen1": ConfigValue{Value: "nine"},
"twenty1": ConfigValue{Value: "ten"},
}
err = s.SetAllConfig(ctx, cfg)
if err != nil {
b.Errorf("failed to set config, err: %v", err)
b.FailNow()
}
defer func() {
// -- pulumi stack rm --
err = s.Workspace().RemoveStack(ctx, s.Name())
assert.Nil(b, err, "failed to remove stack. Resources have leaked.")
}()
}
func BenchmarkBulkSetConfigSecret(b *testing.B) {
ctx := context.Background()
stackName := FullyQualifiedStackName(pulumiOrg, "set_config_plain", "dev")
// initialize
s, err := NewStackInlineSource(ctx, stackName, "set_config_plain", func(ctx *pulumi.Context) error { return nil })
if err != nil {
b.Errorf("failed to initialize stack, err: %v", err)
b.FailNow()
}
cfg := ConfigMap{
"one": ConfigValue{Value: "one", Secret: true},
"two": ConfigValue{Value: "two", Secret: true},
"three": ConfigValue{Value: "three", Secret: true},
"four": ConfigValue{Value: "four", Secret: true},
"five": ConfigValue{Value: "five", Secret: true},
"six": ConfigValue{Value: "six", Secret: true},
"seven": ConfigValue{Value: "seven", Secret: true},
"eight": ConfigValue{Value: "eight", Secret: true},
"nine": ConfigValue{Value: "nine", Secret: true},
"ten": ConfigValue{Value: "ten", Secret: true},
"eleven": ConfigValue{Value: "one", Secret: true},
"twelve": ConfigValue{Value: "two", Secret: true},
"thirteen": ConfigValue{Value: "three", Secret: true},
"fourteen": ConfigValue{Value: "four", Secret: true},
"fifteen": ConfigValue{Value: "five", Secret: true},
"sixteen": ConfigValue{Value: "six", Secret: true},
"seventeen": ConfigValue{Value: "seven", Secret: true},
"eighteen": ConfigValue{Value: "eight", Secret: true},
"nineteen": ConfigValue{Value: "nine", Secret: true},
"1twenty": ConfigValue{Value: "ten", Secret: true},
"one1": ConfigValue{Value: "one", Secret: true},
"two1": ConfigValue{Value: "two", Secret: true},
"three1": ConfigValue{Value: "three", Secret: true},
"four1": ConfigValue{Value: "four", Secret: true},
"five1": ConfigValue{Value: "five", Secret: true},
"six1": ConfigValue{Value: "six", Secret: true},
"seven1": ConfigValue{Value: "seven", Secret: true},
"eight1": ConfigValue{Value: "eight", Secret: true},
"nine1": ConfigValue{Value: "nine", Secret: true},
"ten1": ConfigValue{Value: "ten", Secret: true},
"eleven1": ConfigValue{Value: "one", Secret: true},
"twelve1": ConfigValue{Value: "two", Secret: true},
"thirteen1": ConfigValue{Value: "three", Secret: true},
"fourteen1": ConfigValue{Value: "four", Secret: true},
"fifteen1": ConfigValue{Value: "five", Secret: true},
"sixteen1": ConfigValue{Value: "six", Secret: true},
"seventeen1": ConfigValue{Value: "seven", Secret: true},
"eighteen1": ConfigValue{Value: "eight", Secret: true},
"nineteen1": ConfigValue{Value: "nine", Secret: true},
"twenty1": ConfigValue{Value: "ten", Secret: true},
}
err = s.SetAllConfig(ctx, cfg)
if err != nil {
b.Errorf("failed to set config, err: %v", err)
b.FailNow()
}
defer func() {
// -- pulumi stack rm --
err = s.Workspace().RemoveStack(ctx, s.Name())
assert.Nil(b, err, "failed to remove stack. Resources have leaked.")
}()
}
func getTestOrg() string {
testOrg := "pulumi-test"
if _, set := os.LookupEnv("PULUMI_TEST_ORG"); set {

View file

@ -382,10 +382,13 @@ export class LocalWorkspace implements Workspace {
* @param config The `ConfigMap` to upsert against the existing config.
*/
async setAllConfig(stackName: string, config: ConfigMap): Promise<void> {
// TODO: do this in parallel after this is fixed https://github.com/pulumi/pulumi/issues/6050
let args = ["config", "set-all", "--stack", stackName];
for (const [key, value] of Object.entries(config)) {
await this.setConfig(stackName, key, value);
const secretArg = value.secret ? "--secret" : "--plaintext";
args = [...args, secretArg, `${key}=${value.value}`];
}
await this.runPulumiCmd(args);
}
/**
* Removes the specified key-value pair on the provided stack name.
@ -407,10 +410,7 @@ export class LocalWorkspace implements Workspace {
* @param keys The list of keys to remove from the underlying config
*/
async removeAllConfig(stackName: string, keys: string[]): Promise<void> {
// TODO: do this in parallel after this is fixed https://github.com/pulumi/pulumi/issues/6050
for (const key of keys) {
await this.removeConfig(stackName, key);
}
await this.runPulumiCmd(["config", "rm-all", "--stack", stackName, ...keys]);
}
/**
* Gets and sets the config map used with the last update for Stack matching stack name.

View file

@ -150,7 +150,7 @@ __all__ = [
"CommandResult",
"OnOutput",
# config
# _config
"ConfigMap",
"ConfigValue",
@ -163,14 +163,14 @@ __all__ = [
"RuntimeError",
"CompilationError",
# local_workspace
# _local_workspace
"LocalWorkspace",
"LocalWorkspaceOptions",
"create_stack",
"select_stack",
"create_or_select_stack",
# workspace
# _workspace
"PluginInfo",
"StackSummary",
"PulumiFn",
@ -178,14 +178,14 @@ __all__ = [
"Deployment",
"WhoAmIResult",
# project_settings
# _project_settings
"ProjectSettings",
"ProjectRuntimeInfo",
# stack_settings
# _stack_settings
"StackSettings",
# stack
# _stack
"Stack",
"UpdateSummary",
"UpResult",

View file

@ -170,18 +170,22 @@ class LocalWorkspace(Workspace):
self._run_pulumi_cmd_sync(["config", "set", key, value.value, secret_arg])
def set_all_config(self, stack_name: str, config: ConfigMap) -> None:
# TODO: Do this in parallel after https://github.com/pulumi/pulumi/issues/6050
args = ["config", "set-all", "--stack", stack_name]
for key, value in config.items():
self.set_config(stack_name, key, value)
secret_arg = "--secret" if value.secret else "--plaintext"
args.extend([secret_arg, f"{key}={value.value}"])
self._run_pulumi_cmd_sync(args)
def remove_config(self, stack_name: str, key: str) -> None:
self.select_stack(stack_name)
self._run_pulumi_cmd_sync(["config", "rm", key])
def remove_all_config(self, stack_name: str, keys: List[str]) -> None:
# TODO: Do this in parallel after https://github.com/pulumi/pulumi/issues/6050
for key in keys:
self.remove_config(stack_name, key)
args = ["config", "rm-all", "--stack", stack_name]
args.extend(keys)
self._run_pulumi_cmd_sync(args)
def refresh_config(self, stack_name: str) -> None:
self.select_stack(stack_name)