Пример #1
0
// applyLayer is the entry-point for docker-applylayer on re-exec. This is not
// used on Windows as it does not support chroot, hence no point sandboxing
// through chroot and rexec.
func applyLayer() {

	var (
		tmpDir  string
		err     error
		options *archive.TarOptions
	)
	runtime.LockOSThread()
	flag.Parse()

	inUserns := rsystem.RunningInUserNS()
	if err := chroot(flag.Arg(0)); err != nil {
		fatal(err)
	}

	// We need to be able to set any perms
	oldmask, err := system.Umask(0)
	defer system.Umask(oldmask)
	if err != nil {
		fatal(err)
	}

	if err := json.Unmarshal([]byte(os.Getenv("OPT")), &options); err != nil {
		fatal(err)
	}

	if inUserns {
		options.InUserNS = true
	}

	if tmpDir, err = ioutil.TempDir("/", "temp-docker-extract"); err != nil {
		fatal(err)
	}

	os.Setenv("TMPDIR", tmpDir)
	size, err := archive.UnpackLayer("/", os.Stdin, options)
	os.RemoveAll(tmpDir)
	if err != nil {
		fatal(err)
	}

	encoder := json.NewEncoder(os.Stdout)
	if err := encoder.Encode(applyLayerResponse{size}); err != nil {
		fatal(fmt.Errorf("unable to encode layerSize JSON: %s", err))
	}

	if _, err := flush(os.Stdin); err != nil {
		fatal(err)
	}

	os.Exit(0)
}
Пример #2
0
func do_export(ctx *context, ctrl *ext.Controller) bool {
	r := ctrl.Request
	if r.MethodToLower() != "get" {
		ctrl.JsonError(http.StatusMethodNotAllowed, errors.New("method not allowed"))
		return true
	}

	directory := path.Join(ctx.app.Options.Root, r.TrimSuffixURI(".export"))
	var tarOpt archive.TarOptions
	tarOpt.ExcludePatterns = append(tarOpt.ExcludePatterns,
		".tmp", ".h2object", "h2object.pid", "h2object.conf")
	tarOpt.Compression = archive.Gzip
	rd, err := archive.TarWithOptions(directory, &tarOpt)
	if err != nil {
		ctrl.JsonError(http.StatusInternalServerError, err)
		return true
	}
	defer rd.Close()

	_, fname := path.Split(r.TrimSuffixURI(".export"))
	if fname == "" {
		fname = "h2object"
	}
	fname = fname + ".tar.gz"
	fn := path.Join(ctx.app.Options.TempRoot, fname)

	fd, err := os.Create(fn)
	if err != nil {
		ctrl.JsonError(http.StatusInternalServerError, err)
		return true
	}
	if _, err := io.Copy(fd, rd); err != nil {
		ctrl.JsonError(http.StatusInternalServerError, err)
		return true
	}
	fd.Close()

	fout, err := os.Open(fn)
	if err != nil {
		ctrl.JsonError(http.StatusInternalServerError, err)
		return true
	}
	fstat, err := fout.Stat()
	if err != nil {
		ctrl.JsonError(http.StatusInternalServerError, err)
		return true
	}

	ctrl.Binary(fname, fout, fstat.Size())
	return true
}
Пример #3
0
// Untar reads a stream of bytes from `archive`, parses it as a tar archive,
// and unpacks it into the directory at `dest`.
// The archive may be compressed with one of the following algorithms:
//  identity (uncompressed), gzip, bzip2, xz.
func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error {

	if tarArchive == nil {
		return fmt.Errorf("Empty archive")
	}
	if options == nil {
		options = &archive.TarOptions{}
	}
	if options.ExcludePatterns == nil {
		options.ExcludePatterns = []string{}
	}

	dest = filepath.Clean(dest)
	if _, err := os.Stat(dest); os.IsNotExist(err) {
		if err := system.MkdirAll(dest, 0777); err != nil {
			return err
		}
	}

	decompressedArchive, err := archive.DecompressStream(tarArchive)
	if err != nil {
		return err
	}
	defer decompressedArchive.Close()

	return invokeUnpack(decompressedArchive, dest, options)
}
Пример #4
0
// applyLayerHandler parses a diff in the standard layer format from `layer`, and
// applies it to the directory `dest`. Returns the size in bytes of the
// contents of the layer.
func applyLayerHandler(dest string, layer io.Reader, options *archive.TarOptions, decompress bool) (size int64, err error) {
	dest = filepath.Clean(dest)
	if decompress {
		decompressed, err := archive.DecompressStream(layer)
		if err != nil {
			return 0, err
		}
		defer decompressed.Close()

		layer = decompressed
	}
	if options == nil {
		options = &archive.TarOptions{}
		if rsystem.RunningInUserNS() {
			options.InUserNS = true
		}
	}
	if options.ExcludePatterns == nil {
		options.ExcludePatterns = []string{}
	}

	data, err := json.Marshal(options)
	if err != nil {
		return 0, fmt.Errorf("ApplyLayer json encode: %v", err)
	}

	cmd := reexec.Command("docker-applyLayer", dest)
	cmd.Stdin = layer
	cmd.Env = append(cmd.Env, fmt.Sprintf("OPT=%s", data))

	outBuf, errBuf := new(bytes.Buffer), new(bytes.Buffer)
	cmd.Stdout, cmd.Stderr = outBuf, errBuf

	if err = cmd.Run(); err != nil {
		return 0, fmt.Errorf("ApplyLayer %s stdout: %s stderr: %s", err, outBuf, errBuf)
	}

	// Stdout should be a valid JSON struct representing an applyLayerResponse.
	response := applyLayerResponse{}
	decoder := json.NewDecoder(outBuf)
	if err = decoder.Decode(&response); err != nil {
		return 0, fmt.Errorf("unable to decode ApplyLayer JSON response: %s", err)
	}

	return response.LayerSize, nil
}
Пример #5
0
func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error {
	if tarArchive == nil {
		return fmt.Errorf("Empty archive")
	}
	if options == nil {
		options = &archive.TarOptions{}
	}
	if options.ExcludePatterns == nil {
		options.ExcludePatterns = []string{}
	}

	dest = filepath.Clean(dest)
	if _, err := os.Stat(dest); os.IsNotExist(err) {
		if err := os.MkdirAll(dest, 0777); err != nil {
			return err
		}
	}

	decompressedArchive, err := archive.DecompressStream(tarArchive)
	if err != nil {
		return err
	}
	defer decompressedArchive.Close()

	// We can't pass a potentially large exclude list directly via cmd line
	// because we easily overrun the kernel's max argument/environment size
	// when the full image list is passed (e.g. when this is used by
	// `docker load`). We will marshall the options via a pipe to the
	// child
	r, w, err := os.Pipe()
	if err != nil {
		return fmt.Errorf("Untar pipe failure: %v", err)
	}
	cmd := reexec.Command("docker-untar", dest)
	cmd.Stdin = decompressedArchive
	cmd.ExtraFiles = append(cmd.ExtraFiles, r)
	var output bytes.Buffer
	cmd.Stdout = &output
	cmd.Stderr = &output

	if err := cmd.Start(); err != nil {
		return fmt.Errorf("Untar error on re-exec cmd: %v", err)
	}
	//write the options to the pipe for the untar exec to read
	if err := json.NewEncoder(w).Encode(options); err != nil {
		return fmt.Errorf("Untar json encode to pipe failed: %v", err)
	}
	w.Close()

	if err := cmd.Wait(); err != nil {
		return fmt.Errorf("Untar re-exec error: %v: output: %s", err, output)
	}
	return nil
}
Пример #6
0
func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error {
	if tarArchive == nil {
		return fmt.Errorf("Empty archive")
	}
	if options == nil {
		options = &archive.TarOptions{}
	}
	if options.ExcludePatterns == nil {
		options.ExcludePatterns = []string{}
	}

	dest = filepath.Clean(dest)
	if _, err := os.Stat(dest); os.IsNotExist(err) {
		if err := os.MkdirAll(dest, 0777); err != nil {
			return err
		}
	}

	// We can't pass the exclude list directly via cmd line
	// because we easily overrun the shell max argument list length
	// when the full image list is passed (e.g. when this is used
	// by `docker load`). Instead we will add the JSON marshalled
	// and placed in the env, which has significantly larger
	// max size
	data, err := json.Marshal(options)
	if err != nil {
		return fmt.Errorf("Untar json encode: %v", err)
	}
	decompressedArchive, err := archive.DecompressStream(tarArchive)
	if err != nil {
		return err
	}
	defer decompressedArchive.Close()

	cmd := reexec.Command("docker-untar", dest)
	cmd.Stdin = decompressedArchive
	cmd.Env = append(cmd.Env, fmt.Sprintf("OPT=%s", data))
	out, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("Untar %s %s", err, out)
	}
	return nil
}
Пример #7
0
func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error {
	if tarArchive == nil {
		return fmt.Errorf("Empty archive")
	}
	if options == nil {
		options = &archive.TarOptions{}
	}
	if options.ExcludePatterns == nil {
		options.ExcludePatterns = []string{}
	}

	var (
		buf bytes.Buffer
		enc = json.NewEncoder(&buf)
	)
	if err := enc.Encode(options); err != nil {
		return fmt.Errorf("Untar json encode: %v", err)
	}
	if _, err := os.Stat(dest); os.IsNotExist(err) {
		if err := os.MkdirAll(dest, 0777); err != nil {
			return err
		}
	}
	dest = filepath.Clean(dest)
	decompressedArchive, err := archive.DecompressStream(tarArchive)
	if err != nil {
		return err
	}
	defer decompressedArchive.Close()

	cmd := reexec.Command("docker-untar", dest, buf.String())
	cmd.Stdin = decompressedArchive
	out, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("Untar %s %s", err, out)
	}
	return nil
}
Пример #8
0
// Handler for teasing out the automatic decompression
func untarHandler(tarArchive io.Reader, dest string, options *archive.TarOptions, decompress bool) error {

	if tarArchive == nil {
		return fmt.Errorf("Empty archive")
	}
	if options == nil {
		options = &archive.TarOptions{}
	}
	if options.ExcludePatterns == nil {
		options.ExcludePatterns = []string{}
	}

	rootUID, rootGID, err := idtools.GetRootUIDGID(options.UIDMaps, options.GIDMaps)
	if err != nil {
		return err
	}

	dest = filepath.Clean(dest)
	if _, err := os.Stat(dest); os.IsNotExist(err) {
		if err := idtools.MkdirAllNewAs(dest, 0755, rootUID, rootGID); err != nil {
			return err
		}
	}

	r := ioutil.NopCloser(tarArchive)
	if decompress {
		decompressedArchive, err := archive.DecompressStream(tarArchive)
		if err != nil {
			return err
		}
		defer decompressedArchive.Close()
		r = decompressedArchive
	}

	return invokeUnpack(r, dest, options)
}
Пример #9
0
func Untar(tarArchive io.Reader, dest string, options *archive.TarOptions) error {
	if tarArchive == nil {
		return fmt.Errorf("Empty archive")
	}
	if options == nil {
		options = &archive.TarOptions{}
	}
	if options.ExcludePatterns == nil {
		options.ExcludePatterns = []string{}
	}

	dest = filepath.Clean(dest)
	if _, err := os.Stat(dest); os.IsNotExist(err) {
		if err := system.MkdirAll(dest, 0777); err != nil {
			return err
		}
	}

	decompressedArchive, err := archive.DecompressStream(tarArchive)
	if err != nil {
		return err
	}

	var data []byte
	var r, w *os.File
	defer decompressedArchive.Close()

	if runtime.GOOS != "windows" {
		// We can't pass a potentially large exclude list directly via cmd line
		// because we easily overrun the kernel's max argument/environment size
		// when the full image list is passed (e.g. when this is used by
		// `docker load`). We will marshall the options via a pipe to the
		// child

		// This solution won't work on Windows as it will fail in golang
		// exec_windows.go as at the lowest layer because attr.Files > 3
		r, w, err = os.Pipe()
		if err != nil {
			return fmt.Errorf("Untar pipe failure: %v", err)
		}
	} else {
		// We can't pass the exclude list directly via cmd line
		// because we easily overrun the shell max argument list length
		// when the full image list is passed (e.g. when this is used
		// by `docker load`). Instead we will add the JSON marshalled
		// and placed in the env, which has significantly larger
		// max size
		data, err = json.Marshal(options)
		if err != nil {
			return fmt.Errorf("Untar json encode: %v", err)
		}
	}

	cmd := reexec.Command("docker-untar", dest)
	cmd.Stdin = decompressedArchive

	if runtime.GOOS != "windows" {
		cmd.ExtraFiles = append(cmd.ExtraFiles, r)
		output := bytes.NewBuffer(nil)
		cmd.Stdout = output
		cmd.Stderr = output

		if err := cmd.Start(); err != nil {
			return fmt.Errorf("Untar error on re-exec cmd: %v", err)
		}
		//write the options to the pipe for the untar exec to read
		if err := json.NewEncoder(w).Encode(options); err != nil {
			return fmt.Errorf("Untar json encode to pipe failed: %v", err)
		}
		w.Close()

		if err := cmd.Wait(); err != nil {
			return fmt.Errorf("Untar re-exec error: %v: output: %s", err, output)
		}
		return nil
	} else {
		cmd.Env = append(cmd.Env, fmt.Sprintf("OPT=%s", data))
		out, err := cmd.CombinedOutput()
		if err != nil {
			return fmt.Errorf("Untar %s %s", err, out)
		}
		return nil
	}

}
Пример #10
0
func themePushCommand(ctx *cli.Context) {
	workdir := ctx.GlobalString("workdir")
	if workdir == "" {
		fmt.Println("unknown working directory, please use -w to provide.")
		os.Exit(1)
	}
	// directory
	directory, err := filepath.Abs(workdir)
	if err != nil {
		fmt.Println("workdir:", err)
		return
	}

	stdout := os.Stdout
	stderr := os.Stderr

	// auth check
	config, err := LoadConfigFile(directory)
	if err != nil {
		fmt.Fprintln(stderr, err.Error())
		os.Exit(1)
	}

	if config.Auth.Token == "" || config.Auth.Secret == "" {
		fmt.Fprintln(stdout, "theme push need login first. ")
		os.Exit(1)
	}

	h2oconf, err := app.LoadCONFIG(path.Join(directory, "h2object.conf"))
	if err != nil {
		fmt.Fprintln(stdout, err)
		os.Exit(1)
	}

	host := ctx.String("Host")
	port := ctx.Int("Port")
	client := NewClient(directory, host, port)

	var pkg Package
	h2oconf.SetSection("theme")
	pkg.Provider = h2oconf.StringDefault("provider", "")
	if pkg.Provider == "" {
		fmt.Fprintln(stderr, "please set h2object.conf [theme]provider first.")
		os.Exit(1)
	}
	pkg.Name = h2oconf.StringDefault("name", "")
	if pkg.Name == "" {
		fmt.Fprintln(stderr, "please set h2object.conf [theme]name first.")
		os.Exit(1)
	}

	pkg.Description = h2oconf.StringDefault("description", "")
	if pkg.Description == "" {
		fmt.Fprintln(stderr, "please set h2object.conf [theme]description first.")
		os.Exit(1)
	}

	pkg.Version = h2oconf.StringDefault("version", "1.0.0")
	public := h2oconf.BoolDefault("public", false)
	pkg.Status = 1
	if public == true {
		pkg.Status = 2
	}
	pkg.Price = h2oconf.FloatDefault("price", 0.0)
	pkg.Catagory = int64(h2oconf.IntDefault("catagory", 1))

	var tarOpt archive.TarOptions
	tarOpt.ExcludePatterns = append(tarOpt.ExcludePatterns, ".h2object")
	tarOpt.Compression = archive.Gzip
	rd, err := archive.TarWithOptions(directory, &tarOpt)
	if err != nil {
		fmt.Fprintln(stderr, err.Error())
		os.Exit(1)
	}
	defer rd.Close()
	pkg.ArchiveReader = rd
	pkg.ArchiveName = pkg.Version + ".tar.gz"

	if err := client.ThemePush(config.Auth.Token, &pkg); err != nil {
		fmt.Fprintln(stderr, err.Error())
		os.Exit(1)
	}
	os.Exit(0)
}