From 161aa66a1688bf64df7d130d5dcf4a297f0d6a6d Mon Sep 17 00:00:00 2001 From: Chris Seto Date: Fri, 19 Apr 2024 14:38:53 -0400 Subject: [PATCH] redpanda: assert backwards compat guarantees This commit utilizes `valuesutil.Generate` to assert the backwards compatibility guarantees of the redpanda chart's values.schema.json across all minor versions start with the 5.6.x series. The guarantee is both documented and enforced by `TestSchemaBackwardCompat` test. --- Taskfile.yaml | 7 + charts/redpanda/chart_test.go | 197 +- charts/redpanda/schema.go | 20 + .../testdata/schemas/5.6.x.schema.json | 1557 ++++++++++++++ .../testdata/schemas/5.7.x.schema.json | 1799 +++++++++++++++++ charts/redpanda/values.go | 15 +- charts/redpanda/values.schema.json | 7 +- charts/redpanda/values_partial.gen.go | 10 +- flake.nix | 3 +- 9 files changed, 3600 insertions(+), 15 deletions(-) create mode 100644 charts/redpanda/schema.go create mode 100644 charts/redpanda/testdata/schemas/5.6.x.schema.json create mode 100644 charts/redpanda/testdata/schemas/5.7.x.schema.json diff --git a/Taskfile.yaml b/Taskfile.yaml index 83b50588e7..23e816645d 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -82,6 +82,13 @@ tasks: - nix run .#genschema > charts/redpanda/values.schema.json # Generate helm templates from Go definitions - nix run .#gotohelm -- -write ./charts/redpanda/templates ./charts/redpanda + # Copy the most recent values.schema.json of each minor version, starting + # with 5.6.x into testdata for backwards compat assertions. + # TODO should probably find a way to automate this as we'll need to add + # in a line for each minor version bump. + - | + git show $(git for-each-ref --sort=authordate --format '%(refname)' 'refs/tags/redpanda-5.7.*' | tail -n 1):charts/redpanda/values.schema.json > ./charts/redpanda/testdata/schemas/5.7.x.schema.json + git show $(git for-each-ref --sort=authordate --format '%(refname)' 'refs/tags/redpanda-5.6.*' | tail -n 1):charts/redpanda/values.schema.json > ./charts/redpanda/testdata/schemas/5.6.x.schema.json create-test-rack-awareness: cmds: diff --git a/charts/redpanda/chart_test.go b/charts/redpanda/chart_test.go index d01bf62ebb..5447080378 100644 --- a/charts/redpanda/chart_test.go +++ b/charts/redpanda/chart_test.go @@ -2,18 +2,31 @@ package redpanda_test import ( "bytes" + "context" + "encoding/json" + "fmt" + "maps" + "math/rand" "os" "os/exec" + "path" + "reflect" + "slices" "testing" + "testing/quick" + "time" + "github.com/invopop/jsonschema" "github.com/redpanda-data/helm-charts/charts/redpanda" "github.com/redpanda-data/helm-charts/pkg/helm" "github.com/redpanda-data/helm-charts/pkg/helm/helmtest" "github.com/redpanda-data/helm-charts/pkg/kube" "github.com/redpanda-data/helm-charts/pkg/testutil" + "github.com/redpanda-data/helm-charts/pkg/valuesutil" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" ) func TieredStorageStatic(t *testing.T) redpanda.PartialValues { @@ -91,6 +104,96 @@ func TieredStorageSecretRefs(t *testing.T, secret *corev1.Secret) redpanda.Parti } } +// TestSchemaBackwardCompat asserts that all values.schema.json are backwards +// compatible by one minor version **provided that no deprecated fields are +// specified**. +func TestSchemaBackwardCompat(t *testing.T) { + schemaFiles, err := os.ReadDir("testdata/schemas") + require.NoError(t, err) + + var schemas []*jsonschema.Schema + var names []string + + // TODO at somepoint we'll have to figure out how to sort these. + for _, schemaFile := range schemaFiles { + schemaBytes, err := os.ReadFile(path.Join("testdata/schemas", schemaFile.Name())) + require.NoError(t, err) + + var data map[string]any + require.NoError(t, json.Unmarshal(schemaBytes, &data)) + + schema, err := valuesutil.UnmarshalInto[*jsonschema.Schema](fixSchema(data)) + require.NoError(t, err) + + schemas = append(schemas, schema) + names = append(names, schemaFile.Name()[:len(schemaFile.Name())-len(".schema.json")]) + } + + // Inject the most recent chart schema as HEAD to check for any breaking + // changes across patch versions or new minor versions. + schemas = append(schemas, redpanda.JSONSchema()) + names = append(names, "HEAD") + + for i := 0; i < len(names)-1; i++ { + fromName := names[i] + toName := names[i+1] + fromSchema := schemas[i] + toSchema := schemas[i+1] + + t.Run(fmt.Sprintf("%s to %s", fromName, toName), func(t *testing.T) { + quick.Check(func(values map[string]any, schema *jsonschema.Schema) bool { + return valuesutil.Validate(schema, values) == nil + }, &quick.Config{ + Values: func(v []reflect.Value, r *rand.Rand) { + // Generate a valid value from the previous schema. + v[0] = reflect.ValueOf(valuesutil.Generate(r, fromSchema)) + // Validate it against the next schema. + v[1] = reflect.ValueOf(toSchema) + }, + }) + }) + } +} + +func TestTemplateProperties(t *testing.T) { + // - Setting statefulset.replicas > 1000 causes timeouts. + // - Not setting advertisedPorts causes out of index errors. + t.Skip("Currently finding too many failures") + + ctx := testutil.Context(t) + client, err := helm.New(helm.Options{ConfigHome: testutil.TempDir(t)}) + require.NoError(t, err) + + f := func(values *redpanda.PartialValues) error { + // Helm template can hang on some values. We don't want that to stall + // tests nor would we want customers to experience that. Cut it off + // with a deadline. + ctx, cancel := context.WithTimeout(ctx, 5*time.Second) + defer cancel() + + _, err := client.Template(ctx, ".", helm.TemplateOptions{ + Name: "redpanda", + Values: values, + Set: []string{ + "tests.enabled=false", + }, + }) + return err + } + + err = quick.Check(func(values *redpanda.PartialValues) bool { + return f(values) == nil + }, &quick.Config{ + Values: func(args []reflect.Value, rng *rand.Rand) { + values := valuesutil.Generate(rng, redpanda.JSONSchema()) + partial, _ := valuesutil.UnmarshalInto[redpanda.PartialValues](values) + FixPartialCerts(&partial) + args[0] = reflect.ValueOf(&partial) + }, + }) + require.NoError(t, err) +} + func TestTemplate(t *testing.T) { ctx := testutil.Context(t) client, err := helm.New(helm.Options{ConfigHome: testutil.TempDir(t)}) @@ -142,7 +245,7 @@ func TestTemplate(t *testing.T) { t.Logf("kube-linter error(s) found for %q: \n%s", v.Name(), errKubeLinter) } // TODO: remove comment below and the logging above once we agree to linter - //require.NoError(t, errKubeLinter) + // require.NoError(t, errKubeLinter) testutil.AssertGolden(t, testutil.YAML, "./testdata/"+v.Name()+".golden", out) }) @@ -195,3 +298,95 @@ func TestChart(t *testing.T) { require.Equal(t, "from-secret-access-key", config["cloud_storage_access_key"]) }) } + +// FixPartialCerts is a helper for tests utilizing valuesutil.Generate. There's +// no way to constraint values in a JSON schema to those that exist as keys of +// another object (our TLS certs). FixPartialCerts will traverse a +// [redpanda.PartialValues] and retroactively create certificates if they don't +// exist to ensure validity. +func FixPartialCerts(values *redpanda.PartialValues) { + if values.TLS == nil { + values.TLS = &redpanda.PartialTLS{Enabled: ptr.To(true)} + } + + if values.TLS.Certs == nil { + values.TLS.Certs = &redpanda.PartialTLSCertMap{} + } + + expectedCerts := []*redpanda.PartialExternalTLS{ + values.Listeners.Admin.TLS, + values.Listeners.Kafka.TLS, + values.Listeners.HTTP.TLS, + } + + for _, cert := range expectedCerts { + if cert == nil { + continue + } + + if _, ok := (*values.TLS.Certs)[*cert.Cert]; ok { + continue + } + + (*values.TLS.Certs)[*cert.Cert] = redpanda.PartialTLSCert{CAEnabled: ptr.To(false)} + } +} + +// fixSchema fixes minor issues with older hand written jsonschemas and expands +// arrays in "type" to oneOf's as our jsonschema library requires type to be a +// string. +// NB: Dynamic fixing was elected to ensure that it's easy to repopulate +// testdata/schema with raw git commands. +func fixSchema(schema map[string]any) map[string]any { + for _, propKey := range []string{"properties", "patternProperties", "additionalProperties"} { + if props, ok := schema[propKey].(map[string]any); ok { + for key, value := range props { + if asMap, ok := value.(map[string]any); ok { + props[key] = fixSchema(asMap) + } + } + } + } + + if items, ok := schema["items"].(map[string]any); ok { + schema["items"] = fixSchema(items) + } + + if typeArr, ok := schema["type"].([]any); ok { + var oneOf []map[string]any + for _, t := range typeArr { + clone := maps.Clone(schema) + clone["type"] = t + oneOf = append(oneOf, clone) + } + schema = map[string]any{"oneOf": oneOf} + } + + // Rename parameters to properties. + if props, ok := schema["parameters"]; ok { + schema["properties"] = props + delete(schema, "parameters") + } + + // Add missing object types. + _, hasType := schema["type"] + _, hasProps := schema["properties"] + if !hasType && hasProps { + schema["type"] = "object" + } + + // Remove any unspecified properties from required. + if required, ok := schema["required"].([]any); ok { + for i := 0; i < len(required); i++ { + key := required[i].(string) + _, hasProp := schema["properties"].(map[string]any)[key] + if !hasProp { + required = slices.Delete(required, i, i+1) + i-- + } + } + schema["required"] = required + } + + return schema +} diff --git a/charts/redpanda/schema.go b/charts/redpanda/schema.go new file mode 100644 index 0000000000..0c2b20e155 --- /dev/null +++ b/charts/redpanda/schema.go @@ -0,0 +1,20 @@ +// +gotohelm:ignore=true +package redpanda + +import ( + _ "embed" + "encoding/json" + + "github.com/invopop/jsonschema" +) + +//go:embed values.schema.json +var schemaBytes []byte + +func JSONSchema() *jsonschema.Schema { + var s jsonschema.Schema + if err := json.Unmarshal(schemaBytes, &s); err != nil { + panic(err) + } + return &s +} diff --git a/charts/redpanda/testdata/schemas/5.6.x.schema.json b/charts/redpanda/testdata/schemas/5.6.x.schema.json new file mode 100644 index 0000000000..2c1bf5d122 --- /dev/null +++ b/charts/redpanda/testdata/schemas/5.6.x.schema.json @@ -0,0 +1,1557 @@ +{ + "$schema": "http://json-schema.org/schema#", + "type": "object", + "required": [ + "image" + ], + "properties": { + "nameOverride": { + "type": "string" + }, + "fullnameOverride": { + "type": "string" + }, + "clusterDomain": { + "type": "string" + }, + "commonLabels": { + "type": "object" + }, + "nodeSelector": { + "type": "object" + }, + "affinity": { + "type": "object", + "properties": { + "nodeAffinity": { + "type": "object" + }, + "podAffinity": { + "type": "object" + }, + "podAntiAffinity": { + "type": "object" + } + } + }, + "tolerations": { + "type": "array" + }, + "image": { + "description": "Values used to define the container image to be used for Redpanda", + "type": "object", + "required": [ + "repository", + "pullPolicy" + ], + "properties": { + "repository": { + "description": "container image repository", + "default": "docker.redpanda.com/redpandadata/redpanda", + "type": "string", + "pattern": "^[a-z0-9-_/.]+$" + }, + "tag": { + "description": "The container image tag. Use the Redpanda release version. Must be a valid semver prefixed with a 'v'.", + "default": "Chart.appVersion", + "type": "string", + "pattern": "^v(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$|^$" + }, + "pullPolicy": { + "description": "The Kubernetes Pod image pull policy.", + "type": "string", + "pattern": "^(Always|Never|IfNotPresent)$" + } + } + }, + "service": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "internal": { + "type": "object", + "properties": { + "annotations": { + "type": "object" + } + } + } + } + }, + "license_key": { + "type": "string", + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?\\.(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$|^$", + "deprecated": true + }, + "license_secret_ref": { + "type": "object", + "deprecated": true, + "properties": { + "secret_name": { + "type": "string" + }, + "secret_key": { + "type": "string" + } + } + }, + "enterprise": { + "type": "object", + "properties": { + "license": { + "type": "string" + }, + "licenseSecretRef": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "key": { + "type": "string" + } + } + } + } + }, + "rackAwareness": { + "type": "object", + "required": [ + "enabled", + "nodeAnnotation" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "nodeAnnotation": { + "type": "string" + } + } + }, + "auth": { + "type": "object", + "required": [ + "sasl" + ], + "properties": { + "sasl": { + "type": "object", + "required": [ + "enabled" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "mechanism": { + "type": "string" + }, + "secretRef": { + "type": "string" + }, + "users": { + "type": "array", + "minItems": 0, + "items": { + "properties": { + "name": { + "type": "string" + }, + "password": { + "type": "string" + }, + "mechanism": { + "type": "string", + "pattern": "^(SCRAM-SHA-512|SCRAM-SHA-256)$" + } + } + } + } + } + } + } + }, + "tls": { + "type": "object", + "required": [ + "enabled" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "certs": { + "type": "object", + "minProperties": 1, + "patternProperties": { + "^[A-Za-z_][A-Za-z0-9_]*$": { + "type": "object", + "required": [ + "caEnabled" + ], + "properties": { + "issuerRef": { + "type": "object", + "additionalProperties": false, + "properties": { + "kind": { + "type": "string", + "enum": ["ClusterIssuer", "Issuer"] + }, + "name": { + "type": "string" + } + } + }, + "secretRef": { + "type": "object", + "properties": { + "name": { + "type": "string" + } + } + }, + "caEnabled": { + "type": "boolean" + }, + "duration": { + "type": "string", + "pattern": ".*[smh]$" + } + } + } + } + } + } + }, + "external": { + "type": "object", + "required": [ + "enabled" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "service": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + } + }, + "type": { + "type": "string", + "pattern": "^(LoadBalancer|NodePort)$" + }, + "domain": { + "type": "string", + "format": "idn-hostname" + }, + "addresses": { + "type": "array" + }, + "sourceRanges": { + "type": "array" + }, + "prefixTemplate": { + "type": "string" + }, + "annotations": { + "type": "object" + }, + "externalDns": { + "type": "object", + "required": [ + "enabled" + ], + "properties": { + "enabled": { + "type": "boolean" + } + } + } + } + }, + "logging": { + "type": "object", + "required": [ + "logLevel", + "usageStats" + ], + "parameters": { + "logLevel": { + "type": "string", + "pattern": "^(error|warn|info|debug|trace)$" + }, + "usageStats": { + "type": "object", + "required": [ + "enabled" + ], + "properties": { + "enabled": { + "type": "boolean" + } + } + } + } + }, + "monitoring": { + "type": "object", + "required": [ + "enabled", + "scrapeInterval" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "scrapeInterval": { + "type": "string", + "pattern": ".*[smh]$" + }, + "labels": { + "type": "object" + }, + "tlsConfig": { + "type": "object" + } + } + }, + "resources": { + "type": "object", + "required": [ + "cpu", + "memory" + ], + "properties": { + "cpu": { + "type": "object", + "required": [ + "cores" + ], + "properties": { + "cores": { + "type": ["integer", "string"] + }, + "overprovisioned": { + "type": "boolean" + } + } + }, + "memory": { + "type": "object", + "required": [ + "container" + ], + "properties": { + "enable_memory_locking": { + "type": "boolean" + }, + "container": { + "type": "object", + "required": [ + "max" + ], + "properties": { + "min": { + "type": "string", + "pattern": "^[0-9]+(\\.[0-9]){0,1}(k|M|G|Ki|Mi|Gi)$" + }, + "max": { + "type": "string", + "pattern": "^[0-9]+(\\.[0-9]){0,1}(k|M|G|Ki|Mi|Gi)$" + } + } + } + } + } + } + }, + "storage": { + "type": "object", + "required": [ + "hostPath", + "persistentVolume", + "tiered" + ], + "properties": { + "hostPath": { + "type": "string" + }, + "tiered": { + "type": "object", + "required": [ + "mountType" + ], + "properties": { + "mountType": { + "type": "string", + "pattern": "^(none|hostPath|emptyDir|persistentVolume)$" + }, + "hostPath": { + "type": "string" + }, + "persistentVolume": { + "type": "object", + "required": [ + "storageClass", + "labels", + "annotations" + ], + "properties": { + "storageClass": { + "type": "string" + }, + "labels": { + "type": "object" + }, + "annotations": { + "type": "object" + } + } + }, + "config":{ + "type": "object", + "required": [ + "cloud_storage_enabled", + "cloud_storage_region", + "cloud_storage_bucket" + ], + "properties": { + "cloud_storage_enable_remote_write": { + "type": "boolean" + }, + "cloud_storage_enable_remote_read": { + "type": "boolean" + }, + "cloud_storage_credentials_source": { + "type": "string", + "pattern": "^(config_file|aws_instance_metadata|sts|gcp_instance_metadata)$" + }, + "cloud_storage_region": { + "type": "string" + }, + "cloud_storage_bucket": { + "type": "string" + }, + "cloud_storage_api_endpoint": { + "type": "string" + }, + "cloud_storage_cache_size": { + "type": ["integer", "string"] + }, + "cloud_storage_cache_directory": { + "type": "string" + }, + "cloud_storage_cache_check_interval": { + "type": "integer" + }, + "cloud_storage_initial_backoff_ms": { + "type": "integer" + }, + "cloud_storage_max_connections": { + "type": "integer" + }, + "cloud_storage_segment_upload_timeout_ms": { + "type": "integer" + }, + "cloud_storage_manifest_upload_timeout_ms": { + "type": "integer" + }, + "cloud_storage_max_connection_idle_time_ms": { + "type": "integer" + }, + "cloud_storage_segment_max_upload_interval_sec": { + "type": "integer" + }, + "cloud_storage_trust_file": { + "type": "string" + }, + "cloud_storage_upload_ctrl_update_interval_ms": { + "type": "integer" + }, + "cloud_storage_upload_ctrl_p_coeff": { + "type": "integer" + }, + "cloud_storage_upload_ctrl_d_coeff": { + "type": "integer" + }, + "cloud_storage_upload_ctrl_min_shares": { + "type": "integer" + }, + "cloud_storage_upload_ctrl_max_shares": { + "type": "integer" + }, + "cloud_storage_reconciliation_interval_ms": { + "type": "integer" + }, + "cloud_storage_disable_tls": { + "type": "boolean" + }, + "cloud_storage_api_endpoint_port": { + "type": "integer" + }, + "cloud_storage_azure_adls_endpoint": { + "type": "string" + }, + "cloud_storage_azure_adls_port": { + "type": "integer" + } + } + } + } + }, + "tieredStorageHostPath": { + "deprecated": true, + "type": "string" + }, + "persistentVolume": { + "deprecated": true, + "type": "object", + "required": [ + "enabled", + "size", + "storageClass", + "labels", + "annotations" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "size": { + "type": "string", + "pattern": "^[0-9]+(\\.[0-9]){0,1}(k|M|G|Ki|Mi|Gi)$" + }, + "storageClass": { + "type": "string" + }, + "labels": { + "type": "object" + }, + "annotations": { + "type": "object" + } + } + }, + "tieredStoragePersistentVolume": { + "deprecated": true, + "type": "object", + "required": [ + "enabled", + "storageClass", + "labels", + "annotations" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "storageClass": { + "type": "string" + }, + "labels": { + "type": "object" + }, + "annotations": { + "type": "object" + } + } + }, + "tieredConfig":{ + "deprecated": true, + "type": "object", + "properties": { + "cloud_storage_enable_remote_write": { + "type": "boolean" + }, + "cloud_storage_enable_remote_read": { + "type": "boolean" + }, + "cloud_storage_credentials_source": { + "type": "string", + "pattern": "^(config_file|aws_instance_metadata|sts|gcp_instance_metadata)$" + }, + "cloud_storage_region": { + "type": "string" + }, + "cloud_storage_bucket": { + "type": "string" + }, + "cloud_storage_api_endpoint": { + "type": "string" + }, + "cloud_storage_cache_size": { + "type": "integer" + }, + "cloud_storage_cache_directory": { + "type": "string" + }, + "cloud_storage_cache_check_interval": { + "type": "integer" + }, + "cloud_storage_initial_backoff_ms": { + "type": "integer" + }, + "cloud_storage_max_connections": { + "type": "integer" + }, + "cloud_storage_segment_upload_timeout_ms": { + "type": "integer" + }, + "cloud_storage_manifest_upload_timeout_ms": { + "type": "integer" + }, + "cloud_storage_max_connection_idle_time_ms": { + "type": "integer" + }, + "cloud_storage_segment_max_upload_interval_sec": { + "type": "integer" + }, + "cloud_storage_trust_file": { + "type": "string" + }, + "cloud_storage_upload_ctrl_update_interval_ms": { + "type": "integer" + }, + "cloud_storage_upload_ctrl_p_coeff": { + "type": "integer" + }, + "cloud_storage_upload_ctrl_d_coeff": { + "type": "integer" + }, + "cloud_storage_upload_ctrl_min_shares": { + "type": "integer" + }, + "cloud_storage_upload_ctrl_max_shares": { + "type": "integer" + }, + "cloud_storage_reconciliation_interval_ms": { + "type": "integer" + }, + "cloud_storage_disable_tls": { + "type": "boolean" + }, + "cloud_storage_api_endpoint_port": { + "type": "integer" + }, + "cloud_storage_azure_adls_endpoint": { + "type": "string" + }, + "cloud_storage_azure_adls_port": { + "type": "integer" + } + } + } + } + }, + "post_install_job": { + "type": "object", + "properties": { + "resources": { + "type": "object", + "properties": { + "requests": { + "type": "object", + "properties": { + "cpu": { + "type": "integer" + }, + "memory": { + "type": "string", + "pattern": "^[0-9]+(\\.[0-9]){0,1}(k|M|G|Ki|Mi|Gi)$" + } + } + }, + "limits": { + "type": "object", + "properties": { + "cpu": { + "type": "integer" + }, + "memory": { + "type": "string", + "pattern": "^[0-9]+(\\.[0-9]){0,1}(k|M|G|Ki|Mi|Gi)$" + } + } + } + } + }, + "affinity": { + "type": "object" + } + } + }, + "post_upgrade_job": { + "type": "object", + "properties": { + "resources": { + "type": "object", + "properties": { + "requests": { + "type": "object", + "properties": { + "cpu": { + "type": "integer" + }, + "memory": { + "type": "string", + "pattern": "^[0-9]+(\\.[0-9]){0,1}(k|M|G|Ki|Mi|Gi)$" + } + } + }, + "limits": { + "type": "object", + "properties": { + "cpu": { + "type": "integer" + }, + "memory": { + "type": "string", + "pattern": "^[0-9]+(\\.[0-9]){0,1}(k|M|G|Ki|Mi|Gi)$" + } + } + } + } + }, + "extraEnv": { + "type": ["array", "string"] + }, + "extraEnvFrom": { + "type": ["array", "string"] + }, + "affinity": { + "type": "object" + } + } + }, + "statefulset": { + "type": "object", + "required": [ + "replicas", + "updateStrategy", + "budget", + "annotations", + "startupProbe", + "livenessProbe", + "readinessProbe", + "podAffinity", + "podAntiAffinity", + "nodeSelector", + "priorityClassName", + "tolerations", + "topologySpreadConstraints", + "securityContext", + "sideCars" + ], + "properties": { + "replicas": { + "type": "integer" + }, + "updateStrategy": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "pattern": "^(RollingUpdate|OnDelete)$" + } + } + }, + "budget": { + "type": "object", + "required": [ + "maxUnavailable" + ], + "properties": { + "maxUnavailable": { + "type": "integer" + } + } + }, + "annotations": { + "type": "object" + }, + "startupProbe": { + "type": "object", + "required": [ + "initialDelaySeconds", + "failureThreshold", + "periodSeconds" + ], + "properties": { + "initialDelaySeconds": { + "type": "integer" + }, + "failureThreshold": { + "type": "integer" + }, + "periodSeconds": { + "type": "integer" + } + } + }, + "livenessProbe": { + "type": "object", + "required": [ + "initialDelaySeconds", + "failureThreshold", + "periodSeconds" + ], + "properties": { + "initialDelaySeconds": { + "type": "integer" + }, + "failureThreshold": { + "type": "integer" + }, + "periodSeconds": { + "type": "integer" + } + } + }, + "readinessProbe": { + "type": "object", + "required": [ + "initialDelaySeconds", + "failureThreshold", + "periodSeconds" + ], + "properties": { + "initialDelaySeconds": { + "type": "integer" + }, + "failureThreshold": { + "type": "integer" + }, + "periodSeconds": { + "type": "integer" + } + } + }, + "nodeAffinity": { + "type": "object" + }, + "podAffinity": { + "type": "object" + }, + "podAntiAffinity": { + "type": "object", + "required": [ + "topologyKey", + "type", + "weight" + ], + "properties": { + "topologyKey": { + "type": "string" + }, + "type": { + "type": "string", + "pattern": "^(hard|soft|custom)$" + }, + "weight": { + "type": "integer" + }, + "custom": { + "type": "object" + } + } + }, + "nodeSelector": { + "type": "object" + }, + "priorityClassName": { + "type": "string" + }, + "tolerations": { + "type": "array" + }, + "topologySpreadConstraints": { + "type": "array", + "minItems": 1, + "items": { + "properties": { + "maxSkew": { + "type": "integer" + }, + "topologyKey": { + "type": "string" + }, + "whenUnsatisfiable": { + "type": "string", + "pattern": "^(ScheduleAnyway|DoNotSchedule)$" + } + } + } + }, + "securityContext": { + "type": "object", + "required": [ + "fsGroup", + "runAsUser" + ], + "properties": { + "fsGroup": { + "type": "integer" + }, + "runAsUser": { + "type": "integer" + }, + "fsGroupChangePolicy": { + "type": "string", + "pattern": "^(OnRootMismatch|Always)$" + } + } + }, + "sideCars": { + "type": "object", + "properties": { + "configWatcher": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "resources": { + "type": "object" + }, + "securityContext": { + "type": "object" + }, + "extraVolumeMounts": { + "type": "string" + } + }, + "controllers": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "resources": { + "type": "object" + }, + "securityContext": { + "type": "object" + }, + "run": { + "type": "array" + }, + "healthProbeAddress": { + "type": "string" + }, + "metricsAddress": { + "type": "string" + }, + "image": { + "description": "Values used to define the container image to be used for Redpanda", + "type": "object", + "required": [ + "repository", + "tag" + ], + "properties": { + "repository": { + "description": "container image repository", + "default": "docker.redpanda.com/redpandadata/redpanda-operator", + "type": "string", + "pattern": "^[a-z0-9-_/.]+$" + }, + "tag": { + "description": "The container image tag. Use the Redpanda release version. Must be a valid semver prefixed with a 'v'.", + "default": "Chart.appVersion", + "type": "string", + "pattern": "^v(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$|^$" + } + } + } + } + } + } + } + }, + "initContainers": { + "type": "object", + "properties": { + "fsValidator": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "expectedFS": { + "type": "string" + }, + "resources": { + "type": "object" + }, + "extraVolumeMounts": { + "type": "string" + } + } + }, + "tuning": { + "type": "object", + "properties": { + "resources": { + "type": "object" + }, + "extraVolumeMounts": { + "type": "string" + } + } + }, + "setDataDirOwnership": { + "type": "object", + "properties": { + "resources": { + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "extraVolumeMounts": { + "type": "string" + } + } + }, + "setTieredStorageCacheDirOwnership": { + "type": "object", + "properties": { + "resources": { + "type": "object" + }, + "extraVolumeMounts": { + "type": "string" + } + } + }, + "configurator": { + "type": "object", + "properties": { + "resources": { + "type": "object" + }, + "extraVolumeMounts": { + "type": "string" + } + } + }, + "extraInitContainers": { + "type": "string" + } + } + }, + "additionalRedpandaCmdFlags": { + "type": "array" + }, + "terminationGracePeriodSeconds": { + "type": "integer" + }, + "extraVolumes": { + "type": "string" + }, + "extraVolumeMounts": { + "type": "string" + } + } + }, + "serviceAccount": { + "type": "object", + "required": [ + "create", + "annotations", + "name" + ], + "properties": { + "create": { + "type": "boolean" + }, + "annotations": { + "type": "object" + }, + "name": { + "type": "string" + } + } + }, + "rbac": { + "type": "object", + "required": [ + "enabled", + "annotations" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "annotations": { + "type": "object" + } + } + }, + "tuning": { + "type": "object", + "properties": { + "tune_aio_events": { + "type": "boolean" + }, + "tune_clocksource": { + "type": "boolean" + }, + "tune_ballast_file": { + "type": "boolean" + }, + "ballast_file_path": { + "type": "string" + }, + "ballast_file_size": { + "type": "string" + }, + "well_known_io": { + "type": "string" + } + } + }, + "listeners": { + "type": "object", + "required": [ + "admin", + "kafka", + "http", + "rpc", + "schemaRegistry" + ], + "properties": { + "admin": { + "type": "object", + "required": [ + "port", + "tls" + ], + "properties": { + "port": { + "type": "integer" + }, + "external": { + "type": "object", + "minProperties": 1, + "patternProperties": { + "^[A-Za-z_][A-Za-z0-9_]*$": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "advertisedPorts": { + "type": "array", + "minItems": 1, + "items": { + "type": "integer" + } + } + } + } + } + }, + "tls": { + "type": "object", + "required": [ + "cert", + "requireClientAuth" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "cert": { + "type": "string" + }, + "requireClientAuth": { + "type": "boolean" + } + } + } + } + }, + "kafka": { + "type": "object", + "required": [ + "port", + "tls" + ], + "properties": { + "port": { + "type": "integer" + }, + "external": { + "type": "object", + "minProperties": 1, + "patternProperties": { + "^[A-Za-z_][A-Za-z0-9_]*$": { + "type": "object", + "required": [ + "port" + ], + "properties": { + "prefixTemplate": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "port": { + "type": "integer" + }, + "advertisedPorts": { + "type": "array", + "minItems": 1, + "items": { + "type": "integer" + } + }, + "authenticationMethod": { + "type": ["string", "null"], + "pattern": "sasl|none|mtls_identity" + } + } + } + } + }, + "tls": { + "type": "object", + "required": [ + "cert", + "requireClientAuth" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "cert": { + "type": "string" + }, + "requireClientAuth": { + "type": "boolean" + } + } + }, + "authenticationMethod": { + "type": ["string", "null"], + "pattern": "sasl|none|mtls_identity" + } + } + }, + "http": { + "type": "object", + "required": [ + "enabled", + "port", + "kafkaEndpoint", + "tls" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "port": { + "type": "integer" + }, + "kafkaEndpoint": { + "type": "string", + "pattern": "^[A-Za-z_-][A-Za-z0-9_-]*$" + }, + "authenticationMethod": { + "type": ["string", "null"], + "pattern": "http_basic|none" + }, + "external": { + "type": "object", + "minProperties": 1, + "patternProperties": { + "^[A-Za-z_][A-Za-z0-9_]*$": { + "type": "object", + "required": [ + "port" + ], + "properties": { + "prefixTemplate": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "port": { + "type": "integer" + }, + "advertisedPorts": { + "type": "array", + "minItems": 1, + "items": { + "type": "integer" + } + }, + "authenticationMethod": { + "type": ["string", "null"], + "pattern": "http_basic|none" + }, + "tls": { + "type": "object", + "required": [], + "properties": { + "enabled": { + "type": "boolean" + }, + "cert": { + "type": "string" + }, + "requireClientAuth": { + "type": "boolean" + } + } + } + } + } + } + }, + "tls": { + "type": "object", + "required": [ + "cert", + "requireClientAuth" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "cert": { + "type": "string" + }, + "requireClientAuth": { + "type": "boolean" + } + } + } + } + }, + "rpc": { + "type": "object", + "required": [ + "port", + "tls" + ], + "properties": { + "port": { + "type": "integer" + }, + "tls": { + "type": "object", + "required": [ + "cert", + "requireClientAuth" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "cert": { + "type": "string" + }, + "requireClientAuth": { + "type": "boolean" + } + } + } + } + }, + "schemaRegistry": { + "type": "object", + "required": [ + "enabled", + "port", + "kafkaEndpoint", + "tls" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "port": { + "type": "integer" + }, + "kafkaEndpoint": { + "type": "string", + "pattern": "^[A-Za-z_-][A-Za-z0-9_-]*$" + }, + "authenticationMethod": { + "type": ["string", "null"], + "pattern": "http_basic|none" + }, + "external": { + "type": "object", + "minProperties": 1, + "patternProperties": { + "^[A-Za-z_][A-Za-z0-9_]*$": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "port": { + "type": "integer" + }, + "advertisedPorts": { + "type": "array", + "minItems": 1, + "items": { + "type": "integer" + } + }, + "authenticationMethod": { + "type": ["string", "null"], + "pattern": "http_basic|none" + }, + "tls": { + "type": "object", + "required": [], + "properties": { + "enabled": { + "type": "boolean" + }, + "cert": { + "type": "string" + }, + "requireClientAuth": { + "type": "boolean" + } + } + } + } + } + } + }, + "tls": { + "type": "object", + "required": [ + "cert", + "requireClientAuth" + ], + "properties": { + "enabled": { + "type": "boolean" + }, + "cert": { + "type": "string" + }, + "requireClientAuth": { + "type": "boolean" + } + } + } + } + } + } + }, + "config": { + "type": "object", + "required": [ + "cluster", + "tunable", + "node" + ], + "properties": { + "cluster": { + "type": "object" + }, + "tunable": { + "type": "object" + }, + "node": { + "type": "object" + }, + "rpk": { + "type": "object" + }, + "schema_registry_client": { + "type": "object", + "properties": { + "retries": { + "type": "integer" + }, + "retry_base_backoff_ms": { + "type": "integer" + }, + "produce_batch_record_count": { + "type": "integer" + }, + "produce_batch_size_bytes": { + "type": "integer" + }, + "produce_batch_delay_ms": { + "type": "integer" + }, + "consumer_request_timeout_ms": { + "type": "integer" + }, + "consumer_request_max_bytes": { + "type": "integer" + }, + "consumer_session_timeout_ms": { + "type": "integer" + }, + "consumer_rebalance_timeout_ms": { + "type": "integer" + }, + "consumer_heartbeat_interval_ms": { + "type": "integer" + } + } + }, + "pandaproxy_client": { + "type": "object", + "properties": { + "retries": { + "type": "integer" + }, + "retry_base_backoff_ms": { + "type": "integer" + }, + "produce_batch_record_count": { + "type": "integer" + }, + "produce_batch_size_bytes": { + "type": "integer" + }, + "produce_batch_delay_ms": { + "type": "integer" + }, + "consumer_request_timeout_ms": { + "type": "integer" + }, + "consumer_request_max_bytes": { + "type": "integer" + }, + "consumer_session_timeout_ms": { + "type": "integer" + }, + "consumer_rebalance_timeout_ms": { + "type": "integer" + }, + "consumer_heartbeat_interval_ms": { + "type": "integer" + } + } + } + } + } + } +} diff --git a/charts/redpanda/testdata/schemas/5.7.x.schema.json b/charts/redpanda/testdata/schemas/5.7.x.schema.json new file mode 100644 index 0000000000..45b191921c --- /dev/null +++ b/charts/redpanda/testdata/schemas/5.7.x.schema.json @@ -0,0 +1,1799 @@ +{ + "$schema": "http://json-schema.org/schema#", + "properties": { + "affinity": { + "properties": { + "nodeAffinity": { + "type": "object" + }, + "podAffinity": { + "type": "object" + }, + "podAntiAffinity": { + "type": "object" + } + }, + "type": "object" + }, + "auditLogging": { + "properties": { + "clientMaxBufferSize": { + "type": "integer" + }, + "enabled": { + "type": "boolean" + }, + "enabledEventTypes": { + "items": { + "type": "string" + }, + "type": [ + "array", + "null" + ] + }, + "excludedPrincipals": { + "items": { + "type": "string" + }, + "type": [ + "array", + "null" + ] + }, + "excludedTopics": { + "items": { + "type": "string" + }, + "type": [ + "array", + "null" + ] + }, + "listener": { + "type": "string" + }, + "partitions": { + "type": "integer" + }, + "queueDrainIntervalMs": { + "type": "integer" + }, + "queueMaxBufferSizePerShard": { + "type": "integer" + }, + "replicationFactor": { + "type": [ + "integer", + "null" + ] + } + }, + "type": "object" + }, + "auth": { + "properties": { + "sasl": { + "properties": { + "enabled": { + "type": "boolean" + }, + "mechanism": { + "type": "string" + }, + "secretRef": { + "type": "string" + }, + "users": { + "items": { + "properties": { + "mechanism": { + "pattern": "^(SCRAM-SHA-512|SCRAM-SHA-256)$", + "type": "string" + }, + "name": { + "type": "string" + }, + "password": { + "type": "string" + } + }, + "type": "object" + }, + "type": "array" + } + }, + "required": [ + "enabled" + ], + "type": "object" + } + }, + "required": [ + "sasl" + ], + "type": "object" + }, + "clusterDomain": { + "type": "string" + }, + "commonLabels": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "config": { + "properties": { + "cluster": { + "type": "object" + }, + "node": { + "type": "object" + }, + "pandaproxy_client": { + "properties": { + "consumer_heartbeat_interval_ms": { + "type": "integer" + }, + "consumer_rebalance_timeout_ms": { + "type": "integer" + }, + "consumer_request_max_bytes": { + "type": "integer" + }, + "consumer_request_timeout_ms": { + "type": "integer" + }, + "consumer_session_timeout_ms": { + "type": "integer" + }, + "produce_batch_delay_ms": { + "type": "integer" + }, + "produce_batch_record_count": { + "type": "integer" + }, + "produce_batch_size_bytes": { + "type": "integer" + }, + "retries": { + "type": "integer" + }, + "retry_base_backoff_ms": { + "type": "integer" + } + }, + "type": "object" + }, + "rpk": { + "type": "object" + }, + "schema_registry_client": { + "properties": { + "consumer_heartbeat_interval_ms": { + "type": "integer" + }, + "consumer_rebalance_timeout_ms": { + "type": "integer" + }, + "consumer_request_max_bytes": { + "type": "integer" + }, + "consumer_request_timeout_ms": { + "type": "integer" + }, + "consumer_session_timeout_ms": { + "type": "integer" + }, + "produce_batch_delay_ms": { + "type": "integer" + }, + "produce_batch_record_count": { + "type": "integer" + }, + "produce_batch_size_bytes": { + "type": "integer" + }, + "retries": { + "type": "integer" + }, + "retry_base_backoff_ms": { + "type": "integer" + } + }, + "type": "object" + }, + "tunable": { + "additionalProperties": true, + "properties": { + "group_initial_rebalance_delay": { + "type": "integer" + }, + "log_retention_ms": { + "type": "integer" + } + }, + "type": "object" + } + }, + "required": [ + "cluster", + "node", + "tunable" + ], + "type": "object" + }, + "enterprise": { + "properties": { + "license": { + "type": "string" + }, + "licenseSecretRef": { + "properties": { + "key": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "external": { + "properties": { + "addresses": { + "items": { + "type": "string" + }, + "type": "array" + }, + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "domain": { + "format": "idn-hostname", + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "externalDns": { + "properties": { + "enabled": { + "type": "boolean" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, + "prefixTemplate": { + "type": "string" + }, + "service": { + "properties": { + "enabled": { + "type": "boolean" + } + }, + "type": "object" + }, + "sourceRanges": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": { + "pattern": "^(LoadBalancer|NodePort)$", + "type": "string" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, + "fullnameOverride": { + "type": "string" + }, + "image": { + "description": "Values used to define the container image to be used for Redpanda", + "properties": { + "pullPolicy": { + "description": "The Kubernetes Pod image pull policy.", + "pattern": "^(Always|Never|IfNotPresent)$", + "type": "string" + }, + "repository": { + "default": "docker.redpanda.com/redpandadata/redpanda", + "description": "container image repository", + "pattern": "^[a-z0-9-_/.]+$", + "type": "string" + }, + "tag": { + "default": "Chart.appVersion", + "description": "The container image tag. Use the Redpanda release version. Must be a valid semver prefixed with a 'v'.", + "pattern": "^v(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$|^$", + "type": "string" + } + }, + "required": [ + "repository", + "pullPolicy" + ], + "type": "object" + }, + "license_key": { + "deprecated": true, + "pattern": "^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?\\.(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$|^$", + "type": "string" + }, + "license_secret_ref": { + "deprecated": true, + "properties": { + "secret_key": { + "type": "string" + }, + "secret_name": { + "type": "string" + } + }, + "type": "object" + }, + "listeners": { + "properties": { + "admin": { + "properties": { + "external": { + "minProperties": 1, + "patternProperties": { + "^[A-Za-z_][A-Za-z0-9_]*$": { + "properties": { + "advertisedPorts": { + "items": { + "type": "integer" + }, + "minItems": 1, + "type": "array" + }, + "enabled": { + "type": "boolean" + }, + "port": { + "type": "integer" + } + }, + "required": [ + "port" + ], + "type": "object" + } + }, + "type": "object" + }, + "port": { + "type": "integer" + }, + "tls": { + "properties": { + "cert": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "requireClientAuth": { + "type": "boolean" + } + }, + "required": [ + "cert", + "requireClientAuth" + ], + "type": "object" + } + }, + "required": [ + "port", + "tls" + ], + "type": "object" + }, + "http": { + "properties": { + "authenticationMethod": { + "pattern": "http_basic|none", + "type": [ + "string", + "null" + ] + }, + "enabled": { + "type": "boolean" + }, + "external": { + "minProperties": 1, + "patternProperties": { + "^[A-Za-z_][A-Za-z0-9_]*$": { + "properties": { + "advertisedPorts": { + "items": { + "type": "integer" + }, + "minItems": 1, + "type": "array" + }, + "authenticationMethod": { + "pattern": "http_basic|none", + "type": [ + "string", + "null" + ] + }, + "enabled": { + "type": "boolean" + }, + "port": { + "type": "integer" + }, + "prefixTemplate": { + "type": "string" + }, + "tls": { + "properties": { + "cert": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "requireClientAuth": { + "type": "boolean" + } + }, + "required": [], + "type": "object" + } + }, + "required": [ + "port" + ], + "type": "object" + } + }, + "type": "object" + }, + "kafkaEndpoint": { + "pattern": "^[A-Za-z_-][A-Za-z0-9_-]*$", + "type": "string" + }, + "port": { + "type": "integer" + }, + "tls": { + "properties": { + "cert": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "requireClientAuth": { + "type": "boolean" + } + }, + "required": [ + "cert", + "requireClientAuth" + ], + "type": "object" + } + }, + "required": [ + "enabled", + "tls", + "kafkaEndpoint", + "port" + ], + "type": "object" + }, + "kafka": { + "properties": { + "authenticationMethod": { + "pattern": "sasl|none|mtls_identity", + "type": [ + "string", + "null" + ] + }, + "external": { + "minProperties": 1, + "patternProperties": { + "^[A-Za-z_][A-Za-z0-9_]*$": { + "properties": { + "advertisedPorts": { + "items": { + "type": "integer" + }, + "minItems": 1, + "type": "array" + }, + "authenticationMethod": { + "pattern": "sasl|none|mtls_identity", + "type": [ + "string", + "null" + ] + }, + "enabled": { + "type": "boolean" + }, + "port": { + "type": "integer" + }, + "prefixTemplate": { + "type": "string" + } + }, + "required": [ + "port" + ], + "type": "object" + } + }, + "type": "object" + }, + "port": { + "type": "integer" + }, + "tls": { + "properties": { + "cert": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "requireClientAuth": { + "type": "boolean" + } + }, + "required": [ + "cert", + "requireClientAuth" + ], + "type": "object" + } + }, + "required": [ + "tls", + "port" + ], + "type": "object" + }, + "rpc": { + "properties": { + "port": { + "type": "integer" + }, + "tls": { + "properties": { + "cert": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "requireClientAuth": { + "type": "boolean" + } + }, + "required": [ + "cert", + "requireClientAuth" + ], + "type": "object" + } + }, + "required": [ + "port", + "tls" + ], + "type": "object" + }, + "schemaRegistry": { + "properties": { + "authenticationMethod": { + "pattern": "http_basic|none", + "type": [ + "string", + "null" + ] + }, + "enabled": { + "type": "boolean" + }, + "external": { + "minProperties": 1, + "patternProperties": { + "^[A-Za-z_][A-Za-z0-9_]*$": { + "properties": { + "advertisedPorts": { + "items": { + "type": "integer" + }, + "minItems": 1, + "type": "array" + }, + "authenticationMethod": { + "pattern": "http_basic|none", + "type": [ + "string", + "null" + ] + }, + "enabled": { + "type": "boolean" + }, + "port": { + "type": "integer" + }, + "tls": { + "properties": { + "cert": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "requireClientAuth": { + "type": "boolean" + } + }, + "required": [], + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "kafkaEndpoint": { + "pattern": "^[A-Za-z_-][A-Za-z0-9_-]*$", + "type": "string" + }, + "port": { + "type": "integer" + }, + "tls": { + "properties": { + "cert": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "requireClientAuth": { + "type": "boolean" + } + }, + "required": [ + "cert", + "requireClientAuth" + ], + "type": "object" + } + }, + "required": [ + "enabled", + "kafkaEndpoint", + "port", + "tls" + ], + "type": "object" + } + }, + "required": [ + "admin", + "http", + "kafka", + "schemaRegistry", + "rpc" + ], + "type": "object" + }, + "logging": { + "properties": { + "logLevel": { + "pattern": "^(error|warn|info|debug|trace)$", + "type": "string" + }, + "usageStats": { + "properties": { + "enabled": { + "type": "boolean" + } + }, + "required": [ + "enabled" + ], + "type": "object" + } + }, + "required": [ + "logLevel", + "usageStats" + ], + "type": "object" + }, + "monitoring": { + "properties": { + "enabled": { + "type": "boolean" + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "scrapeInterval": { + "pattern": ".*[smh]$", + "type": "string" + }, + "tlsConfig": { + "type": "object" + } + }, + "required": [ + "enabled", + "scrapeInterval" + ], + "type": "object" + }, + "nameOverride": { + "type": "string" + }, + "nodeSelector": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "post_install_job": { + "properties": { + "affinity": { + "type": "object" + }, + "resources": { + "properties": { + "limits": { + "properties": { + "cpu": { + "type": [ + "integer", + "string" + ] + }, + "memory": { + "pattern": "^[0-9]+(\\.[0-9]){0,1}(k|M|G|Ki|Mi|Gi)$", + "type": "string" + } + }, + "type": "object" + }, + "requests": { + "properties": { + "cpu": { + "type": [ + "integer", + "string" + ] + }, + "memory": { + "pattern": "^[0-9]+(\\.[0-9]){0,1}(k|M|G|Ki|Mi|Gi)$", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "post_upgrade_job": { + "properties": { + "affinity": { + "type": "object" + }, + "extraEnv": { + "type": [ + "array", + "string" + ] + }, + "extraEnvFrom": { + "type": [ + "array", + "string" + ] + }, + "resources": { + "properties": { + "limits": { + "properties": { + "cpu": { + "type": [ + "integer", + "string" + ] + }, + "memory": { + "pattern": "^[0-9]+(\\.[0-9]){0,1}(k|M|G|Ki|Mi|Gi)$", + "type": "string" + } + }, + "type": "object" + }, + "requests": { + "properties": { + "cpu": { + "type": [ + "integer", + "string" + ] + }, + "memory": { + "pattern": "^[0-9]+(\\.[0-9]){0,1}(k|M|G|Ki|Mi|Gi)$", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "rackAwareness": { + "properties": { + "enabled": { + "type": "boolean" + }, + "nodeAnnotation": { + "type": "string" + } + }, + "required": [ + "enabled", + "nodeAnnotation" + ], + "type": "object" + }, + "rbac": { + "properties": { + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "enabled": { + "type": "boolean" + } + }, + "required": [ + "enabled", + "annotations" + ], + "type": "object" + }, + "resources": { + "properties": { + "cpu": { + "properties": { + "cores": { + "type": [ + "integer", + "string" + ] + }, + "overprovisioned": { + "type": "boolean" + } + }, + "required": [ + "cores" + ], + "type": "object" + }, + "memory": { + "properties": { + "container": { + "properties": { + "max": { + "pattern": "^[0-9]+(\\.[0-9]){0,1}(k|M|G|Ki|Mi|Gi)$", + "type": "string" + }, + "min": { + "pattern": "^[0-9]+(\\.[0-9]){0,1}(k|M|G|Ki|Mi|Gi)$", + "type": "string" + } + }, + "required": [ + "max" + ], + "type": "object" + }, + "enable_memory_locking": { + "type": "boolean" + } + }, + "required": [ + "container" + ], + "type": "object" + } + }, + "required": [ + "cpu", + "memory" + ], + "type": "object" + }, + "service": { + "properties": { + "internal": { + "properties": { + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + } + }, + "type": "object" + }, + "name": { + "type": "string" + } + }, + "type": "object" + }, + "serviceAccount": { + "properties": { + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "create": { + "type": "boolean" + }, + "name": { + "type": "string" + } + }, + "required": [ + "create", + "name", + "annotations" + ], + "type": "object" + }, + "statefulset": { + "properties": { + "additionalRedpandaCmdFlags": { + "items": { + "type": "string" + }, + "type": "array" + }, + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "budget": { + "properties": { + "maxUnavailable": { + "type": "integer" + } + }, + "required": [ + "maxUnavailable" + ], + "type": "object" + }, + "extraVolumeMounts": { + "type": "string" + }, + "extraVolumes": { + "type": "string" + }, + "initContainers": { + "properties": { + "configurator": { + "properties": { + "extraVolumeMounts": { + "type": "string" + }, + "resources": { + "type": "object" + } + }, + "type": "object" + }, + "extraInitContainers": { + "type": "string" + }, + "fsValidator": { + "properties": { + "enabled": { + "type": "boolean" + }, + "expectedFS": { + "type": "string" + }, + "extraVolumeMounts": { + "type": "string" + }, + "resources": { + "type": "object" + } + }, + "type": "object" + }, + "setDataDirOwnership": { + "properties": { + "enabled": { + "type": "boolean" + }, + "extraVolumeMounts": { + "type": "string" + }, + "resources": { + "type": "object" + } + }, + "type": "object" + }, + "setTieredStorageCacheDirOwnership": { + "properties": { + "extraVolumeMounts": { + "type": "string" + }, + "resources": { + "type": "object" + } + }, + "type": "object" + }, + "tuning": { + "properties": { + "extraVolumeMounts": { + "type": "string" + }, + "resources": { + "type": "object" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "livenessProbe": { + "properties": { + "failureThreshold": { + "type": "integer" + }, + "initialDelaySeconds": { + "type": "integer" + }, + "periodSeconds": { + "type": "integer" + } + }, + "required": [ + "initialDelaySeconds", + "failureThreshold", + "periodSeconds" + ], + "type": "object" + }, + "nodeAffinity": { + "type": "object" + }, + "nodeSelector": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "podAffinity": { + "type": "object" + }, + "podAntiAffinity": { + "properties": { + "custom": { + "type": "object" + }, + "topologyKey": { + "type": "string" + }, + "type": { + "pattern": "^(hard|soft|custom)$", + "type": "string" + }, + "weight": { + "type": "integer" + } + }, + "required": [ + "topologyKey", + "type", + "weight" + ], + "type": "object" + }, + "podTemplate": { + "properties": { + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "annotations" + ], + "type": "object" + }, + "priorityClassName": { + "type": "string" + }, + "readinessProbe": { + "properties": { + "failureThreshold": { + "type": "integer" + }, + "initialDelaySeconds": { + "type": "integer" + }, + "periodSeconds": { + "type": "integer" + } + }, + "required": [ + "initialDelaySeconds", + "failureThreshold", + "periodSeconds" + ], + "type": "object" + }, + "replicas": { + "type": "integer" + }, + "securityContext": { + "properties": { + "fsGroup": { + "type": "integer" + }, + "fsGroupChangePolicy": { + "pattern": "^(OnRootMismatch|Always)$", + "type": "string" + }, + "runAsUser": { + "type": "integer" + } + }, + "required": [ + "fsGroup", + "runAsUser" + ], + "type": "object" + }, + "sideCars": { + "properties": { + "configWatcher": { + "properties": { + "enabled": { + "type": "boolean" + }, + "extraVolumeMounts": { + "type": "string" + }, + "resources": { + "type": "object" + }, + "securityContext": { + "type": "object" + } + }, + "type": "object" + }, + "controllers": { + "properties": { + "enabled": { + "type": "boolean" + }, + "image": { + "properties": { + "repository": { + "default": "docker.redpanda.com/redpandadata/redpanda-operator", + "pattern": "^[a-z0-9-_/.]+$", + "type": "string" + }, + "tag": { + "default": "Chart.appVersion", + "pattern": "^v(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$|^$", + "type": "string" + } + }, + "required": [ + "tag", + "repository" + ], + "type": "object" + }, + "resources": true, + "securityContext": true + }, + "type": "object" + } + }, + "type": "object" + }, + "startupProbe": { + "properties": { + "failureThreshold": { + "type": "integer" + }, + "initialDelaySeconds": { + "type": "integer" + }, + "periodSeconds": { + "type": "integer" + } + }, + "required": [ + "initialDelaySeconds", + "failureThreshold", + "periodSeconds" + ], + "type": "object" + }, + "terminationGracePeriodSeconds": { + "type": "integer" + }, + "tolerations": { + "items": true, + "type": "array" + }, + "topologySpreadConstraints": { + "items": { + "properties": { + "maxSkew": { + "type": "integer" + }, + "topologyKey": { + "type": "string" + }, + "whenUnsatisfiable": { + "pattern": "^(ScheduleAnyway|DoNotSchedule)$", + "type": "string" + } + }, + "type": "object" + }, + "minItems": 1, + "type": "array" + }, + "updateStrategy": { + "properties": { + "type": { + "pattern": "^(RollingUpdate|OnDelete)$", + "type": "string" + } + }, + "required": [ + "type" + ], + "type": "object" + } + }, + "required": [ + "replicas", + "updateStrategy", + "budget", + "startupProbe", + "livenessProbe", + "readinessProbe", + "podAffinity", + "podAntiAffinity", + "nodeSelector", + "priorityClassName", + "topologySpreadConstraints", + "tolerations", + "securityContext", + "sideCars" + ], + "type": "object" + }, + "storage": { + "properties": { + "hostPath": { + "type": "string" + }, + "persistentVolume": { + "deprecated": true, + "properties": { + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "size": { + "pattern": "^[0-9]+(\\.[0-9]){0,1}(k|M|G|Ki|Mi|Gi)$", + "type": "string" + }, + "storageClass": { + "type": "string" + } + }, + "required": [ + "annotations", + "enabled", + "labels", + "size", + "storageClass" + ], + "type": "object" + }, + "tiered": { + "properties": { + "config": { + "properties": { + "cloud_storage_api_endpoint": { + "type": "string" + }, + "cloud_storage_api_endpoint_port": { + "type": "integer" + }, + "cloud_storage_azure_adls_endpoint": { + "type": "string" + }, + "cloud_storage_azure_adls_port": { + "type": "integer" + }, + "cloud_storage_bucket": { + "type": "string" + }, + "cloud_storage_cache_check_interval": { + "type": "integer" + }, + "cloud_storage_cache_directory": { + "type": "string" + }, + "cloud_storage_cache_size": { + "type": [ + "integer", + "string" + ] + }, + "cloud_storage_credentials_source": { + "pattern": "^(config_file|aws_instance_metadata|sts|gcp_instance_metadata)$", + "type": "string" + }, + "cloud_storage_disable_tls": { + "type": "boolean" + }, + "cloud_storage_enable_remote_read": { + "type": "boolean" + }, + "cloud_storage_enable_remote_write": { + "type": "boolean" + }, + "cloud_storage_initial_backoff_ms": { + "type": "integer" + }, + "cloud_storage_manifest_upload_timeout_ms": { + "type": "integer" + }, + "cloud_storage_max_connection_idle_time_ms": { + "type": "integer" + }, + "cloud_storage_max_connections": { + "type": "integer" + }, + "cloud_storage_reconciliation_interval_ms": { + "type": "integer" + }, + "cloud_storage_region": { + "type": "string" + }, + "cloud_storage_segment_max_upload_interval_sec": { + "type": "integer" + }, + "cloud_storage_segment_upload_timeout_ms": { + "type": "integer" + }, + "cloud_storage_trust_file": { + "type": "string" + }, + "cloud_storage_upload_ctrl_d_coeff": { + "type": "integer" + }, + "cloud_storage_upload_ctrl_max_shares": { + "type": "integer" + }, + "cloud_storage_upload_ctrl_min_shares": { + "type": "integer" + }, + "cloud_storage_upload_ctrl_p_coeff": { + "type": "integer" + }, + "cloud_storage_upload_ctrl_update_interval_ms": { + "type": "integer" + } + }, + "required": [ + "cloud_storage_enabled", + "cloud_storage_bucket", + "cloud_storage_region" + ], + "type": "object" + }, + "credentialsSecretRef": { + "properties": { + "accessKey": { + "properties": { + "configurationKey": { + "type": "string" + }, + "key": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "type": "object" + }, + "configurationKey": { + "deprecated": true, + "type": "string" + }, + "key": { + "deprecated": true, + "type": "string" + }, + "name": { + "deprecated": true, + "type": "string" + }, + "secretKey": { + "properties": { + "configurationKey": { + "type": "string" + }, + "key": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "hostPath": { + "type": "string" + }, + "mountType": { + "pattern": "^(none|hostPath|emptyDir|persistentVolume)$", + "type": "string" + }, + "persistentVolume": { + "properties": { + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "nameOverwrite": { + "type": "string" + }, + "size": { + "type": "string" + }, + "storageClass": { + "type": "string" + } + }, + "required": [ + "annotations", + "labels", + "storageClass" + ], + "type": "object" + } + }, + "required": [ + "mountType" + ], + "type": "object" + }, + "tieredConfig": { + "deprecated": true, + "properties": { + "cloud_storage_api_endpoint": { + "type": "string" + }, + "cloud_storage_api_endpoint_port": { + "type": "integer" + }, + "cloud_storage_azure_adls_endpoint": { + "type": "string" + }, + "cloud_storage_azure_adls_port": { + "type": "integer" + }, + "cloud_storage_bucket": { + "type": "string" + }, + "cloud_storage_cache_check_interval": { + "type": "integer" + }, + "cloud_storage_cache_directory": { + "type": "string" + }, + "cloud_storage_cache_size": { + "type": "integer" + }, + "cloud_storage_credentials_source": { + "pattern": "^(config_file|aws_instance_metadata|sts|gcp_instance_metadata)$", + "type": "string" + }, + "cloud_storage_disable_tls": { + "type": "boolean" + }, + "cloud_storage_enable_remote_read": { + "type": "boolean" + }, + "cloud_storage_enable_remote_write": { + "type": "boolean" + }, + "cloud_storage_initial_backoff_ms": { + "type": "integer" + }, + "cloud_storage_manifest_upload_timeout_ms": { + "type": "integer" + }, + "cloud_storage_max_connection_idle_time_ms": { + "type": "integer" + }, + "cloud_storage_max_connections": { + "type": "integer" + }, + "cloud_storage_reconciliation_interval_ms": { + "type": "integer" + }, + "cloud_storage_region": { + "type": "string" + }, + "cloud_storage_segment_max_upload_interval_sec": { + "type": "integer" + }, + "cloud_storage_segment_upload_timeout_ms": { + "type": "integer" + }, + "cloud_storage_trust_file": { + "type": "string" + }, + "cloud_storage_upload_ctrl_d_coeff": { + "type": "integer" + }, + "cloud_storage_upload_ctrl_max_shares": { + "type": "integer" + }, + "cloud_storage_upload_ctrl_min_shares": { + "type": "integer" + }, + "cloud_storage_upload_ctrl_p_coeff": { + "type": "integer" + }, + "cloud_storage_upload_ctrl_update_interval_ms": { + "type": "integer" + } + }, + "type": "object" + }, + "tieredStorageHostPath": { + "deprecated": true, + "type": "string" + }, + "tieredStoragePersistentVolume": { + "deprecated": true, + "properties": { + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "enabled": { + "type": "boolean" + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + "storageClass": { + "type": "string" + } + }, + "required": [ + "annotations", + "enabled", + "labels", + "storageClass" + ], + "type": "object" + } + }, + "required": [ + "hostPath", + "tiered", + "persistentVolume" + ], + "type": "object" + }, + "tests": { + "properties": { + "enabled": { + "type": "boolean" + } + }, + "type": "object" + }, + "tls": { + "properties": { + "certs": { + "minProperties": 1, + "patternProperties": { + "^[A-Za-z_][A-Za-z0-9_]*$": { + "properties": { + "applyInternalDNSNames": { + "type": "boolean" + }, + "caEnabled": { + "type": "boolean" + }, + "duration": { + "pattern": ".*[smh]$", + "type": "string" + }, + "issuerRef": { + "properties": { + "kind": { + "enum": [ + "ClusterIssuer", + "Issuer" + ], + "type": "string" + }, + "name": { + "type": "string" + } + }, + "type": "object" + }, + "secretRef": { + "properties": { + "name": { + "type": "string" + } + }, + "type": "object" + } + }, + "required": [ + "caEnabled" + ], + "type": "object" + } + }, + "type": "object" + }, + "enabled": { + "type": "boolean" + } + }, + "required": [ + "enabled" + ], + "type": "object" + }, + "tolerations": { + "items": { + "type": "object" + }, + "type": "array" + }, + "tuning": { + "properties": { + "ballast_file_path": { + "type": "string" + }, + "ballast_file_size": { + "type": "string" + }, + "tune_aio_events": { + "type": "boolean" + }, + "tune_ballast_file": { + "type": "boolean" + }, + "tune_clocksource": { + "type": "boolean" + }, + "well_known_io": { + "type": "string" + } + }, + "type": "object" + } + }, + "required": [ + "image" + ], + "type": "object" +} diff --git a/charts/redpanda/values.go b/charts/redpanda/values.go index 3f1bf47e78..040c0d3ebd 100644 --- a/charts/redpanda/values.go +++ b/charts/redpanda/values.go @@ -35,19 +35,19 @@ type Values struct { // Console any `json:"console"` // Connectors any `json:"connectors"` Auth Auth `json:"auth"` - TLS TLS `json:"tls"` + TLS TLS `json:"tls" jsonschema:"required"` External ExternalConfig `json:"external"` Logging Logging `json:"logging"` Monitoring Monitoring `json:"monitoring"` Resources RedpandaResources `json:"resources"` Storage Storage `json:"storage"` - PostInstallJob PostInstallJob `json:"post_install_job"` - PostUpgradeJob PostUpgradeJob `json:"post_upgrade_job"` + PostInstallJob PostInstallJob `json:"post_install_job" jsonschema:"required"` + PostUpgradeJob PostUpgradeJob `json:"post_upgrade_job" jsonschema:"required"` Statefulset Statefulset `json:"statefulset"` ServiceAccount ServiceAccount `json:"serviceAccount"` RBAC RBAC `json:"rbac"` Tuning Tuning `json:"tuning"` - Listeners Listeners `json:"listeners"` + Listeners Listeners `json:"listeners" jsonschema:"required"` Config Config `json:"config"` Tests *struct { Enabled bool `json:"enabled"` @@ -125,8 +125,8 @@ type Auth struct { } type TLS struct { - Enabled *bool `json:"enabled" jsonschema:"required"` - Certs *TLSCertMap `json:"certs"` + Enabled *bool `json:"enabled" jsonschema:"required"` + Certs TLSCertMap `json:"certs"` } type ExternalConfig struct { @@ -233,7 +233,7 @@ type PodTemplate struct { type Statefulset struct { NodeAffinity map[string]any `json:"nodeAffinity"` - Replicas int `json:"replicas" jsonschema:"required"` + Replicas int `json:"replicas" jsonschema:"required,maximum=250"` UpdateStrategy struct { Type string `json:"type" jsonschema:"required,pattern=^(RollingUpdate|OnDelete)$"` } `json:"updateStrategy" jsonschema:"required"` @@ -381,6 +381,7 @@ type JobResources struct { Memory MemoryAmount `json:"memory"` } `json:"requests"` } + type SchemaRegistryClient struct { Retries int `json:"retries"` RetryBaseBackoffMS int `json:"retry_base_backoff_ms"` diff --git a/charts/redpanda/values.schema.json b/charts/redpanda/values.schema.json index f71e53f32e..b9981b2bfe 100644 --- a/charts/redpanda/values.schema.json +++ b/charts/redpanda/values.schema.json @@ -1282,6 +1282,7 @@ "type": "object" }, "replicas": { + "maximum": 250, "type": "integer" }, "securityContext": { @@ -1909,7 +1910,11 @@ } }, "required": [ - "image" + "image", + "tls", + "post_install_job", + "post_upgrade_job", + "listeners" ], "type": "object" } diff --git a/charts/redpanda/values_partial.gen.go b/charts/redpanda/values_partial.gen.go index 5c2c396695..51d632956c 100644 --- a/charts/redpanda/values_partial.gen.go +++ b/charts/redpanda/values_partial.gen.go @@ -22,19 +22,19 @@ type PartialValues struct { RackAwareness *PartialRackAwareness `json:"rackAwareness,omitempty"` Auth *PartialAuth `json:"auth,omitempty"` - TLS *PartialTLS `json:"tls,omitempty"` + TLS *PartialTLS `json:"tls,omitempty" jsonschema:"required"` External *PartialExternalConfig `json:"external,omitempty"` Logging *PartialLogging `json:"logging,omitempty"` Monitoring *PartialMonitoring `json:"monitoring,omitempty"` Resources *PartialRedpandaResources `json:"resources,omitempty"` Storage *PartialStorage `json:"storage,omitempty"` - PostInstallJob *PartialPostInstallJob `json:"post_install_job,omitempty"` - PostUpgradeJob *PartialPostUpgradeJob `json:"post_upgrade_job,omitempty"` + PostInstallJob *PartialPostInstallJob `json:"post_install_job,omitempty" jsonschema:"required"` + PostUpgradeJob *PartialPostUpgradeJob `json:"post_upgrade_job,omitempty" jsonschema:"required"` Statefulset *PartialStatefulset `json:"statefulset,omitempty"` ServiceAccount *PartialServiceAccount `json:"serviceAccount,omitempty"` RBAC *PartialRBAC `json:"rbac,omitempty"` Tuning *PartialTuning `json:"tuning,omitempty"` - Listeners *PartialListeners `json:"listeners,omitempty"` + Listeners *PartialListeners `json:"listeners,omitempty" jsonschema:"required"` Config *PartialConfig `json:"config,omitempty"` Tests *struct { Enabled *bool `json:"enabled,omitempty"` @@ -183,7 +183,7 @@ type PartialPodTemplate struct { type PartialStatefulset struct { NodeAffinity map[string]any `json:"nodeAffinity,omitempty"` - Replicas *int `json:"replicas,omitempty" jsonschema:"required"` + Replicas *int `json:"replicas,omitempty" jsonschema:"required,maximum=250"` UpdateStrategy struct { Type *string `json:"type,omitempty" jsonschema:"required,pattern=^(RollingUpdate|OnDelete)$"` } `json:"updateStrategy,omitempty" jsonschema:"required"` diff --git a/flake.nix b/flake.nix index bde18f3354..cbc0c63f12 100644 --- a/flake.nix +++ b/flake.nix @@ -91,7 +91,8 @@ # it uses reflection. "^charts$" "^charts/redpanda$" - "^charts(/.*\.go)?$" + "^charts/.*\.go$" + "^charts/.*\.schema.json$" ]; }; };