Skip to content

Commit 037e88a

Browse files
committed
add latest docker compose improvements for services support
Signed-off-by: Vasek - Tom C <tom@quartz.technology>
1 parent 5e5ef3f commit 037e88a

File tree

26 files changed

+994
-50
lines changed

26 files changed

+994
-50
lines changed

docker_sdk/src/codebase/dockercompose/docker_compose.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@ func (d *DockerCompose) Services() []*Service {
4646
return services
4747
}
4848

49+
func (d *DockerCompose) GetService(name string) (*Service, error) {
50+
for _, service := range d.Services() {
51+
if service.Name() == name {
52+
return service, nil
53+
}
54+
}
55+
56+
return nil, fmt.Errorf("no such service: %s", name)
57+
}
58+
4959
func (d *DockerCompose) String() string {
5060
yaml, err := d.project.MarshalYAML()
5161
if err != nil {

docker_sdk/src/codebase/dockercompose/service.go

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,15 @@ func (s *Service) Ports() []int {
107107
ports = append(ports, published)
108108
}
109109

110+
for _, port := range s.s.Expose {
111+
published, err := strconv.Atoi(port)
112+
if err != nil {
113+
fmt.Println(fmt.Errorf("failed to parse port published: %w, ignoring it", err))
114+
}
115+
116+
ports = append(ports, published)
117+
}
118+
110119
return ports
111120
}
112121

@@ -144,9 +153,19 @@ func (s *Service) Volumes() ([]*Volume, []*Cache) {
144153
case "volume":
145154
caches = append(caches, &Cache{name: v.Source, path: v.Target})
146155
case "bind":
147-
volumes = append(volumes, &Volume{origin: v.Source, target: v.Target})
156+
volumes = append(volumes, &Volume{origin: trimHostPath(v.Source), target: v.Target})
148157
}
149158
}
150159

151160
return volumes, caches
152161
}
162+
163+
func (s *Service) DependsOn() []string{
164+
dependentServices := []string{}
165+
166+
for key := range s.s.DependsOn {
167+
dependentServices = append(dependentServices, key)
168+
}
169+
170+
return dependentServices
171+
}

docker_sdk/src/codebase/to_module.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@ func (c *Codebase) ToModule(name string) *module.Module {
1313
}
1414

1515
if c.dockercompose != nil {
16-
17-
for _, service := range c.dockercompose.Services() {
18-
dockerModule = dockerModule.WithService(service)
19-
}
16+
dockerModule = dockerModule.WithDockerCompose(c.dockercompose)
2017
}
2118

2219
return module.Build(name, dockerModule)
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
package compose
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"strings"
7+
8+
"dagger.io/dagger"
9+
"dagger.io/dagger/dag"
10+
"dagger.io/dockersdk/module/object"
11+
"dagger.io/dockersdk/module/proxy"
12+
)
13+
14+
// allFunc is a function that starts all services using
15+
// a proxy module to group them together.
16+
//
17+
// It MUST be registered AFTER all services have been registered.
18+
// The proxy is a simple duplication of: github.com/kpenfound/dagger-modules/proxy@v0.2.5 module.
19+
type allFunc struct {
20+
c *Compose
21+
}
22+
23+
func (u *allFunc) up(services []*proxy.Service) *dagger.Container {
24+
proxy := proxy.New()
25+
26+
for _, service := range services {
27+
proxy = proxy.WithService(service)
28+
}
29+
30+
return proxy.Service()
31+
}
32+
33+
func (u *allFunc) Invoke(ctx context.Context, state object.State, input object.InputArgs) (object.Result, error) {
34+
compose, err := u.c.load(state)
35+
if err != nil {
36+
return nil, fmt.Errorf("failed to load object state: %w", err)
37+
}
38+
39+
services := []*proxy.Service{}
40+
for _, service := range u.c.dockercompose.Services() {
41+
service := &serviceFunc{c: compose, service: service}
42+
servicePrefix := fmt.Sprintf("%s_", service.service.Name())
43+
44+
serviceInput := input
45+
for argName, argValue := range input {
46+
if strings.HasPrefix(argName, servicePrefix) {
47+
serviceInput[strings.TrimPrefix(argName, servicePrefix)] = argValue
48+
}
49+
}
50+
51+
serviceCtr, err := service.ToService(ctx, state, serviceInput)
52+
if err != nil {
53+
return nil, fmt.Errorf("failed to get service %s: %w", service.service.Name(), err)
54+
}
55+
56+
services = append(services, serviceCtr)
57+
}
58+
59+
return (*allFunc).up(
60+
&allFunc{c: compose},
61+
services,
62+
), nil
63+
}
64+
65+
func (u *allFunc) Arguments() []*object.FunctionArg {
66+
// This method should not be called for this function
67+
return nil
68+
}
69+
70+
func (u *allFunc) AddTypeDefToObject(ctx context.Context, mod *dagger.Module, obj *dagger.TypeDef) (*dagger.Module, *dagger.TypeDef) {
71+
args := []*object.FunctionArg{}
72+
73+
serviceNames := []string{}
74+
for name, service := range u.c.funcMap {
75+
serviceNames = append(serviceNames, name)
76+
77+
serviceArgs := service.Arguments()
78+
for _, arg := range serviceArgs {
79+
args = append(args, &object.FunctionArg{
80+
// Prefix the argument name with the service name to avoid colission
81+
Name: fmt.Sprintf("%s_%s", name, arg.Name),
82+
Type: arg.Type,
83+
Opts: arg.Opts,
84+
})
85+
}
86+
}
87+
88+
typedef := dag.Function("All", dag.TypeDef().WithObject("Container")).
89+
WithDescription(fmt.Sprintf("Start all service containers (%s)", strings.Join(serviceNames, ", ")))
90+
91+
for _, arg := range args {
92+
typedef = typedef.WithArg(arg.Name, arg.Type, arg.Opts)
93+
}
94+
95+
return mod, obj.
96+
WithFunction(typedef)
97+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package compose
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
8+
"dagger.io/dagger"
9+
"dagger.io/dagger/dag"
10+
"dagger.io/dockersdk/codebase/dockercompose"
11+
"dagger.io/dockersdk/module/object"
12+
"dagger.io/dockersdk/utils"
13+
)
14+
15+
type Compose struct {
16+
Dir *dagger.Directory
17+
18+
dockercompose *dockercompose.DockerCompose
19+
funcMap map[string]object.Function
20+
}
21+
22+
func New(
23+
dir *dagger.Directory,
24+
dockercomposeFile *dockercompose.DockerCompose,
25+
) *Compose {
26+
c := &Compose{
27+
Dir: dir,
28+
dockercompose: dockercomposeFile,
29+
funcMap: make(map[string]object.Function),
30+
}
31+
32+
for _, service := range dockercomposeFile.Services() {
33+
c.funcMap[service.Name()] = &serviceFunc{c: c, service: service}
34+
}
35+
36+
// Add up for all services
37+
c.funcMap["All"] = &allFunc{c: c}
38+
39+
return c
40+
}
41+
42+
func (c *Compose) Name() string {
43+
return "Compose"
44+
}
45+
46+
func (c *Compose) Description() string {
47+
return "Manage compos services"
48+
}
49+
50+
func (c *Compose) New(input object.InputArgs) object.Object {
51+
var dir *dagger.Directory
52+
53+
if input["dir"] != nil {
54+
dir = utils.LoadDirectoryFromID([]byte(input["dir"]))
55+
}
56+
57+
return &Compose{
58+
Dir: dir,
59+
dockercompose: c.dockercompose,
60+
}
61+
}
62+
63+
func (c *Compose) AddTypeDef(ctx context.Context) dagger.WithModuleFunc {
64+
return func(mod *dagger.Module) *dagger.Module {
65+
object := dag.TypeDef().WithObject(c.Name())
66+
67+
for _, fct := range c.funcMap {
68+
mod, object = fct.AddTypeDefToObject(ctx, mod, object)
69+
}
70+
71+
return mod.WithObject(object)
72+
}
73+
}
74+
75+
func (c *Compose) Load(state object.State) (object.Object, error) {
76+
return c.load(state)
77+
}
78+
79+
func (c *Compose) load(state object.State) (*Compose, error) {
80+
parentMap := make(map[string]interface{})
81+
err := json.Unmarshal(state, &parentMap)
82+
if err != nil {
83+
return nil, fmt.Errorf("failed to unmarshal parent object: %w", err)
84+
}
85+
86+
cpyCompose := &Compose{
87+
dockercompose: c.dockercompose,
88+
funcMap: c.funcMap,
89+
}
90+
91+
if parentMap["Dir"] != nil {
92+
cpyCompose.Dir = dag.LoadDirectoryFromID(dagger.DirectoryID(parentMap["Dir"].(string)))
93+
}
94+
95+
return cpyCompose, nil
96+
}
97+
98+
func (c *Compose) Invoke(ctx context.Context, state object.State, fnName string, input object.InputArgs) (object.Result, error) {
99+
if c.funcMap[fnName] == nil {
100+
return nil, fmt.Errorf("unknown function %s", fnName)
101+
}
102+
103+
return c.funcMap[fnName].Invoke(ctx, state, input)
104+
}

0 commit comments

Comments
 (0)