1 package image
2
3 import (
4 "fmt"
5 "net/http"
6 "net/http/httptest"
7 "path/filepath"
8 "strings"
9 "testing"
10
11 devfile "github.com/devfile/api/v2/pkg/apis/workspaces/v1alpha2"
12 "github.com/google/go-cmp/cmp"
13
14 "github.com/redhat-developer/odo/pkg/testingutil/filesystem"
15 )
16
17 func TestGetShellCommand(t *testing.T) {
18 type test struct {
19 name string
20 cmdName string
21 globalExtraArgs []string
22 buildExtraArgs []string
23 image *devfile.ImageComponent
24 devfilePath string
25 want []string
26 }
27 devfilePath := filepath.Join("home", "user", "project1")
28 tests := []test{
29 {
30 name: "test 1",
31 cmdName: "cli",
32 image: &devfile.ImageComponent{
33 Image: devfile.Image{
34 ImageName: "registry.io/myimagename:tag",
35 ImageUnion: devfile.ImageUnion{
36 Dockerfile: &devfile.DockerfileImage{
37 DockerfileSrc: devfile.DockerfileSrc{
38 Uri: "./Dockerfile",
39 },
40 Dockerfile: devfile.Dockerfile{
41 BuildContext: "${PROJECTS_ROOT}",
42 },
43 },
44 },
45 },
46 },
47 devfilePath: devfilePath,
48 want: []string{
49 "cli", "build", "-t", "registry.io/myimagename:tag", "-f", filepath.Join(devfilePath, "Dockerfile"), "${PROJECTS_ROOT}",
50 },
51 },
52 {
53 name: "test 2",
54 cmdName: "cli",
55 image: &devfile.ImageComponent{
56 Image: devfile.Image{
57 ImageName: "registry.io/myimagename:tag",
58 ImageUnion: devfile.ImageUnion{
59 Dockerfile: &devfile.DockerfileImage{
60 DockerfileSrc: devfile.DockerfileSrc{
61 Uri: "Dockerfile",
62 },
63 Dockerfile: devfile.Dockerfile{
64 BuildContext: "${PROJECTS_ROOT}",
65 },
66 },
67 },
68 },
69 },
70 devfilePath: devfilePath,
71 want: []string{
72 "cli", "build", "-t", "registry.io/myimagename:tag", "-f", filepath.Join(devfilePath, "Dockerfile"), "${PROJECTS_ROOT}",
73 },
74 },
75 {
76 name: "test with args",
77 cmdName: "cli",
78 image: &devfile.ImageComponent{
79 Image: devfile.Image{
80 ImageName: "registry.io/myimagename:tag",
81 ImageUnion: devfile.ImageUnion{
82 Dockerfile: &devfile.DockerfileImage{
83 DockerfileSrc: devfile.DockerfileSrc{
84 Uri: "Dockerfile",
85 },
86 Dockerfile: devfile.Dockerfile{
87 BuildContext: "${PROJECTS_ROOT}",
88 Args: []string{"--flag", "value"},
89 },
90 },
91 },
92 },
93 },
94 devfilePath: devfilePath,
95 want: []string{
96 "cli", "build", "-t", "registry.io/myimagename:tag", "-f", filepath.Join(devfilePath, "Dockerfile"), "${PROJECTS_ROOT}", "--flag", "value",
97 },
98 },
99 {
100 name: "test with no build context in Devfile",
101 cmdName: "cli",
102 image: &devfile.ImageComponent{
103 Image: devfile.Image{
104 ImageName: "registry.io/myimagename:tag",
105 ImageUnion: devfile.ImageUnion{
106 Dockerfile: &devfile.DockerfileImage{
107 DockerfileSrc: devfile.DockerfileSrc{
108 Uri: "Dockerfile.rhel",
109 },
110 },
111 },
112 },
113 },
114 devfilePath: devfilePath,
115 want: []string{
116 "cli", "build", "-t", "registry.io/myimagename:tag", "-f", filepath.Join(devfilePath, "Dockerfile.rhel"), devfilePath,
117 },
118 },
119 {
120 name: "using an absolute Dockerfile path",
121 cmdName: "cli",
122 image: &devfile.ImageComponent{
123 Image: devfile.Image{
124 ImageName: "registry.io/myimagename:tag",
125 ImageUnion: devfile.ImageUnion{
126 Dockerfile: &devfile.DockerfileImage{
127 DockerfileSrc: devfile.DockerfileSrc{
128 Uri: filepath.Join("/", "path", "to", "Dockerfile.rhel"),
129 },
130 },
131 },
132 },
133 },
134 devfilePath: devfilePath,
135 want: []string{
136 "cli", "build", "-t", "registry.io/myimagename:tag", "-f", filepath.Join("/", "path", "to", "Dockerfile.rhel"), devfilePath,
137 },
138 },
139 }
140
141 allTests := make([]test, len(tests))
142 copy(allTests, tests)
143 globalExtraArgs := []string{
144 "--global-flag1=value1",
145 "--global-flag2=value2",
146 }
147 buildExtraArgs := []string{
148 "--flag1=value1",
149 "--flag2=value2",
150 }
151 for _, tt := range tests {
152 var want []string
153 if len(tt.want) != 0 {
154 want = append(want, tt.cmdName)
155 want = append(want, globalExtraArgs...)
156 if len(tt.want) >= 2 {
157 want = append(want, tt.want[1])
158 }
159 want = append(want, buildExtraArgs...)
160 if len(tt.want) > 3 {
161 want = append(want, tt.want[2:]...)
162 }
163 }
164 allTests = append(allTests, test{
165 name: tt.name + " - with extra args",
166 cmdName: tt.cmdName,
167 globalExtraArgs: globalExtraArgs,
168 buildExtraArgs: buildExtraArgs,
169 image: tt.image,
170 devfilePath: devfilePath,
171 want: want,
172 })
173 }
174
175 for _, tt := range allTests {
176 t.Run(tt.name, func(t *testing.T) {
177 got := getShellCommand(tt.cmdName, tt.globalExtraArgs, tt.buildExtraArgs, tt.image, tt.devfilePath, tt.image.Dockerfile.Uri)
178 if diff := cmp.Diff(tt.want, got); diff != "" {
179 t.Errorf("getShellCommand() mismatch (-want +got):\n%s", diff)
180 }
181 })
182 }
183 }
184
185 func Test_resolveAndDownloadDockerfile(t *testing.T) {
186 fakeFs := filesystem.NewFakeFs()
187
188 for _, tt := range []struct {
189 name string
190 uriFunc func() (*httptest.Server, string)
191 wantErr bool
192 wantIsTemp bool
193 want string
194 }{
195 {
196 name: "local file",
197 uriFunc: func() (*httptest.Server, string) { return nil, "Dockerfile" },
198 want: "Dockerfile",
199 },
200 {
201 name: "remote file (non-HTTP)",
202 uriFunc: func() (*httptest.Server, string) { return nil, "ftp://example.com/Dockerfile" },
203 want: "ftp://example.com/Dockerfile",
204 },
205 {
206 name: "remote file with error (HTTP)",
207 uriFunc: func() (*httptest.Server, string) {
208 s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
209 w.WriteHeader(http.StatusNotFound)
210 }))
211 return s, s.URL + "/404"
212 },
213 wantErr: true,
214 wantIsTemp: true,
215 },
216 {
217 name: "remote file (HTTP)",
218 uriFunc: func() (*httptest.Server, string) {
219 s := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
220 fmt.Fprintln(w, "FROM alpine:3.6")
221 fmt.Fprintln(w, "RUN echo Hello World")
222 fmt.Fprintln(w, "ENTRYPOINT [\"/bin/tail\"]")
223 fmt.Fprintln(w, "CMD [\"-f\", \"/dev/null\"]")
224 }))
225 return s, s.URL
226 },
227 wantIsTemp: true,
228 },
229 } {
230 t.Run(tt.name, func(t *testing.T) {
231 server, uri := tt.uriFunc()
232 if server != nil {
233 defer server.Close()
234 }
235 got, gotIsTemp, err := resolveAndDownloadDockerfile(fakeFs, uri)
236 if (err != nil) != tt.wantErr {
237 t.Errorf("%s:\n Expected error %v,\n got %v", tt.name, tt.wantErr, err)
238 }
239 if gotIsTemp != tt.wantIsTemp {
240 t.Errorf("%s:\n For 'isTemp', expected %v,\n got %v", tt.name, tt.wantIsTemp, gotIsTemp)
241 }
242 if gotIsTemp {
243 defer func(fs filesystem.Filesystem, name string) {
244 _ = fs.Remove(name)
245 }(fakeFs, got)
246
247 if strings.TrimSpace(got) == "" {
248 t.Errorf("%s:\n Expected non-blank path,\n got blank path: %s", tt.name, got)
249 }
250 } else if got != tt.want {
251 t.Errorf("%s:\n Expected %v,\n got %v", tt.name, tt.want, got)
252 }
253 })
254 }
255 }
256
View as plain text