github.com/r3labs/libcompose@v0.4.1-0.20171123133234-495fe0619cc3/docker/project.go (about)

     1  package docker
     2  
     3  import (
     4  	"golang.org/x/net/context"
     5  
     6  	"github.com/docker/docker/api/types"
     7  	"github.com/docker/docker/api/types/filters"
     8  	"github.com/r3labs/libcompose/config"
     9  	"github.com/r3labs/libcompose/docker/auth"
    10  	"github.com/r3labs/libcompose/docker/client"
    11  	"github.com/r3labs/libcompose/docker/ctx"
    12  	"github.com/r3labs/libcompose/docker/network"
    13  	"github.com/r3labs/libcompose/docker/service"
    14  	"github.com/r3labs/libcompose/docker/volume"
    15  	"github.com/r3labs/libcompose/labels"
    16  	"github.com/r3labs/libcompose/project"
    17  	"github.com/sirupsen/logrus"
    18  )
    19  
    20  // NewProject creates a Project with the specified context.
    21  func NewProject(context *ctx.Context, parseOptions *config.ParseOptions) (project.APIProject, error) {
    22  
    23  	if err := context.LookupConfig(); err != nil {
    24  		logrus.Errorf("Failed to load docker config: %v", err)
    25  	}
    26  
    27  	if context.AuthLookup == nil {
    28  		context.AuthLookup = auth.NewConfigLookup(context.ConfigFile)
    29  	}
    30  
    31  	if context.ServiceFactory == nil {
    32  		context.ServiceFactory = service.NewFactory(context)
    33  	}
    34  
    35  	if context.ClientFactory == nil {
    36  		factory, err := client.NewDefaultFactory(client.Options{})
    37  		if err != nil {
    38  			return nil, err
    39  		}
    40  		context.ClientFactory = factory
    41  	}
    42  
    43  	if context.NetworksFactory == nil {
    44  		networksFactory := &network.DockerFactory{
    45  			ClientFactory: context.ClientFactory,
    46  		}
    47  		context.NetworksFactory = networksFactory
    48  	}
    49  
    50  	if context.VolumesFactory == nil {
    51  		volumesFactory := &volume.DockerFactory{
    52  			ClientFactory: context.ClientFactory,
    53  		}
    54  		context.VolumesFactory = volumesFactory
    55  	}
    56  
    57  	// FIXME(vdemeester) Remove the context duplication ?
    58  	runtime := &Project{
    59  		clientFactory: context.ClientFactory,
    60  	}
    61  	p := project.NewProject(&context.Context, runtime, parseOptions)
    62  
    63  	err := p.Parse()
    64  	if err != nil {
    65  		return nil, err
    66  	}
    67  
    68  	return p, err
    69  }
    70  
    71  // Project implements project.RuntimeProject and define docker runtime specific methods.
    72  type Project struct {
    73  	clientFactory client.Factory
    74  }
    75  
    76  // RemoveOrphans implements project.RuntimeProject.RemoveOrphans.
    77  // It will remove orphan containers that are part of the project but not to any services.
    78  func (p *Project) RemoveOrphans(ctx context.Context, projectName string, serviceConfigs *config.ServiceConfigs) error {
    79  	client := p.clientFactory.Create(nil)
    80  	filter := filters.NewArgs()
    81  	filter.Add("label", labels.PROJECT.EqString(projectName))
    82  	containers, err := client.ContainerList(ctx, types.ContainerListOptions{
    83  		Filters: filter,
    84  	})
    85  	if err != nil {
    86  		return err
    87  	}
    88  	currentServices := map[string]struct{}{}
    89  	for _, serviceName := range serviceConfigs.Keys() {
    90  		currentServices[serviceName] = struct{}{}
    91  	}
    92  	for _, container := range containers {
    93  		serviceLabel := container.Labels[labels.SERVICE.Str()]
    94  		if _, ok := currentServices[serviceLabel]; !ok {
    95  			if err := client.ContainerKill(ctx, container.ID, "SIGKILL"); err != nil {
    96  				return err
    97  			}
    98  			if err := client.ContainerRemove(ctx, container.ID, types.ContainerRemoveOptions{
    99  				Force: true,
   100  			}); err != nil {
   101  				return err
   102  			}
   103  		}
   104  	}
   105  	return nil
   106  }