Skip to content

Commit

Permalink
crd: add hosts max length
Browse files Browse the repository at this point in the history
controller-gen does not support validating internal list items on list types,
see kubernetes-sigs/controller-tools#342

To add host pattern we used perl hack that is hard to extend to multiple
validations.

Also #16 added optional tls spec that contains hosts field for which
perl hack worked by accident, see #16 (comment)

This change replaces perl hack for a go hack and adds max length constraint.

Signed-off-by: Alexander Yastrebov <alexander.yastrebov@zalando.de>
  • Loading branch information
AlexanderYastrebov committed Mar 26, 2024
1 parent d0c44d0 commit d4ea708
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 6 deletions.
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ $(GENERATED): $(CRD_TYPE_SOURCE)

$(GENERATED_CRD): go.mod $(GENERATED)
go run sigs.k8s.io/controller-tools/cmd/controller-gen@v0.14.0 crd:crdVersions=v1 paths=./apis/... output:crd:dir=.
# workaround to add pattern to array items. Not supported by controller-gen
# workaround to add validation to array items. Not supported by controller-gen
# ref: https://github.com/kubernetes-sigs/controller-tools/issues/342
perl -i -p0e 's|(\s*)(hosts:.*?items:)|$$1$$2$$1 pattern: "^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*\$$"|sg' $(GENERATED_CRD)
go run hack/crd/add_hosts_validation.go $(GENERATED_CRD)

build.local: $(LOCAL_BINARIES) $(GENERATED_CRD)
build.linux: $(LINUX_BINARIES) $(GENERATED_CRD)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ require (
k8s.io/apimachinery v0.25.16
k8s.io/client-go v0.25.16
k8s.io/code-generator v0.25.16
sigs.k8s.io/yaml v1.3.0 // indirect
sigs.k8s.io/yaml v1.3.0
)
93 changes: 93 additions & 0 deletions hack/crd/add_hosts_validation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// This program adds host validation to CRD yaml.
//
// # Why
//
// controller-gen does not support validating internal list items on list types,
// see https://github.com/kubernetes-sigs/controller-tools/issues/342
package main

import (
"log"
"os"

"sigs.k8s.io/yaml"
)

const (
hostPattern = `^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$`
hostMaxLength = 255 // https://datatracker.ietf.org/doc/html/rfc1035#section-2.3.4
)

func must(err error) {
if err != nil {
log.Fatal(err)
}
}

func mustGet(v []byte, err error) []byte {
must(err)
return v
}

type setter struct {
o interface{}
}

func (s *setter) field(name string) *setter {
return &setter{s.o.(map[string]interface{})[name]}
}

func (s *setter) item(i int) *setter {
return &setter{s.o.([]interface{})[i]}
}

func (s *setter) setField(name string, value interface{}) *setter {
s.o.(map[string]interface{})[name] = value
return s
}

func main() {
if len(os.Args) != 2 {
log.Fatalf("CRD filename required")
}
crdFilename := os.Args[1]

yamlBytes := mustGet(os.ReadFile(crdFilename))

o := make(map[string]interface{})
must(yaml.Unmarshal(yamlBytes, &o))

s := &setter{o}

s.field("spec").
field("versions").
item(0).
field("schema").
field("openAPIV3Schema").
field("properties").
field("spec").
field("properties").
field("hosts").
field("items").
setField("pattern", hostPattern).
setField("maxLength", hostMaxLength)

s.field("spec").
field("versions").
item(0).
field("schema").
field("openAPIV3Schema").
field("properties").
field("spec").
field("properties").
field("tls").
field("items").
field("properties").
field("hosts").
field("items").
setField("pattern", hostPattern).
setField("maxLength", hostMaxLength)

outYaml := mustGet(yaml.Marshal(o))
must(os.WriteFile(crdFilename, outYaml, 0664))
}
7 changes: 4 additions & 3 deletions zalando.org_routegroups.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
Expand Down Expand Up @@ -132,7 +131,8 @@ spec:
hosts:
description: List of hostnames for the RouteGroup
items:
pattern: "^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"
maxLength: 255
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
type: string
minItems: 1
type: array
Expand Down Expand Up @@ -216,7 +216,8 @@ spec:
The values in this list must match the host name(s) used for
the RouteGroup in order to terminate TLS for the host(s).
items:
pattern: "^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$"
maxLength: 255
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?([.][a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
type: string
minItems: 1
type: array
Expand Down

0 comments on commit d4ea708

Please sign in to comment.