fix(crdinstall): hardcode CRD GVK, add timeout test, document dual install

- Use explicit apiextensions.k8s.io/v1 CRD GVK in waitForCRDsEstablished
  instead of fragile objects[0].GroupVersionKind()
- Add TestInstall_crdNotEstablished for context timeout path
- Add --recursive to diff in verify-crds Makefile target
- Document why both crds/ and --install-crds exist in deployment template

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
This commit is contained in:
Aleksei Sviridkin 2026-02-17 23:49:20 +03:00
parent 962f8e96f4
commit b3fe6a8c4a
No known key found for this signature in database
GPG key ID: 7988329FDF395282
4 changed files with 56 additions and 2 deletions

View file

@ -81,7 +81,7 @@ test:
make -C packages/core/testing test
verify-crds:
@diff packages/core/installer/crds/ internal/crdinstall/manifests/ --exclude=.gitattributes \
@diff --recursive packages/core/installer/crds/ internal/crdinstall/manifests/ --exclude=.gitattributes \
|| (echo "ERROR: CRD manifests out of sync. Run 'make generate' to fix." && exit 1)
unit-tests: helm-unit-tests verify-crds

View file

@ -28,6 +28,7 @@ import (
"time"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
k8syaml "k8s.io/apimachinery/pkg/util/yaml"
"sigs.k8s.io/controller-runtime/pkg/client"
@ -124,7 +125,11 @@ func waitForCRDsEstablished(ctx context.Context, k8sClient client.Client, object
allEstablished := true
for _, name := range crdNames {
crd := &unstructured.Unstructured{}
crd.SetGroupVersionKind(objects[0].GroupVersionKind())
crd.SetGroupVersionKind(schema.GroupVersionKind{
Group: "apiextensions.k8s.io",
Version: "v1",
Kind: "CustomResourceDefinition",
})
if err := k8sClient.Get(ctx, types.NamespacedName{Name: name}, crd); err != nil {
allEstablished = false
break

View file

@ -354,6 +354,52 @@ func TestInstall_writeManifestsFails(t *testing.T) {
}
}
func TestInstall_crdNotEstablished(t *testing.T) {
log.SetLogger(zap.New(zap.UseDevMode(true)))
scheme := runtime.NewScheme()
if err := apiextensionsv1.AddToScheme(scheme); err != nil {
t.Fatalf("failed to add apiextensions to scheme: %v", err)
}
// No interceptor: CRDs will never get Established condition
fakeClient := fake.NewClientBuilder().WithScheme(scheme).Build()
writeManifests := func(dir string) error {
crd := `apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: packages.cozystack.io
spec:
group: cozystack.io
names:
kind: Package
plural: packages
scope: Namespaced
versions:
- name: v1alpha1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
`
return os.WriteFile(filepath.Join(dir, "crd.yaml"), []byte(crd), 0600)
}
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
ctx = log.IntoContext(ctx, log.FromContext(context.Background()))
err := Install(ctx, fakeClient, writeManifests)
if err == nil {
t.Fatal("Install() expected error when CRDs never become established, got nil")
}
if !strings.Contains(err.Error(), "CRDs not established") {
t.Errorf("Install() error = %v, want error containing 'CRDs not established'", err)
}
}
func TestWriteEmbeddedManifests_filePermissions(t *testing.T) {
tmpDir := t.TempDir()

View file

@ -53,6 +53,9 @@ spec:
args:
- --leader-elect=true
- --install-flux=true
# CRDs are also in crds/ for initial helm install, but Helm never updates
# them on upgrade. The operator applies embedded CRDs via server-side apply
# on every startup, ensuring they stay up to date.
- --install-crds=true
- --metrics-bind-address=0
- --health-probe-bind-address=