Skip to content

Conversation

@mikkeloscar
Copy link
Member

@mikkeloscar mikkeloscar commented Dec 3, 2025

This introduces CRD (yaml) generation based on the Go structs by using controler-gen

It's only done for the Postgresteam type for now, with the intention to add more, the problem with the existing CRD manifests is that they have been managed "manually" so to get the generation correct/similar takes a bit of iteration.

Main value of this is that changes to the CRD only have to happen in one place (go) and then the CRD with schema is automatically updated.

The NamespacedName type was explicitly copied and adjusted from upstream because it gave the following error:

go tool controller-gen crd:crdVersions=v1,allowDangerousTypes=true paths=./pkg/apis/... output:crd:dir=manifests
/home/moscar/projects/go/pkg/mod/k8s.io/apimachinery@v0.32.9/pkg/types/namespacedname.go:28:2: encountered struct field "Namespace" without JSON tag in type "NamespacedName"
/home/moscar/projects/go/pkg/mod/k8s.io/apimachinery@v0.32.9/pkg/types/namespacedname.go:29:2: encountered struct field "Name" without JSON tag in type "NamespacedName"
Error: not all generators ran successfully

It was anyway defined as a local type so the interface doesn't change.

There are some changes to the go structs to make it possible to generate a proper CRD:

  • Custom types: Users, Teams, SuperUserTeams which are all just []string under the hood. This is needed to be able to have map value level descriptions (and future validation). This also requires some type conversion dance in pkg/teams/postgres_team.go but most of the interface is left the same.
  • I haven't found a way to set nullable: true at the map value level like it's set today in the CRD. I would also argue the API is clearer if you can't set a null value instead of an array. Will check compatibility with existing resources.

TODO

  • Validate new CRD against existing psotgresteam resources (at least in Zalando clusters) to validate that all existing resources a valid against the new schema.

This was validated by running the script:

check_pgteam.sh
#!/bin/bash

cluster="${1:-"playground"}"
resource_type="postgresteams"

# Check if resource type exists in the cluster
if ! kubectl --context "$cluster" api-resources | grep -q "${resource_type}"; then
    echo "Resource type '${resource_type}' not found in cluster '$cluster'"
    exit 0
fi

for rs in $(kubectl --context "$cluster" get "${resource_type}" --all-namespaces -o json | jq -c '.items[] | {deployment_id:.metadata.labels["deployment-id"], application:.metadata.labels.application,name: .metadata.name,namespace:.metadata.namespace}'); do
    name="$(echo -n "$rs" | jq -r '.name')"
    namespace="$(echo -n "$rs" | jq -r '.namespace')"

    # Get the last-applied-configuration annotation
    config=$(kubectl --context "$cluster" -n "$namespace" get "${resource_type}" "$name" \
        -o json | jq -r \
        '.metadata.annotations["kubectl.kubernetes.io/last-applied-configuration"]')

    # Skip if annotation doesn't exist
    if [[ "$config" == "null" ]]; then
        continue
    fi

    # Validate against target cluster, handling resource type errors
    validation=$(echo "$config" | kubectl --context teapot apply -f - --dry-run=server 2>&1)

    if [[ "$validation" == *"ValidationError"* ]] || [[ "$validation" == *"no matches for kind"* ]] || [[ "$validation" == *"the server doesn't have a resource type"* ]]; then
        # echo "{\"cluster\":\"$cluster\", $(echo "$fes" | sed 's/^{//')}"
        echo "$validation"
    fi
done

Against all clusters:

# setup new CRD in `teapot` cluster
kubectl --context teapot apply -f manifests/postgresteam.crd.yaml

# run check for all clusters
for c in $(zregistry clusters list --lifecycle-status ready -q); do ./check_pgteam.sh "$c"; done

@mikkeloscar mikkeloscar added do-not-merge major Major feature changes or updates, e.g. feature rollout to a new country, new API calls. labels Dec 3, 2025
@FxKu FxKu added this to the 2.0.0 milestone Dec 16, 2025
@FxKu FxKu moved this to Waiting for review in Postgres Operator Dec 16, 2025
@mikkeloscar mikkeloscar force-pushed the gen-crds-postgresteam branch from 3cec0d3 to 6028d75 Compare January 9, 2026 12:37
Base automatically changed from modern-go-tools to master January 9, 2026 13:22
Signed-off-by: Mikkel Oscar Lyderik Larsen <mikkel.larsen@zalando.de>
Signed-off-by: Mikkel Oscar Lyderik Larsen <mikkel.larsen@zalando.de>
@mikkeloscar mikkeloscar force-pushed the gen-crds-postgresteam branch from 6028d75 to dfce521 Compare January 9, 2026 15:12
@FxKu FxKu marked this pull request as ready for review January 9, 2026 16:29
@FxKu FxKu removed the do-not-merge label Jan 10, 2026
@FxKu FxKu moved this from Waiting for review to Good state for merge in Postgres Operator Jan 10, 2026
@FxKu
Copy link
Member

FxKu commented Jan 10, 2026

👍

1 similar comment
@mikkeloscar
Copy link
Member Author

👍

@mikkeloscar mikkeloscar merged commit 0a44252 into master Jan 10, 2026
10 checks passed
@mikkeloscar mikkeloscar deleted the gen-crds-postgresteam branch January 10, 2026 18:39
@github-project-automation github-project-automation bot moved this from Good state for merge to Done in Postgres Operator Jan 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

major Major feature changes or updates, e.g. feature rollout to a new country, new API calls.

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants