mirror of https://github.com/docker/cli.git
Added support for generic resource update
Signed-off-by: Renaud Gaubert <renaud.gaubert@gmail.com>
This commit is contained in:
parent
4a6da88f7a
commit
20a6ff32ee
|
@ -77,6 +77,8 @@ func runCreate(dockerCli command.Cli, flags *pflag.FlagSet, opts *serviceOptions
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fmt.Printf("%v\n", service.TaskTemplate.Resources)
|
||||||
|
|
||||||
specifiedSecrets := opts.secrets.Value()
|
specifiedSecrets := opts.secrets.Value()
|
||||||
if len(specifiedSecrets) > 0 {
|
if len(specifiedSecrets) > 0 {
|
||||||
// parse and validate secrets
|
// parse and validate secrets
|
||||||
|
|
|
@ -74,3 +74,32 @@ func genericResourcesFromGRPC(genericRes []*swarmapi.GenericResource) []swarm.Ge
|
||||||
|
|
||||||
return generic
|
return generic
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func buildGenericResourceMap(genericRes []swarm.GenericResource) (map[string]swarm.GenericResource, error) {
|
||||||
|
m := make(map[string]swarm.GenericResource)
|
||||||
|
|
||||||
|
for _, res := range genericRes {
|
||||||
|
if res.DiscreteResourceSpec == nil {
|
||||||
|
return nil, fmt.Errorf("invalid generic-resource `%+v` for service task", res)
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := m[res.DiscreteResourceSpec.Kind]
|
||||||
|
if ok {
|
||||||
|
return nil, fmt.Errorf("duplicate generic-resource `%+v` for service task", res.DiscreteResourceSpec.Kind)
|
||||||
|
}
|
||||||
|
|
||||||
|
m[res.DiscreteResourceSpec.Kind] = res
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildGenericResourceList(genericRes map[string]swarm.GenericResource) []swarm.GenericResource {
|
||||||
|
var l []swarm.GenericResource
|
||||||
|
|
||||||
|
for _, res := range genericRes {
|
||||||
|
l = append(l, res)
|
||||||
|
}
|
||||||
|
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
|
@ -830,6 +830,8 @@ const (
|
||||||
flagEnvFile = "env-file"
|
flagEnvFile = "env-file"
|
||||||
flagEnvRemove = "env-rm"
|
flagEnvRemove = "env-rm"
|
||||||
flagEnvAdd = "env-add"
|
flagEnvAdd = "env-add"
|
||||||
|
flagGenericResourcesRemove = "generic-resource-rm"
|
||||||
|
flagGenericResourcesAdd = "generic-resource-add"
|
||||||
flagGroup = "group"
|
flagGroup = "group"
|
||||||
flagGroupAdd = "group-add"
|
flagGroupAdd = "group-add"
|
||||||
flagGroupRemove = "group-rm"
|
flagGroupRemove = "group-rm"
|
||||||
|
|
|
@ -95,6 +95,12 @@ func newUpdateCommand(dockerCli command.Cli) *cobra.Command {
|
||||||
flags.Var(&options.hosts, flagHostAdd, "Add a custom host-to-IP mapping (host:ip)")
|
flags.Var(&options.hosts, flagHostAdd, "Add a custom host-to-IP mapping (host:ip)")
|
||||||
flags.SetAnnotation(flagHostAdd, "version", []string{"1.25"})
|
flags.SetAnnotation(flagHostAdd, "version", []string{"1.25"})
|
||||||
|
|
||||||
|
// Add needs parsing, Remove only needs the key
|
||||||
|
flags.Var(newListOptsVar(), flagGenericResourcesRemove, "Remove a Generic resource")
|
||||||
|
flags.SetAnnotation(flagHostAdd, "version", []string{"1.32"})
|
||||||
|
flags.Var(newListOptsVarWithValidator(ValidateSingleGenericResource), flagGenericResourcesAdd, "Add a Generic resource")
|
||||||
|
flags.SetAnnotation(flagHostAdd, "version", []string{"1.32"})
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +108,10 @@ func newListOptsVar() *opts.ListOpts {
|
||||||
return opts.NewListOptsRef(&[]string{}, nil)
|
return opts.NewListOptsRef(&[]string{}, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newListOptsVarWithValidator(validator opts.ValidatorFctType) *opts.ListOpts {
|
||||||
|
return opts.NewListOptsRef(&[]string{}, validator)
|
||||||
|
}
|
||||||
|
|
||||||
// nolint: gocyclo
|
// nolint: gocyclo
|
||||||
func runUpdate(dockerCli command.Cli, flags *pflag.FlagSet, options *serviceOptions, serviceID string) error {
|
func runUpdate(dockerCli command.Cli, flags *pflag.FlagSet, options *serviceOptions, serviceID string) error {
|
||||||
apiClient := dockerCli.Client()
|
apiClient := dockerCli.Client()
|
||||||
|
@ -314,6 +324,14 @@ func updateService(ctx context.Context, apiClient client.NetworkAPIClient, flags
|
||||||
updateInt64Value(flagReserveMemory, &task.Resources.Reservations.MemoryBytes)
|
updateInt64Value(flagReserveMemory, &task.Resources.Reservations.MemoryBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := addGenericResources(flags, task); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := removeGenericResources(flags, task); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
updateDurationOpt(flagStopGracePeriod, &cspec.StopGracePeriod)
|
updateDurationOpt(flagStopGracePeriod, &cspec.StopGracePeriod)
|
||||||
|
|
||||||
if anyChanged(flags, flagRestartCondition, flagRestartDelay, flagRestartMaxAttempts, flagRestartWindow) {
|
if anyChanged(flags, flagRestartCondition, flagRestartDelay, flagRestartMaxAttempts, flagRestartWindow) {
|
||||||
|
@ -470,6 +488,72 @@ func anyChanged(flags *pflag.FlagSet, fields ...string) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addGenericResources(flags *pflag.FlagSet, spec *swarm.TaskSpec) error {
|
||||||
|
if !flags.Changed(flagGenericResourcesAdd) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if spec.Resources == nil {
|
||||||
|
spec.Resources = &swarm.ResourceRequirements{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if spec.Resources.Reservations == nil {
|
||||||
|
spec.Resources.Reservations = &swarm.Resources{}
|
||||||
|
}
|
||||||
|
|
||||||
|
values := flags.Lookup(flagGenericResourcesAdd).Value.(*opts.ListOpts).GetAll()
|
||||||
|
generic, err := ParseGenericResources(values)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
m, err := buildGenericResourceMap(spec.Resources.Reservations.GenericResources)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, toAddRes := range generic {
|
||||||
|
m[toAddRes.DiscreteResourceSpec.Kind] = toAddRes
|
||||||
|
}
|
||||||
|
|
||||||
|
spec.Resources.Reservations.GenericResources = buildGenericResourceList(m)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func removeGenericResources(flags *pflag.FlagSet, spec *swarm.TaskSpec) error {
|
||||||
|
// Can only be Discrete Resources
|
||||||
|
if !flags.Changed(flagGenericResourcesRemove) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if spec.Resources == nil {
|
||||||
|
spec.Resources = &swarm.ResourceRequirements{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if spec.Resources.Reservations == nil {
|
||||||
|
spec.Resources.Reservations = &swarm.Resources{}
|
||||||
|
}
|
||||||
|
|
||||||
|
values := flags.Lookup(flagGenericResourcesRemove).Value.(*opts.ListOpts).GetAll()
|
||||||
|
|
||||||
|
m, err := buildGenericResourceMap(spec.Resources.Reservations.GenericResources)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, toRemoveRes := range values {
|
||||||
|
if _, ok := m[toRemoveRes]; !ok {
|
||||||
|
return fmt.Errorf("could not find generic-resource `%s` to remove it", toRemoveRes)
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(m, toRemoveRes)
|
||||||
|
}
|
||||||
|
|
||||||
|
spec.Resources.Reservations.GenericResources = buildGenericResourceList(m)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func updatePlacementConstraints(flags *pflag.FlagSet, placement *swarm.Placement) {
|
func updatePlacementConstraints(flags *pflag.FlagSet, placement *swarm.Placement) {
|
||||||
if flags.Changed(flagConstraintAdd) {
|
if flags.Changed(flagConstraintAdd) {
|
||||||
values := flags.Lookup(flagConstraintAdd).Value.(*opts.ListOpts).GetAll()
|
values := flags.Lookup(flagConstraintAdd).Value.(*opts.ListOpts).GetAll()
|
||||||
|
|
|
@ -547,3 +547,42 @@ func TestUpdateIsolationInvalid(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, container.Isolation("test"), spec.TaskTemplate.ContainerSpec.Isolation)
|
assert.Equal(t, container.Isolation("test"), spec.TaskTemplate.ContainerSpec.Isolation)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAddGenericResources(t *testing.T) {
|
||||||
|
task := &swarm.TaskSpec{}
|
||||||
|
flags := newUpdateCommand(nil).Flags()
|
||||||
|
|
||||||
|
assert.Nil(t, addGenericResources(flags, task))
|
||||||
|
|
||||||
|
flags.Set(flagGenericResourcesAdd, "foo=1")
|
||||||
|
assert.NoError(t, addGenericResources(flags, task))
|
||||||
|
assert.Len(t, task.Resources.Reservations.GenericResources, 1)
|
||||||
|
|
||||||
|
// Checks that foo isn't added a 2nd time
|
||||||
|
flags = newUpdateCommand(nil).Flags()
|
||||||
|
flags.Set(flagGenericResourcesAdd, "bar=1")
|
||||||
|
assert.NoError(t, addGenericResources(flags, task))
|
||||||
|
assert.Len(t, task.Resources.Reservations.GenericResources, 2)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoveGenericResources(t *testing.T) {
|
||||||
|
task := &swarm.TaskSpec{}
|
||||||
|
flags := newUpdateCommand(nil).Flags()
|
||||||
|
|
||||||
|
assert.Nil(t, removeGenericResources(flags, task))
|
||||||
|
|
||||||
|
flags.Set(flagGenericResourcesRemove, "foo")
|
||||||
|
assert.Error(t, removeGenericResources(flags, task))
|
||||||
|
|
||||||
|
flags = newUpdateCommand(nil).Flags()
|
||||||
|
flags.Set(flagGenericResourcesAdd, "foo=1")
|
||||||
|
addGenericResources(flags, task)
|
||||||
|
flags = newUpdateCommand(nil).Flags()
|
||||||
|
flags.Set(flagGenericResourcesAdd, "bar=1")
|
||||||
|
addGenericResources(flags, task)
|
||||||
|
|
||||||
|
flags = newUpdateCommand(nil).Flags()
|
||||||
|
flags.Set(flagGenericResourcesRemove, "foo")
|
||||||
|
assert.NoError(t, removeGenericResources(flags, task))
|
||||||
|
assert.Len(t, task.Resources.Reservations.GenericResources, 1)
|
||||||
|
}
|
||||||
|
|
|
@ -41,6 +41,8 @@ Options:
|
||||||
--env-add list Add or update an environment variable
|
--env-add list Add or update an environment variable
|
||||||
--env-rm list Remove an environment variable
|
--env-rm list Remove an environment variable
|
||||||
--force Force update even if no changes require it
|
--force Force update even if no changes require it
|
||||||
|
--generic-resource-add list Add an additional generic resource to the service's resources requirements
|
||||||
|
--generic-resource-rm list Remove a previously added generic resource to the service's resources requirements
|
||||||
--group-add list Add an additional supplementary user group to the container
|
--group-add list Add an additional supplementary user group to the container
|
||||||
--group-rm list Remove a previously added supplementary user group from the container
|
--group-rm list Remove a previously added supplementary user group from the container
|
||||||
--health-cmd string Command to run to check health
|
--health-cmd string Command to run to check health
|
||||||
|
|
Loading…
Reference in New Issue