Skip to content

Commit

Permalink
Merge #11201 #11302
Browse files Browse the repository at this point in the history
11201: [cli] Abstract out terminal interactions r=pgavlin a=pgavlin

Replace direct interaction with the terminal with an abstraction. This
abstraction is tightly constrained to the capabilities needed for the
CLI's display. Using this abstraction allows for straightforward testing
of the interactive renderers.

11302: Changelog and go.mod updates for v3.46.1 r=pulumi-bot a=pulumi-bot

bors merge

Co-authored-by: Pat Gavlin <pat@pulumi.com>
Co-authored-by: github-actions <github-actions@github.com>
  • Loading branch information
3 people committed Nov 9, 2022
3 parents 8c2c6f3 + a20ddff + 978ca87 commit fdb5ea2
Show file tree
Hide file tree
Showing 119 changed files with 25,125 additions and 311 deletions.
35 changes: 35 additions & 0 deletions CHANGELOG.md
@@ -1,5 +1,40 @@
# Changelog

## 3.46.1 (2022-11-09)


### Features

- [cli] Enables debug tracing of Pulumi gRPC internals: `PULUMI_DEBUG_GRPC=$PWD/grpc.json pulumi up`
[#11085](https://github.com/pulumi/pulumi/pull/11085)

- [cli/display] Improve the usability of the interactive dipslay by making the treetable scrollable
[#11200](https://github.com/pulumi/pulumi/pull/11200)

- [pkg] Add `DeletedWith` as a resource option.
[#11095](https://github.com/pulumi/pulumi/pull/11095)

- [programgen] More programs can be converted to Pulumi when using `pulumi convert`, provider bridging, and conversion tools by allowing property accesses and field names to fall back to a case insensitive lookup.
[#11266](https://github.com/pulumi/pulumi/pull/11266)


### Bug Fixes

- [engine] Disable auto parenting to see if that fixes #10950.
[#11272](https://github.com/pulumi/pulumi/pull/11272)

- [yaml] [Updates Pulumi YAML to v1.0.2](https://github.com/pulumi/pulumi-yaml/releases/tag/v1.0.2) which fixes a bug encountered using templates with project level config.
[#11296](https://github.com/pulumi/pulumi/pull/11296)

- [sdkgen/go] Allow resource names that conflict with additional types.
[#11244](https://github.com/pulumi/pulumi/pull/11244)

- [sdkgen/go] Guard against conflicting field names.
[#11262](https://github.com/pulumi/pulumi/pull/11262)

- [sdk/python] Handle None being passed to register_resource_outputs.
[#11226](https://github.com/pulumi/pulumi/pull/11226)

## 3.46.0 (2022-11-02)


Expand Down

This file was deleted.

This file was deleted.

4 changes: 0 additions & 4 deletions changelog/pending/20221102--cli--pulumi-debug-grpc.yaml

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

4 changes: 0 additions & 4 deletions changelog/pending/20221108--yaml1-0-2.yaml

This file was deleted.

1 change: 1 addition & 0 deletions pkg/backend/display/diff_test.go
@@ -1,3 +1,4 @@
//nolint:goconst
package display

import (
Expand Down
79 changes: 79 additions & 0 deletions pkg/backend/display/internal/terminal/info.go
@@ -0,0 +1,79 @@
package terminal

import (
"fmt"
"io"

gotty "github.com/ijc/Gotty"
)

type Info interface {
Parse(attr string, params ...interface{}) (string, error)

ClearLine(out io.Writer)
CursorUp(out io.Writer, count int)
CursorDown(out io.Writer, count int)
}

/* Satisfied by gotty.TermInfo as well as noTermInfo from below */
type termInfo interface {
Parse(attr string, params ...interface{}) (string, error)
}

type noTermInfo int // canary used when no terminfo.

func (ti noTermInfo) Parse(attr string, params ...interface{}) (string, error) {
return "", fmt.Errorf("noTermInfo")
}

type info struct {
termInfo
}

var _ = Info(info{})

func OpenInfo(terminal string) Info {
if i, err := gotty.OpenTermInfo(terminal); err == nil {
return info{i}
}
return info{noTermInfo(0)}
}

func (i info) ClearLine(out io.Writer) {
// el2 (clear whole line) is not exposed by terminfo.

// First clear line from beginning to cursor
if attr, err := i.Parse("el1"); err == nil {
fmt.Fprintf(out, "%s", attr)
} else {
fmt.Fprintf(out, "\x1b[1K")
}
// Then clear line from cursor to end
if attr, err := i.Parse("el"); err == nil {
fmt.Fprintf(out, "%s", attr)
} else {
fmt.Fprintf(out, "\x1b[K")
}
}

func (i info) CursorUp(out io.Writer, count int) {
if count == 0 { // Should never be the case, but be tolerant
return
}
if attr, err := i.Parse("cuu", count); err == nil {
fmt.Fprintf(out, "%s", attr)
} else {
fmt.Fprintf(out, "\x1b[%dA", count)
}
}

func (i info) CursorDown(out io.Writer, count int) {
if count == 0 { // Should never be the case, but be tolerant
return
}
if attr, err := i.Parse("cud", count); err == nil {
fmt.Fprintf(out, "%s", attr)
} else {
fmt.Fprintf(out, "\x1b[%dB", count)
}
}
80 changes: 80 additions & 0 deletions pkg/backend/display/internal/terminal/mock.go
@@ -0,0 +1,80 @@
package terminal

import (
"io"
"sync"
)

type MockTerminal struct {
m sync.Mutex

width, height int
raw bool
info Info

keys chan string

dest io.Writer
}

func NewMockTerminal(dest io.Writer, width, height int, raw bool) *MockTerminal {
return &MockTerminal{
width: width,
height: height,
raw: raw,
info: info{noTermInfo(0)},
keys: make(chan string),
dest: dest,
}
}

func (t *MockTerminal) IsRaw() bool {
return t.raw
}

func (t *MockTerminal) Close() error {
close(t.keys)
return nil
}

func (t *MockTerminal) Size() (width, height int, err error) {
t.m.Lock()
defer t.m.Unlock()

return t.width, t.height, nil
}

func (t *MockTerminal) Write(b []byte) (int, error) {
return t.dest.Write(b)
}

func (t *MockTerminal) ClearLine() {
t.info.ClearLine(t)
}

func (t *MockTerminal) CursorUp(count int) {
t.info.CursorUp(t, count)
}

func (t *MockTerminal) CursorDown(count int) {
t.info.CursorDown(t, count)
}

func (t *MockTerminal) ReadKey() (string, error) {
k, ok := <-t.keys
if !ok {
return "", io.EOF
}
return k, nil
}

func (t *MockTerminal) SetSize(width, height int) {
t.m.Lock()
defer t.m.Unlock()

t.width, t.height = width, height
}

func (t *MockTerminal) SendKey(key string) {
t.keys <- key
}

0 comments on commit fdb5ea2

Please sign in to comment.