Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .bingo/Variables.mk
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ $(CONTROLLER_GEN): $(BINGO_DIR)/controller-gen.mod
@echo "(re)installing $(GOBIN)/controller-gen-v0.20.1"
@cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=controller-gen.mod -o=$(GOBIN)/controller-gen-v0.20.1 "sigs.k8s.io/controller-tools/cmd/controller-gen"

CRD_DIFF := $(GOBIN)/crd-diff-v0.5.0
CRD_DIFF := $(GOBIN)/crd-diff-v0.5.1-0.20260309184313-54162f2e3097
$(CRD_DIFF): $(BINGO_DIR)/crd-diff.mod
@# Install binary/ries using Go 1.14+ build command. This is using bwplotka/bingo-controlled, separate go module with pinned dependencies.
@echo "(re)installing $(GOBIN)/crd-diff-v0.5.0"
@cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=crd-diff.mod -o=$(GOBIN)/crd-diff-v0.5.0 "sigs.k8s.io/crdify"
@echo "(re)installing $(GOBIN)/crd-diff-v0.5.1-0.20260309184313-54162f2e3097"
@cd $(BINGO_DIR) && GOWORK=off $(GO) build -mod=mod -modfile=crd-diff.mod -o=$(GOBIN)/crd-diff-v0.5.1-0.20260309184313-54162f2e3097 "sigs.k8s.io/crdify"

CRD_REF_DOCS := $(GOBIN)/crd-ref-docs-v0.3.0
$(CRD_REF_DOCS): $(BINGO_DIR)/crd-ref-docs.mod
Expand Down
2 changes: 1 addition & 1 deletion .bingo/crd-diff.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ module _ // Auto generated by https://github.com/bwplotka/bingo. DO NOT EDIT

go 1.24.6

require sigs.k8s.io/crdify v0.5.0
require sigs.k8s.io/crdify v0.5.1-0.20260309184313-54162f2e3097
2 changes: 2 additions & 0 deletions .bingo/crd-diff.sum
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,8 @@ sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQ
sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU=
sigs.k8s.io/crdify v0.5.0 h1:mrMH9CgXQPTZUpTU6Klqfnlys8bggv/7uvLT2lXSP7A=
sigs.k8s.io/crdify v0.5.0/go.mod h1:ZIFxaYNgKYmFtZCLPysncXQ8oqwnNlHQbRUfxJHZwzU=
sigs.k8s.io/crdify v0.5.1-0.20260309184313-54162f2e3097 h1:gwDRFCc64lhEpxY944IJFW+CrmMFXWH+JjpE0JHp42Y=
sigs.k8s.io/crdify v0.5.1-0.20260309184313-54162f2e3097/go.mod h1:ZIFxaYNgKYmFtZCLPysncXQ8oqwnNlHQbRUfxJHZwzU=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo=
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4=
Expand Down
2 changes: 1 addition & 1 deletion .bingo/variables.env
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ CONFTEST="${GOBIN}/conftest-v0.62.0"

CONTROLLER_GEN="${GOBIN}/controller-gen-v0.20.1"

CRD_DIFF="${GOBIN}/crd-diff-v0.5.0"
CRD_DIFF="${GOBIN}/crd-diff-v0.5.1-0.20260309184313-54162f2e3097"

CRD_REF_DOCS="${GOBIN}/crd-ref-docs-v0.3.0"

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ require (
pkg.package-operator.run/boxcutter v0.12.0
sigs.k8s.io/controller-runtime v0.23.3
sigs.k8s.io/controller-tools v0.20.1
sigs.k8s.io/crdify v0.5.0
sigs.k8s.io/crdify v0.5.1-0.20260309184313-54162f2e3097
sigs.k8s.io/structured-merge-diff/v6 v6.3.2
sigs.k8s.io/yaml v1.6.0
)
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -804,8 +804,8 @@ sigs.k8s.io/controller-runtime v0.23.3 h1:VjB/vhoPoA9l1kEKZHBMnQF33tdCLQKJtydy4i
sigs.k8s.io/controller-runtime v0.23.3/go.mod h1:B6COOxKptp+YaUT5q4l6LqUJTRpizbgf9KSRNdQGns0=
sigs.k8s.io/controller-tools v0.20.1 h1:gkfMt9YodI0K85oT8rVi80NTXO/kDmabKR5Ajn5GYxs=
sigs.k8s.io/controller-tools v0.20.1/go.mod h1:b4qPmjGU3iZwqn34alUU5tILhNa9+VXK+J3QV0fT/uU=
sigs.k8s.io/crdify v0.5.0 h1:mrMH9CgXQPTZUpTU6Klqfnlys8bggv/7uvLT2lXSP7A=
sigs.k8s.io/crdify v0.5.0/go.mod h1:ZIFxaYNgKYmFtZCLPysncXQ8oqwnNlHQbRUfxJHZwzU=
sigs.k8s.io/crdify v0.5.1-0.20260309184313-54162f2e3097 h1:gwDRFCc64lhEpxY944IJFW+CrmMFXWH+JjpE0JHp42Y=
sigs.k8s.io/crdify v0.5.1-0.20260309184313-54162f2e3097/go.mod h1:ZIFxaYNgKYmFtZCLPysncXQ8oqwnNlHQbRUfxJHZwzU=
sigs.k8s.io/gateway-api v1.5.0 h1:duoo14Ky/fJXpjpmyMISE2RTBGnfCg8zICfTYLTnBJA=
sigs.k8s.io/gateway-api v1.5.0/go.mod h1:GvCETiaMAlLym5CovLxGjS0NysqFk3+Yuq3/rh6QL2o=
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 h1:IpInykpT6ceI+QxKBbEflcR5EXP7sU1kvOlxwZh5txg=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,15 +160,15 @@ func sameVersionErrors(results *runner.Results) []error {
}

errs := []error{}
for version, propertyResults := range results.SameVersionValidation {
for property, comparisonResults := range propertyResults {
for _, result := range comparisonResults {
for _, versionResult := range results.SameVersionValidation {
for _, propertyResult := range versionResult.PropertyComparisons {
for _, result := range propertyResult.ComparisonResults {
for _, err := range result.Errors {
msg := err
if result.Name == "unhandled" {
msg = conciseUnhandledMessage(err)
}
errs = append(errs, fmt.Errorf("%s: %s: %s: %s", version, property, result.Name, msg))
errs = append(errs, fmt.Errorf("%s: %s: %s: %s", versionResult.Version, propertyResult.Property, result.Name, msg))
}
}
}
Expand All @@ -183,15 +183,15 @@ func servedVersionErrors(results *runner.Results) []error {
}

errs := []error{}
for version, propertyResults := range results.ServedVersionValidation {
for property, comparisonResults := range propertyResults {
for _, result := range comparisonResults {
for _, versionResult := range results.ServedVersionValidation {
for _, propertyResult := range versionResult.PropertyComparisons {
for _, result := range propertyResult.ComparisonResults {
for _, err := range result.Errors {
msg := err
if result.Name == "unhandled" {
msg = conciseUnhandledMessage(err)
}
errs = append(errs, fmt.Errorf("%s: %s: %s: %s", version, property, result.Name, msg))
errs = append(errs, fmt.Errorf("%s: %s: %s: %s", versionResult.Version, propertyResult.Property, result.Name, msg))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,14 @@ func TestInstall(t *testing.T) {
Manifest: getManifestString(t, "crd-description-changed.json"),
},
},
{
name: "optional field addition should not fail",
oldCrdPath: "crd-optional-field-old.json",
release: &release.Release{
Name: "test-release",
Manifest: getManifestString(t, "crd-optional-field-new.json"),
},
},
}

for _, tc := range tests {
Expand Down Expand Up @@ -370,6 +378,35 @@ func TestUpgrade(t *testing.T) {
)
},
},
{
name: "optional field addition should not fail",
oldCrdPath: "crd-optional-field-old.json",
release: &release.Release{
Name: "test-release",
Manifest: getManifestString(t, "crd-optional-field-new.json"),
},
},
{
name: "complex breaking changes should fail",
oldCrdPath: "crd-complex-breaking-changes-old.json",
release: &release.Release{
Name: "test-release",
Manifest: getManifestString(t, "crd-complex-breaking-changes-new.json"),
},
// This test verifies detection of multiple breaking changes in a single CRD upgrade:
// 1. Type changed from "object" to "" - Properly detected by type validator
// 2. Nullable changed from false to true - Properly detected by nullable validator
// 3. OneOf constraint added - Reported as "unhandled" (needs crdify support)
// See: https://github.com/kubernetes-sigs/crdify/issues/25
// The upgrade is correctly blocked, but OneOf changes need better categorization.
requireErr: wantErrorMsgs([]string{
`validating upgrade for CRD "services.networking.example.com"`,
`type: type changed`,
`nullable: nullable added`,
`unhandled: unhandled changes found`,
`OneOf`,
}),
},
}

for _, tc := range tests {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
{
"apiVersion": "apiextensions.k8s.io/v1",
"kind": "CustomResourceDefinition",
"metadata": {
"name": "services.networking.example.com"
},
"spec": {
"group": "networking.example.com",
"versions": [
{
"name": "v1beta1",
"served": true,
"storage": true,
"schema": {
"openAPIV3Schema": {
"type": "object",
"properties": {
"spec": {
"type": "object",
"properties": {
"ingress": {
"type": "object",
"properties": {
"gateway": {
"type": "object",
"properties": {
"servers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"hosts": {
"description": "One or more hosts exposed by this gateway",
"type": "array",
"items": {
"type": "string"
}
},
"port": {
"type": "object",
"properties": {
"name": {
"description": "Label assigned to the port",
"type": "string"
},
"number": {
"description": "Port number",
"type": "integer"
}
}
},
"tls": {
"nullable": true,
"oneOf": [
{
"required": ["mode", "credentialName"]
},
{
"required": ["httpsRedirect"]
}
],
"properties": {
"credentialName": {
"description": "TLS certificate name",
"type": "string"
},
"httpsRedirect": {
"description": "If set to true, the load balancer will send a 301 redirect to HTTPS",
"type": "boolean"
},
"mode": {
"description": "TLS mode",
"type": "string"
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
],
"scope": "Namespaced",
"names": {
"plural": "services",
"singular": "service",
"kind": "Service",
"shortNames": [
"svc"
]
}
},
"status": {
"storedVersions": [
"v1beta1"
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
{
"apiVersion": "apiextensions.k8s.io/v1",
"kind": "CustomResourceDefinition",
"metadata": {
"name": "services.networking.example.com"
},
"spec": {
"group": "networking.example.com",
"versions": [
{
"name": "v1beta1",
"served": true,
"storage": true,
"schema": {
"openAPIV3Schema": {
"type": "object",
"properties": {
"spec": {
"type": "object",
"properties": {
"ingress": {
"type": "object",
"properties": {
"gateway": {
"type": "object",
"properties": {
"servers": {
"type": "array",
"items": {
"type": "object",
"properties": {
"hosts": {
"description": "One or more hosts exposed by this gateway",
"type": "array",
"items": {
"type": "string"
}
},
"port": {
"type": "object",
"properties": {
"name": {
"description": "Label assigned to the port",
"type": "string"
},
"number": {
"description": "Port number",
"type": "integer"
}
}
},
"tls": {
"type": "object",
"nullable": false,
"properties": {
"credentialName": {
"description": "TLS certificate name",
"type": "string"
},
"mode": {
"description": "TLS mode",
"type": "string"
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
],
"scope": "Namespaced",
"names": {
"plural": "services",
"singular": "service",
"kind": "Service",
"shortNames": [
"svc"
]
}
},
"status": {
"storedVersions": [
"v1beta1"
]
}
}
Loading
Loading