func parsePortMapping(portmap string) (*pod.UserContainerPort, error) { var ( port = pod.UserContainerPort{} proto string hPort string cPort string err error ) fields := strings.Split(portmap, ":") if len(fields) < 2 { return nil, fmt.Errorf("flag needs host port and container port: --publish") } else if len(fields) == 2 { proto = "tcp" hPort = fields[0] cPort = fields[1] } else { proto = fields[0] if proto != "tcp" && proto != "udp" { return nil, fmt.Errorf("flag needs protocol(tcp or udp): --publish") } hPort = fields[1] cPort = fields[2] } port.Protocol = proto port.HostPort, err = strconv.Atoi(hPort) if err != nil { return nil, fmt.Errorf("flag needs host port and container port: --publish: %v", err) } port.ContainerPort, err = strconv.Atoi(cPort) if err != nil { return nil, fmt.Errorf("flag needs host port and container port: --publish: %v", err) } return &port, nil }
// hyper run [OPTIONS] image [COMMAND] [ARGS...] func (cli *HyperClient) HyperCmdRun(args ...string) error { if len(args) == 0 { return fmt.Errorf("%s ERROR: Can not accept the 'run' command without argument!\n", os.Args[0]) } var opts struct { PodFile string `short:"p" long:"podfile" value-name:"\"\"" description:"Create and Run a pod based on the pod file"` K8s string `short:"k" long:"kubernetes" value-name:"\"\"" description:"Create and Run a pod based on the kubernetes pod file"` Yaml bool `short:"y" long:"yaml" default:"false" default-mask:"-" description:"Create a pod based on Yaml file"` Name string `long:"name" value-name:"\"\"" description:"Assign a name to the container"` Attach bool `long:"attach" default:"true" default-mask:"-" description:"Attach the stdin, stdout and stderr to the container"` Workdir string `long:"workdir" default:"/" value-name:"\"\"" default-mask:"-" description:"Working directory inside the container"` Tty bool `long:"tty" default:"true" default-mask:"-" description:"Allocate a pseudo-TTY"` Cpu int `long:"cpu" default:"1" value-name:"1" default-mask:"-" description:"CPU number for the VM"` Memory int `long:"memory" default:"128" value-name:"128" default-mask:"-" description:"Memory size (MB) for the VM"` Env []string `long:"env" value-name:"[]" default-mask:"-" description:"Set environment variables"` EntryPoint string `long:"entrypoint" value-name:"\"\"" default-mask:"-" description:"Overwrite the default ENTRYPOINT of the image"` RestartPolicy string `long:"restart" default:"never" value-name:"\"\"" default-mask:"-" description:"Restart policy to apply when a container exits (never, onFailure, always)"` Remove bool `long:"rm" default:"false" value-name:"" default-mask:"-" description:"Automatically remove the pod when it exits"` Portmap []string `long:"publish" value-name:"[]" default-mask:"-" description:"Publish a container's port to the host, format: --publish [tcp/udp:]hostPort:containerPort"` } var parser = gflag.NewParser(&opts, gflag.Default|gflag.IgnoreUnknown) parser.Usage = "run [OPTIONS] IMAGE [COMMAND] [ARG...]\n\nCreate a pod, and launch a new VM to run the pod" args, err := parser.Parse() if err != nil { if !strings.Contains(err.Error(), "Usage") { return err } else { return nil } } if opts.PodFile != "" { if _, err := os.Stat(opts.PodFile); err != nil { return err } jsonbody, err := ioutil.ReadFile(opts.PodFile) if err != nil { return err } if opts.Yaml == true { jsonbody, err = cli.ConvertYamlToJson(jsonbody) if err != nil { return err } } t1 := time.Now() podId, err := cli.RunPod(string(jsonbody), opts.Remove) if err != nil { return err } fmt.Printf("POD id is %s\n", podId) t2 := time.Now() fmt.Printf("Time to run a POD is %d ms\n", (t2.UnixNano()-t1.UnixNano())/1000000) return nil } if opts.K8s != "" { var ( kpod pod.KPod userpod *pod.UserPod ) if _, err := os.Stat(opts.K8s); err != nil { return err } jsonbody, err := ioutil.ReadFile(opts.K8s) if err != nil { return err } if opts.Yaml == true { jsonbody, err = cli.ConvertYamlToJson(jsonbody) if err != nil { return err } } if err := json.Unmarshal(jsonbody, &kpod); err != nil { return err } userpod, err = kpod.Convert() if err != nil { return err } jsonbody, err = json.Marshal(*userpod) if err != nil { return err } t1 := time.Now() podId, err := cli.RunPod(string(jsonbody), opts.Remove) if err != nil { return err } fmt.Printf("POD id is %s\n", podId) t2 := time.Now() fmt.Printf("Time to run a POD is %d ms\n", (t2.UnixNano()-t1.UnixNano())/1000000) return nil } if len(args) == 0 { return fmt.Errorf("%s: \"run\" requires a minimum of 1 argument, please provide the image.", os.Args[0]) } var ( image = args[1] command = []string{} env = []pod.UserEnvironmentVar{} ports = []pod.UserContainerPort{} proto string hPort string cPort string ) if len(args) > 1 { command = args[2:] } if opts.Name == "" { opts.Name = image fields := strings.Split(image, "/") if len(fields) > 1 { opts.Name = fields[len(fields)-1] } fields = strings.Split(opts.Name, ":") if len(fields) < 2 { opts.Name = opts.Name + "-" + utils.RandStr(10, "number") } else { opts.Name = fields[0] + "-" + fields[1] + "-" + utils.RandStr(10, "number") } validContainerNameChars := `[a-zA-Z0-9][a-zA-Z0-9_.-]` validContainerNamePattern := regexp.MustCompile(`^/?` + validContainerNameChars + `+$`) if !validContainerNamePattern.MatchString(opts.Name) { opts.Name = namesgenerator.GetRandomName(0) } } if opts.Memory == 0 { opts.Memory = 128 } if opts.Cpu == 0 { opts.Cpu = 1 } for _, v := range opts.Env { if v == "" || !strings.Contains(v, "=") { continue } userEnv := pod.UserEnvironmentVar{ Env: v[:strings.Index(v, "=")], Value: v[strings.Index(v, "=")+1:], } env = append(env, userEnv) } for _, v := range opts.Portmap { port := pod.UserContainerPort{} fields := strings.Split(v, ":") if len(fields) < 2 { return fmt.Errorf("flag needs host port and container port: --publish") } else if len(fields) == 2 { proto = "tcp" hPort = fields[0] cPort = fields[1] } else { proto = fields[0] if proto != "tcp" && proto != "udp" { return fmt.Errorf("flag needs protocol(tcp or udp): --publish") } hPort = fields[1] cPort = fields[2] } port.Protocol = proto port.HostPort, err = strconv.Atoi(hPort) if err != nil { return fmt.Errorf("flag needs host port and container port: --publish") } port.ContainerPort, err = strconv.Atoi(cPort) if err != nil { return fmt.Errorf("flag needs host port and container port: --publish") } ports = append(ports, port) } var containerList = []pod.UserContainer{} var container = pod.UserContainer{ Name: opts.Name, Image: image, Command: command, Workdir: opts.Workdir, Entrypoint: []string{}, Ports: ports, Envs: env, Volumes: []pod.UserVolumeReference{}, Files: []pod.UserFileReference{}, RestartPolicy: opts.RestartPolicy, } containerList = append(containerList, container) var userPod = &pod.UserPod{ Name: opts.Name, Containers: containerList, Resource: pod.UserResource{Vcpu: opts.Cpu, Memory: opts.Memory}, Files: []pod.UserFile{}, Volumes: []pod.UserVolume{}, Tty: opts.Tty, } jsonString, _ := json.Marshal(userPod) podId, err := cli.RunPod(string(jsonString), opts.Remove) if err != nil { return err } fmt.Printf("POD id is %s\n", podId) // Get the container ID of this POD containerId, err := cli.GetContainerByPod(podId) if err != nil { return err } var ( tag = cli.GetTag() hijacked = make(chan io.Closer) errCh chan error ) v := url.Values{} v.Set("type", "container") v.Set("value", containerId) v.Set("tag", tag) // Block the return until the chan gets closed defer func() { // fmt.Printf("End of CmdExec(), Waiting for hijack to finish.\n") if _, ok := <-hijacked; ok { fmt.Printf("Hijack did not finish (chan still open)\n") } }() errCh = promise.Go(func() error { return cli.hijack("POST", "/attach?"+v.Encode(), true, cli.in, cli.out, cli.out, hijacked, nil, "") }) if err := cli.monitorTtySize(podId, tag); err != nil { fmt.Printf("Monitor tty size fail for %s!\n", podId) } // Acknowledge the hijack before starting select { case closer := <-hijacked: // Make sure that hijack gets closed when returning. (result // in closing hijack chan and freeing server's goroutines. if closer != nil { defer closer.Close() } case err := <-errCh: if err != nil { fmt.Printf("Error hijack: %s", err.Error()) return err } } if err := <-errCh; err != nil { fmt.Printf("Error hijack: %s", err.Error()) return err } // fmt.Printf("Success to exec the command %s for POD %s!\n", command, podId) return nil }