Skip to content

Commit cc39f2c

Browse files
authored
cli: add the esc CLI (#10)
Add the `esc` CLI to the repo. This includes some basic build scaffolding for the CLI to ensure version stamping.
1 parent 16e7620 commit cc39f2c

27 files changed

+5492
-24
lines changed

.github/scripts/get-version

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/usr/bin/env bash
2+
3+
set -euo pipefail
4+
5+
ROOT=$(dirname "${0}")/../..
6+
7+
if [ -n "${CI:-""}" ]; then
8+
>&2 echo "::group::Get version"
9+
trap ">&2 echo '::endgroup::'" EXIT # bash equivalent of defer func()
10+
fi
11+
12+
# Remove whitespace, this is our version:
13+
tr -d '[:space:]' < "${ROOT}/.version"

.version

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0.0.1

Makefile

+8-3
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ PULUMI_LIVE_TEST ?= false
44
export PULUMI_TEST_ORG
55
export PULUMI_TEST_OWNER
66

7-
CONCURRENCY := 10
7+
VERSION := $(if ${PULUMI_VERSION},${PULUMI_VERSION},$(shell ./scripts/pulumi-version.sh))
8+
9+
CONCURRENCY := 10
810
SHELL := sh
911

10-
GO := go
12+
GO := go
1113

1214
.phony: .EXPORT_ALL_VARIABLES
1315
.EXPORT_ALL_VARIABLES:
@@ -31,7 +33,10 @@ lint-copyright:
3133
pulumictl copyright
3234

3335
build:: ensure
34-
${GO} build -p ${CONCURRENCY} ./...
36+
${GO} install -ldflags "-X github.com/pulumi/esc/cmd/internal/version.Version=${VERSION}" ./cmd/esc
37+
38+
build_debug:: ensure
39+
${GO} install -gcflags="all=-N -l" -ldflags "-X github.com/pulumi/esc/cmd/internal/version.Version=${VERSION}" ./cmd/esc
3540

3641
test:: build
3742
${GO} test --timeout 30m -short -count 1 -parallel ${CONCURRENCY} ./...

cmd/esc/env.go

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
// Copyright 2023, Pulumi Corporation.
2+
3+
package main
4+
5+
import (
6+
"fmt"
7+
"io"
8+
"os"
9+
"sort"
10+
"strings"
11+
12+
"github.com/hashicorp/hcl/v2"
13+
"github.com/spf13/cobra"
14+
"golang.org/x/term"
15+
16+
"github.com/pulumi/esc/cmd/esc/internal/client"
17+
"github.com/pulumi/pulumi/sdk/v3/go/common/diag/colors"
18+
"github.com/pulumi/pulumi/sdk/v3/go/common/util/cmdutil"
19+
)
20+
21+
type envCommand struct {
22+
esc *escCommand
23+
24+
envNameFlag string
25+
}
26+
27+
func newEnvCmd(esc *escCommand) *cobra.Command {
28+
cmd := &cobra.Command{
29+
Use: "env",
30+
Short: "Manage environments",
31+
Long: "Manage environments\n" +
32+
"\n" +
33+
"An environment is a named collection of possibly-secret, possibly-dynamic data.\n" +
34+
"Each environment has a definition and may be opened in order to access its contents." +
35+
"Opening an environment may involve generating new dynamic data.\n",
36+
Args: cmdutil.NoArgs,
37+
}
38+
39+
env := &envCommand{esc: esc}
40+
41+
cmd.PersistentFlags().StringVar(&env.envNameFlag, "env", "", "The name of the environment to operate on.")
42+
43+
cmd.AddCommand(newEnvInitCmd(env))
44+
cmd.AddCommand(newEnvEditCmd(env))
45+
cmd.AddCommand(newEnvGetCmd(env))
46+
cmd.AddCommand(newEnvSetCmd(env))
47+
cmd.AddCommand(newEnvLsCmd(env))
48+
cmd.AddCommand(newEnvRmCmd(env))
49+
cmd.AddCommand(newEnvOpenCmd(env))
50+
cmd.AddCommand(newEnvRunCmd(env))
51+
52+
return cmd
53+
}
54+
55+
func (cmd *envCommand) getEnvName(args []string) (org, env string, rest []string, err error) {
56+
if cmd.envNameFlag == "" {
57+
if len(args) == 0 {
58+
return "", "", nil, fmt.Errorf("no environment name specified")
59+
}
60+
cmd.envNameFlag, args = args[0], args[1:]
61+
}
62+
63+
orgName, envName, hasOrgName := strings.Cut(cmd.envNameFlag, "/")
64+
if !hasOrgName {
65+
orgName, envName = cmd.esc.account.DefaultOrg, orgName
66+
}
67+
return orgName, envName, args, nil
68+
}
69+
70+
func sortEnvironmentDiagnostics(diags []client.EnvironmentDiagnostic) {
71+
sort.Slice(diags, func(i, j int) bool {
72+
di, dj := diags[i], diags[j]
73+
if di.Range == nil {
74+
if dj.Range == nil {
75+
return di.Summary < dj.Summary
76+
}
77+
return true
78+
}
79+
if dj.Range == nil {
80+
return false
81+
}
82+
if di.Range.Environment != dj.Range.Environment {
83+
return di.Range.Environment < dj.Range.Environment
84+
}
85+
if di.Range.Begin.Line != dj.Range.Begin.Line {
86+
return di.Range.Begin.Line < dj.Range.Begin.Line
87+
}
88+
return di.Range.Begin.Column < dj.Range.Begin.Column
89+
})
90+
}
91+
92+
func (cmd *envCommand) writeYAMLEnvironmentDiagnostics(
93+
out io.Writer,
94+
envName string,
95+
yaml []byte,
96+
diags []client.EnvironmentDiagnostic,
97+
) error {
98+
width, color := 0, false
99+
if file, ok := out.(*os.File); ok {
100+
w, _, err := term.GetSize(int(file.Fd()))
101+
if err != nil {
102+
w = 0
103+
}
104+
width, color = w, cmd.esc.colors != colors.Never
105+
}
106+
107+
files := map[string]*hcl.File{envName: {Bytes: yaml}}
108+
writer := hcl.NewDiagnosticTextWriter(out, files, uint(width), color)
109+
110+
sortEnvironmentDiagnostics(diags)
111+
112+
for _, d := range diags {
113+
var subject *hcl.Range
114+
if d.Range != nil {
115+
subject = &hcl.Range{
116+
Filename: d.Range.Environment,
117+
Start: hcl.Pos{
118+
Line: d.Range.Begin.Line,
119+
Column: d.Range.Begin.Column,
120+
Byte: d.Range.Begin.Byte,
121+
},
122+
End: hcl.Pos{
123+
Line: d.Range.End.Line,
124+
Column: d.Range.End.Column,
125+
Byte: d.Range.End.Byte,
126+
},
127+
}
128+
}
129+
err := writer.WriteDiagnostic(&hcl.Diagnostic{
130+
Severity: hcl.DiagError,
131+
Summary: d.Summary,
132+
Detail: d.Detail,
133+
Subject: subject,
134+
})
135+
if err != nil {
136+
return err
137+
}
138+
}
139+
140+
return nil
141+
}
142+
143+
func (cmd *envCommand) writePropertyEnvironmentDiagnostics(out io.Writer, diags []client.EnvironmentDiagnostic) error {
144+
sortEnvironmentDiagnostics(diags)
145+
146+
var b strings.Builder
147+
for _, d := range diags {
148+
b.Reset()
149+
150+
if d.Range != nil {
151+
fmt.Fprintf(&b, "%v%v:", colors.Red, d.Range.Environment)
152+
if d.Range.Begin.Line != 0 {
153+
fmt.Fprintf(&b, "%v:%v:", d.Range.Begin.Line, d.Range.Begin.Column)
154+
}
155+
fmt.Fprintf(&b, " ")
156+
}
157+
fmt.Fprintln(&b, d.Summary)
158+
159+
fmt.Fprint(out, cmd.esc.colors.Colorize(b.String()))
160+
}
161+
162+
return nil
163+
}

0 commit comments

Comments
 (0)