Skip to content
This repository was archived by the owner on Jul 18, 2025. It is now read-only.

Commit 5588741

Browse files
authored
Merge pull request #353 from vdemeester/project_refactoring
Split project/project.go into smaller files
2 parents 19fa764 + c5201a3 commit 5588741

19 files changed

+443
-309
lines changed

project/project.go

Lines changed: 0 additions & 309 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"github.com/docker/libcompose/config"
1212
"github.com/docker/libcompose/logger"
1313
"github.com/docker/libcompose/project/events"
14-
"github.com/docker/libcompose/project/options"
1514
"github.com/docker/libcompose/utils"
1615
"github.com/docker/libcompose/yaml"
1716
)
@@ -333,314 +332,6 @@ func (p *Project) loadWrappers(wrappers map[string]*serviceWrapper, servicesToCo
333332
return nil
334333
}
335334

336-
// Build builds the specified services (like docker build).
337-
func (p *Project) Build(ctx context.Context, buildOptions options.Build, services ...string) error {
338-
return p.perform(events.ProjectBuildStart, events.ProjectBuildDone, services, wrapperAction(func(wrapper *serviceWrapper, wrappers map[string]*serviceWrapper) {
339-
wrapper.Do(wrappers, events.ServiceBuildStart, events.ServiceBuild, func(service Service) error {
340-
return service.Build(ctx, buildOptions)
341-
})
342-
}), nil)
343-
}
344-
345-
// Create creates the specified services (like docker create).
346-
func (p *Project) Create(ctx context.Context, options options.Create, services ...string) error {
347-
if options.NoRecreate && options.ForceRecreate {
348-
return fmt.Errorf("no-recreate and force-recreate cannot be combined")
349-
}
350-
return p.perform(events.ProjectCreateStart, events.ProjectCreateDone, services, wrapperAction(func(wrapper *serviceWrapper, wrappers map[string]*serviceWrapper) {
351-
wrapper.Do(wrappers, events.ServiceCreateStart, events.ServiceCreate, func(service Service) error {
352-
return service.Create(ctx, options)
353-
})
354-
}), nil)
355-
}
356-
357-
// Stop stops the specified services (like docker stop).
358-
func (p *Project) Stop(ctx context.Context, timeout int, services ...string) error {
359-
return p.perform(events.ProjectStopStart, events.ProjectStopDone, services, wrapperAction(func(wrapper *serviceWrapper, wrappers map[string]*serviceWrapper) {
360-
wrapper.Do(nil, events.ServiceStopStart, events.ServiceStop, func(service Service) error {
361-
return service.Stop(ctx, timeout)
362-
})
363-
}), nil)
364-
}
365-
366-
// Down stops the specified services and clean related containers (like docker stop + docker rm).
367-
func (p *Project) Down(ctx context.Context, opts options.Down, services ...string) error {
368-
if !opts.RemoveImages.Valid() {
369-
return fmt.Errorf("--rmi flag must be local, all or empty")
370-
}
371-
if err := p.Stop(ctx, 10, services...); err != nil {
372-
return err
373-
}
374-
if opts.RemoveOrphans {
375-
if err := p.runtime.RemoveOrphans(ctx, p.Name, p.ServiceConfigs); err != nil {
376-
return err
377-
}
378-
}
379-
if err := p.Delete(ctx, options.Delete{
380-
RemoveVolume: opts.RemoveVolume,
381-
}, services...); err != nil {
382-
return err
383-
}
384-
385-
networks, err := p.context.NetworksFactory.Create(p.Name, p.NetworkConfigs, p.ServiceConfigs, p.isNetworkEnabled())
386-
if err != nil {
387-
return err
388-
}
389-
if err := networks.Remove(ctx); err != nil {
390-
return err
391-
}
392-
393-
if opts.RemoveVolume {
394-
volumes, err := p.context.VolumesFactory.Create(p.Name, p.VolumeConfigs, p.ServiceConfigs, p.isVolumeEnabled())
395-
if err != nil {
396-
return err
397-
}
398-
if err := volumes.Remove(ctx); err != nil {
399-
return err
400-
}
401-
}
402-
403-
return p.forEach([]string{}, wrapperAction(func(wrapper *serviceWrapper, wrappers map[string]*serviceWrapper) {
404-
wrapper.Do(wrappers, events.NoEvent, events.NoEvent, func(service Service) error {
405-
return service.RemoveImage(ctx, opts.RemoveImages)
406-
})
407-
}), func(service Service) error {
408-
return service.Create(ctx, options.Create{})
409-
})
410-
}
411-
412-
// RemoveOrphans implements project.RuntimeProject.RemoveOrphans.
413-
// It does nothing by default as it is supposed to be overriden by specific implementation.
414-
func (p *Project) RemoveOrphans(ctx context.Context) error {
415-
return nil
416-
}
417-
418-
// Restart restarts the specified services (like docker restart).
419-
func (p *Project) Restart(ctx context.Context, timeout int, services ...string) error {
420-
return p.perform(events.ProjectRestartStart, events.ProjectRestartDone, services, wrapperAction(func(wrapper *serviceWrapper, wrappers map[string]*serviceWrapper) {
421-
wrapper.Do(wrappers, events.ServiceRestartStart, events.ServiceRestart, func(service Service) error {
422-
return service.Restart(ctx, timeout)
423-
})
424-
}), nil)
425-
}
426-
427-
// Port returns the public port for a port binding of the specified service.
428-
func (p *Project) Port(ctx context.Context, index int, protocol, serviceName, privatePort string) (string, error) {
429-
service, err := p.CreateService(serviceName)
430-
if err != nil {
431-
return "", err
432-
}
433-
434-
containers, err := service.Containers(ctx)
435-
if err != nil {
436-
return "", err
437-
}
438-
439-
if index < 1 || index > len(containers) {
440-
return "", fmt.Errorf("Invalid index %d", index)
441-
}
442-
443-
return containers[index-1].Port(ctx, fmt.Sprintf("%s/%s", privatePort, protocol))
444-
}
445-
446-
// Ps list containers for the specified services.
447-
func (p *Project) Ps(ctx context.Context, services ...string) (InfoSet, error) {
448-
allInfo := InfoSet{}
449-
for _, name := range p.ServiceConfigs.Keys() {
450-
service, err := p.CreateService(name)
451-
if err != nil {
452-
return nil, err
453-
}
454-
455-
info, err := service.Info(ctx)
456-
if err != nil {
457-
return nil, err
458-
}
459-
460-
allInfo = append(allInfo, info...)
461-
}
462-
return allInfo, nil
463-
}
464-
465-
// Start starts the specified services (like docker start).
466-
func (p *Project) Start(ctx context.Context, services ...string) error {
467-
return p.perform(events.ProjectStartStart, events.ProjectStartDone, services, wrapperAction(func(wrapper *serviceWrapper, wrappers map[string]*serviceWrapper) {
468-
wrapper.Do(wrappers, events.ServiceStartStart, events.ServiceStart, func(service Service) error {
469-
return service.Start(ctx)
470-
})
471-
}), nil)
472-
}
473-
474-
// Run executes a one off command (like `docker run image command`).
475-
func (p *Project) Run(ctx context.Context, serviceName string, commandParts []string, opts options.Run) (int, error) {
476-
if !p.ServiceConfigs.Has(serviceName) {
477-
return 1, fmt.Errorf("%s is not defined in the template", serviceName)
478-
}
479-
480-
if err := p.initialize(ctx); err != nil {
481-
return 1, err
482-
}
483-
var exitCode int
484-
err := p.forEach([]string{}, wrapperAction(func(wrapper *serviceWrapper, wrappers map[string]*serviceWrapper) {
485-
wrapper.Do(wrappers, events.ServiceRunStart, events.ServiceRun, func(service Service) error {
486-
if service.Name() == serviceName {
487-
code, err := service.Run(ctx, commandParts, opts)
488-
exitCode = code
489-
return err
490-
}
491-
return nil
492-
})
493-
}), func(service Service) error {
494-
return service.Create(ctx, options.Create{})
495-
})
496-
return exitCode, err
497-
}
498-
499-
// Up creates and starts the specified services (kinda like docker run).
500-
func (p *Project) Up(ctx context.Context, options options.Up, services ...string) error {
501-
if err := p.initialize(ctx); err != nil {
502-
return err
503-
}
504-
return p.perform(events.ProjectUpStart, events.ProjectUpDone, services, wrapperAction(func(wrapper *serviceWrapper, wrappers map[string]*serviceWrapper) {
505-
wrapper.Do(wrappers, events.ServiceUpStart, events.ServiceUp, func(service Service) error {
506-
return service.Up(ctx, options)
507-
})
508-
}), func(service Service) error {
509-
return service.Create(ctx, options.Create)
510-
})
511-
}
512-
513-
// Log aggregates and prints out the logs for the specified services.
514-
func (p *Project) Log(ctx context.Context, follow bool, services ...string) error {
515-
return p.forEach(services, wrapperAction(func(wrapper *serviceWrapper, wrappers map[string]*serviceWrapper) {
516-
wrapper.Do(nil, events.NoEvent, events.NoEvent, func(service Service) error {
517-
return service.Log(ctx, follow)
518-
})
519-
}), nil)
520-
}
521-
522-
// Scale scales the specified services.
523-
func (p *Project) Scale(ctx context.Context, timeout int, servicesScale map[string]int) error {
524-
// This code is a bit verbose but I wanted to parse everything up front
525-
order := make([]string, 0, 0)
526-
services := make(map[string]Service)
527-
528-
for name := range servicesScale {
529-
if !p.ServiceConfigs.Has(name) {
530-
return fmt.Errorf("%s is not defined in the template", name)
531-
}
532-
533-
service, err := p.CreateService(name)
534-
if err != nil {
535-
return fmt.Errorf("Failed to lookup service: %s: %v", service, err)
536-
}
537-
538-
order = append(order, name)
539-
services[name] = service
540-
}
541-
542-
for _, name := range order {
543-
scale := servicesScale[name]
544-
log.Infof("Setting scale %s=%d...", name, scale)
545-
err := services[name].Scale(ctx, scale, timeout)
546-
if err != nil {
547-
return fmt.Errorf("Failed to set the scale %s=%d: %v", name, scale, err)
548-
}
549-
}
550-
return nil
551-
}
552-
553-
// Pull pulls the specified services (like docker pull).
554-
func (p *Project) Pull(ctx context.Context, services ...string) error {
555-
return p.forEach(services, wrapperAction(func(wrapper *serviceWrapper, wrappers map[string]*serviceWrapper) {
556-
wrapper.Do(nil, events.ServicePullStart, events.ServicePull, func(service Service) error {
557-
return service.Pull(ctx)
558-
})
559-
}), nil)
560-
}
561-
562-
// Containers lists the containers for the specified services. Can be filter using
563-
// the Filter struct.
564-
func (p *Project) Containers(ctx context.Context, filter Filter, services ...string) ([]string, error) {
565-
containers := []string{}
566-
err := p.forEach(services, wrapperAction(func(wrapper *serviceWrapper, wrappers map[string]*serviceWrapper) {
567-
wrapper.Do(nil, events.NoEvent, events.NoEvent, func(service Service) error {
568-
serviceContainers, innerErr := service.Containers(ctx)
569-
if innerErr != nil {
570-
return innerErr
571-
}
572-
573-
for _, container := range serviceContainers {
574-
running, innerErr := container.IsRunning(ctx)
575-
if innerErr != nil {
576-
log.Error(innerErr)
577-
}
578-
switch filter.State {
579-
case Running:
580-
if !running {
581-
continue
582-
}
583-
case Stopped:
584-
if running {
585-
continue
586-
}
587-
case AnyState:
588-
// Don't do a thing
589-
default:
590-
// Invalid state filter
591-
return fmt.Errorf("Invalid container filter: %s", filter.State)
592-
}
593-
containerID, innerErr := container.ID()
594-
if innerErr != nil {
595-
log.Error(innerErr)
596-
}
597-
containers = append(containers, containerID)
598-
}
599-
return nil
600-
})
601-
}), nil)
602-
if err != nil {
603-
return nil, err
604-
}
605-
return containers, nil
606-
}
607-
608-
// Delete removes the specified services (like docker rm).
609-
func (p *Project) Delete(ctx context.Context, options options.Delete, services ...string) error {
610-
return p.perform(events.ProjectDeleteStart, events.ProjectDeleteDone, services, wrapperAction(func(wrapper *serviceWrapper, wrappers map[string]*serviceWrapper) {
611-
wrapper.Do(nil, events.ServiceDeleteStart, events.ServiceDelete, func(service Service) error {
612-
return service.Delete(ctx, options)
613-
})
614-
}), nil)
615-
}
616-
617-
// Kill kills the specified services (like docker kill).
618-
func (p *Project) Kill(ctx context.Context, signal string, services ...string) error {
619-
return p.perform(events.ProjectKillStart, events.ProjectKillDone, services, wrapperAction(func(wrapper *serviceWrapper, wrappers map[string]*serviceWrapper) {
620-
wrapper.Do(nil, events.ServiceKillStart, events.ServiceKill, func(service Service) error {
621-
return service.Kill(ctx, signal)
622-
})
623-
}), nil)
624-
}
625-
626-
// Pause pauses the specified services containers (like docker pause).
627-
func (p *Project) Pause(ctx context.Context, services ...string) error {
628-
return p.perform(events.ProjectPauseStart, events.ProjectPauseDone, services, wrapperAction(func(wrapper *serviceWrapper, wrappers map[string]*serviceWrapper) {
629-
wrapper.Do(nil, events.ServicePauseStart, events.ServicePause, func(service Service) error {
630-
return service.Pause(ctx)
631-
})
632-
}), nil)
633-
}
634-
635-
// Unpause pauses the specified services containers (like docker pause).
636-
func (p *Project) Unpause(ctx context.Context, services ...string) error {
637-
return p.perform(events.ProjectUnpauseStart, events.ProjectUnpauseDone, services, wrapperAction(func(wrapper *serviceWrapper, wrappers map[string]*serviceWrapper) {
638-
wrapper.Do(nil, events.ServiceUnpauseStart, events.ServiceUnpause, func(service Service) error {
639-
return service.Unpause(ctx)
640-
})
641-
}), nil)
642-
}
643-
644335
func (p *Project) perform(start, done events.EventType, services []string, action wrapperAction, cycleAction serviceAction) error {
645336
p.Notify(start, "", nil)
646337

project/project_build.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package project
2+
3+
import (
4+
"golang.org/x/net/context"
5+
6+
"github.com/docker/libcompose/project/events"
7+
"github.com/docker/libcompose/project/options"
8+
)
9+
10+
// Build builds the specified services (like docker build).
11+
func (p *Project) Build(ctx context.Context, buildOptions options.Build, services ...string) error {
12+
return p.perform(events.ProjectBuildStart, events.ProjectBuildDone, services, wrapperAction(func(wrapper *serviceWrapper, wrappers map[string]*serviceWrapper) {
13+
wrapper.Do(wrappers, events.ServiceBuildStart, events.ServiceBuild, func(service Service) error {
14+
return service.Build(ctx, buildOptions)
15+
})
16+
}), nil)
17+
}

project/project_containers.go

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package project
2+
3+
import (
4+
"fmt"
5+
6+
"golang.org/x/net/context"
7+
8+
log "github.com/Sirupsen/logrus"
9+
"github.com/docker/libcompose/project/events"
10+
)
11+
12+
// Containers lists the containers for the specified services. Can be filter using
13+
// the Filter struct.
14+
func (p *Project) Containers(ctx context.Context, filter Filter, services ...string) ([]string, error) {
15+
containers := []string{}
16+
err := p.forEach(services, wrapperAction(func(wrapper *serviceWrapper, wrappers map[string]*serviceWrapper) {
17+
wrapper.Do(nil, events.NoEvent, events.NoEvent, func(service Service) error {
18+
serviceContainers, innerErr := service.Containers(ctx)
19+
if innerErr != nil {
20+
return innerErr
21+
}
22+
23+
for _, container := range serviceContainers {
24+
running, innerErr := container.IsRunning(ctx)
25+
if innerErr != nil {
26+
log.Error(innerErr)
27+
}
28+
switch filter.State {
29+
case Running:
30+
if !running {
31+
continue
32+
}
33+
case Stopped:
34+
if running {
35+
continue
36+
}
37+
case AnyState:
38+
// Don't do a thing
39+
default:
40+
// Invalid state filter
41+
return fmt.Errorf("Invalid container filter: %s", filter.State)
42+
}
43+
containerID, innerErr := container.ID()
44+
if innerErr != nil {
45+
log.Error(innerErr)
46+
}
47+
containers = append(containers, containerID)
48+
}
49+
return nil
50+
})
51+
}), nil)
52+
if err != nil {
53+
return nil, err
54+
}
55+
return containers, nil
56+
}

0 commit comments

Comments
 (0)