func parseUpdate(flags *pflag.FlagSet, spec *api.ServiceSpec) error { if flags.Changed("update-parallelism") { parallelism, err := flags.GetUint64("update-parallelism") if err != nil { return err } if spec.Update == nil { spec.Update = &api.UpdateConfig{} } spec.Update.Parallelism = parallelism } if flags.Changed("update-delay") { delay, err := flags.GetString("update-delay") if err != nil { return err } delayDuration, err := time.ParseDuration(delay) if err != nil { return err } if spec.Update == nil { spec.Update = &api.UpdateConfig{} } spec.Update.Delay = *ptypes.DurationProto(delayDuration) } return nil }
func validateMode(s *api.ServiceSpec) error { m := s.GetMode() switch m.(type) { case *api.ServiceSpec_Replicated: if int64(m.(*api.ServiceSpec_Replicated).Replicated.Replicas) < 0 { return grpc.Errorf(codes.InvalidArgument, "Number of replicas must be non-negative") } case *api.ServiceSpec_Global: default: return grpc.Errorf(codes.InvalidArgument, "Unrecognized service mode") } return nil }
func parseUpdate(flags *pflag.FlagSet, spec *api.ServiceSpec) error { if flags.Changed("update-parallelism") { parallelism, err := flags.GetUint64("update-parallelism") if err != nil { return err } if spec.Update == nil { spec.Update = &api.UpdateConfig{} } spec.Update.Parallelism = parallelism } if flags.Changed("update-delay") { delay, err := flags.GetString("update-delay") if err != nil { return err } delayDuration, err := time.ParseDuration(delay) if err != nil { return err } if spec.Update == nil { spec.Update = &api.UpdateConfig{} } spec.Update.Delay = delayDuration } if flags.Changed("update-on-failure") { if spec.Update == nil { spec.Update = &api.UpdateConfig{} } action, err := flags.GetString("update-on-failure") if err != nil { return err } switch action { case "pause": spec.Update.FailureAction = api.UpdateConfig_PAUSE case "continue": spec.Update.FailureAction = api.UpdateConfig_CONTINUE default: return errors.New("--update-on-failure value must be pause or continue") } } return nil }
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 }
func parseMode(flags *pflag.FlagSet, spec *api.ServiceSpec) error { if flags.Changed("mode") { mode, err := flags.GetString("mode") if err != nil { return err } switch mode { case "global": if spec.GetGlobal() == nil { spec.Mode = &api.ServiceSpec_Global{ Global: &api.GlobalService{}, } } case "replicated": if spec.GetReplicated() == nil { spec.Mode = &api.ServiceSpec_Replicated{ Replicated: &api.ReplicatedService{}, } } } } if flags.Changed("replicas") { if spec.GetReplicated() == nil { return fmt.Errorf("--replicas can only be specified in --mode replicated") } replicas, err := flags.GetUint64("replicas") if err != nil { return err } spec.GetReplicated().Replicas = replicas } return nil }
// ResolveServiceNetworks takes a service spec and resolves network names to network IDs. func ResolveServiceNetworks(ctx context.Context, c api.ControlClient, spec *api.ServiceSpec) error { if len(spec.Networks) == 0 { return nil } networks := make([]*api.ServiceSpec_NetworkAttachmentConfig, 0, len(spec.Networks)) for _, na := range spec.Networks { n, err := GetNetwork(ctx, c, na.Target) if err != nil { return err } networks = append(networks, &api.ServiceSpec_NetworkAttachmentConfig{ Target: n.ID, }) } spec.Networks = networks return nil }
func parseNetworks(cmd *cobra.Command, spec *api.ServiceSpec, c api.ControlClient) error { flags := cmd.Flags() if !flags.Changed("network") { return nil } input, err := flags.GetString("network") if err != nil { return err } n, err := network.GetNetwork(common.Context(cmd), c, input) if err != nil { return err } spec.Networks = []*api.ServiceSpec_NetworkAttachmentConfig{ { Target: n.ID, }, } return nil }
func serviceSpecFromGRPC(spec *swarmapi.ServiceSpec) *types.ServiceSpec { if spec == nil { return nil } serviceNetworks := make([]types.NetworkAttachmentConfig, 0, len(spec.Networks)) for _, n := range spec.Networks { serviceNetworks = append(serviceNetworks, types.NetworkAttachmentConfig{Target: n.Target, Aliases: n.Aliases}) } taskNetworks := make([]types.NetworkAttachmentConfig, 0, len(spec.Task.Networks)) for _, n := range spec.Task.Networks { taskNetworks = append(taskNetworks, types.NetworkAttachmentConfig{Target: n.Target, Aliases: n.Aliases}) } containerConfig := spec.Task.Runtime.(*swarmapi.TaskSpec_Container).Container convertedSpec := &types.ServiceSpec{ Annotations: types.Annotations{ Name: spec.Annotations.Name, Labels: spec.Annotations.Labels, }, TaskTemplate: types.TaskSpec{ ContainerSpec: containerSpecFromGRPC(containerConfig), Resources: resourcesFromGRPC(spec.Task.Resources), RestartPolicy: restartPolicyFromGRPC(spec.Task.Restart), Placement: placementFromGRPC(spec.Task.Placement), LogDriver: driverFromGRPC(spec.Task.LogDriver), Networks: taskNetworks, ForceUpdate: spec.Task.ForceUpdate, }, Networks: serviceNetworks, EndpointSpec: endpointSpecFromGRPC(spec.Endpoint), } // UpdateConfig if spec.Update != nil { convertedSpec.UpdateConfig = &types.UpdateConfig{ Parallelism: spec.Update.Parallelism, MaxFailureRatio: spec.Update.MaxFailureRatio, } convertedSpec.UpdateConfig.Delay, _ = ptypes.Duration(&spec.Update.Delay) if spec.Update.Monitor != nil { convertedSpec.UpdateConfig.Monitor, _ = ptypes.Duration(spec.Update.Monitor) } switch spec.Update.FailureAction { case swarmapi.UpdateConfig_PAUSE: convertedSpec.UpdateConfig.FailureAction = types.UpdateFailureActionPause case swarmapi.UpdateConfig_CONTINUE: convertedSpec.UpdateConfig.FailureAction = types.UpdateFailureActionContinue } } // Mode switch t := spec.GetMode().(type) { case *swarmapi.ServiceSpec_Global: convertedSpec.Mode.Global = &types.GlobalService{} case *swarmapi.ServiceSpec_Replicated: convertedSpec.Mode.Replicated = &types.ReplicatedService{ Replicas: &t.Replicated.Replicas, } } return convertedSpec }
// ServiceSpecToGRPC converts a ServiceSpec to a grpc ServiceSpec. func ServiceSpecToGRPC(s types.ServiceSpec) (swarmapi.ServiceSpec, error) { name := s.Name if name == "" { name = namesgenerator.GetRandomName(0) } serviceNetworks := make([]*swarmapi.NetworkAttachmentConfig, 0, len(s.Networks)) for _, n := range s.Networks { serviceNetworks = append(serviceNetworks, &swarmapi.NetworkAttachmentConfig{Target: n.Target, Aliases: n.Aliases}) } taskNetworks := make([]*swarmapi.NetworkAttachmentConfig, 0, len(s.TaskTemplate.Networks)) for _, n := range s.TaskTemplate.Networks { taskNetworks = append(taskNetworks, &swarmapi.NetworkAttachmentConfig{Target: n.Target, Aliases: n.Aliases}) } spec := swarmapi.ServiceSpec{ Annotations: swarmapi.Annotations{ Name: name, Labels: s.Labels, }, Task: swarmapi.TaskSpec{ Resources: resourcesToGRPC(s.TaskTemplate.Resources), LogDriver: driverToGRPC(s.TaskTemplate.LogDriver), Networks: taskNetworks, ForceUpdate: s.TaskTemplate.ForceUpdate, }, Networks: serviceNetworks, } containerSpec, err := containerToGRPC(s.TaskTemplate.ContainerSpec) if err != nil { return swarmapi.ServiceSpec{}, err } spec.Task.Runtime = &swarmapi.TaskSpec_Container{Container: containerSpec} restartPolicy, err := restartPolicyToGRPC(s.TaskTemplate.RestartPolicy) if err != nil { return swarmapi.ServiceSpec{}, err } spec.Task.Restart = restartPolicy if s.TaskTemplate.Placement != nil { spec.Task.Placement = &swarmapi.Placement{ Constraints: s.TaskTemplate.Placement.Constraints, } } if s.UpdateConfig != nil { var failureAction swarmapi.UpdateConfig_FailureAction switch s.UpdateConfig.FailureAction { case types.UpdateFailureActionPause, "": failureAction = swarmapi.UpdateConfig_PAUSE case types.UpdateFailureActionContinue: failureAction = swarmapi.UpdateConfig_CONTINUE default: return swarmapi.ServiceSpec{}, fmt.Errorf("unrecongized update failure action %s", s.UpdateConfig.FailureAction) } spec.Update = &swarmapi.UpdateConfig{ Parallelism: s.UpdateConfig.Parallelism, Delay: *ptypes.DurationProto(s.UpdateConfig.Delay), FailureAction: failureAction, MaxFailureRatio: s.UpdateConfig.MaxFailureRatio, } if s.UpdateConfig.Monitor != 0 { spec.Update.Monitor = ptypes.DurationProto(s.UpdateConfig.Monitor) } } if s.EndpointSpec != nil { if s.EndpointSpec.Mode != "" && s.EndpointSpec.Mode != types.ResolutionModeVIP && s.EndpointSpec.Mode != types.ResolutionModeDNSRR { return swarmapi.ServiceSpec{}, fmt.Errorf("invalid resolution mode: %q", s.EndpointSpec.Mode) } spec.Endpoint = &swarmapi.EndpointSpec{} spec.Endpoint.Mode = swarmapi.EndpointSpec_ResolutionMode(swarmapi.EndpointSpec_ResolutionMode_value[strings.ToUpper(string(s.EndpointSpec.Mode))]) for _, portConfig := range s.EndpointSpec.Ports { spec.Endpoint.Ports = append(spec.Endpoint.Ports, &swarmapi.PortConfig{ Name: portConfig.Name, Protocol: swarmapi.PortConfig_Protocol(swarmapi.PortConfig_Protocol_value[strings.ToUpper(string(portConfig.Protocol))]), PublishMode: swarmapi.PortConfig_PublishMode(swarmapi.PortConfig_PublishMode_value[strings.ToUpper(string(portConfig.PublishMode))]), TargetPort: portConfig.TargetPort, PublishedPort: portConfig.PublishedPort, }) } } // Mode if s.Mode.Global != nil && s.Mode.Replicated != nil { return swarmapi.ServiceSpec{}, fmt.Errorf("cannot specify both replicated mode and global mode") } if s.Mode.Global != nil { spec.Mode = &swarmapi.ServiceSpec_Global{ Global: &swarmapi.GlobalService{}, } } else if s.Mode.Replicated != nil && s.Mode.Replicated.Replicas != nil { spec.Mode = &swarmapi.ServiceSpec_Replicated{ Replicated: &swarmapi.ReplicatedService{Replicas: *s.Mode.Replicated.Replicas}, } } else { spec.Mode = &swarmapi.ServiceSpec_Replicated{ Replicated: &swarmapi.ReplicatedService{Replicas: 1}, } } return spec, nil }
// ServiceSpecToGRPC converts a ServiceSpec to a grpc ServiceSpec. func ServiceSpecToGRPC(s types.ServiceSpec) (swarmapi.ServiceSpec, error) { name := s.Name if name == "" { name = namesgenerator.GetRandomName(0) } networks := make([]*swarmapi.ServiceSpec_NetworkAttachmentConfig, 0, len(s.Networks)) for _, n := range s.Networks { networks = append(networks, &swarmapi.ServiceSpec_NetworkAttachmentConfig{Target: n.Target, Aliases: n.Aliases}) } spec := swarmapi.ServiceSpec{ Annotations: swarmapi.Annotations{ Name: name, Labels: s.Labels, }, Task: swarmapi.TaskSpec{ Resources: resourcesToGRPC(s.TaskTemplate.Resources), LogDriver: driverToGRPC(s.TaskTemplate.LogDriver), }, Networks: networks, } containerSpec, err := containerToGRPC(s.TaskTemplate.ContainerSpec) if err != nil { return swarmapi.ServiceSpec{}, err } spec.Task.Runtime = &swarmapi.TaskSpec_Container{Container: containerSpec} restartPolicy, err := restartPolicyToGRPC(s.TaskTemplate.RestartPolicy) if err != nil { return swarmapi.ServiceSpec{}, err } spec.Task.Restart = restartPolicy if s.TaskTemplate.Placement != nil { spec.Task.Placement = &swarmapi.Placement{ Constraints: s.TaskTemplate.Placement.Constraints, } } if s.UpdateConfig != nil { spec.Update = &swarmapi.UpdateConfig{ Parallelism: s.UpdateConfig.Parallelism, Delay: *ptypes.DurationProto(s.UpdateConfig.Delay), } } if s.EndpointSpec != nil { if s.EndpointSpec.Mode != "" && s.EndpointSpec.Mode != types.ResolutionModeVIP && s.EndpointSpec.Mode != types.ResolutionModeDNSRR { return swarmapi.ServiceSpec{}, fmt.Errorf("invalid resolution mode: %q", s.EndpointSpec.Mode) } spec.Endpoint = &swarmapi.EndpointSpec{} spec.Endpoint.Mode = swarmapi.EndpointSpec_ResolutionMode(swarmapi.EndpointSpec_ResolutionMode_value[strings.ToUpper(string(s.EndpointSpec.Mode))]) for _, portConfig := range s.EndpointSpec.Ports { spec.Endpoint.Ports = append(spec.Endpoint.Ports, &swarmapi.PortConfig{ Name: portConfig.Name, Protocol: swarmapi.PortConfig_Protocol(swarmapi.PortConfig_Protocol_value[strings.ToUpper(string(portConfig.Protocol))]), TargetPort: portConfig.TargetPort, PublishedPort: portConfig.PublishedPort, }) } } //Mode if s.Mode.Global != nil { spec.Mode = &swarmapi.ServiceSpec_Global{ Global: &swarmapi.GlobalService{}, } } else if s.Mode.Replicated != nil && s.Mode.Replicated.Replicas != nil { spec.Mode = &swarmapi.ServiceSpec_Replicated{ Replicated: &swarmapi.ReplicatedService{Replicas: *s.Mode.Replicated.Replicas}, } } else { spec.Mode = &swarmapi.ServiceSpec_Replicated{ Replicated: &swarmapi.ReplicatedService{Replicas: 1}, } } return spec, nil }