Browse Source

Changed way to run docker

luisf 8 years ago
parent
commit
db6abd425b

+ 5 - 1
buildme.yml

@@ -9,7 +9,11 @@ tasks:
   build:
     use: builder
     command: 
-      - make dist
+      - RUN make dist
+      - RUN sh -c "echo test > t.txt"
+      - COPY /buildme/t.txt .
+      - COPY /buildme/dist.tar.gz .
+        #- /buildme/dist.tar.gz ./dist.tar.gz
     copy: /dist.tar.gz ./test.tar.gz
 
 

+ 3 - 0
src/buildme/cmd/builder/main.go

@@ -6,6 +6,7 @@ import (
 
 	_ "buildme/fetcher/git"
 	_ "buildme/fetcher/path"
+	"buildme/utils"
 
 	"dev.hexasoftware.com/hxs/prettylog"
 )
@@ -17,6 +18,8 @@ var (
 func main() {
 	prettylog.Global()
 
+	log.Println("R:", utils.ParseField(`this is a "test    1 2 3"`))
+
 	var fetchType string
 	var fetchPath string
 	var fetchName string

+ 142 - 98
src/buildme/docker.go

@@ -5,6 +5,7 @@ import (
 	"context"
 	"io"
 	"os"
+	"path"
 
 	"dev.hexasoftware.com/hxs/prettylog"
 	"dev.hexasoftware.com/x/seq"
@@ -14,7 +15,103 @@ import (
 	docker "github.com/docker/docker/client"
 )
 
-func RunContainerX(imageName string, containerName string, command string) error {
+type ImageCtx struct {
+	imageName string // Starting image
+	//conID     string
+	tmpImgID string
+	//containerName string // Temporary
+	cli *docker.Client
+}
+
+func ImageCli(imageName string) (*ImageCtx, error) {
+	cli, err := docker.NewEnvClient()
+	if err != nil {
+		return nil, err
+	}
+	return &ImageCtx{imageName, "", cli}, nil
+}
+
+func (c *ImageCtx) Run(command []string) error {
+	log := prettylog.New("RUN in IMAGE:")
+	log.Println("RUN", command)
+
+	ctx := context.Background()
+
+	if c.tmpImgID == "" {
+		c.tmpImgID = c.imageName
+	}
+
+	conConfig := &container.Config{Image: c.tmpImgID, Cmd: command}
+	ncon, err := c.cli.ContainerCreate(ctx, conConfig, nil, nil, "")
+	if err != nil {
+		return err
+	}
+	defer c.cli.ContainerRemove(ctx, ncon.ID, types.ContainerRemoveOptions{})
+	//c.conID = ncon.ID
+
+	err = c.cli.ContainerStart(ctx, ncon.ID, types.ContainerStartOptions{})
+	if err != nil {
+		return err
+	}
+	retCode, err := c.cli.ContainerWait(ctx, ncon.ID)
+	if err != nil {
+		return err
+	}
+	_ = retCode
+	/*if retCode != 0 {
+		return errors.New("Container did not complete successfully")
+	}*/
+
+	imgRes, err := c.cli.ContainerCommit(ctx, ncon.ID, types.ContainerCommitOptions{Config: conConfig})
+	c.tmpImgID = imgRes.ID
+
+	c.cli.ImageTag(ctx, imgRes.ID, c.imageName+":building")
+	return nil
+}
+
+func (c *ImageCtx) Copy(src string, dst string) error {
+	log := prettylog.New("COPY in IMAGE:")
+	log.Println("COPY", src, dst)
+	ctx := context.Background()
+
+	conConfig := &container.Config{Image: c.tmpImgID}
+	// Create container
+	log.Println("ContainerCreate")
+	ncon, err := c.cli.ContainerCreate(ctx, conConfig, nil, nil, "")
+	if err != nil {
+		return err
+	}
+	defer c.cli.ContainerRemove(ctx, ncon.ID, types.ContainerRemoveOptions{})
+
+	rd, p, err := c.cli.CopyFromContainer(ctx, ncon.ID, src)
+	if err != nil {
+		return err
+	}
+	defer rd.Close()
+	log.Println("Copy:", p)
+
+	dstStat, err := os.Stat(dst)
+	if err != nil {
+		return err
+	}
+	if dstStat.IsDir() {
+		dst = path.Join(dst, p.Name)
+		log.Println("Desitnation is dir, adding path", dst)
+	}
+
+	f, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY, p.Mode)
+	if err != nil {
+		return err
+	}
+
+	io.Copy(f, rd)
+	f.Sync()
+	f.Close()
+
+	return nil
+}
+
+func RunContainerX(imageName string, containerName string, command []string) error {
 	log := prettylog.New("RUN CONTAINER")
 
 	cli, err := docker.NewEnvClient()
@@ -41,29 +138,41 @@ func RunContainerX(imageName string, containerName string, command string) error
 	}
 	log.Println("Check if container running")
 	if !res.State.Running {
-		s := seq.New()
-		s.Add("Commit", cli.ContainerCommit, ctx, containerName, types.ContainerCommitOptions{Config: res.Config})
-		s.Add("Tag", func(imgRes types.IDResponse) error { return cli.ImageTag(ctx, imgRes.ID, imageName+"build-1") }, seq.SeqReturn(0, 0))
+
+		var imgRes types.IDResponse
+		var ncon container.ContainerCreateCreatedBody
+
+		s := seq.NewSeq()
+		s.Add("Commit", func() error {
+			var err error
+			imgRes, err = cli.ContainerCommit(ctx, containerName, types.ContainerCommitOptions{Config: res.Config})
+			return err
+		})
+
+		s.Add("Tag", func() error { return cli.ImageTag(ctx, imgRes.ID, imageName+"build-1") })
+
 		s.Add("Remove", cli.ContainerRemove, ctx, containerName, types.ContainerRemoveOptions{})
-		s.Add("Create", func(imgRes types.IDResponse) (container.ContainerCreateCreatedBody, error) {
-			return cli.ContainerCreate(ctx, &container.Config{Image: imgRes.ID, Cmd: utils.ParseField(command)}, res.HostConfig, nil, res.Name)
-		}, seq.SeqReturn(0, 0))
 
-		s.Add("Start", func(ncon container.ContainerCreateCreatedBody) error {
+		s.Add("Create", func() (container.ContainerCreateCreatedBody, error) {
+			return cli.ContainerCreate(ctx, &container.Config{Image: imgRes.ID, Cmd: command}, res.HostConfig, nil, res.Name)
+		}).Grab(&ncon)
+
+		s.Add("Start", func() error {
 			return cli.ContainerStart(ctx, ncon.ID, types.ContainerStartOptions{})
-		}, seq.SeqReturn(3, 0))
-		s.Add("Wait", func(ncon container.ContainerCreateCreatedBody) (int64, error) {
+		})
+		s.Add("Wait", func() (int64, error) {
 			return cli.ContainerWait(ctx, ncon.ID)
-		}, seq.SeqReturn(3, 0))
-		s.Add("Copy", func(ncon container.ContainerCreateCreatedBody) (io.ReadCloser, types.ContainerPathStat, error) {
+		})
+		var rd io.ReadCloser
+		s.Add("Copy", func() (io.ReadCloser, types.ContainerPathStat, error) {
 			return cli.CopyFromContainer(ctx, ncon.ID, "/buildme/dist.tar.gz")
-		}, seq.SeqReturn(3, 0))
+		}).Grab(&rd)
 
-		s.Add("Save", func(rd io.ReadCloser) error {
+		s.Add("Save", func() error {
 			f, err := os.OpenFile("./data/dist.tar.gz", os.O_CREATE|os.O_WRONLY, os.FileMode(0644))
 			io.Copy(f, rd)
 			return err
-		}, seq.SeqReturn(6, 0))
+		})
 
 		err := s.Exec()
 		if err != nil {
@@ -72,7 +181,7 @@ func RunContainerX(imageName string, containerName string, command string) error
 
 	} else {
 		log.Println("ContainerExecCreate")
-		r, err := cli.ContainerExecCreate(ctx, containerName, types.ExecConfig{Cmd: utils.ParseField(command)})
+		r, err := cli.ContainerExecCreate(ctx, containerName, types.ExecConfig{Cmd: command})
 		if err != nil {
 			return err
 		}
@@ -122,32 +231,34 @@ func RunContainer(imageName string, containerName string, command string) error
 
 		//nImageName := containerName + "-tmp"
 		log.Println("Container commit to")
-		imgRes, err := cli.ContainerCommit(ctx, containerName, types.ContainerCommitOptions{Config: res.Config})
-		if err != nil {
+		var err error
+		var imgRes types.IDResponse
+
+		if imgRes, err = cli.ContainerCommit(ctx, containerName, types.ContainerCommitOptions{Config: res.Config}); err != nil {
+			return err
+		}
+
+		if err = cli.ImageTag(ctx, imgRes.ID, imageName+"build-1"); err != nil {
 			return err
 		}
-		cli.ImageTag(ctx, imgRes.ID, imageName+"build-1")
-		// Remove Container and start other
+
 		log.Println("Removing container")
-		err = cli.ContainerRemove(ctx, containerName, types.ContainerRemoveOptions{})
-		if err != nil {
+		if err = cli.ContainerRemove(ctx, containerName, types.ContainerRemoveOptions{}); err != nil {
 			return err
 		}
 
 		log.Println("Starting new container with", imgRes.ID)
-		timeout := 10
-		ncon, err := cli.ContainerCreate(ctx, &container.Config{AttachStdin: true, AttachStderr: true, AttachStdout: true, OpenStdin: true, StopTimeout: &timeout,
-			Image: imgRes.ID, Cmd: utils.ParseField(command)}, res.HostConfig, nil, res.Name)
-		if err != nil {
+		var ncon container.ContainerCreateCreatedBody
+		if ncon, err = cli.ContainerCreate(ctx, &container.Config{Image: imgRes.ID, Cmd: utils.ParseField(command)}, res.HostConfig, nil, res.Name); err != nil {
 			return err
 		}
-		log.Println("Starting the created container timeout was:", timeout)
-		err = cli.ContainerStart(ctx, ncon.ID, types.ContainerStartOptions{})
-		if err != nil {
+
+		if err = cli.ContainerStart(ctx, ncon.ID, types.ContainerStartOptions{}); err != nil {
 			return err
 		}
-		ret, err := cli.ContainerWait(ctx, ncon.ID)
-		if err != nil {
+
+		var ret int64
+		if ret, err = cli.ContainerWait(ctx, ncon.ID); err != nil {
 			return err
 		}
 		log.Println("Returning withcode:", ret)
@@ -232,70 +343,3 @@ func RunImageCmd(image string, command string) error {
 	}
 	return nil
 }
-
-/*
-func DockerBuild(p *Project) error {
-	log.Println("New docker environ")
-	cli, err := docker.NewEnvClient()
-	if err != nil {
-		log.Println("Docker failed", err)
-		return err
-	}
-
-	dockertag := fmt.Sprintf("%s-builder", p.conf.Meta.Project)
-	log.Println("Building and tagging:", dockertag)
-	///////////////
-	/// DOCKER OPERATION / BUILDER operation
-	ctx := context.Background()
-	{
-		log.Println("Docker image build dockerfile:", p.Dockerfile)
-		imageRes, err := cli.ImageBuild(ctx, p.Reader(), types.ImageBuildOptions{Tags: []string{dockertag}, Dockerfile: p.Dockerfile})
-		if err != nil {
-			log.Println("Error building image:", err)
-			return err
-		}
-		defer imageRes.Body.Close()
-		io.Copy(os.Stdout, imageRes.Body) // Do some treatment somehow
-		//inf, err := cli.Info(ctx)
-		//log.Println("Info:", inf, err)
-	}
-
-	{
-		log.Println("Testing running the builder")
-		containerName := dockertag
-		containerCfg := &container.Config{AttachStdout: true, Cmd: []string{"cat", "/buildme/dist.tar.gz"}}
-		res, err := cli.ContainerCreate(ctx, containerCfg, nil, nil, containerName)
-		if err != nil {
-			return err
-		}
-		log.Println("Created container ID:", res)
-		log.Println("Starting container test")
-
-		cr, _, err := cli.CopyFromContainer(ctx, res.ID, "/buildme/dist.tar.gz")
-		if err != nil {
-			log.Println("Copy error", err)
-			return err
-		}
-		defer cr.Close()
-
-		log.Println("Creating writing file")
-		f, err := os.OpenFile("test.tar.gz", os.O_CREATE|os.O_WRONLY, os.FileMode(0600))
-		if err != nil {
-			log.Println("Error opening file", err)
-			return err
-		}
-		defer f.Close()
-
-		io.Copy(f, cr)
-		f.Sync()
-
-
-		log.Println("Please execute docker run", containerName, "> dist.tar.gz")
-		log.Println("Trying to remove container", res)
-		err = cli.ContainerRemove(ctx, res.ID, types.ContainerRemoveOptions{})
-		if err != nil {
-			return err
-		}
-	}
-	return nil
-}*/

+ 19 - 7
src/buildme/project.go

@@ -10,6 +10,8 @@ import (
 	"os"
 	"strings"
 
+	yaml "gopkg.in/yaml.v2"
+
 	"github.com/docker/docker/api/types"
 	docker "github.com/docker/docker/client"
 )
@@ -38,6 +40,10 @@ func NewProject() *Project {
 	}
 }
 
+func (p *Project) ParseConf(data []byte) error {
+	return yaml.Unmarshal(data, &p.conf)
+}
+
 //SetTarFile sets the source project tar
 func (p *Project) SetTarFile(tarFile string, isTemp bool) *Project {
 	p.tarFilename = tarFile
@@ -61,11 +67,7 @@ func (p *Project) SetConf(projConf ProjectConf) *Project {
 
 func (p *Project) Reader() io.ReadCloser {
 	f, _ := os.Open(p.tarFilename)
-	stat, _ := f.Stat()
-	return utils.NewStatReadCloser(f, int(stat.Size()), func(progress float64) {
-		log.Progress("Readed %.2f", progress)
-	})
-	//return f
+	return f
 }
 
 func (p *Project) Close() {
@@ -154,10 +156,20 @@ func (p *Project) Task(name string) error {
 	_ = containerRes*/
 
 	log.Println("Executing commands")
+	img, err := ImageCli(dockerTag)
+	if err != nil {
+		return err
+	}
 	// Builds image
 	for _, cmd := range taskconf.Command {
-		log.Println("Exec:", cmd)
-		err = RunContainerX(dockerTag, dockerTag, cmd)
+		vcmd := utils.ParseField(cmd)
+		var err error
+		switch vcmd[0] {
+		case "RUN":
+			err = img.Run(vcmd[1:])
+		case "COPY":
+			err = img.Copy(vcmd[1], vcmd[2])
+		}
 		if err != nil {
 			return err
 		}

+ 0 - 58
src/buildme/utils/seq.go

@@ -1,58 +0,0 @@
-package utils
-
-import "reflect"
-
-type seqEntry struct {
-	fn     interface{} // Function
-	fnVal  reflect.Value
-	params []interface{}
-
-	res []reflect.Value
-}
-
-type Seq struct {
-	seq []seqEntry
-}
-
-func NewSeq() *Seq {
-	return &Seq{[]seqEntry{}}
-}
-
-func (s *Seq) Add(fn interface{}, params ...interface{}) {
-	fnTyp := reflect.TypeOf(fn)
-	fnVal := reflect.ValueOf(fn)
-	if fnTyp.Kind() != reflect.Func {
-		log.Fatal("First paran should be a func")
-	}
-	if fnTyp.NumIn() != len(params) {
-		log.Fatal("Param len mismatch required")
-	}
-
-	if reflect.TypeOf(fn).Kind() != reflect.Func {
-		panic("First param should be a function")
-
-	}
-	s.seq = append(s.seq, seqEntry{fn: fn, fnVal: fnVal, params: params, res: []reflect.Value{}})
-}
-
-func (s *Seq) Exec() error {
-	for _, v := range s.seq {
-		vVal := reflect.ValueOf(v)
-		vparam := []reflect.Value{}
-		for _, p := range v.params {
-			vparam = append(vparam, reflect.ValueOf(p))
-		}
-		v.res = vVal.Call(vparam)
-
-		for _, r := range v.res {
-			err, ok := r.Interface().(error)
-			if ok {
-				log.Println("Error in a func:", err)
-				// We got error
-				return err
-			}
-		}
-	}
-
-	return nil
-}

+ 11 - 12
src/buildme/utils/string.go

@@ -8,19 +8,18 @@ import (
 // Smart splitter
 //ParseField
 func ParseField(s string) []string {
-	res := []string{}
 
-	re := regexp.MustCompile("[^\\\\]\"") // Non escaped '"'
-
-	fparts := re.Split(s, -1)
-	for i, v := range fparts {
-		if i&0x1 == 1 { // Even
-			res = append(res, v)
-			continue
-		}
-		res = append(res, strings.Split(v, " ")...)
+	re := regexp.MustCompile(`'.+'|".+"|\S+`)
+	m := re.FindAllString(s, -1)
+	// for now
+	for i, v := range m {
+		m[i] = strings.TrimFunc(v, func(r rune) bool {
+			if r == '"' || r == '\'' {
+				return true
+			}
+			return false
+		})
 	}
 
-	return res
-
+	return m
 }

+ 1 - 0
src/buildme/utils/tardir.go

@@ -61,6 +61,7 @@ func Tar(fpath string, w *os.File) error {
 		if err != nil {
 			return err
 		}
+		defer f.Close()
 
 		_, err = io.Copy(tw, f)
 		if err != nil {

BIN
t.txt