/
builder.go
159 lines (143 loc) · 3.71 KB
/
builder.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
151
152
153
154
155
156
157
158
159
// Copyright 2017 tsuru authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package builder
import (
"archive/tar"
"bytes"
"io"
"github.com/pkg/errors"
tsuruErrors "github.com/tsuru/tsuru/errors"
"github.com/tsuru/tsuru/event"
"github.com/tsuru/tsuru/provision"
appTypes "github.com/tsuru/tsuru/types/app"
)
var DefaultBuilder = "docker"
type BuildOpts struct {
BuildFromFile bool
Rebuild bool
Redeploy bool
IsTsuruBuilderImage bool
ArchiveURL string
ArchiveFile io.Reader
ArchiveTarFile io.ReadCloser
ArchiveSize int64
ImageID string
Tag string
}
// Builder is the basic interface of this package.
type Builder interface {
Build(p provision.BuilderDeploy, app provision.App, evt *event.Event, opts *BuildOpts) (string, error)
}
var builders = make(map[string]Builder)
// PlatformBuilder is a builder where administrators can manage
// platforms (automatically adding, removing and updating platforms).
type PlatformBuilder interface {
PlatformAdd(appTypes.PlatformOptions) error
PlatformUpdate(appTypes.PlatformOptions) error
PlatformRemove(name string) error
}
// Register registers a new builder in the Builder registry.
func Register(name string, builder Builder) {
builders[name] = builder
}
// GetForProvisioner gets the builder required by the provisioner.
func GetForProvisioner(p provision.Provisioner) (Builder, error) {
builder, err := get(p.GetName())
if err != nil {
if _, ok := p.(provision.BuilderDeployDockerClient); ok {
return get("docker")
} else if _, ok := p.(provision.BuilderDeployKubeClient); ok {
return get("kubernetes")
}
}
return builder, err
}
// get gets the named builder from the registry.
func get(name string) (Builder, error) {
b, ok := builders[name]
if !ok {
return nil, errors.Errorf("unknown builder: %q", name)
}
return b, nil
}
// Registry returns the list of registered builders.
func Registry() ([]Builder, error) {
registry := make([]Builder, 0, len(builders))
for _, b := range builders {
registry = append(registry, b)
}
return registry, nil
}
func PlatformAdd(opts appTypes.PlatformOptions) error {
builders, err := Registry()
if err != nil {
return err
}
multiErr := tsuruErrors.NewMultiError()
for _, b := range builders {
if platformBuilder, ok := b.(PlatformBuilder); ok {
err = platformBuilder.PlatformAdd(opts)
if err == nil {
return nil
}
multiErr.Add(err)
}
}
if multiErr.Len() > 0 {
return multiErr
}
return errors.New("No builder available")
}
func PlatformUpdate(opts appTypes.PlatformOptions) error {
builders, err := Registry()
if err != nil {
return err
}
multiErr := tsuruErrors.NewMultiError()
for _, b := range builders {
if platformBuilder, ok := b.(PlatformBuilder); ok {
err = platformBuilder.PlatformUpdate(opts)
if err == nil {
return nil
}
multiErr.Add(err)
}
}
if multiErr.Len() > 0 {
return multiErr
}
return errors.New("No builder available")
}
func PlatformRemove(name string) error {
builders, err := Registry()
if err != nil {
return err
}
multiErr := tsuruErrors.NewMultiError()
for _, b := range builders {
if platformBuilder, ok := b.(PlatformBuilder); ok {
err = platformBuilder.PlatformRemove(name)
if err == nil {
return nil
}
multiErr.Add(err)
}
}
if multiErr.Len() > 0 {
return multiErr
}
return errors.New("No builder available")
}
func CompressDockerFile(data []byte) io.Reader {
var buf bytes.Buffer
writer := tar.NewWriter(&buf)
writer.WriteHeader(&tar.Header{
Name: "Dockerfile",
Mode: 0644,
Size: int64(len(data)),
})
writer.Write(data)
writer.Close()
return &buf
}