github.com/rish1988/moby@v25.0.2+incompatible/client/image_build_test.go (about) 1 package client // import "github.com/docker/docker/client" 2 3 import ( 4 "bytes" 5 "context" 6 "fmt" 7 "io" 8 "net/http" 9 "reflect" 10 "strings" 11 "testing" 12 13 "github.com/docker/docker/api/types" 14 "github.com/docker/docker/api/types/container" 15 "github.com/docker/docker/api/types/registry" 16 "github.com/docker/docker/errdefs" 17 units "github.com/docker/go-units" 18 "gotest.tools/v3/assert" 19 is "gotest.tools/v3/assert/cmp" 20 ) 21 22 func TestImageBuildError(t *testing.T) { 23 client := &Client{ 24 client: newMockClient(errorMock(http.StatusInternalServerError, "Server error")), 25 } 26 _, err := client.ImageBuild(context.Background(), nil, types.ImageBuildOptions{}) 27 assert.Check(t, is.ErrorType(err, errdefs.IsSystem)) 28 } 29 30 func TestImageBuild(t *testing.T) { 31 v1 := "value1" 32 v2 := "value2" 33 emptyRegistryConfig := "bnVsbA==" 34 buildCases := []struct { 35 buildOptions types.ImageBuildOptions 36 expectedQueryParams map[string]string 37 expectedTags []string 38 expectedRegistryConfig string 39 }{ 40 { 41 buildOptions: types.ImageBuildOptions{ 42 SuppressOutput: true, 43 NoCache: true, 44 Remove: true, 45 ForceRemove: true, 46 PullParent: true, 47 }, 48 expectedQueryParams: map[string]string{ 49 "q": "1", 50 "nocache": "1", 51 "rm": "1", 52 "forcerm": "1", 53 "pull": "1", 54 }, 55 expectedTags: []string{}, 56 expectedRegistryConfig: emptyRegistryConfig, 57 }, 58 { 59 buildOptions: types.ImageBuildOptions{ 60 SuppressOutput: false, 61 NoCache: false, 62 Remove: false, 63 ForceRemove: false, 64 PullParent: false, 65 }, 66 expectedQueryParams: map[string]string{ 67 "q": "", 68 "nocache": "", 69 "rm": "0", 70 "forcerm": "", 71 "pull": "", 72 }, 73 expectedTags: []string{}, 74 expectedRegistryConfig: emptyRegistryConfig, 75 }, 76 { 77 buildOptions: types.ImageBuildOptions{ 78 RemoteContext: "remoteContext", 79 Isolation: container.Isolation("isolation"), 80 CPUSetCPUs: "2", 81 CPUSetMems: "12", 82 CPUShares: 20, 83 CPUQuota: 10, 84 CPUPeriod: 30, 85 Memory: 256, 86 MemorySwap: 512, 87 ShmSize: 10, 88 CgroupParent: "cgroup_parent", 89 Dockerfile: "Dockerfile", 90 }, 91 expectedQueryParams: map[string]string{ 92 "remote": "remoteContext", 93 "isolation": "isolation", 94 "cpusetcpus": "2", 95 "cpusetmems": "12", 96 "cpushares": "20", 97 "cpuquota": "10", 98 "cpuperiod": "30", 99 "memory": "256", 100 "memswap": "512", 101 "shmsize": "10", 102 "cgroupparent": "cgroup_parent", 103 "dockerfile": "Dockerfile", 104 "rm": "0", 105 }, 106 expectedTags: []string{}, 107 expectedRegistryConfig: emptyRegistryConfig, 108 }, 109 { 110 buildOptions: types.ImageBuildOptions{ 111 BuildArgs: map[string]*string{ 112 "ARG1": &v1, 113 "ARG2": &v2, 114 "ARG3": nil, 115 }, 116 }, 117 expectedQueryParams: map[string]string{ 118 "buildargs": `{"ARG1":"value1","ARG2":"value2","ARG3":null}`, 119 "rm": "0", 120 }, 121 expectedTags: []string{}, 122 expectedRegistryConfig: emptyRegistryConfig, 123 }, 124 { 125 buildOptions: types.ImageBuildOptions{ 126 Ulimits: []*units.Ulimit{ 127 { 128 Name: "nproc", 129 Hard: 65557, 130 Soft: 65557, 131 }, 132 { 133 Name: "nofile", 134 Hard: 20000, 135 Soft: 40000, 136 }, 137 }, 138 }, 139 expectedQueryParams: map[string]string{ 140 "ulimits": `[{"Name":"nproc","Hard":65557,"Soft":65557},{"Name":"nofile","Hard":20000,"Soft":40000}]`, 141 "rm": "0", 142 }, 143 expectedTags: []string{}, 144 expectedRegistryConfig: emptyRegistryConfig, 145 }, 146 { 147 buildOptions: types.ImageBuildOptions{ 148 AuthConfigs: map[string]registry.AuthConfig{ 149 "https://index.docker.io/v1/": { 150 Auth: "dG90bwo=", 151 }, 152 }, 153 }, 154 expectedQueryParams: map[string]string{ 155 "rm": "0", 156 }, 157 expectedTags: []string{}, 158 expectedRegistryConfig: "eyJodHRwczovL2luZGV4LmRvY2tlci5pby92MS8iOnsiYXV0aCI6ImRHOTBid289In19", 159 }, 160 } 161 for _, buildCase := range buildCases { 162 expectedURL := "/build" 163 client := &Client{ 164 client: newMockClient(func(r *http.Request) (*http.Response, error) { 165 if !strings.HasPrefix(r.URL.Path, expectedURL) { 166 return nil, fmt.Errorf("Expected URL '%s', got '%s'", expectedURL, r.URL) 167 } 168 // Check request headers 169 registryConfig := r.Header.Get("X-Registry-Config") 170 if registryConfig != buildCase.expectedRegistryConfig { 171 return nil, fmt.Errorf("X-Registry-Config header not properly set in the request. Expected '%s', got %s", buildCase.expectedRegistryConfig, registryConfig) 172 } 173 contentType := r.Header.Get("Content-Type") 174 if contentType != "application/x-tar" { 175 return nil, fmt.Errorf("Content-type header not properly set in the request. Expected 'application/x-tar', got %s", contentType) 176 } 177 178 // Check query parameters 179 query := r.URL.Query() 180 for key, expected := range buildCase.expectedQueryParams { 181 actual := query.Get(key) 182 if actual != expected { 183 return nil, fmt.Errorf("%s not set in URL query properly. Expected '%s', got %s", key, expected, actual) 184 } 185 } 186 187 // Check tags 188 if len(buildCase.expectedTags) > 0 { 189 tags := query["t"] 190 if !reflect.DeepEqual(tags, buildCase.expectedTags) { 191 return nil, fmt.Errorf("t (tags) not set in URL query properly. Expected '%s', got %s", buildCase.expectedTags, tags) 192 } 193 } 194 195 headers := http.Header{} 196 headers.Add("Server", "Docker/v1.23 (MyOS)") 197 return &http.Response{ 198 StatusCode: http.StatusOK, 199 Body: io.NopCloser(bytes.NewReader([]byte("body"))), 200 Header: headers, 201 }, nil 202 }), 203 } 204 buildResponse, err := client.ImageBuild(context.Background(), nil, buildCase.buildOptions) 205 if err != nil { 206 t.Fatal(err) 207 } 208 if buildResponse.OSType != "MyOS" { 209 t.Fatalf("expected OSType to be 'MyOS', got %s", buildResponse.OSType) 210 } 211 response, err := io.ReadAll(buildResponse.Body) 212 if err != nil { 213 t.Fatal(err) 214 } 215 buildResponse.Body.Close() 216 if string(response) != "body" { 217 t.Fatalf("expected Body to contain 'body' string, got %s", response) 218 } 219 } 220 } 221 222 func TestGetDockerOS(t *testing.T) { 223 cases := map[string]string{ 224 "Docker/v1.22 (linux)": "linux", 225 "Docker/v1.22 (windows)": "windows", 226 "Foo/v1.22 (bar)": "", 227 } 228 for header, os := range cases { 229 g := getDockerOS(header) 230 if g != os { 231 t.Fatalf("Expected %s, got %s", os, g) 232 } 233 } 234 }