Fix operatorconfigurations CRD: NamespacedName must render as type string (#3145)
Upgrading to v2.0.0 fails at the CRD apply step. The apiserver rejects the
OperatorConfiguration CRD:
CustomResourceDefinition "operatorconfigurations.acid.zalan.do" is invalid:
...oauth_token_secret_name.default: Invalid value: "string": in body must
be of type object
Root cause: these CRDs are generated by controller-gen from the Go types.
spec.NamespacedName is a struct {Namespace, Name}, so controller-gen emits an
object schema for every NamespacedName field. But NamespacedName has custom
MarshalJSON/UnmarshalJSON that (de)serialize it as a plain JSON string
("namespace/name"). The generated object schema therefore never matched how
the operator actually reads and writes these fields (it did in 1.15.x, where
they were type: string).
For oauth_token_secret_name this is a hard failure: it also carries
`// +kubebuilder:default=postgres-operator`, and a scalar string default on an
object-typed property is rejected by the apiserver, blocking the whole
1.15.x -> 2.0.0 upgrade before the operator Deployment is touched.
Fix at the source by annotating the NamespacedName type with
`// +kubebuilder:validation:Type=string` and regenerating the CRDs. This makes
controller-gen emit `type: string` for all NamespacedName fields
(oauth_token_secret_name, infrastructure_roles_secret_name,
pod_environment_configmap, and the nested infrastructure role secretname),
matching their runtime serialization and restoring 1.15.x behaviour. A
field-level Type override cannot be used here: it conflicts with the
struct-derived schema ("object vs string in allOf") and fails generation.
Regenerated manifests/operatorconfiguration.crd.yaml and its two synced
copies (pkg/apis/... embed source and charts/.../crds). Verified with a
server-side dry-run apply: the unpatched CRD is rejected, the regenerated CRD
is accepted.
Fixes #3143
This commit is contained in:
parent
8eda2cd1a2
commit
29168ca0bc
|
|
@ -226,24 +226,7 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
infrastructure_roles_secret_name:
|
||||
description: |-
|
||||
NamespacedName comprises a resource name, with a mandatory namespace,
|
||||
rendered as "<namespace>/<name>". Being a type captures intent and
|
||||
helps make sure that UIDs, namespaced names and non-namespaced names
|
||||
do not get conflated in code. For most use cases, namespace and name
|
||||
will already have been format validated at the API entry point, so we
|
||||
don't do that here. Where that's not the case (e.g. in testing),
|
||||
consider using NamespacedNameOrDie() in testing.go in this package.
|
||||
|
||||
from: https://github.com/kubernetes/apimachinery/blob/master/pkg/types/namespacedname.go
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: string
|
||||
infrastructure_roles_secrets:
|
||||
description: namespaced name of the secret containing infrastructure
|
||||
roles names and passwords
|
||||
|
|
@ -265,14 +248,7 @@ spec:
|
|||
description: |-
|
||||
Name of a secret which describes the role, and optionally name of a
|
||||
configmap with an extra information
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: string
|
||||
template:
|
||||
type: boolean
|
||||
userkey:
|
||||
|
|
@ -458,14 +434,7 @@ spec:
|
|||
default: postgres-operator
|
||||
description: namespaced name of the secret containing the OAuth2
|
||||
token to pass to the teams API
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: string
|
||||
pdb_master_label_selector:
|
||||
default: true
|
||||
type: boolean
|
||||
|
|
@ -485,14 +454,7 @@ spec:
|
|||
pod_environment_configmap:
|
||||
description: namespaced name of the ConfigMap with environment
|
||||
variables to populate on every pod
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: string
|
||||
pod_environment_secret:
|
||||
type: string
|
||||
pod_management_policy:
|
||||
|
|
|
|||
|
|
@ -226,24 +226,7 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
infrastructure_roles_secret_name:
|
||||
description: |-
|
||||
NamespacedName comprises a resource name, with a mandatory namespace,
|
||||
rendered as "<namespace>/<name>". Being a type captures intent and
|
||||
helps make sure that UIDs, namespaced names and non-namespaced names
|
||||
do not get conflated in code. For most use cases, namespace and name
|
||||
will already have been format validated at the API entry point, so we
|
||||
don't do that here. Where that's not the case (e.g. in testing),
|
||||
consider using NamespacedNameOrDie() in testing.go in this package.
|
||||
|
||||
from: https://github.com/kubernetes/apimachinery/blob/master/pkg/types/namespacedname.go
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: string
|
||||
infrastructure_roles_secrets:
|
||||
description: namespaced name of the secret containing infrastructure
|
||||
roles names and passwords
|
||||
|
|
@ -265,14 +248,7 @@ spec:
|
|||
description: |-
|
||||
Name of a secret which describes the role, and optionally name of a
|
||||
configmap with an extra information
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: string
|
||||
template:
|
||||
type: boolean
|
||||
userkey:
|
||||
|
|
@ -458,14 +434,7 @@ spec:
|
|||
default: postgres-operator
|
||||
description: namespaced name of the secret containing the OAuth2
|
||||
token to pass to the teams API
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: string
|
||||
pdb_master_label_selector:
|
||||
default: true
|
||||
type: boolean
|
||||
|
|
@ -485,14 +454,7 @@ spec:
|
|||
pod_environment_configmap:
|
||||
description: namespaced name of the ConfigMap with environment
|
||||
variables to populate on every pod
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: string
|
||||
pod_environment_secret:
|
||||
type: string
|
||||
pod_management_policy:
|
||||
|
|
|
|||
|
|
@ -226,24 +226,7 @@ spec:
|
|||
type: string
|
||||
type: array
|
||||
infrastructure_roles_secret_name:
|
||||
description: |-
|
||||
NamespacedName comprises a resource name, with a mandatory namespace,
|
||||
rendered as "<namespace>/<name>". Being a type captures intent and
|
||||
helps make sure that UIDs, namespaced names and non-namespaced names
|
||||
do not get conflated in code. For most use cases, namespace and name
|
||||
will already have been format validated at the API entry point, so we
|
||||
don't do that here. Where that's not the case (e.g. in testing),
|
||||
consider using NamespacedNameOrDie() in testing.go in this package.
|
||||
|
||||
from: https://github.com/kubernetes/apimachinery/blob/master/pkg/types/namespacedname.go
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: string
|
||||
infrastructure_roles_secrets:
|
||||
description: namespaced name of the secret containing infrastructure
|
||||
roles names and passwords
|
||||
|
|
@ -265,14 +248,7 @@ spec:
|
|||
description: |-
|
||||
Name of a secret which describes the role, and optionally name of a
|
||||
configmap with an extra information
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: string
|
||||
template:
|
||||
type: boolean
|
||||
userkey:
|
||||
|
|
@ -458,14 +434,7 @@ spec:
|
|||
default: postgres-operator
|
||||
description: namespaced name of the secret containing the OAuth2
|
||||
token to pass to the teams API
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: string
|
||||
pdb_master_label_selector:
|
||||
default: true
|
||||
type: boolean
|
||||
|
|
@ -485,14 +454,7 @@ spec:
|
|||
pod_environment_configmap:
|
||||
description: namespaced name of the ConfigMap with environment
|
||||
variables to populate on every pod
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
namespace:
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: string
|
||||
pod_environment_secret:
|
||||
type: string
|
||||
pod_management_policy:
|
||||
|
|
|
|||
|
|
@ -23,6 +23,11 @@ import (
|
|||
// consider using NamespacedNameOrDie() in testing.go in this package.
|
||||
//
|
||||
// from: https://github.com/kubernetes/apimachinery/blob/master/pkg/types/namespacedname.go
|
||||
//
|
||||
// NamespacedName marshals to and unmarshals from a plain JSON string
|
||||
// ("<namespace>/<name>") via its custom MarshalJSON/UnmarshalJSON, so its CRD
|
||||
// schema must be a string rather than the struct controller-gen would infer.
|
||||
// +kubebuilder:validation:Type=string
|
||||
type NamespacedName struct {
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Name string `json:"name"`
|
||||
|
|
|
|||
Loading…
Reference in New Issue