diff --git a/pulumi b/pulumi index 1e3ee619cf4..aec19d44f93 160000 --- a/pulumi +++ b/pulumi @@ -1 +1 @@ -Subproject commit 1e3ee619cf4dc42e0091cf8c9ff84f131cc325fe +Subproject commit aec19d44f93c770eee0f1eda7ec4b148b53664a5 diff --git a/sdk/java/pulumi/src/main/java/com/pulumi/automation/ConfigOptions.java b/sdk/java/pulumi/src/main/java/com/pulumi/automation/ConfigOptions.java new file mode 100644 index 00000000000..261bff4e703 --- /dev/null +++ b/sdk/java/pulumi/src/main/java/com/pulumi/automation/ConfigOptions.java @@ -0,0 +1,20 @@ +package com.pulumi.automation; + +/** + * ConfigOptions represents options for config operations. + */ +public class ConfigOptions { + private final boolean path; + private final String configFile; + private final boolean showSecrets; + + public ConfigOptions(boolean path, String configFile, boolean showSecrets) { + this.path = path; + this.configFile = configFile; + this.showSecrets = showSecrets; + } + + public boolean getPath() { return path; } + public String getConfigFile() { return configFile; } + public boolean getShowSecrets() { return showSecrets; } +} \ No newline at end of file diff --git a/sdk/java/pulumi/src/main/java/com/pulumi/automation/GetAllConfigOptions.java b/sdk/java/pulumi/src/main/java/com/pulumi/automation/GetAllConfigOptions.java new file mode 100644 index 00000000000..952a02d4a3d --- /dev/null +++ b/sdk/java/pulumi/src/main/java/com/pulumi/automation/GetAllConfigOptions.java @@ -0,0 +1,20 @@ +package com.pulumi.automation; + +/** + * GetAllConfigOptions represents options for retrieving all config values. + */ +public class GetAllConfigOptions { + private final boolean path; + private final String configFile; + private final boolean showSecrets; + + public GetAllConfigOptions(boolean path, String configFile, boolean showSecrets) { + this.path = path; + this.configFile = configFile; + this.showSecrets = showSecrets; + } + + public boolean getPath() { return path; } + public String getConfigFile() { return configFile; } + public boolean getShowSecrets() { return showSecrets; } +} \ No newline at end of file diff --git a/sdk/java/pulumi/src/main/java/com/pulumi/automation/LocalWorkspace.java b/sdk/java/pulumi/src/main/java/com/pulumi/automation/LocalWorkspace.java index 428aabfb8a6..5834f83f834 100644 --- a/sdk/java/pulumi/src/main/java/com/pulumi/automation/LocalWorkspace.java +++ b/sdk/java/pulumi/src/main/java/com/pulumi/automation/LocalWorkspace.java @@ -1090,13 +1090,129 @@ public void close() throws Exception { } } - // private static boolean optOutOfVersionCheck(Map - // environmentVariables) { - // boolean hasSkipEnvVar = environmentVariables != null && - // environmentVariables.containsKey("PULUMI_SKIP"); - // boolean optOut = hasSkipEnvVar || System.getenv("PULUMI_SKIP") != null; - // return optOut; - // } + @Override + public ConfigValue getConfigWithOptions(String stackName, String key, ConfigOptions options) throws AutomationException { + var args = new ArrayList(); + args.add("config"); + args.add("get"); + if (options.getPath()) { + args.add("--path"); + } + if (options.getConfigFile() != null) { + args.add("--config-file"); + args.add(options.getConfigFile()); + } + args.add(Objects.requireNonNull(key)); + args.add("--json"); + args.add("--stack"); + args.add(Objects.requireNonNull(stackName)); + var result = runCommand(args); + return serializer.deserializeJson(result.standardOutput(), ConfigValue.class); + } + + @Override + public void setConfigWithOptions(String stackName, String key, ConfigValue value, ConfigOptions options) throws AutomationException { + var args = new ArrayList(); + args.add("config"); + args.add("set"); + if (options.getPath()) { + args.add("--path"); + } + if (options.getConfigFile() != null) { + args.add("--config-file"); + args.add(options.getConfigFile()); + } + args.add(Objects.requireNonNull(key)); + Objects.requireNonNull(value); + var secretArg = value.isSecret() ? "--secret" : "--plaintext"; + args.add(secretArg); + args.add("--stack"); + args.add(Objects.requireNonNull(stackName)); + args.add("--non-interactive"); + args.add("--"); + args.add(value.value()); + runCommand(args); + } + + @Override + public void removeConfigWithOptions(String stackName, String key, ConfigOptions options) throws AutomationException { + var args = new ArrayList(); + args.add("config"); + args.add("rm"); + args.add(Objects.requireNonNull(key)); + args.add("--stack"); + args.add(Objects.requireNonNull(stackName)); + if (options.getPath()) { + args.add("--path"); + } + if (options.getConfigFile() != null) { + args.add("--config-file"); + args.add(options.getConfigFile()); + } + runCommand(args); + } + + @Override + public Map getAllConfigWithOptions(String stackName, GetAllConfigOptions options) throws AutomationException { + var args = new ArrayList(); + args.add("config"); + if (options.getShowSecrets()) { + args.add("--show-secrets"); + } + if (options.getConfigFile() != null) { + args.add("--config-file"); + args.add(options.getConfigFile()); + } + args.add("--json"); + args.add("--stack"); + args.add(Objects.requireNonNull(stackName)); + var result = runCommand(args); + if (result.standardOutput().isBlank()) { + return Collections.emptyMap(); + } + var mapType = new TypeToken>() {}.getType(); + return serializer.deserializeJson(result.standardOutput(), mapType); + } + + @Override + public void setAllConfigWithOptions(String stackName, Map configMap, ConfigOptions options) throws AutomationException { + var args = new ArrayList(); + args.add("config"); + args.add("set-all"); + args.add("--stack"); + args.add(Objects.requireNonNull(stackName)); + if (options.getPath()) { + args.add("--path"); + } + if (options.getConfigFile() != null) { + args.add("--config-file"); + args.add(options.getConfigFile()); + } + for (var entry : configMap.entrySet()) { + String secretArg = entry.getValue().isSecret() ? "--secret" : "--plaintext"; + args.add(secretArg); + args.add(entry.getKey() + "=" + entry.getValue().value()); + } + runCommand(args); + } + + @Override + public void removeAllConfigWithOptions(String stackName, Collection keys, ConfigOptions options) throws AutomationException { + var args = new ArrayList(); + args.add("config"); + args.add("rm-all"); + args.add("--stack"); + args.add(Objects.requireNonNull(stackName)); + if (options.getPath()) { + args.add("--path"); + } + if (options.getConfigFile() != null) { + args.add("--config-file"); + args.add(options.getConfigFile()); + } + args.addAll(Objects.requireNonNull(keys)); + runCommand(args); + } @FunctionalInterface private interface WorkspaceStackFactory { diff --git a/sdk/java/pulumi/src/main/java/com/pulumi/automation/Workspace.java b/sdk/java/pulumi/src/main/java/com/pulumi/automation/Workspace.java index 88b4ad09dc4..699006aa8ef 100644 --- a/sdk/java/pulumi/src/main/java/com/pulumi/automation/Workspace.java +++ b/sdk/java/pulumi/src/main/java/com/pulumi/automation/Workspace.java @@ -561,4 +561,66 @@ CommandResult runCommand(List args, CommandRunOptions options) throws Au options = options.withWorkingDir(workDir()); return cmd.run(args, options); } + + /** + * Returns the value associated with the specified stack name and key, scoped to the Workspace, using the provided options. + * + * @param stackName the name of the stack to read config from + * @param key the key to use for the config lookup + * @param options the options for the config operation + * @return the value associated with the key + * @throws AutomationException if there was an issue reading the config + */ + public abstract ConfigValue getConfigWithOptions(String stackName, String key, ConfigOptions options) throws AutomationException; + + /** + * Sets the specified key-value pair in the provided stack's config, using the provided options. + * + * @param stackName the name of the stack to operate on + * @param key the config key to set + * @param value the config value to set + * @param options the options for the config operation + * @throws AutomationException if there was an issue setting the config + */ + public abstract void setConfigWithOptions(String stackName, String key, ConfigValue value, ConfigOptions options) throws AutomationException; + + /** + * Removes the specified key-value pair from the provided stack's config, using the provided options. + * + * @param stackName the name of the stack to operate on + * @param key the config key to remove + * @param options the options for the config operation + * @throws AutomationException if there was an issue removing the config + */ + public abstract void removeConfigWithOptions(String stackName, String key, ConfigOptions options) throws AutomationException; + + /** + * Returns the config map for the specified stack name, scoped to the current Workspace, using the provided options. + * + * @param stackName the name of the stack to read config from + * @param options the options for retrieving all config + * @return the config map for the specified stack name + * @throws AutomationException if there was an issue listing the config + */ + public abstract Map getAllConfigWithOptions(String stackName, GetAllConfigOptions options) throws AutomationException; + + /** + * Sets all values in the provided config map for the specified stack name, using the provided options. + * + * @param stackName the name of the stack to operate on + * @param configMap the config map to upsert against the existing config + * @param options the options for the config operation + * @throws AutomationException if there was an issue setting the config + */ + public abstract void setAllConfigWithOptions(String stackName, Map configMap, ConfigOptions options) throws AutomationException; + + /** + * Removes all values in the provided key collection from the config map for the specified stack name, using the provided options. + * + * @param stackName the name of the stack to operate on + * @param keys the collection of keys to remove from the underlying config map + * @param options the options for the config operation + * @throws AutomationException if there was an issue removing the config + */ + public abstract void removeAllConfigWithOptions(String stackName, Collection keys, ConfigOptions options) throws AutomationException; } diff --git a/sdk/java/pulumi/src/main/java/com/pulumi/automation/WorkspaceStack.java b/sdk/java/pulumi/src/main/java/com/pulumi/automation/WorkspaceStack.java index b259f25824b..a6c67c658e6 100644 --- a/sdk/java/pulumi/src/main/java/com/pulumi/automation/WorkspaceStack.java +++ b/sdk/java/pulumi/src/main/java/com/pulumi/automation/WorkspaceStack.java @@ -184,6 +184,74 @@ public Map listTags() throws AutomationException { return this.workspace.listTags(this.name); } + /** + * Returns the config value associated with the specified key, using the provided options. + * + * @param key the key to use for the config lookup + * @param options the options for the config operation + * @return the value associated with the key + * @throws AutomationException if an error occurs + */ + public ConfigValue getConfigWithOptions(String key, ConfigOptions options) throws AutomationException { + return this.workspace.getConfigWithOptions(this.name, key, options); + } + + /** + * Sets the config key-value pair on the Stack in the associated Workspace, using the provided options. + * + * @param key the config key to set + * @param value the config value to set + * @param options the options for the config operation + * @throws AutomationException if an error occurs + */ + public void setConfigWithOptions(String key, ConfigValue value, ConfigOptions options) throws AutomationException { + this.workspace.setConfigWithOptions(this.name, key, value, options); + } + + /** + * Removes the specified config key from the Stack in the associated Workspace, using the provided options. + * + * @param key the config key to remove + * @param options the options for the config operation + * @throws AutomationException if an error occurs + */ + public void removeConfigWithOptions(String key, ConfigOptions options) throws AutomationException { + this.workspace.removeConfigWithOptions(this.name, key, options); + } + + /** + * Returns the full config map associated with the stack in the Workspace, using the provided options. + * + * @param options the options for retrieving all config + * @return the config map + * @throws AutomationException if an error occurs + */ + public Map getAllConfigWithOptions(GetAllConfigOptions options) throws AutomationException { + return this.workspace.getAllConfigWithOptions(this.name, options); + } + + /** + * Sets all specified config values on the stack in the associated Workspace, using the provided options. + * + * @param configMap the map of config key-value pairs to set + * @param options the options for the config operation + * @throws AutomationException if an error occurs + */ + public void setAllConfigWithOptions(Map configMap, ConfigOptions options) throws AutomationException { + this.workspace.setAllConfigWithOptions(this.name, configMap, options); + } + + /** + * Removes the specified config keys from the Stack in the associated Workspace, using the provided options. + * + * @param keys the config keys to remove + * @param options the options for the config operation + * @throws AutomationException if an error occurs + */ + public void removeAllConfigWithOptions(Collection keys, ConfigOptions options) throws AutomationException { + this.workspace.removeAllConfigWithOptions(this.name, keys, options); + } + /** * Returns the config value associated with the specified key. * diff --git a/sdk/java/pulumi/src/test/java/com/pulumi/automation/LocalWorkspaceTest.java b/sdk/java/pulumi/src/test/java/com/pulumi/automation/LocalWorkspaceTest.java index 82934b375d7..17f68af13fc 100644 --- a/sdk/java/pulumi/src/test/java/com/pulumi/automation/LocalWorkspaceTest.java +++ b/sdk/java/pulumi/src/test/java/com/pulumi/automation/LocalWorkspaceTest.java @@ -933,4 +933,65 @@ void testStateDeleteForce(@EnvVars Map envVars) throws Exception } } } + + @Test + public void testConfigWithOptions(@EnvVars Map envVars) throws Exception { + var env = new HashMap(envVars); + env.put("PULUMI_CONFIG_PASSPHRASE", "test"); + + try (var workspace = LocalWorkspace.create(LocalWorkspaceOptions.builder() + .projectSettings(ProjectSettings.builder( + "config_options_test", + ProjectRuntimeName.NODEJS).build()) + .environmentVariables(env) + .build())) { + + var stackName = randomStackName(); + var stack = WorkspaceStack.create(stackName, workspace); + + // Test getConfigWithOptions + var getOptions = new ConfigOptions(true, "Pulumi.test.yaml", false); + stack.setConfigWithOptions("key1", new ConfigValue("value1"), getOptions); + var value = stack.getConfigWithOptions("key1", getOptions); + assertThat(value.value()).isEqualTo("value1"); + + // Test setConfigWithOptions + var setOptions = new ConfigOptions(false, "Pulumi.test.yaml", false); + stack.setConfigWithOptions("key2", new ConfigValue("value2"), setOptions); + value = stack.getConfigWithOptions("key2", setOptions); + assertThat(value.value()).isEqualTo("value2"); + + // Test removeConfigWithOptions + var removeOptions = new ConfigOptions(true, "Pulumi.test.yaml", false); + stack.removeConfigWithOptions("key1", removeOptions); + assertThrows(AutomationException.class, () -> stack.getConfigWithOptions("key1", removeOptions)); + + // Test getAllConfigWithOptions + var getAllOptions = new GetAllConfigOptions(false, "Pulumi.test.yaml", true); + var config = stack.getAllConfigWithOptions(getAllOptions); + assertThat(config).hasEntrySatisfying("key2", v -> assertThat(v.value()).isEqualTo("value2")); + + // Test setAllConfigWithOptions + var setAllOptions = new ConfigOptions(true, "Pulumi.test.yaml", false); + var configMap = Map.of( + "key3", new ConfigValue("value3"), + "key4", new ConfigValue("value4", true) + ); + stack.setAllConfigWithOptions(configMap, setAllOptions); + config = stack.getAllConfigWithOptions(getAllOptions); + assertThat(config).hasEntrySatisfying("key3", v -> assertThat(v.value()).isEqualTo("value3")); + assertThat(config).hasEntrySatisfying("key4", v -> { + assertThat(v.value()).isEqualTo("value4"); + assertThat(v.isSecret()).isTrue(); + }); + + // Test removeAllConfigWithOptions + var removeAllOptions = new ConfigOptions(false, "Pulumi.test.yaml", false); + stack.removeAllConfigWithOptions(List.of("key2", "key3"), removeAllOptions); + config = stack.getAllConfigWithOptions(getAllOptions); + assertThat(config).doesNotContainKey("key2"); + assertThat(config).doesNotContainKey("key3"); + assertThat(config).containsKey("key4"); + } + } }