func (s *DockerServer) serviceCreate(w http.ResponseWriter, r *http.Request) { var config swarm.ServiceSpec defer r.Body.Close() err := json.NewDecoder(r.Body).Decode(&config) if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } s.cMut.Lock() defer s.cMut.Unlock() s.swarmMut.Lock() defer s.swarmMut.Unlock() if len(s.nodes) == 0 || s.swarm == nil { http.Error(w, "no swarm nodes available", http.StatusNotAcceptable) return } if config.Name == "" { config.Name = s.generateID() } for _, s := range s.services { if s.Spec.Name == config.Name { http.Error(w, "there's already a service with this name", http.StatusConflict) return } } service := swarm.Service{ ID: s.generateID(), Spec: config, } containerCount := 1 if service.Spec.Mode.Global != nil { containerCount = len(s.nodes) } else if repl := service.Spec.Mode.Replicated; repl != nil { if repl.Replicas != nil { containerCount = int(*repl.Replicas) } } for i := 0; i < containerCount; i++ { container := s.containerForService(&service, fmt.Sprintf("%s-%d", config.Name, i)) chosenNode := s.nodes[s.nodeRR] s.nodeRR = (s.nodeRR + 1) % len(s.nodes) task := swarm.Task{ ID: s.generateID(), ServiceID: service.ID, NodeID: chosenNode.ID, Status: swarm.TaskStatus{ State: swarm.TaskStateReady, ContainerStatus: swarm.ContainerStatus{ ContainerID: container.ID, }, }, DesiredState: swarm.TaskStateReady, Spec: config.TaskTemplate, } s.tasks = append(s.tasks, &task) s.containers = append(s.containers, container) s.notify(container) } s.services = append(s.services, &service) w.WriteHeader(http.StatusOK) json.NewEncoder(w).Encode(service) }