Skip to content
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
1 change: 1 addition & 0 deletions CHANGELOG_PENDING.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
### Improvements

- `esc env set` now supports --file parameter to read content from a file or stdin [#556](https://github.com/pulumi/esc/pull/556)
- `--draft` flag for `esc env set`, `esc env edit`, `esc env versions rollback` to create a change request rather than updating directly. **Warning: this feature is in preview, limited to specific orgs, and subject to change.**
[#552](https://github.com/pulumi/esc/pull/552)

Expand Down
2 changes: 1 addition & 1 deletion cmd/esc/cli/env_get.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func newEnvGetCmd(env *envCommand) *cobra.Command {
"Set to print just the definition.")
cmd.Flags().StringVar(
&value, "value", "",
"Set to print just the value in the given format. May be 'dotenv', 'json', 'detailed', or 'shell'")
"Set to print just the value in the given format. May be 'dotenv', 'json', 'detailed', 'shell' or 'string'")
cmd.Flags().BoolVar(
&showSecrets, "show-secrets", false,
"Show static secrets in plaintext rather than ciphertext")
Expand Down
10 changes: 8 additions & 2 deletions cmd/esc/cli/env_open.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"encoding/json"
"fmt"
"io"
"strings"
"time"

"github.com/pulumi/esc"
Expand Down Expand Up @@ -78,7 +79,7 @@ func newEnvOpenCmd(envcmd *envCommand) *cobra.Command {
"the lifetime of the opened environment in the form HhMm (e.g. 2h, 1h30m, 15m)")
cmd.Flags().StringVarP(
&format, "format", "f", "json",
"the output format to use. May be 'dotenv', 'json', 'yaml', 'detailed', or 'shell'")
"the output format to use. May be 'dotenv', 'json', 'yaml', 'detailed', 'shell' or 'string'")

return cmd
}
Expand Down Expand Up @@ -138,7 +139,12 @@ func (env *envCommand) renderValue(
}
return nil
case "string":
fmt.Fprintf(out, "%v\n", val.ToString(!showSecrets))
s := val.ToString(!showSecrets)
if strings.HasSuffix(s, "\n") {
fmt.Fprintf(out, "%v", s)
} else {
fmt.Fprintf(out, "%v\n", s)
}
return nil
default:
// NOTE: we shouldn't get here. This was checked at the beginning of the function.
Expand Down
39 changes: 36 additions & 3 deletions cmd/esc/cli/env_set.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ package cli
import (
"context"
"fmt"
"io"
"regexp"
"strconv"
"strings"
"unicode/utf8"

"github.com/ccojocar/zxcvbn-go"
"github.com/spf13/cobra"
Expand All @@ -23,10 +25,11 @@ func newEnvSetCmd(env *envCommand) *cobra.Command {
var plaintext bool
var rawString bool
var draft bool
var file string

cmd := &cobra.Command{
Use: "set [<org-name>/][<project-name>/]<environment-name> <path> <value>",
Args: cobra.RangeArgs(2, 3),
Args: cobra.RangeArgs(1, 3),
Short: "Set a value within an environment.",
Long: "Set a value within an environment\n" +
"\n" +
Expand All @@ -48,19 +51,48 @@ func newEnvSetCmd(env *envCommand) *cobra.Command {
if ref.version != "" {
return fmt.Errorf("the set command does not accept versions")
}
if len(args) < 2 {

switch {
case file == "" && len(args) < 2:
return fmt.Errorf("expected a path and a value")
case file != "" && len(args) < 1:
return fmt.Errorf("expected a path")
}

path, err := resource.ParsePropertyPath(args[0])
if err != nil {

return fmt.Errorf("invalid path: %w", err)
}
if len(path) == 0 {
return fmt.Errorf("path must contain at least one element")
}

input := args[1]
var input string
if file != "" {
var content []byte
switch file {
case "-":
content, err = io.ReadAll(env.esc.stdin)
if err != nil {
return fmt.Errorf("could not read from stdin: %w", err)
}
default:
content, err = env.esc.fs.ReadFile(file)
if err != nil {
return fmt.Errorf("could not read file: %w", err)
}
}

if !utf8.Valid(content) {
return fmt.Errorf("file content must be valid UTF-8")
}

input = string(content)
} else {
input = args[1]
}

var yamlValue yaml.Node
if rawString {
yamlValue.SetString(input)
Expand Down Expand Up @@ -163,6 +195,7 @@ func newEnvSetCmd(env *envCommand) *cobra.Command {
cmd.Flags().BoolVar(
&rawString, "string", false,
"true to treat the value as a string rather than attempting to parse it as YAML")
cmd.Flags().StringVarP(&file, "file", "f", "", "If set, the value is read from the specified file. Pass `-` to read from standard input.")
cmd.Flags().BoolVar(
&draft, "draft", false,
"true to create a draft rather than saving changes directly, returns a submitted Change Request ID and its URL")
Expand Down
5 changes: 5 additions & 0 deletions cmd/esc/cli/fs.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type escFS interface {
fs.FS

CreateTemp(dir, pattern string) (string, io.ReadWriteCloser, error)
ReadFile(filename string) ([]byte, error)
Remove(name string) error
}

Expand All @@ -41,3 +42,7 @@ func (defaultFS) CreateTemp(dir, pattern string) (string, io.ReadWriteCloser, er
func (defaultFS) Remove(name string) error {
return os.Remove(name)
}

func (defaultFS) ReadFile(name string) ([]byte, error) {
return os.ReadFile(name)
}
104 changes: 104 additions & 0 deletions cmd/esc/cli/testdata/env-set-file.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
run: |
echo "hello" | esc env set default/test foo -f=-
esc env get default/test
echo "hello world" >test.file
esc env set default/test foo -f=test.file
esc env get default/test
esc env get default/test --value string
esc env set default/test foo -f=test.file --string
esc env get default/test
esc env set default/test -f=test.file || echo -n ""
esc env set -f=test.file || echo -n ""
esc env set default/test -f=binary foo || echo -n ""
esc env set -f=- default/test foo <binary || echo -n ""
esc env set --string -f=multiline default/test foo
esc env get default/test foo --value string
process:
fs:
binary: !!binary sFOZJGpvmbYHwHRLnCYSnQ==
multiline: |
this is a
multiline
file
environments:
test-user/default/test:
values:
foo: bar

---
> esc env set default/test foo -f=-
> esc env get default/test
# Value
```json
{
"foo": "hello"
}
```
# Definition
```yaml
values:
foo: hello

```

> esc env set default/test foo -f=test.file
> esc env get default/test
# Value
```json
{
"foo": "hello world"
}
```
# Definition
```yaml
values:
foo: hello world

```

> esc env get default/test --value string
"foo"="hello world"
> esc env set default/test foo -f=test.file --string
> esc env get default/test
# Value
```json
{
"foo": "hello world\n"
}
```
# Definition
```yaml
values:
foo: |
hello world

```

> esc env set default/test -f=test.file
> esc env set -f=test.file
> esc env set default/test -f=binary foo
> esc env set -f=- default/test foo
> esc env set --string -f=multiline default/test foo
> esc env get default/test foo --value string
this is a
multiline
file

---
> esc env set default/test foo -f=-
> esc env get default/test
> esc env set default/test foo -f=test.file
> esc env get default/test
> esc env get default/test --value string
> esc env set default/test foo -f=test.file --string
> esc env get default/test
> esc env set default/test -f=test.file
Error: expected a path
> esc env set -f=test.file
Error: accepts between 1 and 3 arg(s), received 0
> esc env set default/test -f=binary foo
Error: file content must be valid UTF-8
> esc env set -f=- default/test foo
Error: file content must be valid UTF-8
> esc env set --string -f=multiline default/test foo
> esc env get default/test foo --value string
Loading