示例#1
0
文件: common.go 项目: docker/swarmkit
// ParseLogDriverFlags parses a silly string format for log driver and options.
// Fully baked log driver config should be returned.
//
// If no log driver is available, nil, nil will be returned.
func ParseLogDriverFlags(flags *pflag.FlagSet) (*api.Driver, error) {
	if !flags.Changed("log-driver") {
		return nil, nil
	}

	name, err := flags.GetString("log-driver")
	if err != nil {
		return nil, err
	}

	var opts map[string]string
	if flags.Changed("log-opt") {
		rawOpts, err := flags.GetStringSlice("log-opt")
		if err != nil {
			return nil, err
		}

		opts = make(map[string]string, len(rawOpts))
		for _, rawOpt := range rawOpts {
			parts := strings.SplitN(rawOpt, "=", 2)
			if len(parts) == 1 {
				opts[parts[0]] = ""
				continue
			}

			opts[parts[0]] = parts[1]
		}
	}

	return &api.Driver{
		Name:    name,
		Options: opts,
	}, nil
}
示例#2
0
func updatePlacement(flags *pflag.FlagSet, placement *swarm.Placement) {
	field, _ := flags.GetStringSlice(flagConstraintAdd)
	placement.Constraints = append(placement.Constraints, field...)

	toRemove := buildToRemoveSet(flags, flagConstraintRemove)
	placement.Constraints = removeItems(placement.Constraints, toRemove, itemKey)
}
示例#3
0
// parseBind only supports a very simple version of bind for testing the most
// basic of data flows. Replace with a --mount flag, similar to what we have in
// docker service.
func parseBind(flags *pflag.FlagSet, spec *api.ServiceSpec) error {
	if flags.Changed("bind") {
		binds, err := flags.GetStringSlice("bind")
		if err != nil {
			return err
		}

		container := spec.Task.GetContainer()

		for _, bind := range binds {
			parts := strings.SplitN(bind, ":", 2)
			if len(parts) != 2 {
				return fmt.Errorf("bind format %q not supported", bind)
			}
			container.Mounts = append(container.Mounts, api.Mount{
				Type:     api.MountTypeBind,
				Source:   parts[0],
				Target:   parts[1],
				Writable: true,
			})
		}
	}

	return nil
}
示例#4
0
func parseContainer(flags *pflag.FlagSet, spec *api.ServiceSpec) error {
	if flags.Changed("image") {
		image, err := flags.GetString("image")
		if err != nil {
			return err
		}
		spec.Task.GetContainer().Image = image
	}

	if flags.Changed("args") {
		args, err := flags.GetStringSlice("args")
		if err != nil {
			return err
		}
		spec.Task.GetContainer().Args = args
	}

	if flags.Changed("env") {
		env, err := flags.GetStringSlice("env")
		if err != nil {
			return err
		}
		spec.Task.GetContainer().Env = env
	}

	return nil
}
示例#5
0
文件: port.go 项目: docker/swarmkit
func parsePorts(flags *pflag.FlagSet, spec *api.ServiceSpec) error {
	if !flags.Changed("ports") {
		return nil
	}
	portConfigs, err := flags.GetStringSlice("ports")
	if err != nil {
		return err
	}

	ports := []*api.PortConfig{}
	for _, portConfig := range portConfigs {
		name, protocol, port, swarmPort, err := parsePortConfig(portConfig)
		if err != nil {
			return err
		}

		ports = append(ports, &api.PortConfig{
			Name:          name,
			Protocol:      protocol,
			TargetPort:    port,
			PublishedPort: swarmPort,
			// In swarmctl all ports are by default
			// PublishModeHost
			PublishMode: api.PublishModeHost,
		})
	}

	spec.Endpoint = &api.EndpointSpec{
		Ports: ports,
	}

	return nil
}
示例#6
0
func mergeNetworks(flags *pflag.FlagSet, attachments *[]swarm.NetworkAttachmentConfig) {
	if !flags.Changed("network") {
		return
	}
	networks, _ := flags.GetStringSlice("network")
	for _, network := range networks {
		*attachments = append(*attachments, swarm.NetworkAttachmentConfig{Target: network})
	}
}
示例#7
0
func updateNetworks(flags *pflag.FlagSet, attachments *[]swarm.NetworkAttachmentConfig) {
	if !flags.Changed(flagNetwork) {
		return
	}
	networks, _ := flags.GetStringSlice(flagNetwork)

	var localAttachments []swarm.NetworkAttachmentConfig
	for _, network := range networks {
		localAttachments = append(localAttachments, swarm.NetworkAttachmentConfig{Target: network})
	}
	*attachments = localAttachments
}
示例#8
0
func parsePlacement(flags *pflag.FlagSet, spec *api.ServiceSpec) error {
	if flags.Changed("constraint") {
		constraints, err := flags.GetStringSlice("constraint")
		if err != nil {
			return err
		}
		if spec.Task.Placement == nil {
			spec.Task.Placement = &api.Placement{}
		}
		spec.Task.Placement.Constraints = constraints
	}

	return nil
}
示例#9
0
func updateNetworks(flags *pflag.FlagSet, attachments *[]swarm.NetworkAttachmentConfig) {
	if flags.Changed(flagNetworkAdd) {
		networks, _ := flags.GetStringSlice(flagNetworkAdd)
		for _, network := range networks {
			*attachments = append(*attachments, swarm.NetworkAttachmentConfig{Target: network})
		}
	}
	toRemove := buildToRemoveSet(flags, flagNetworkRemove)
	newNetworks := []swarm.NetworkAttachmentConfig{}
	for _, network := range *attachments {
		if _, exists := toRemove[network.Target]; !exists {
			newNetworks = append(newNetworks, network)
		}
	}
	*attachments = newNetworks
}
示例#10
0
func mergeNodeUpdate(flags *pflag.FlagSet) func(*swarm.Node) {
	return func(node *swarm.Node) {
		mergeString := func(flag string, field *string) {
			if flags.Changed(flag) {
				*field, _ = flags.GetString(flag)
			}
		}

		mergeRole := func(flag string, field *swarm.NodeRole) {
			if flags.Changed(flag) {
				str, _ := flags.GetString(flag)
				*field = swarm.NodeRole(str)
			}
		}

		mergeMembership := func(flag string, field *swarm.NodeMembership) {
			if flags.Changed(flag) {
				str, _ := flags.GetString(flag)
				*field = swarm.NodeMembership(str)
			}
		}

		mergeAvailability := func(flag string, field *swarm.NodeAvailability) {
			if flags.Changed(flag) {
				str, _ := flags.GetString(flag)
				*field = swarm.NodeAvailability(str)
			}
		}

		mergeLabels := func(flag string, field *map[string]string) {
			if flags.Changed(flag) {
				values, _ := flags.GetStringSlice(flag)
				for key, value := range runconfigopts.ConvertKVStringsToMap(values) {
					(*field)[key] = value
				}
			}
		}

		spec := &node.Spec
		mergeString("name", &spec.Name)
		// TODO: setting labels is not working
		mergeLabels("label", &spec.Labels)
		mergeRole("role", &spec.Role)
		mergeMembership("membership", &spec.Membership)
		mergeAvailability("availability", &spec.Availability)
	}
}
示例#11
0
func updateGroups(flags *pflag.FlagSet, groups *[]string) error {
	if flags.Changed(flagGroupAdd) {
		values, err := flags.GetStringSlice(flagGroupAdd)
		if err != nil {
			return err
		}
		*groups = append(*groups, values...)
	}
	toRemove := buildToRemoveSet(flags, flagGroupRemove)

	newGroups := []string{}
	for _, group := range *groups {
		if _, exists := toRemove[group]; !exists {
			newGroups = append(newGroups, group)
		}
	}
	// Sort so that result is predictable.
	sort.Strings(newGroups)

	*groups = newGroups
	return nil
}
示例#12
0
// parseVolume only supports a very simple version of annonymous volumes for
// testing the most basic of data flows. Replace with a --mount flag, similar
// to what we have in docker service.
func parseVolume(flags *pflag.FlagSet, spec *api.ServiceSpec) error {
	if flags.Changed("volume") {
		volumes, err := flags.GetStringSlice("volume")
		if err != nil {
			return err
		}

		container := spec.Task.GetContainer()

		for _, volume := range volumes {
			if strings.Contains(volume, ":") {
				return fmt.Errorf("volume format %q not supported", volume)
			}
			container.Mounts = append(container.Mounts, api.Mount{
				Type:   api.MountTypeVolume,
				Target: volume,
			})
		}
	}

	return nil
}
示例#13
0
func mergeService(spec *swarm.ServiceSpec, flags *pflag.FlagSet) error {

	mergeString := func(flag string, field *string) {
		if flags.Changed(flag) {
			*field, _ = flags.GetString(flag)
		}
	}

	mergeListOpts := func(flag string, field *[]string) {
		if flags.Changed(flag) {
			value := flags.Lookup(flag).Value.(*opts.ListOpts)
			*field = value.GetAll()
		}
	}

	mergeSlice := func(flag string, field *[]string) {
		if flags.Changed(flag) {
			*field, _ = flags.GetStringSlice(flag)
		}
	}

	mergeInt64Value := func(flag string, field *int64) {
		if flags.Changed(flag) {
			*field = flags.Lookup(flag).Value.(int64Value).Value()
		}
	}

	mergeDuration := func(flag string, field *time.Duration) {
		if flags.Changed(flag) {
			*field, _ = flags.GetDuration(flag)
		}
	}

	mergeDurationOpt := func(flag string, field *time.Duration) {
		if flags.Changed(flag) {
			*field = *flags.Lookup(flag).Value.(*DurationOpt).Value()
		}
	}

	mergeUint64 := func(flag string, field *uint64) {
		if flags.Changed(flag) {
			*field, _ = flags.GetUint64(flag)
		}
	}

	mergeUint64Opt := func(flag string, field *uint64) {
		if flags.Changed(flag) {
			*field = *flags.Lookup(flag).Value.(*Uint64Opt).Value()
		}
	}

	cspec := &spec.TaskTemplate.ContainerSpec
	task := &spec.TaskTemplate
	mergeString("name", &spec.Name)
	mergeLabels(flags, &spec.Labels)
	mergeString("image", &cspec.Image)
	mergeSlice("command", &cspec.Command)
	mergeSlice("arg", &cspec.Command)
	mergeListOpts("env", &cspec.Env)
	mergeString("workdir", &cspec.Dir)
	mergeString("user", &cspec.User)
	mergeMounts(flags, &cspec.Mounts)

	mergeInt64Value("limit-cpu", &task.Resources.Limits.NanoCPUs)
	mergeInt64Value("limit-memory", &task.Resources.Limits.MemoryBytes)
	mergeInt64Value("reserve-cpu", &task.Resources.Reservations.NanoCPUs)
	mergeInt64Value("reserve-memory", &task.Resources.Reservations.MemoryBytes)

	mergeDurationOpt("stop-grace-period", cspec.StopGracePeriod)

	if flags.Changed("restart-policy-condition") {
		value, _ := flags.GetString("restart-policy-condition")
		task.RestartPolicy.Condition = swarm.RestartPolicyCondition(value)
	}
	mergeDurationOpt("restart-policy-delay", task.RestartPolicy.Delay)
	mergeUint64Opt("restart-policy-max-attempts", task.RestartPolicy.MaxAttempts)
	mergeDurationOpt("restart-policy-window", task.RestartPolicy.Window)
	mergeSlice("constraint", &task.Placement.Constraints)

	if err := mergeMode(flags, &spec.Mode); err != nil {
		return err
	}

	mergeUint64("updateconfig-parallelism", &spec.UpdateConfig.Parallelism)
	mergeDuration("updateconfig-delay", &spec.UpdateConfig.Delay)

	mergeNetworks(flags, &spec.Networks)
	if flags.Changed("endpoint-mode") {
		value, _ := flags.GetString("endpoint-mode")
		spec.EndpointSpec.Mode = swarm.ResolutionMode(value)
	}

	mergePorts(flags, &spec.EndpointSpec.Ports)

	return nil
}
示例#14
0
func mergeService(spec *swarm.ServiceSpec, flags *pflag.FlagSet) error {

	mergeString := func(flag string, field *string) {
		if flags.Changed(flag) {
			*field, _ = flags.GetString(flag)
		}
	}

	mergeListOpts := func(flag string, field *[]string) {
		if flags.Changed(flag) {
			value := flags.Lookup(flag).Value.(*opts.ListOpts)
			*field = value.GetAll()
		}
	}

	mergeSlice := func(flag string, field *[]string) {
		if flags.Changed(flag) {
			*field, _ = flags.GetStringSlice(flag)
		}
	}

	mergeInt64Value := func(flag string, field *int64) {
		if flags.Changed(flag) {
			*field = flags.Lookup(flag).Value.(int64Value).Value()
		}
	}

	mergeDuration := func(flag string, field *time.Duration) {
		if flags.Changed(flag) {
			*field, _ = flags.GetDuration(flag)
		}
	}

	mergeDurationOpt := func(flag string, field *time.Duration) {
		if flags.Changed(flag) {
			*field = *flags.Lookup(flag).Value.(*DurationOpt).Value()
		}
	}

	mergeUint64 := func(flag string, field *uint64) {
		if flags.Changed(flag) {
			*field, _ = flags.GetUint64(flag)
		}
	}

	mergeUint64Opt := func(flag string, field *uint64) {
		if flags.Changed(flag) {
			*field = *flags.Lookup(flag).Value.(*Uint64Opt).Value()
		}
	}

	cspec := &spec.TaskTemplate.ContainerSpec
	task := &spec.TaskTemplate
	mergeString(flagName, &spec.Name)
	mergeLabels(flags, &spec.Labels)
	mergeString("image", &cspec.Image)
	mergeSlice("command", &cspec.Command)
	mergeSlice("arg", &cspec.Command)
	mergeListOpts("env", &cspec.Env)
	mergeString("workdir", &cspec.Dir)
	mergeString("user", &cspec.User)
	mergeMounts(flags, &cspec.Mounts)

	if flags.Changed(flagLimitCPU) || flags.Changed(flagLimitMemory) {
		if task.Resources == nil {
			task.Resources = &swarm.ResourceRequirements{}
		}
		task.Resources.Limits = &swarm.Resources{}
		mergeInt64Value(flagLimitCPU, &task.Resources.Limits.NanoCPUs)
		mergeInt64Value(flagLimitMemory, &task.Resources.Limits.MemoryBytes)

	}
	if flags.Changed(flagReserveCPU) || flags.Changed(flagReserveMemory) {
		if task.Resources == nil {
			task.Resources = &swarm.ResourceRequirements{}
		}
		task.Resources.Reservations = &swarm.Resources{}
		mergeInt64Value(flagReserveCPU, &task.Resources.Reservations.NanoCPUs)
		mergeInt64Value(flagReserveMemory, &task.Resources.Reservations.MemoryBytes)
	}

	mergeDurationOpt("stop-grace-period", cspec.StopGracePeriod)

	if flags.Changed(flagRestartCondition) || flags.Changed(flagRestartDelay) || flags.Changed(flagRestartMaxAttempts) || flags.Changed(flagRestartWindow) {
		if task.RestartPolicy == nil {
			task.RestartPolicy = &swarm.RestartPolicy{}
		}

		if flags.Changed(flagRestartCondition) {
			value, _ := flags.GetString(flagRestartCondition)
			task.RestartPolicy.Condition = swarm.RestartPolicyCondition(value)
		}
		mergeDurationOpt(flagRestartDelay, task.RestartPolicy.Delay)
		mergeUint64Opt(flagRestartMaxAttempts, task.RestartPolicy.MaxAttempts)
		mergeDurationOpt((flagRestartWindow), task.RestartPolicy.Window)
	}

	if flags.Changed(flagConstraint) {
		task.Placement = &swarm.Placement{}
		mergeSlice(flagConstraint, &task.Placement.Constraints)
	}

	if err := mergeMode(flags, &spec.Mode); err != nil {
		return err
	}

	if flags.Changed(flagUpdateParallelism) || flags.Changed(flagUpdateDelay) {
		if spec.UpdateConfig == nil {
			spec.UpdateConfig = &swarm.UpdateConfig{}
		}
		mergeUint64(flagUpdateParallelism, &spec.UpdateConfig.Parallelism)
		mergeDuration(flagUpdateDelay, &spec.UpdateConfig.Delay)
	}

	mergeNetworks(flags, &spec.Networks)
	if flags.Changed(flagEndpointMode) {
		value, _ := flags.GetString(flagEndpointMode)
		spec.EndpointSpec.Mode = swarm.ResolutionMode(value)
	}

	if flags.Changed(flagPublish) {
		if spec.EndpointSpec == nil {
			spec.EndpointSpec = &swarm.EndpointSpec{}
		}
		mergePorts(flags, &spec.EndpointSpec.Ports)
	}
	return nil
}
示例#15
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
}
示例#16
0
func parseContainer(flags *pflag.FlagSet, spec *api.ServiceSpec) error {
	if flags.Changed("image") {
		image, err := flags.GetString("image")
		if err != nil {
			return err
		}
		spec.Task.GetContainer().Image = image
	}

	if flags.Changed("hostname") {
		hostname, err := flags.GetString("hostname")
		if err != nil {
			return err
		}
		spec.Task.GetContainer().Hostname = hostname
	}

	if flags.Changed("command") {
		command, err := flags.GetStringSlice("command")
		if err != nil {
			return err
		}
		spec.Task.GetContainer().Command = command
	}

	if flags.Changed("args") {
		args, err := flags.GetStringSlice("args")
		if err != nil {
			return err
		}
		spec.Task.GetContainer().Args = args
	}

	if flags.Changed("env") {
		env, err := flags.GetStringSlice("env")
		if err != nil {
			return err
		}
		spec.Task.GetContainer().Env = env
	}

	if flags.Changed("tty") {
		tty, err := flags.GetBool("tty")
		if err != nil {
			return err
		}

		spec.Task.GetContainer().TTY = tty
	}

	if flags.Changed("open-stdin") {
		openStdin, err := flags.GetBool("open-stdin")
		if err != nil {
			return err
		}

		spec.Task.GetContainer().OpenStdin = openStdin
	}

	return nil
}