This repository has been archived by the owner on Nov 20, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathcompose.go
150 lines (137 loc) · 4.7 KB
/
compose.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package fishfinger
import (
"context"
"fmt"
"strings"
"github.com/docker/libcompose/docker"
"github.com/docker/libcompose/docker/ctx"
"github.com/docker/libcompose/project"
"github.com/docker/libcompose/project/options"
)
// -----------------------------------------------------------------------------
// Compose is a structure using `libcompose` to manage a Docker environment
// from a compose-file.
type Compose struct {
*project.Project
}
// NewCompose returns a new `Compose` or an `error` if something occurs during
// setup. It uses `composeFile` as the path to the compose-file to up.
//
// NOTE: .env files are not currently supported.
func NewCompose(composeFile string) (*Compose, error) {
p, err := docker.NewProject(
&ctx.Context{
Context: project.Context{ComposeFiles: []string{composeFile}},
}, nil)
if err != nil {
return nil, err
}
return &Compose{Project: p.(*project.Project)}, nil
}
// -----------------------------------------------------------------------------
// Start launches all `services` specified. If `services` is empty, all services
// described in the compose-file are launched. If something occurs during any
// `services` start, it returns an `error`.
func (c *Compose) Start(services ...string) error {
return c.Up(context.Background(), options.Up{}, services...)
}
// StartBackoff launches all `services` specified and returns only when
// `backoffFunc` completes. If `services` is empty, all services described in
// the compose-file are launched and `backoffFunc` is used for each of them.
//
// NOTE: This project offers default implementations of `backoffFunc` but user
// should provide an implementation according to the Docker images used.
//
// `backoffFunc` takes as input this `*Compose`, service name and port/protocol:
//
// `backoffFunc(c, "redis", "6379/tcp")`
//
// `services` has format "service:port/protocol", e.g., "redis:6379/tcp".
func (c *Compose) StartBackoff(backoffFunc func(*Compose, string, string) error, services ...string) error {
for _, service := range services {
parts := strings.Split(service, ":")
if len(parts) != 2 {
return fmt.Errorf("Invalid 'service' parameter %s. "+
"Should have format 'service:port/protocol'.", service)
}
if err := c.Up(context.Background(), options.Up{}, parts[0]); err != nil {
return err
}
if err := backoffFunc(c, parts[0], parts[1]); err != nil {
return err
}
}
return nil
}
// Stop removes all `services` specified. If `services` is empty, all services
// described in the compose-file are removed. If something occurs during any
// `services` stop, it returns an `error`.
func (c *Compose) Stop(services ...string) error {
if err := c.Down(context.Background(), options.Down{}, services...); err != nil {
return err
}
return c.Delete(context.Background(), options.Delete{}, services...)
}
// Status returns `true` if `service` is in running state, `false` otherwise.
// If `service` does not exist, it returns an `error`.
func (c *Compose) Status(service string) (bool, error) {
serviceObj, err := c.CreateService(service)
if err != nil {
return false, err
}
ctnrs, err := serviceObj.Containers(context.Background())
if err != nil || len(ctnrs) == 0 {
return false, err
}
return ctnrs[0].IsRunning(context.Background()), nil
}
// Port returns the host address where `service` is bound to `port`. If
// `service` does not exist or `port` is not bound, it returns an `error`.
//
// NOTE: `port` MUST be of the following form `<portNb>/<protocol>` such as
// `80/tcp`.
func (c *Compose) Port(service, port string) (string, error) {
s, err := c.CreateService(service)
if err != nil {
return "", err
}
ctnr, err := s.Containers(context.Background())
if err != nil {
return "", err
} else if len(ctnr) == 0 {
return "", fmt.Errorf("no container available")
}
addr, err := ctnr[0].Port(context.Background(), port)
if err != nil {
return "", err
} else if addr == "" {
return "", fmt.Errorf("port not bound")
}
return addr, nil
}
// Env returns the value of the environment variable `varName` set in container
// `service` by the compose-file. If `service` or `varName` does not exist, It
// returns an `error`.
func (c *Compose) Env(service, varName string) (string, error) {
s, err := c.CreateService(service)
if err != nil {
return "", err
}
v, ok := s.Config().Environment.ToMap()[varName]
if !ok {
return "", fmt.Errorf("environment var not found")
}
return v, nil
}
// Info returns a `project.InfoSet` about a specified `service`.
func (c *Compose) Info(service string) (project.InfoSet, error) {
serviceObj, err := c.CreateService(service)
if err != nil {
return nil, err
}
info, err := serviceObj.Info(context.Background())
if err != nil {
return nil, err
}
return info, nil
}