func (c *fileCmd) edit(config *lxd.Config, args []string) error { if len(args) != 1 { return errArgs } // If stdin isn't a terminal, read text from it if !termios.IsTerminal(int(syscall.Stdin)) { return c.push(config, append([]string{os.Stdin.Name()}, args[0])) } // Create temp file f, err := ioutil.TempFile("", "lxd_file_edit_") fname := f.Name() f.Close() os.Remove(fname) defer os.Remove(fname) // Extract current value err = c.pull(config, append([]string{args[0]}, fname)) if err != nil { return err } _, err = shared.TextEditor(fname, []byte{}) if err != nil { return err } err = c.push(config, append([]string{fname}, args[0])) if err != nil { return err } return nil }
func (c *networkCmd) doNetworkSet(client *lxd.Client, name string, args []string) error { // we shifted @args so so it should read "<key> [<value>]" if len(args) < 1 { return errArgs } network, err := client.NetworkGet(name) if err != nil { return err } key := args[0] var value string if len(args) < 2 { value = "" } else { value = args[1] } if !termios.IsTerminal(int(syscall.Stdin)) && value == "-" { buf, err := ioutil.ReadAll(os.Stdin) if err != nil { return fmt.Errorf("Can't read from stdin: %s", err) } value = string(buf[:]) } network.Config[key] = value return client.NetworkPut(name, network) }
func (c *profileCmd) doProfileSet(client *lxd.Client, p string, args []string) error { // we shifted @args so so it should read "<key> [<value>]" if len(args) < 1 { return errArgs } key := args[0] var value string if len(args) < 2 { value = "" } else { value = args[1] } if !termios.IsTerminal(int(syscall.Stdin)) && value == "-" { buf, err := ioutil.ReadAll(os.Stdin) if err != nil { return fmt.Errorf("Can't read from stdin: %s", err) } value = string(buf[:]) } err := client.SetProfileConfigItem(p, key, value) return err }
func (c *configCmd) doSet(config *lxd.Config, args []string, unset bool) error { if len(args) != 4 { return errArgs } // [[lxc config]] set dakara:c1 limits.memory 200000 remote, container := config.ParseRemoteAndContainer(args[1]) d, err := lxd.NewClient(config, remote) if err != nil { return err } key := args[2] value := args[3] if !termios.IsTerminal(int(syscall.Stdin)) && value == "-" { buf, err := ioutil.ReadAll(os.Stdin) if err != nil { return fmt.Errorf(i18n.G("Can't read from stdin: %s"), err) } value = string(buf[:]) } if unset { st, err := d.ContainerInfo(container) if err != nil { return err } _, ok := st.Config[key] if !ok { return fmt.Errorf(i18n.G("Can't unset key '%s', it's not currently set."), key) } } return d.SetContainerConfig(container, key, value) }
func (c *imageCmd) doImageEdit(client *lxd.Client, image string) error { // If stdin isn't a terminal, read text from it if !termios.IsTerminal(int(syscall.Stdin)) { contents, err := ioutil.ReadAll(os.Stdin) if err != nil { return err } newdata := shared.BriefImageInfo{} err = yaml.Unmarshal(contents, &newdata) if err != nil { return err } return client.PutImageInfo(image, newdata) } // Extract the current value config, err := client.GetImageInfo(image) if err != nil { return err } brief := config.Brief() data, err := yaml.Marshal(&brief) if err != nil { return err } // Spawn the editor content, err := shared.TextEditor("", []byte(c.imageEditHelp()+"\n\n"+string(data))) if err != nil { return err } for { // Parse the text received from the editor newdata := shared.BriefImageInfo{} err = yaml.Unmarshal(content, &newdata) if err == nil { err = client.PutImageInfo(image, newdata) } // Respawn the editor if err != nil { fmt.Fprintf(os.Stderr, i18n.G("Config parsing error: %s")+"\n", err) fmt.Println(i18n.G("Press enter to start the editor again")) _, err := os.Stdin.Read(make([]byte, 1)) if err != nil { return err } content, err = shared.TextEditor("", content) if err != nil { return err } continue } break } return nil }
func (c *execCmd) run(config *lxd.Config, args []string) error { if len(args) < 2 { return errArgs } remote, name := config.ParseRemoteAndContainer(args[0]) d, err := lxd.NewClient(config, remote) if err != nil { return err } env := map[string]string{"HOME": "/root", "USER": "******"} myEnv := os.Environ() for _, ent := range myEnv { if strings.HasPrefix(ent, "TERM=") { env["TERM"] = ent[len("TERM="):] } } for _, arg := range c.envArgs { pieces := strings.SplitN(arg, "=", 2) value := "" if len(pieces) > 1 { value = pieces[1] } env[pieces[0]] = value } cfd := int(syscall.Stdin) var interactive bool if c.modeFlag == "interactive" { interactive = true } else if c.modeFlag == "non-interactive" { interactive = false } else { interactive = termios.IsTerminal(cfd) && termios.IsTerminal(int(syscall.Stdout)) } var oldttystate *termios.State if interactive { oldttystate, err = termios.MakeRaw(cfd) if err != nil { return err } defer termios.Restore(cfd, oldttystate) } handler := c.controlSocketHandler if !interactive { handler = nil } stdout := c.getStdout() ret, err := d.Exec(name, args[1:], env, os.Stdin, stdout, os.Stderr, handler) if err != nil { return err } if oldttystate != nil { /* A bit of a special case here: we want to exit with the same code as * the process inside the container, so we explicitly exit here * instead of returning an error. * * Additionally, since os.Exit() exits without running deferred * functions, we restore the terminal explicitly. */ termios.Restore(cfd, oldttystate) } /* we get the result of waitpid() here so we need to transform it */ os.Exit(ret >> 8) return fmt.Errorf(i18n.G("unreachable return reached")) }
func (c *networkCmd) doNetworkEdit(client *lxd.Client, name string) error { // If stdin isn't a terminal, read text from it if !termios.IsTerminal(int(syscall.Stdin)) { contents, err := ioutil.ReadAll(os.Stdin) if err != nil { return err } newdata := shared.NetworkConfig{} err = yaml.Unmarshal(contents, &newdata) if err != nil { return err } return client.NetworkPut(name, newdata) } // Extract the current value network, err := client.NetworkGet(name) if err != nil { return err } data, err := yaml.Marshal(&network) if err != nil { return err } // Spawn the editor content, err := shared.TextEditor("", []byte(c.networkEditHelp()+"\n\n"+string(data))) if err != nil { return err } for { // Parse the text received from the editor newdata := shared.NetworkConfig{} err = yaml.Unmarshal(content, &newdata) if err == nil { err = client.NetworkPut(name, newdata) } // Respawn the editor if err != nil { fmt.Fprintf(os.Stderr, i18n.G("Config parsing error: %s")+"\n", err) fmt.Println(i18n.G("Press enter to open the editor again")) _, err := os.Stdin.Read(make([]byte, 1)) if err != nil { return err } content, err = shared.TextEditor("", content) if err != nil { return err } continue } break } return nil }