|
5 | 5 | "fmt" |
6 | 6 | "log/slog" |
7 | 7 | "net/http" |
| 8 | + "net/url" |
8 | 9 | "strconv" |
9 | | - "strings" |
10 | 10 | "time" |
11 | 11 |
|
12 | 12 | "github.com/metal-stack/metal-api/cmd/metal-api/internal/datastore" |
@@ -321,7 +321,7 @@ func (r *imageResource) createImage(request *restful.Request, response *restful. |
321 | 321 | } |
322 | 322 | } |
323 | 323 |
|
324 | | - err = checkImageURL(requestPayload.ID, requestPayload.URL, "", "") |
| 324 | + err = checkImageURL(requestPayload.ID, requestPayload.URL, nil) |
325 | 325 | if err != nil { |
326 | 326 | r.sendError(request, response, httperrors.BadRequest(err)) |
327 | 327 | return |
@@ -350,33 +350,37 @@ func (r *imageResource) createImage(request *restful.Request, response *restful. |
350 | 350 | r.send(request, response, http.StatusCreated, v1.NewImageResponse(img)) |
351 | 351 | } |
352 | 352 |
|
353 | | -func checkImageURL(id, url, username, password string) error { |
354 | | - if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") { |
355 | | - res, err := http.Head(url) |
| 353 | +func checkImageURL(id, inputURL string, ociCredentials authn.Authenticator) error { |
| 354 | + parsedURL, err := url.Parse(inputURL) |
| 355 | + if err != nil { |
| 356 | + return fmt.Errorf("image:%s with url:%s could not be parsed. error:%w", id, inputURL, err) |
| 357 | + } |
| 358 | + |
| 359 | + switch parsedURL.Scheme { |
| 360 | + case "http", "https": |
| 361 | + res, err := http.Head(inputURL) |
356 | 362 | if err != nil { |
357 | | - return fmt.Errorf("image:%s is not accessible under:%s error:%w", id, url, err) |
| 363 | + return fmt.Errorf("image:%s is not accessible under:%s error:%w", id, inputURL, err) |
358 | 364 | } |
359 | 365 | if res.StatusCode >= 400 { |
360 | | - return fmt.Errorf("image:%s is not accessible under:%s status:%s", id, url, res.Status) |
| 366 | + return fmt.Errorf("image:%s is not accessible under:%s status:%s", id, inputURL, res.Status) |
361 | 367 | } |
362 | | - } else { |
363 | | - ref, err := name.ParseReference(url) |
| 368 | + case "oci": |
| 369 | + ref, err := name.ParseReference(inputURL) |
364 | 370 | if err != nil { |
365 | | - return fmt.Errorf("image reference:%s could not be parsed. error:%w", url, err) |
| 371 | + return fmt.Errorf("image reference:%s could not be parsed. error:%w", inputURL, err) |
366 | 372 | } |
367 | 373 |
|
368 | | - var auth = authn.Anonymous |
369 | | - if username != "" || password != "" { |
370 | | - auth = &authn.Basic{ |
371 | | - Username: username, |
372 | | - Password: password, |
373 | | - } |
| 374 | + if ociCredentials == nil { |
| 375 | + ociCredentials = authn.Anonymous |
374 | 376 | } |
375 | 377 |
|
376 | | - _, err = remote.Head(ref, remote.WithAuth(auth)) |
| 378 | + _, err = remote.Head(ref, remote.WithAuth(ociCredentials)) |
377 | 379 | if err != nil { |
378 | | - return fmt.Errorf("image:%s is not accessible under:%s error:%w", id, url, err) |
| 380 | + return fmt.Errorf("image:%s is not accessible under:%s error:%w", id, inputURL, err) |
379 | 381 | } |
| 382 | + default: |
| 383 | + return fmt.Errorf("image:%s with url:%s has unkown protocol. error:%w", id, inputURL, err) |
380 | 384 | } |
381 | 385 |
|
382 | 386 | return nil |
@@ -435,7 +439,7 @@ func (r *imageResource) updateImage(request *restful.Request, response *restful. |
435 | 439 | newImage.Description = *requestPayload.Description |
436 | 440 | } |
437 | 441 | if requestPayload.URL != nil { |
438 | | - err = checkImageURL(requestPayload.ID, *requestPayload.URL, "", "") |
| 442 | + err = checkImageURL(requestPayload.ID, *requestPayload.URL, nil) |
439 | 443 | if err != nil { |
440 | 444 | r.sendError(request, response, httperrors.BadRequest(err)) |
441 | 445 | return |
|
0 commit comments