Skip to content

Commit

Permalink
Fix create bug when .ch.yaml not present. Closes #7
Browse files Browse the repository at this point in the history
  • Loading branch information
camerondurham committed Jan 18, 2021
1 parent 57fad95 commit ddc932b
Show file tree
Hide file tree
Showing 4 changed files with 119 additions and 42 deletions.
11 changes: 5 additions & 6 deletions cmd/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func CreateCmd(cmd *cobra.Command, args []string) {
opts.BuildOpts.Tag)
} else {
err = cli.DockerClient().PullImage(ctx,
opts.PullOpts.ImageName)
cli.Out(), opts.PullOpts.ImageName)
}

if err != nil {
Expand All @@ -133,16 +133,15 @@ func CreateCmd(cmd *cobra.Command, args []string) {
if err != nil {
if err == util.ErrDoesNotExist {
// save new environment opts into config file
viper.Set(fmt.Sprintf("envs.%s", name), opts)
envs = make(map[string]*util.ContainerOpts)
} else {
fmt.Print("cannot read environment")
util.DebugPrint(fmt.Sprintf("error reading environment: %v", err))
fmt.Print("cannot read environment from .ch.yaml")
os.Exit(1)
}
} else {
envs[name] = opts
viper.Set("envs", envs)
}

envs[name] = opts
util.SetEnvs(envs)

if err = viper.SafeWriteConfig(); err != nil {
Expand Down
40 changes: 4 additions & 36 deletions cmd/util/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import (
"encoding/json"
"errors"
"fmt"
"github.com/camerondurham/ch/cmd/streams"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/pkg/jsonmessage"
"io"
"io/ioutil"
"log"
Expand Down Expand Up @@ -72,7 +74,7 @@ func (d *DockerService) ListRunning() {
}

// PullImage downloads a Docker image from Docker Hub
func (d *DockerService) PullImage(ctx context.Context, imageName string) error {
func (d *DockerService) PullImage(ctx context.Context, out *streams.Out, imageName string) error {
imagePullOutput, err := d.ImagePull(ctx, imageName, types.ImagePullOptions{})

if err != nil {
Expand All @@ -91,41 +93,7 @@ func (d *DockerService) PullImage(ctx context.Context, imageName string) error {

defer imagePullOutput.Close()

rd := bufio.NewReader(imagePullOutput)
var retErr error

for {
str, err := rd.ReadString('\n')
if err == io.EOF {
retErr = nil
break
} else {
var msg ImagePullOutput

err = json.Unmarshal([]byte(str), &msg)

if err != nil {
DebugPrint(fmt.Sprintf("error unmarshalling str: [%v]\nerr:%v", str, err))
}

if msg.Error != "" {
retErr = fmt.Errorf("error pulling image: %v", msg.Error)
break
}

fmt.Printf("%s\n", msg.Status)
}
}

return retErr

//_, err = io.Copy(os.Stdout, imagePullResponse)

//if err != nil {
// return err
//}
//
//return nil
return jsonmessage.DisplayJSONMessagesToStream(imagePullOutput, out, nil)
}

// BuildImageWithContext accepts a build context path and relative Dockerfile path
Expand Down
15 changes: 15 additions & 0 deletions cmd/util/docker_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ type DockerAPI interface {
ContainerExecStart(ctx context.Context, execID string, config types.ExecStartCheck) error
ContainerExecAttach(ctx context.Context, execID string, config types.ExecStartCheck) (types.HijackedResponse, error)
ContainerExecInspect(ctx context.Context, execID string) (types.ContainerExecInspect, error)
ContainerExecResize(ctx context.Context, execID string, options types.ResizeOptions) error
ContainerResize(ctx context.Context, containerID string, options types.ResizeOptions) error
}

type DockerAPIService struct {
Expand Down Expand Up @@ -47,6 +49,14 @@ func (d *DockerAPIService) ContainerExecInspect(ctx context.Context, execID stri
return d.client.ContainerExecInspect(ctx, execID)
}

func (d *DockerAPIService) ContainerExecResize(ctx context.Context, id string, options types.ResizeOptions) error {
return d.client.ContainerExecResize(ctx, id, options)
}

func (d *DockerAPIService) ContainerResize(ctx context.Context, id string, options types.ResizeOptions) error {
return d.client.ContainerResize(ctx, id, options)
}

// CreateExecInteractive creates an exec config to run an exec process
func (d *DockerAPIService) CreateExecInteractive(ctx context.Context, cliClient ContainerClient, container string, config types.ExecConfig) error {
if _, err := d.ContainerInspect(ctx, container); err != nil {
Expand Down Expand Up @@ -116,6 +126,11 @@ func (d *DockerAPIService) InteractiveExec(ctx context.Context, cliClient Contai
}()

// ignore check if config wants a terminal and has appropriate Tty size for now
if execConfig.Tty && cliClient.In().IsTerminal() {
if err := MonitorTtySize(ctx, cliClient, execID, true); err != nil {
fmt.Fprintln(cliClient.Err(), "Error monitoring TTY size:", err)
}
}

// check MonitorTtySize
if err := <-errCh; err != nil {
Expand Down
95 changes: 95 additions & 0 deletions cmd/util/tty.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package util

import (
"context"
"fmt"
"os"
gosignal "os/signal"
"runtime"
"time"

"github.com/docker/docker/api/types"
"github.com/docker/docker/pkg/signal"
"github.com/sirupsen/logrus"
)

// resizeTtyTo resizes tty to specific height and width
func resizeTtyTo(ctx context.Context, client DockerAPI, id string, height, width uint, isExec bool) error {
if height == 0 && width == 0 {
return nil
}

options := types.ResizeOptions{
Height: height,
Width: width,
}

var err error
if isExec {
err = client.ContainerExecResize(ctx, id, options)
} else {
err = client.ContainerResize(ctx, id, options)
}

if err != nil {
logrus.Debugf("Error resize: %s\r", err)
}
return err
}

// resizeTty is to resize the tty with cli out's tty size
func resizeTty(ctx context.Context, cli ContainerClient, id string, isExec bool) error {
height, width := cli.Out().GetTtySize()
return resizeTtyTo(ctx, cli.ApiClient(), id, height, width, isExec)
}

// initTtySize is to init the tty's size to the same as the window, if there is an error, it will retry 5 times.
func initTtySize(ctx context.Context, cli ContainerClient, id string, isExec bool, resizeTtyFunc func(ctx context.Context, cli ContainerClient, id string, isExec bool) error) {
rttyFunc := resizeTtyFunc
if rttyFunc == nil {
rttyFunc = resizeTty
}
if err := rttyFunc(ctx, cli, id, isExec); err != nil {
go func() {
var err error
for retry := 0; retry < 5; retry++ {
time.Sleep(10 * time.Millisecond)
if err = rttyFunc(ctx, cli, id, isExec); err == nil {
break
}
}
if err != nil {
fmt.Fprintln(cli.Err(), "failed to resize tty, using default size")
}
}()
}
}

// MonitorTtySize updates the container tty size when the terminal tty changes size
func MonitorTtySize(ctx context.Context, cli ContainerClient, id string, isExec bool) error {
initTtySize(ctx, cli, id, isExec, resizeTty)
if runtime.GOOS == "windows" {
go func() {
prevH, prevW := cli.Out().GetTtySize()
for {
time.Sleep(time.Millisecond * 250)
h, w := cli.Out().GetTtySize()

if prevW != w || prevH != h {
resizeTty(ctx, cli, id, isExec)
}
prevH = h
prevW = w
}
}()
} else {
sigchan := make(chan os.Signal, 1)
gosignal.Notify(sigchan, signal.SIGWINCH)
go func() {
for range sigchan {
resizeTty(ctx, cli, id, isExec)
}
}()
}
return nil
}

0 comments on commit ddc932b

Please sign in to comment.