-
Notifications
You must be signed in to change notification settings - Fork 224
/
resolver.go
127 lines (108 loc) · 3.33 KB
/
resolver.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
package imgsrc
import (
"context"
"errors"
"fmt"
"github.com/superfly/flyctl/iostreams"
"github.com/superfly/flyctl/api"
"github.com/superfly/flyctl/terminal"
)
type ImageOptions struct {
AppName string
WorkingDir string
DockerfilePath string
ImageRef string
BuildArgs map[string]string
ExtraBuildArgs map[string]string
BuildSecrets map[string]string
ImageLabel string
Publish bool
Tag string
Target string
NoCache bool
BuiltIn string
BuiltInSettings map[string]interface{}
Builder string
Buildpacks []string
}
type RefOptions struct {
AppName string
WorkingDir string
ImageRef string
ImageLabel string
Publish bool
Tag string
}
type DeploymentImage struct {
ID string
Tag string
Size int64
}
type Resolver struct {
dockerFactory *dockerClientFactory
apiClient *api.Client
}
// ResolveReference returns an Image give an reference using either the local docker daemon or remote registry
func (r *Resolver) ResolveReference(ctx context.Context, streams *iostreams.IOStreams, opts RefOptions) (img *DeploymentImage, err error) {
strategies := []imageResolver{
&localImageResolver{},
&remoteImageResolver{flyApi: r.apiClient},
}
for _, s := range strategies {
terminal.Debugf("Trying '%s' strategy\n", s.Name())
img, err = s.Run(ctx, r.dockerFactory, streams, opts)
terminal.Debugf("result image:%+v error:%v\n", img, err)
if err != nil {
return nil, err
}
if img != nil {
return img, nil
}
}
return nil, fmt.Errorf("could not find image \"%s\"", opts.ImageRef)
}
// BuildImage converts source code to an image using a Dockerfile, buildpacks, or builtins.
func (r *Resolver) BuildImage(ctx context.Context, streams *iostreams.IOStreams, opts ImageOptions) (img *DeploymentImage, err error) {
if !r.dockerFactory.mode.IsAvailable() {
return nil, errors.New("docker is unavailable to build the deployment image")
}
if opts.Tag == "" {
opts.Tag = NewDeploymentTag(opts.AppName, opts.ImageLabel)
}
strategies := []imageBuilder{}
if r.dockerFactory.mode.UseNixpacks() {
strategies = append(strategies, &nixpacksBuilder{})
} else {
strategies = []imageBuilder{
&buildpacksBuilder{},
&dockerfileBuilder{},
&builtinBuilder{},
}
}
for _, s := range strategies {
terminal.Debugf("Trying '%s' strategy\n", s.Name())
img, err = s.Run(ctx, r.dockerFactory, streams, opts)
terminal.Debugf("result image:%+v error:%v\n", img, err)
if err != nil {
return nil, err
}
if img != nil {
return img, nil
}
}
return nil, errors.New("app does not have a Dockerfile or buildpacks configured. See https://fly.io/docs/reference/configuration/#the-build-section")
}
func NewResolver(daemonType DockerDaemonType, apiClient *api.Client, appName string, iostreams *iostreams.IOStreams) *Resolver {
return &Resolver{
dockerFactory: newDockerClientFactory(daemonType, apiClient, appName, iostreams),
apiClient: apiClient,
}
}
type imageBuilder interface {
Name() string
Run(ctx context.Context, dockerFactory *dockerClientFactory, streams *iostreams.IOStreams, opts ImageOptions) (*DeploymentImage, error)
}
type imageResolver interface {
Name() string
Run(ctx context.Context, dockerFactory *dockerClientFactory, streams *iostreams.IOStreams, opts RefOptions) (*DeploymentImage, error)
}