Ejemplo n.º 1
0
func newContainer(ctx context.Context, portoConn porto.API, cfg containerConfig, info execInfo) (cnt *container, err error) {
	apexctx.GetLogger(ctx).WithField("container", cfg.ID).Debugf("exec newContainer() with containerConfig: %s; execInfo: %s;", cfg, info)
	volumeProperties := map[string]string{
		"backend": cfg.VolumeBackend,
		"layers":  cfg.Layer,
		"private": "cocaine-app",
	}
	if err = info.applyVolumeLimits(ctx, cfg.ID, volumeProperties); err != nil {
		return nil, err
	}

	volumePath := filepath.Join(cfg.Root, "volume")
	if err = os.MkdirAll(volumePath, 0775); err != nil {
		return nil, err
	}
	defer func(err *error) {
		if *err != nil {
			apexctx.GetLogger(ctx).WithField("container", cfg.ID).Infof("cleaunup unfinished container footprint due to error %v", *err)
			portoConn.UnlinkVolume(volumePath, cfg.ID)
			os.RemoveAll(volumePath)
		}
	}(&err)

	volumeDescription, err := portoConn.CreateVolume(volumePath, volumeProperties)
	apexctx.GetLogger(ctx).WithField("container", cfg.ID).Debugf("create volume with volumeProperties: %s", volumeProperties)
	if err != nil {
		if !isEqualPortoError(err, portorpc.EError_VolumeAlreadyExists) {
			apexctx.GetLogger(ctx).WithError(err).WithField("container", cfg.ID).Error("unable to create volume")
			return nil, err
		}
		apexctx.GetLogger(ctx).WithField("container", cfg.ID).Info("volume already exists")
	} else {
		apexctx.GetLogger(ctx).WithField("container", cfg.ID).Infof("created volume %v", volumeDescription)
	}

	if err = portoConn.Create(cfg.ID); err != nil {
		return nil, err
	}

	if cfg.SetImgURI {
		info.env["image_uri"] = info.portoProfile.Registry() + "/" + info.name
	}

	if err = portoConn.SetProperty(cfg.ID, "bind", formatBinds(&info)); err != nil {
		return nil, err
	}
	if err = portoConn.SetProperty(cfg.ID, "command", formatCommand(info.executable, info.args)); err != nil {
		return nil, err
	}
	if err = portoConn.SetProperty(cfg.ID, "env", formatEnv(info.env)); err != nil {
		return nil, err
	}
	if info.ulimits != "" {
		if err = portoConn.SetProperty(cfg.ID, "ulimit", info.ulimits); err != nil {
			return nil, err
		}
	}
	if cwd := info.Cwd(); cwd != "" {
		if err = portoConn.SetProperty(cfg.ID, "cwd", cwd); err != nil {
			return nil, err
		}
	}
	if err = portoConn.SetProperty(cfg.ID, "net", pickNetwork(string(info.NetworkMode()))); err != nil {
		return nil, err
	}
	if err = portoConn.SetProperty(cfg.ID, "enable_porto", "false"); err != nil {
		return nil, err
	}
	if err = portoConn.SetProperty(cfg.ID, "root", volumePath); err != nil {
		return nil, err
	}
	if err = portoConn.LinkVolume(volumePath, cfg.ID); err != nil {
		return nil, err
	}

	if err = info.portoProfile.applyContainerLimits(ctx, portoConn, cfg.ID); err != nil {
		return nil, err
	}

	cnt = &container{
		ctx: ctx,

		containerID:    cfg.ID,
		rootDir:        cfg.Root,
		volumePath:     volumePath,
		cleanupEnabled: cfg.CleanupEnabled,
		SetImgURI:      cfg.SetImgURI,

		output: ioutil.Discard,
	}
	return cnt, nil
}