Skip to content

Commit 3d0a2b8

Browse files
committed
CLOUDP-381747: Generate Group
Signed-off-by: Jose Vazquez <jose.vazquez@mongodb.com>
1 parent 76c4547 commit 3d0a2b8

File tree

7 files changed

+210
-41
lines changed

7 files changed

+210
-41
lines changed

Makefile

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -671,8 +671,10 @@ gen-sdlc-checklist: ## Generate the SDLC checklist
671671
install-crds: manifests ## Install CRDs in Kubernetes
672672
kubectl apply -k config/crd
673673
ifdef EXPERIMENTAL
674-
$(MAKE) regen-crds
675-
kubectl apply -f config/generated/crd/bases/crds.yaml
674+
@if [ -f config/generated/crd/bases/crds.experimental.yaml ]; then \
675+
echo "Installing experimental CRDs..."; \
676+
kubectl apply -f config/generated/crd/bases/crds.experimental.yaml; \
677+
fi
676678
endif
677679

678680
.PHONY: set-namespace
@@ -927,6 +929,11 @@ gen-crds: tools/openapi2crd/bin/openapi2crd
927929
$(OPENAPI2CRD) --config config/openapi2crd.yaml \
928930
--output $(realpath .)/config/generated/crd/bases/crds.yaml
929931
cp $(realpath .)/config/generated/crd/bases/crds.yaml $(realpath .)/internal/generated/crds/crds.yaml
932+
$(MAKE) split-generated-crds
933+
934+
.PHONY: split-generated-crds
935+
split-generated-crds: ## Split generated CRDs into production and experimental
936+
@./scripts/split-generated-crds.sh
930937

931938
.PHONY: regen-crds
932939
regen-crds: clean-gen-crds gen-crds ## Clean and regenerate CRDs
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[
2+
"Group"
3+
]
4+

internal/controller/registry.go

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -123,35 +123,18 @@ func (r *Registry) registerControllers(c cluster.Cluster, ap atlas.Provider) err
123123
}
124124

125125
var reconcilers []Reconciler
126-
reconcilers = append(reconcilers, atlasproject.NewAtlasProjectReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.logger, r.globalSecretRef, r.maxConcurrentReconciles))
127-
reconcilers = append(reconcilers, atlasdeployment.NewAtlasDeploymentReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.independentSyncPeriod, r.logger, r.globalSecretRef, r.maxConcurrentReconciles))
128-
reconcilers = append(reconcilers, atlasdatabaseuser.NewAtlasDatabaseUserReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.independentSyncPeriod, r.featureFlags, r.logger, r.globalSecretRef, r.maxConcurrentReconciles))
129-
reconcilers = append(reconcilers, atlasdatafederation.NewAtlasDataFederationReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.logger, r.globalSecretRef, r.maxConcurrentReconciles))
130-
reconcilers = append(reconcilers, atlasfederatedauth.NewAtlasFederatedAuthReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.logger, r.globalSecretRef, r.maxConcurrentReconciles))
131-
reconcilers = append(reconcilers, atlasstream.NewAtlasStreamsInstanceReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.logger, r.globalSecretRef, r.maxConcurrentReconciles))
132-
reconcilers = append(reconcilers, atlasstream.NewAtlasStreamsConnectionReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.logger, r.maxConcurrentReconciles))
133-
reconcilers = append(reconcilers, atlassearchindexconfig.NewAtlasSearchIndexConfigReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.logger, r.maxConcurrentReconciles))
134-
reconcilers = append(reconcilers, atlasbackupcompliancepolicy.NewAtlasBackupCompliancePolicyReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.logger, r.maxConcurrentReconciles))
135-
reconcilers = append(reconcilers, atlascustomrole.NewAtlasCustomRoleReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.independentSyncPeriod, r.logger, r.globalSecretRef, r.maxConcurrentReconciles))
136-
reconcilers = append(reconcilers, atlasprivateendpoint.NewAtlasPrivateEndpointReconciler(c, r.defaultPredicates(), ap, r.deletionProtection, r.independentSyncPeriod, r.logger, r.globalSecretRef, r.maxConcurrentReconciles))
137-
reconcilers = append(reconcilers, atlasipaccesslist.NewAtlasIPAccessListReconciler(c, r.defaultPredicates(), ap, r.deletionProtection, r.independentSyncPeriod, r.logger, r.globalSecretRef, r.maxConcurrentReconciles))
138-
reconcilers = append(reconcilers, atlasnetworkcontainer.NewAtlasNetworkContainerReconciler(c, r.defaultPredicates(), ap, r.deletionProtection, r.logger, r.independentSyncPeriod, r.globalSecretRef, r.maxConcurrentReconciles))
139-
reconcilers = append(reconcilers, atlasnetworkpeering.NewAtlasNetworkPeeringsReconciler(c, r.defaultPredicates(), ap, r.deletionProtection, r.logger, r.independentSyncPeriod, r.globalSecretRef, r.maxConcurrentReconciles))
126+
reconcilers = append(reconcilers, r.legacyReconcilers(c, ap)...)
140127

141-
orgSettingsReconciler := atlasorgsettings.NewAtlasOrgSettingsReconciler(c, ap, r.logger, r.globalSecretRef, r.reapplySupport)
142-
reconcilers = append(reconcilers, newCtrlStateReconciler(orgSettingsReconciler, r.maxConcurrentReconciles))
143-
integrationsReconciler := integrations.NewAtlasThirdPartyIntegrationsReconciler(c, ap, r.deletionProtection, r.logger, r.globalSecretRef, r.reapplySupport)
144-
reconcilers = append(reconcilers, newCtrlStateReconciler(integrationsReconciler, r.maxConcurrentReconciles))
128+
generatedReconcilers, err := r.generatedReconcilers(c, ap)
129+
if err != nil {
130+
return fmt.Errorf("error creating generated reconcilers: %w", err)
131+
}
132+
reconcilers = append(reconcilers, generatedReconcilers...)
145133

146134
if version.IsExperimental() {
147135
// Add experimental controllers here
148136
reconcilers = append(reconcilers, connectionsecret.NewConnectionSecretReconciler(c, r.defaultPredicates(), ap, r.logger, r.globalSecretRef))
149137

150-
groupReconciler, err := group.NewGroupReconciler(c, ap, r.logger, r.globalSecretRef, r.deletionProtection, true, r.defaultPredicates())
151-
if err != nil {
152-
return fmt.Errorf("error creating group reconciler: %w", err)
153-
}
154-
155138
clusterController, err := akov2generatedcluster.NewClusterReconciler(c, ap, r.logger, r.globalSecretRef, r.deletionProtection, true, r.defaultPredicates())
156139
if err != nil {
157140
return fmt.Errorf("error creating cluster reconciler: %w", err)
@@ -168,7 +151,6 @@ func (r *Registry) registerControllers(c cluster.Cluster, ap atlas.Provider) err
168151
}
169152

170153
reconcilers = append(reconcilers,
171-
newCtrlStateReconciler(groupReconciler, r.maxConcurrentReconciles),
172154
newCtrlStateReconciler(clusterController, r.maxConcurrentReconciles),
173155
newCtrlStateReconciler(flexController, r.maxConcurrentReconciles),
174156
newCtrlStateReconciler(databaseUserReconciler, r.maxConcurrentReconciles),
@@ -180,6 +162,43 @@ func (r *Registry) registerControllers(c cluster.Cluster, ap atlas.Provider) err
180162
return nil
181163
}
182164

165+
func (r *Registry) legacyReconcilers(c cluster.Cluster, ap atlas.Provider) []Reconciler {
166+
var reconcilers []Reconciler
167+
reconcilers = append(reconcilers, atlasproject.NewAtlasProjectReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.logger, r.globalSecretRef, r.maxConcurrentReconciles))
168+
reconcilers = append(reconcilers, atlasdeployment.NewAtlasDeploymentReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.independentSyncPeriod, r.logger, r.globalSecretRef, r.maxConcurrentReconciles))
169+
reconcilers = append(reconcilers, atlasdatabaseuser.NewAtlasDatabaseUserReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.independentSyncPeriod, r.featureFlags, r.logger, r.globalSecretRef, r.maxConcurrentReconciles))
170+
reconcilers = append(reconcilers, atlasdatafederation.NewAtlasDataFederationReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.logger, r.globalSecretRef, r.maxConcurrentReconciles))
171+
reconcilers = append(reconcilers, atlasfederatedauth.NewAtlasFederatedAuthReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.logger, r.globalSecretRef, r.maxConcurrentReconciles))
172+
reconcilers = append(reconcilers, atlasstream.NewAtlasStreamsInstanceReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.logger, r.globalSecretRef, r.maxConcurrentReconciles))
173+
reconcilers = append(reconcilers, atlasstream.NewAtlasStreamsConnectionReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.logger, r.maxConcurrentReconciles))
174+
reconcilers = append(reconcilers, atlassearchindexconfig.NewAtlasSearchIndexConfigReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.logger, r.maxConcurrentReconciles))
175+
reconcilers = append(reconcilers, atlasbackupcompliancepolicy.NewAtlasBackupCompliancePolicyReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.logger, r.maxConcurrentReconciles))
176+
reconcilers = append(reconcilers, atlascustomrole.NewAtlasCustomRoleReconciler(c, r.deprecatedPredicates(), ap, r.deletionProtection, r.independentSyncPeriod, r.logger, r.globalSecretRef, r.maxConcurrentReconciles))
177+
reconcilers = append(reconcilers, atlasprivateendpoint.NewAtlasPrivateEndpointReconciler(c, r.defaultPredicates(), ap, r.deletionProtection, r.independentSyncPeriod, r.logger, r.globalSecretRef, r.maxConcurrentReconciles))
178+
reconcilers = append(reconcilers, atlasipaccesslist.NewAtlasIPAccessListReconciler(c, r.defaultPredicates(), ap, r.deletionProtection, r.independentSyncPeriod, r.logger, r.globalSecretRef, r.maxConcurrentReconciles))
179+
reconcilers = append(reconcilers, atlasnetworkcontainer.NewAtlasNetworkContainerReconciler(c, r.defaultPredicates(), ap, r.deletionProtection, r.logger, r.independentSyncPeriod, r.globalSecretRef, r.maxConcurrentReconciles))
180+
reconcilers = append(reconcilers, atlasnetworkpeering.NewAtlasNetworkPeeringsReconciler(c, r.defaultPredicates(), ap, r.deletionProtection, r.logger, r.independentSyncPeriod, r.globalSecretRef, r.maxConcurrentReconciles))
181+
182+
orgSettingsReconciler := atlasorgsettings.NewAtlasOrgSettingsReconciler(c, ap, r.logger, r.globalSecretRef, r.reapplySupport)
183+
reconcilers = append(reconcilers, newCtrlStateReconciler(orgSettingsReconciler, r.maxConcurrentReconciles))
184+
integrationsReconciler := integrations.NewAtlasThirdPartyIntegrationsReconciler(c, ap, r.deletionProtection, r.logger, r.globalSecretRef, r.reapplySupport)
185+
reconcilers = append(reconcilers, newCtrlStateReconciler(integrationsReconciler, r.maxConcurrentReconciles))
186+
187+
return reconcilers
188+
}
189+
190+
func (r *Registry) generatedReconcilers(c cluster.Cluster, ap atlas.Provider) ([]Reconciler, error) {
191+
var reconcilers []Reconciler
192+
193+
groupReconciler, err := group.NewGroupReconciler(c, ap, r.logger, r.globalSecretRef, r.deletionProtection, true, r.defaultPredicates())
194+
if err != nil {
195+
return nil, fmt.Errorf("error creating group reconciler: %w", err)
196+
}
197+
reconcilers = append(reconcilers, newCtrlStateReconciler(groupReconciler, r.maxConcurrentReconciles))
198+
199+
return reconcilers, nil
200+
}
201+
183202
// deprecatedPredicates are to be phased out in favor of defaultPredicates
184203
func (r *Registry) deprecatedPredicates() []predicate.Predicate {
185204
return append(r.sharedPredicates, watch.DeprecatedCommonPredicates[client.Object]())

internal/indexer/indexer.go

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,21 @@ type Indexer interface {
3939
func RegisterAll(ctx context.Context, c cluster.Cluster, logger *zap.Logger) error {
4040
logger = logger.Named("indexer")
4141
indexers := []Indexer{}
42-
indexers = append(indexers,
42+
indexers = append(indexers, legacyIndexers(ctx, c, logger)...)
43+
indexers = append(indexers, generatedIndexers(logger)...)
44+
45+
if version.IsExperimental() {
46+
// add experimental indexers here
47+
indexers = append(indexers,
48+
connectionsecretindexer.NewDatabaseUserBySecretIndexer(ctx, c.GetClient(), logger),
49+
indexer.NewDatabaseUserBySecretIndexer(logger),
50+
)
51+
}
52+
return Register(ctx, c, indexers...)
53+
}
54+
55+
func legacyIndexers(ctx context.Context, c cluster.Cluster, logger *zap.Logger) []Indexer {
56+
return []Indexer{
4357
NewAtlasBackupScheduleByBackupPolicyIndexer(logger),
4458
NewAtlasDeploymentByBackupScheduleIndexer(logger),
4559
NewAtlasDeploymentBySearchIndexIndexer(logger),
@@ -70,21 +84,18 @@ func RegisterAll(ctx context.Context, c cluster.Cluster, logger *zap.Logger) err
7084
NewAtlasThirdPartyIntegrationByCredentialIndexer(logger),
7185
NewAtlasThirdPartyIntegrationBySecretsIndexer(logger),
7286
NewAtlasOrgSettingsByConnectionSecretIndexer(logger),
73-
)
74-
if version.IsExperimental() {
75-
// add experimental indexers here
76-
indexers = append(indexers,
77-
connectionsecretindexer.NewFlexClusterByGroupIdIndexer(logger),
78-
connectionsecretindexer.NewClusterByGroupIdIndexer(logger),
79-
connectionsecretindexer.NewDatabaseUserBySecretIndexer(ctx, c.GetClient(), logger),
87+
}
88+
}
8089

81-
indexer.NewFlexClusterByGroupIndexer(logger),
82-
indexer.NewClusterByGroupIndexer(logger),
83-
indexer.NewDatabaseUserBySecretIndexer(logger),
84-
indexer.NewDatabaseUserByGroupIndexer(logger),
85-
)
90+
func generatedIndexers(logger *zap.Logger) []Indexer {
91+
return []Indexer{
92+
// Group-related indexers (Group is production-ready)
93+
indexer.NewDatabaseUserByGroupIndexer(logger),
94+
indexer.NewClusterByGroupIndexer(logger),
95+
indexer.NewFlexClusterByGroupIndexer(logger),
96+
connectionsecretindexer.NewClusterByGroupIdIndexer(logger),
97+
connectionsecretindexer.NewFlexClusterByGroupIdIndexer(logger),
8698
}
87-
return Register(ctx, c, indexers...)
8899
}
89100

90101
// Register registers the given indexers to the given manager's field indexer.

internal/operator/builder_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import (
4141
akov2 "github.com/mongodb/mongodb-atlas-kubernetes/v2/api/v1"
4242
"github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/featureflags"
4343
"github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/mocks/atlas"
44+
generatedv1 "github.com/mongodb/mongodb-atlas-kubernetes/v2/internal/nextapi/generated/v1"
4445
)
4546

4647
type managerMock struct {
@@ -163,6 +164,7 @@ func TestBuildManager(t *testing.T) {
163164
akoScheme := runtime.NewScheme()
164165
require.NoError(t, akov2.AddToScheme(akoScheme))
165166
require.NoError(t, corev1.AddToScheme(akoScheme))
167+
require.NoError(t, generatedv1.AddToScheme(akoScheme))
166168

167169
mgrMock := &managerMock{}
168170
builder := NewBuilder(mgrMock, akoScheme, 5*time.Minute)

internal/run/run.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,10 @@ func Run(ctx context.Context, fs *flag.FlagSet, args []string) error {
7979
ctrl.SetLogger(logrLogger.WithName("ctrl"))
8080
klog.SetLogger(logrLogger.WithName("klog"))
8181
setupLog := logger.Named("setup").Sugar()
82+
// Register generatedv1 scheme unconditionally (Group controller is production-ready)
83+
utilruntime.Must(generatedv1.AddToScheme(akoScheme))
8284
if version.IsExperimental() {
8385
setupLog.Warn("Experimental features enabled!")
84-
utilruntime.Must(generatedv1.AddToScheme(akoScheme))
8586
utilruntime.Must(apiextensionsv1.AddToScheme(akoScheme))
8687
}
8788
setupLog.Info("starting with configuration", zap.Any("config", config), zap.Any("version", version.Version))

scripts/split-generated-crds.sh

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#!/bin/bash
2+
# Copyright 2025 MongoDB Inc
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
16+
# Split generated CRDs into production (individual files for kustomize) and experimental (aggregated file)
17+
#
18+
# This script reads config/generated/crd/bases/crds.yaml and:
19+
# - Production CRDs: extracts to individual files in config/crd/bases/{name}.yaml and adds to kustomization
20+
# - Experimental CRDs: aggregates into config/generated/crd/bases/crds.experimental.yaml
21+
#
22+
# Production CRDs are determined by the kinds listed in config/generated/crd/production-kinds.txt
23+
24+
set -euo pipefail
25+
26+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
27+
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
28+
CRD_BASES_DIR="$REPO_ROOT/config/generated/crd/bases"
29+
PRODUCTION_KINDS_FILE="$REPO_ROOT/config/generated/crd/production-kinds.json"
30+
ALL_CRDS_FILE="$CRD_BASES_DIR/crds.yaml"
31+
EXP_CRDS_FILE="$CRD_BASES_DIR/crds.experimental.yaml"
32+
LEGACY_CRD_BASES_DIR="$REPO_ROOT/config/crd/bases"
33+
34+
cd "$REPO_ROOT"
35+
36+
if [ ! -f "$ALL_CRDS_FILE" ]; then
37+
echo "Error: $ALL_CRDS_FILE not found. Run 'make gen-crds' first." >&2
38+
exit 1
39+
fi
40+
41+
if ! command -v yq >/dev/null 2>&1; then
42+
echo "Error: yq is required but not found. Please install yq." >&2
43+
exit 1
44+
fi
45+
46+
if ! command -v jq >/dev/null 2>&1; then
47+
echo "Error: jq is required but not found. Please install jq." >&2
48+
exit 1
49+
fi
50+
51+
# Read production kinds from JSON file
52+
PRODUCTION_KINDS_JQ="[]"
53+
if [ -f "$PRODUCTION_KINDS_FILE" ]; then
54+
PRODUCTION_KINDS_JQ=$(jq '.' "$PRODUCTION_KINDS_FILE" 2>/dev/null || echo "[]")
55+
fi
56+
57+
if [ "$PRODUCTION_KINDS_JQ" = "[]" ] || [ -z "$PRODUCTION_KINDS_JQ" ]; then
58+
echo "Warning: No production kinds found. All CRDs will be experimental." >&2
59+
echo "# Experimental CRDs" > "$EXP_CRDS_FILE"
60+
cp "$ALL_CRDS_FILE" "$EXP_CRDS_FILE"
61+
echo "✅ CRDs split successfully (all experimental)"
62+
exit 0
63+
fi
64+
65+
echo "Production kinds: $(echo "$PRODUCTION_KINDS_JQ" | jq -r '.[]' | tr '\n' ' ')"
66+
echo "Initializing experimental CRDs file..."
67+
echo "# Experimental CRDs" > "$EXP_CRDS_FILE"
68+
69+
prod_count=0
70+
exp_count=0
71+
first_experimental=true
72+
73+
# Convert CRDs to JSON array and process with jq
74+
temp_json=$(mktemp)
75+
yq eval-all 'select(.kind == "CustomResourceDefinition")' "$ALL_CRDS_FILE" -o json | jq -s '.' > "$temp_json"
76+
77+
# Process each CRD using jq - output name, kind, and is_production flag
78+
# Use process substitution (< <(...)) instead of pipe to avoid subshell issues with counters
79+
while IFS='|' read -r crd_name crd_kind is_production; do
80+
if [ -z "$crd_name" ] || [ -z "$crd_kind" ]; then
81+
continue
82+
fi
83+
84+
# Extract the CRD JSON for this specific CRD
85+
crd_json=$(jq -r --arg name "$crd_name" '.[] | select(.metadata.name == $name and .kind == "CustomResourceDefinition")' "$temp_json")
86+
87+
if [ "$is_production" = "true" ]; then
88+
# Production CRD: write to individual file as YAML
89+
output_file="$LEGACY_CRD_BASES_DIR/$crd_name.yaml"
90+
echo "$crd_json" | jq . | yq eval -P - > "$output_file"
91+
echo " Production: $crd_name"
92+
prod_count=$((prod_count + 1))
93+
94+
# Add to kustomization.yaml if it exists
95+
if [ -f "$LEGACY_CRD_BASES_DIR/kustomization.yaml" ]; then
96+
cd "$LEGACY_CRD_BASES_DIR"
97+
# Add resource if not already present
98+
if ! yq eval ".resources[] | select(. == \"$crd_name.yaml\")" kustomization.yaml >/dev/null 2>&1; then
99+
yq eval -i "(.resources // []) += [\"$crd_name.yaml\"] | .resources |= unique" kustomization.yaml
100+
fi
101+
cd "$REPO_ROOT"
102+
fi
103+
else
104+
# Experimental CRD: append to experimental file as YAML
105+
# Add YAML document separator before each CRD (except the first)
106+
if [ "$first_experimental" = false ]; then
107+
echo "---" >> "$EXP_CRDS_FILE"
108+
fi
109+
echo "$crd_json" | jq . | yq eval -P - >> "$EXP_CRDS_FILE"
110+
echo " Experimental: $crd_name"
111+
exp_count=$((exp_count + 1))
112+
first_experimental=false
113+
fi
114+
done < <(jq -r --argjson prod_kinds "$PRODUCTION_KINDS_JQ" '
115+
.[] |
116+
select(.kind == "CustomResourceDefinition") |
117+
.spec.names.kind as $kind |
118+
.metadata.name as $name |
119+
($prod_kinds | index($kind) != null) as $is_prod |
120+
"\($name)|\($kind)|\($is_prod)"
121+
' "$temp_json")
122+
123+
rm -f "$temp_json"
124+
125+
echo "✅ Split $prod_count production CRDs (individual files) and $exp_count experimental CRDs (aggregated)"

0 commit comments

Comments
 (0)