func (spec *Spec) runCommand(command []string) error { options := lxc.DefaultAttachOptions options.Cwd = "/root" options.Env = util.MinimalEnv() log.Debugf("Exec environment: %#v\n", options.Env) rootfs := spec.State.Container.ConfigItem("lxc.rootfs")[0] var buffer bytes.Buffer buffer.WriteString("#!/bin/bash\n") for _, v := range spec.State.Env { if _, err := buffer.WriteString("export " + v + "\n"); err != nil { return err } } options.ClearEnv = true if spec.State.Cwd != "" { buffer.WriteString("cd " + spec.State.Cwd + "\n") } buffer.WriteString(strings.Join(command, " ")) err := ioutil.WriteFile(filepath.Join(rootfs, "/tmp/dockerfile.sh"), buffer.Bytes(), 0755) if err != nil { log.Errorf("Failed to open file %s. Error: %v", err) return err } log.Debugf("Executing:\n %s\n", buffer.String()) exitCode, err := spec.State.Container.RunCommandStatus([]string{"/bin/bash", "/tmp/dockerfile.sh"}, options) if err != nil { log.Errorf("Failed to execute command: '%s'. Error: %v", command, err) return err } if exitCode != 0 { log.Warnf("Failed to execute command: '%s'. Exit code: %d", strings.Join(command, " "), exitCode) } return nil }
func (c *Builder) PerformBuild(container *lxc.Container, commands []structs.Command) error { for _, cmd := range commands { var wg sync.WaitGroup stdoutReader, stdoutWriter, err := os.Pipe() outWriter := new(bytes.Buffer) errWriter := new(bytes.Buffer) if err != nil { log.Errorf("Failed to create pipe: %v", err) return err } stderrReader, stderrWriter, err := os.Pipe() if err != nil { log.Errorf("Failed to create pipe: %v", err) return err } wg.Add(1) go func() { defer wg.Done() _, err := io.Copy(outWriter, stdoutReader) if err != nil { log.Errorf("Failed to copy stdout. Error: %v", err) } }() wg.Add(1) go func() { defer wg.Done() _, err := io.Copy(errWriter, stderrReader) if err != nil { log.Errorf("Failed to copy stderr. Error: %v", err) } }() log.Infof("Executing command: '%s'", cmd.Command) cwd := "/root" if cmd.Cwd != "" { cwd = cmd.Cwd } options := lxc.DefaultAttachOptions options.Env = util.MinimalEnv() options.StdoutFd = stdoutWriter.Fd() options.StderrFd = stderrWriter.Fd() options.ClearEnv = true options.Cwd = cwd exitCode, err := container.RunCommandStatus(strings.Fields(cmd.Command), options) if e := stdoutWriter.Close(); e != nil { log.Errorf("Failed to close stdout pipe. Error: %v", e) } if e := stderrWriter.Close(); e != nil { log.Errorf("Failed to close stderr pipe. Error: %v", e) } wg.Wait() c.Run.Stdout = strings.Join([]string{c.Run.Stdout, outWriter.String()}, "\n") c.Run.Stderr = strings.Join([]string{c.Run.Stderr, errWriter.String()}, "\n") if err != nil { log.Errorf("Failed to execute command: '%s'. Error: %v", cmd.Command, err) return err } if exitCode != 0 { log.Errorf("Failed to execute command: '%s'. Exit code: %d", cmd.Command, exitCode) return fmt.Errorf("Exit code:%d", exitCode) } } return nil }