Ejemplo n.º 1
0
// parseTmpfs supports a simple tmpfs decl, similar to docker run.
//
// This should go away.
func parseTmpfs(flags *pflag.FlagSet, spec *api.ServiceSpec) error {
	if flags.Changed("tmpfs") {
		tmpfss, err := flags.GetStringSlice("tmpfs")
		if err != nil {
			return err
		}

		container := spec.Task.GetContainer()
		// TODO(stevvooe): Nasty inline parsing code, replace with mount syntax.
		for _, tmpfs := range tmpfss {
			parts := strings.SplitN(tmpfs, ":", 2)

			if len(parts) < 1 {
				return errors.Errorf("invalid mount spec: %v", tmpfs)
			}

			if len(parts[0]) == 0 || !path.IsAbs(parts[0]) {
				return errors.Errorf("invalid mount spec: %v", tmpfs)
			}

			m := api.Mount{
				Type:   api.MountTypeTmpfs,
				Target: parts[0],
			}

			if len(parts) == 2 {
				if strings.Contains(parts[1], ":") {
					// repeated colon is illegal
					return errors.Errorf("invalid mount spec: %v", tmpfs)
				}

				// BUG(stevvooe): Cobra stringslice actually doesn't correctly
				// handle comma separated values, so multiple flags aren't
				// really supported. We'll have to replace StringSlice with a
				// type that doesn't use the csv parser. This is good enough
				// for now.

				flags := strings.Split(parts[1], ",")
				var opts api.Mount_TmpfsOptions
				for _, flag := range flags {
					switch {
					case strings.HasPrefix(flag, "size="):
						meat := strings.TrimPrefix(flag, "size=")

						// try to parse this into bytes
						i, err := strconv.ParseInt(meat, 10, 64)
						if err != nil {
							// remove suffux and try again
							suffix := meat[len(meat)-1]
							meat = meat[:len(meat)-1]
							var multiplier int64 = 1
							switch suffix {
							case 'g':
								multiplier = 1 << 30
							case 'm':
								multiplier = 1 << 20
							case 'k':
								multiplier = 1 << 10
							default:
								return errors.Errorf("invalid size format: %v", flag)
							}

							// reparse the meat
							var err error
							i, err = strconv.ParseInt(meat, 10, 64)
							if err != nil {
								return err
							}

							i *= multiplier
						}
						opts.SizeBytes = i
					case strings.HasPrefix(flag, "mode="):
						meat := strings.TrimPrefix(flag, "mode=")
						i, err := strconv.ParseInt(meat, 8, 32)
						if err != nil {
							return err
						}
						opts.Mode = os.FileMode(i)
					case flag == "ro":
						m.ReadOnly = true
					case flag == "rw":
						m.ReadOnly = false
					default:
						return errors.New("unsupported flag")
					}
				}
				m.TmpfsOptions = &opts
			}

			fmt.Println("mount", m)
			container.Mounts = append(container.Mounts, m)
		}
	}

	return nil
}
Ejemplo n.º 2
0
func containerToGRPC(c types.ContainerSpec) (*swarmapi.ContainerSpec, error) {
	containerSpec := &swarmapi.ContainerSpec{
		Image:     c.Image,
		Labels:    c.Labels,
		Command:   c.Command,
		Args:      c.Args,
		Hostname:  c.Hostname,
		Env:       c.Env,
		Dir:       c.Dir,
		User:      c.User,
		Groups:    c.Groups,
		TTY:       c.TTY,
		OpenStdin: c.OpenStdin,
		Hosts:     c.Hosts,
		Secrets:   secretReferencesToGRPC(c.Secrets),
	}

	if c.DNSConfig != nil {
		containerSpec.DNSConfig = &swarmapi.ContainerSpec_DNSConfig{
			Nameservers: c.DNSConfig.Nameservers,
			Search:      c.DNSConfig.Search,
			Options:     c.DNSConfig.Options,
		}
	}

	if c.StopGracePeriod != nil {
		containerSpec.StopGracePeriod = ptypes.DurationProto(*c.StopGracePeriod)
	}

	// Mounts
	for _, m := range c.Mounts {
		mount := swarmapi.Mount{
			Target:   m.Target,
			Source:   m.Source,
			ReadOnly: m.ReadOnly,
		}

		if mountType, ok := swarmapi.Mount_MountType_value[strings.ToUpper(string(m.Type))]; ok {
			mount.Type = swarmapi.Mount_MountType(mountType)
		} else if string(m.Type) != "" {
			return nil, fmt.Errorf("invalid MountType: %q", m.Type)
		}

		if m.BindOptions != nil {
			if mountPropagation, ok := swarmapi.Mount_BindOptions_MountPropagation_value[strings.ToUpper(string(m.BindOptions.Propagation))]; ok {
				mount.BindOptions = &swarmapi.Mount_BindOptions{Propagation: swarmapi.Mount_BindOptions_MountPropagation(mountPropagation)}
			} else if string(m.BindOptions.Propagation) != "" {
				return nil, fmt.Errorf("invalid MountPropagation: %q", m.BindOptions.Propagation)
			}
		}

		if m.VolumeOptions != nil {
			mount.VolumeOptions = &swarmapi.Mount_VolumeOptions{
				NoCopy: m.VolumeOptions.NoCopy,
				Labels: m.VolumeOptions.Labels,
			}
			if m.VolumeOptions.DriverConfig != nil {
				mount.VolumeOptions.DriverConfig = &swarmapi.Driver{
					Name:    m.VolumeOptions.DriverConfig.Name,
					Options: m.VolumeOptions.DriverConfig.Options,
				}
			}
		}

		if m.TmpfsOptions != nil {
			mount.TmpfsOptions = &swarmapi.Mount_TmpfsOptions{
				SizeBytes: m.TmpfsOptions.SizeBytes,
				Mode:      m.TmpfsOptions.Mode,
			}
		}

		containerSpec.Mounts = append(containerSpec.Mounts, mount)
	}

	if c.Healthcheck != nil {
		containerSpec.Healthcheck = healthConfigToGRPC(c.Healthcheck)
	}

	return containerSpec, nil
}