<commit_before>package client

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/docker/docker/pkg/namesgenerator"
	gflag "github.com/jessevdk/go-flags"

	apitype "github.com/hyperhq/hyperd/types"
	"github.com/hyperhq/hyperd/utils"
	"github.com/hyperhq/runv/lib/term"
)

// hyperctl run [OPTIONS] image [COMMAND] [ARGS...]
func (cli *HyperClient) HyperCmdRun(args ...string) (err error) {
	copt, err := cli.ParseCreateOptions("run", args...)
	if copt == nil {
		return err
	}

	var (
		podId string
		vmId  string
		spec  apitype.UserPod
		code  int
		tty   = false
	)

	if copt.IsContainer {
		return fmt.Errorf("%s: \"run\" command only support run as a pod.", os.Args[0])
	}

	t1 := time.Now()

	err = json.Unmarshal([]byte(copt.JsonBytes), &spec)
	if err != nil {
		return err
	}

	podId, code, err = cli.client.CreatePod(&spec)
	if err != nil {
		if code == http.StatusNotFound {
			err = cli.PullImages(&spec)
			if err != nil {
				return
			}
			podId, code, err = cli.client.CreatePod(&spec)
		}
		if err != nil {
			return
		}
	}
	if !copt.Attach {
		fmt.Printf("POD id is %s\n", podId)
	}

	if copt.Remove {
		defer func() {
			rmerr := cli.client.RmPod(podId)
			if rmerr != nil {
				fmt.Fprintf(cli.out, "failed to rm pod, %v\n", rmerr)
			}
		}()
	}

	if copt.Attach {
		tty = spec.Tty || spec.Containers[0].Tty
		if tty {
			p, err := cli.client.GetPodInfo(podId)
			if err == nil {
				cli.monitorTtySize(p.Spec.Containers[0].ContainerID, "")
			}

			oldState, err := term.SetRawTerminal(cli.inFd)
			if err != nil {
				return err
			}
			defer term.RestoreTerminal(cli.inFd, oldState)
		}

	}

	_, err = cli.client.StartPod(podId, vmId, copt.Attach, tty, cli.in, cli.out, cli.err)
	if err != nil {
		return
	}

	if !copt.Attach {
		t2 := time.Now()
		fmt.Printf("Time to run a POD is %d ms\n", (t2.UnixNano()-t1.UnixNano())/1000000)
	}
	return nil
}

type CreateOptions struct {
	JsonBytes   []byte
	IsContainer bool //true for container, false for Pod
	PodId       string
	Attach      bool<commit_msg>separate start and attach in the client side<commit_after>package client

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"regexp"
	"strconv"
	"strings"
	"time"

	"github.com/docker/docker/pkg/namesgenerator"
	gflag "github.com/jessevdk/go-flags"

	apitype "github.com/hyperhq/hyperd/types"
	"github.com/hyperhq/hyperd/utils"
	"github.com/hyperhq/runv/lib/term"
)

// hyperctl run [OPTIONS] image [COMMAND] [ARGS...]
func (cli *HyperClient) HyperCmdRun(args ...string) (err error) {
	copt, err := cli.ParseCreateOptions("run", args...)
	if copt == nil {
		return err
	}

	var (
		podId string
		vmId  string
		spec  apitype.UserPod
		code  int
		tty   = false
		res   chan error
	)

	if copt.IsContainer {
		return fmt.Errorf("%s: \"run\" command only support run as a pod.", os.Args[0])
	}

	t1 := time.Now()

	err = json.Unmarshal([]byte(copt.JsonBytes), &spec)
	if err != nil {
		return err
	}

	podId, code, err = cli.client.CreatePod(&spec)
	if err != nil {
		if code == http.StatusNotFound {
			err = cli.PullImages(&spec)
			if err != nil {
				return
			}
			podId, code, err = cli.client.CreatePod(&spec)
		}
		if err != nil {
			return
		}
	}
	if !copt.Attach {
		fmt.Printf("POD id is %s\n", podId)
	}

	if copt.Remove {
		defer func() {
			rmerr := cli.client.RmPod(podId)
			if rmerr != nil {
				fmt.Fprintf(cli.out, "failed to rm pod, %v\n", rmerr)
			}
		}()
	}

	if copt.Attach && len(spec.Containers) > 0 {
		res = make(chan error, 1)
		tty = spec.Tty || spec.Containers[0].Tty
		p, err := cli.client.GetPodInfo(podId)
		if err != nil {
			fmt.Fprintf(cli.err, "failed to get pod info: %v", err)
			return err
		}
		if tty {
			cli.monitorTtySize(p.Spec.Containers[0].ContainerID, "")
			oldState, err := term.SetRawTerminal(cli.inFd)
			if err != nil {
				return err
			}
			defer term.RestoreTerminal(cli.inFd, oldState)
		}
		cname := spec.Containers[0].Name

		go func() {
			res <- cli.client.Attach(cname, tty, cli.in, cli.out, cli.err)
		}()
	}

	_, err = cli.client.StartPod(podId, vmId, false, tty, nil, nil, nil)
	if err != nil {
		return err
	}

	if !copt.Attach {
		t2 := time.Now()
		fmt.Printf("Time to run a POD is %d ms\n", (t2.UnixNano()-t1.UnixNano())/1000000)
	}

	if res != nil {
		err = <-res
		return cli.client.GetExitCode(spec.Containers[0].Name, "")
	}

	return nil
}

type CreateOptions struct {
	JsonBytes   []byte
	IsContainer bool //true for container, false for Pod
	PodId       string
	Attach      bool
{'fraction_non_alphanumeric': 0.1552362290441977, 'fraction_numerical': 0.006967123884171565, 'mean_word_length': 2.9569336778639106, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5765382', 'n_tokens_mistral': 2068, 'n_tokens_neox': 1888, 'n_words': 427}