Skip to content

Commit 2034640

Browse files
committed
Simplify validations of baremetal OS URLs
Using the validation framework to do this is unreadable, and results in incorrect field names in error messages. Validate the fields directly instead.
1 parent 4dc3c02 commit 2034640

File tree

3 files changed

+25
-40
lines changed

3 files changed

+25
-40
lines changed

pkg/types/baremetal/platform.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,14 +213,14 @@ type Platform struct {
213213
// e.g https://mirror.example.com/images/qemu.qcow2.gz?sha256=a07bd...
214214
//
215215
// +optional
216-
BootstrapOSImage string `json:"bootstrapOSImage,omitempty" validate:"omitempty,osimageuri,urlexist"`
216+
BootstrapOSImage string `json:"bootstrapOSImage,omitempty"`
217217

218218
// ClusterOSImage is a URL to override the default OS image
219219
// for cluster nodes. The URL must contain a sha256 hash of the image
220220
// e.g https://mirror.example.com/images/metal.qcow2.gz?sha256=3b5a8...
221221
//
222222
// +optional
223-
ClusterOSImage string `json:"clusterOSImage,omitempty" validate:"omitempty,osimageuri,urlexist"`
223+
ClusterOSImage string `json:"clusterOSImage,omitempty"`
224224

225225
// BootstrapExternalStaticIP is the static IP address of the bootstrap node.
226226
// This can be useful in environments without a DHCP server.

pkg/types/baremetal/validation/platform.go

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"net"
77
"net/http"
88
"net/url"
9-
"reflect"
109
"strings"
1110

1211
"github.com/apparentlymart/go-cidr/cidr"
@@ -202,40 +201,26 @@ func validateHostsBMCOnly(hosts []*baremetal.Host, fldPath *field.Path) field.Er
202201
}
203202

204203
func validateOSImages(p *baremetal.Platform, fldPath *field.Path) field.ErrorList {
205-
platformErrs := field.ErrorList{}
204+
var errs field.ErrorList
206205

207-
validate := validator.New()
206+
fields := map[string]string{
207+
"bootstrapOSImage": p.BootstrapOSImage,
208+
"clusterOSImage": p.ClusterOSImage,
209+
}
208210

209-
customErrs := make(map[string]error)
210-
validate.RegisterValidation("osimageuri", func(fl validator.FieldLevel) bool {
211-
err := validateOSImageURI(fl.Field().String())
212-
if err != nil {
213-
customErrs[fl.FieldName()] = err
211+
for fieldName, url := range fields {
212+
if url == "" {
213+
continue
214214
}
215-
return err == nil
216-
})
217-
validate.RegisterValidation("urlexist", func(fl validator.FieldLevel) bool {
218-
if res, err := http.Head(fl.Field().String()); err == nil {
219-
return res.StatusCode == http.StatusOK
220-
}
221-
return false
222-
})
223-
err := validate.Struct(p)
224-
225-
if err != nil {
226-
baseType := reflect.TypeOf(p).Elem().Name()
227-
for _, err := range err.(validator.ValidationErrors) {
228-
childName := fldPath.Child(err.Namespace()[len(baseType)+1:])
229-
switch err.Tag() {
230-
case "osimageuri":
231-
platformErrs = append(platformErrs, field.Invalid(childName, err.Value(), customErrs[err.Field()].Error()))
232-
case "urlexist":
233-
platformErrs = append(platformErrs, field.NotFound(childName, err.Value()))
234-
}
215+
if err := validateOSImageURI(url); err != nil {
216+
errs = append(errs,
217+
field.Invalid(fldPath.Child(fieldName), url, err.Error()))
218+
} else if res, err := http.Head(url); err != nil || res.StatusCode != http.StatusOK /* #nosec G107 */ {
219+
errs = append(errs,
220+
field.NotFound(fldPath.Child(fieldName), url))
235221
}
236222
}
237-
238-
return platformErrs
223+
return errs
239224
}
240225

241226
func validateHostsName(hosts []*baremetal.Host, fldPath *field.Path) (errors field.ErrorList) {

pkg/types/baremetal/validation/platform_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -487,49 +487,49 @@ func TestValidateProvisioning(t *testing.T) {
487487
name: "invalid_bootstraposimage",
488488
platform: platform().
489489
BootstrapOSImage("192.168.111.1/images/qemu.x86_64.qcow2.gz?sha256=3b5a882c2af3e19d515b961855d144f293cab30190c2bdedd661af31a1fc4e2f").build(),
490-
expected: "baremetal.BootstrapOSImage: Invalid value:.*: the URI provided:.*is invalid",
490+
expected: "baremetal.bootstrapOSImage: Invalid value:.*: the URI provided:.*is invalid",
491491
},
492492
{
493493
name: "invalid_clusterosimage",
494494
platform: platform().
495495
ClusterOSImage("http//192.168.111.1/images/metal.x86_64.qcow2.gz?sha256=340dfa4d92450f2eee852ed1e2d02e3138cc68d824827ef9cf0a40a7ea2f93da").build(),
496-
expected: "baremetal.ClusterOSImage: Invalid value:.*: the URI provided:.*is invalid",
496+
expected: "baremetal.clusterOSImage: Invalid value:.*: the URI provided:.*is invalid",
497497
},
498498
{
499499
name: "invalid_bootstraposimage_checksum",
500500
platform: platform().
501501
BootstrapOSImage("http://192.168.111.1/images/qemu.x86_64.qcow2.gz?md5sum=3b5a882c2af3e19d515b961855d144f293cab30190c2bdedd661af31a1fc4e2f").build(),
502-
expected: "baremetal.BootstrapOSImage: Invalid value:.*: the sha256 parameter in the.*URI is missing",
502+
expected: "baremetal.bootstrapOSImage: Invalid value:.*: the sha256 parameter in the.*URI is missing",
503503
},
504504
{
505505
name: "invalid_clusterosimage_checksum",
506506
platform: platform().
507507
ClusterOSImage("http://192.168.111.1/images/metal.x86_64.qcow2.gz?sha256=3ee852ed1e2d02e3138cc68d824827ef9cf0a40a7ea2f93da").build(),
508-
expected: "baremetal.ClusterOSImage: Invalid value:.*: the sha256 parameter in the.*URI is invalid",
508+
expected: "baremetal.clusterOSImage: Invalid value:.*: the sha256 parameter in the.*URI is invalid",
509509
},
510510
{
511511
name: "invalid_bootstraposimage_uri_scheme",
512512
platform: platform().
513513
BootstrapOSImage("xttp://192.168.111.1/images/qemu.x86_64.qcow2.gz?sha256=3b5a882c2af3e19d515b961855d144f293cab30190c2bdedd661af31a1fc4e2f").build(),
514-
expected: "baremetal.BootstrapOSImage: Invalid value:.*: the URI provided.*must begin with http/https",
514+
expected: "baremetal.bootstrapOSImage: Invalid value:.*: the URI provided.*must begin with http/https",
515515
},
516516
{
517517
name: "invalid_clusterosimage_uri_scheme",
518518
platform: platform().
519519
ClusterOSImage("xttp://192.168.111.1/images/qemu.x86_64.qcow2.gz?sha256=3b5a882c2af3e19d515b961855d144f293cab30190c2bdedd661af31a1fc4e2f").build(),
520-
expected: "baremetal.ClusterOSImage: Invalid value:.*: the URI provided.*must begin with http/https",
520+
expected: "baremetal.clusterOSImage: Invalid value:.*: the URI provided.*must begin with http/https",
521521
},
522522
{
523523
name: "notfound_bootstraposimage",
524524
platform: platform().
525525
BootstrapOSImage(imagesServer.URL + "/images/notexistent.x86_64.qcow2.gz?sha256=3b5a882c2af3e19d515b961855d144f293cab30190c2bdedd661af31a1fc4e2f").build(),
526-
expected: "baremetal.BootstrapOSImage: Not found:.*",
526+
expected: "baremetal.bootstrapOSImage: Not found:.*",
527527
},
528528
{
529529
name: "notfound_clusterosimageimage",
530530
platform: platform().
531531
ClusterOSImage(imagesServer.URL + "/images/notexistent.x86_64.qcow2.gz?sha256=3b5a882c2af3e19d515b961855d144f293cab30190c2bdedd661af31a1fc4e2f").build(),
532-
expected: "baremetal.ClusterOSImage: Not found:.*",
532+
expected: "baremetal.clusterOSImage: Not found:.*",
533533
},
534534
{
535535
name: "invalid_extbridge",

0 commit comments

Comments
 (0)