Repository navigation
Conversation
Add internal/testutils/integration, an importable package of fixtures for tests that run CLI commands against an envtest API server: Start sets up a cluster serving Crossplane's CRDs and those generated from a test's XRDs, with its manifests as Crossplane would have left them; CRDsForXRD and PinnedCrossplaneCRDsDir generate and locate CRDs; ReapOrphanedEnvtest kills envtest servers an earlier run left behind. The cluster fixtures build only with the integration tag. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com>
Pin envtest binaries and Crossplane's CRDs in Nix, add an integration-test app that runs the integration-tagged tests against them, and run it in a new integration-tests CI job with Go module caching. The unit tests get CROSSPLANE_CRDS_DIR for the CRD helper tests, and lint covers the integration tag. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 34 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
adamwg
left a comment
There was a problem hiding this comment.
A few questions/comments inline. I haven't reviewed fixtures.go in detail yet, but overall this looks good for me and the tests pass on my machine.
| # integration tests and the CRD helpers' unit tests. Pinned to the | ||
| # github.com/crossplane/crossplane/apis/v2 version in go.mod; bump rev and | ||
| # hash together when that changes. Tests find them through CROSSPLANE_CRDS_DIR. |
There was a problem hiding this comment.
Can we get renovate to update this for us? One option would be to have nix run .#tidy update it (renovate runs that after every go mod bump).
There was a problem hiding this comment.
Done in tidy as you asked.
| # envtest build, so callers can skip wiring them. | ||
| { pkgs }: | ||
| let | ||
| version = "1.30.3"; |
There was a problem hiding this comment.
Any reason not to match the k8s version from our go.mod (currently 1.35.3)? 1.30 has been EOL for over a year.
There was a problem hiding this comment.
envtest only has 1.35.0 so far, so using that.
There was a problem hiding this comment.
I noticed nixpkgs has a package for setup-envtest, which is the controller-tools utility for downloading the envtest binaries and setting relevant envvars. Seems like using it rather than constructing the hashes and URLs ourselves would be more robust.
This is already pretty tidy, so I don't feel strongly about using setup-envtest instead. But, I think it's worth a look to see if it can make it easier to keep this up-to-date.
There was a problem hiding this comment.
I think we can achieve the best of both worlds by making tidy fill in the hashes for us. That way, the tests never need network access (since setup-envtest downloads lazily) and the binaries still live in the nix store.
Integration tests only build with the integration tag, so reaching Start without envtest's binaries or Crossplane's CRDs means a broken environment. Fail loudly instead of skipping. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com>
…eout Start's per-call timeout duplicated go test's -timeout, which already bounds t.Context(). Drop the parameter and use the test's context. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com>
Match the k8s.io/api v0.35 minor that go.mod pins. 1.35.0 is the only 1.35 envtest release controller-tools publishes. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com>
After go mod tidy, tidy sets nix/crossplane-crds.nix's rev to go.mod's crossplane/crossplane/apis/v2 version and refreshes its hash the way it refreshes the vendor hash, so renovate's go.mod bumps carry it along. It fails rather than guess when the module is replaced or at a pseudo-version. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com>
tidy now sets nix/envtest-assets.nix to the newest envtest release for go.mod's k8s.io/api minor, taking each platform's sha512 from controller-tools' envtest-releases.yaml, the index setup-envtest verifies downloads against. The fetchurl hashes move from sha256 to sha512 to match. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Signed-off-by: Jonathan Ogilvie <jonathan.ogilvie@sumologic.com>
Description of your changes
Summary
Adds an integration-test framework: CLI commands run against an envtest API server, a real kube-apiserver and etcd with no controllers. It is made up of:
integration-test, with pinned envtest binaries and Crossplane CRDs;internal/testutils/integration;crossplane resource trace.Why
Unit tests stub the API server, so they can't catch problems that only show up against a real one: CRDs generated from XRDs, server-side apply field ownership, owner references, and claim and XR binding. #436 needs this to test
project simulate. Here the framework is split out on its own, with one small test, so it can be reviewed apart from simulate.What changed
internal/testutils/integration(new). Its main pieces:Start(t, Setup, timeout) *Clusterstarts an envtest cluster. It serves Crossplane's CRDs at the version go.mod pins, the test's own CRDs, and the XR and claim CRDs generated from the test's XRDs.Startalso sets up the test's manifests the way Crossplane's controllers would leave them: controller owner references,resourceRefsand composite/claim labels; composed resources server-side applied under Crossplane's field manager; CompositionRevisions; XRD ownership of the generated CRDs. It can also provision a user with only given RBAC rules.Startskips the test when the envtest binaries or Crossplane's CRDs are missing.integrationtag.CRDsForXRD,PinnedCrossplaneCRDsDir, andReapOrphanedEnvtest. The last one kills kube-apiserver and etcd processes that a crashed earlier run left behind; call it fromTestMain. It kills only orphans (parent PID 1) run from an envtest binary dir whose command line has a--data-dir/--cert-dirunder envtest'sk8s_test_framework_temp dir, so a system server is spared.cmd/crossplane/trace:TestTraceIntegrationsets up a v1 XRD with a claim, the claim's XR, and two composed resources (one ready, one failing to sync). It then runstrace nopclaim test-claimagainst the cluster and checks the tree the default printer draws.nix/envtest-assets.nixpins envtest 1.30.3 for linux and darwin, amd64 and arm64.nix/crossplane-crds.nixpins Crossplane'scluster/crdsat v2.4.1, matchingcrossplane/apis/v2in go.mod.integration-testapp runsgo test -tags integrationwith both of these on every package containing a test file with//go:build integration(found withgo list; it fails if it finds none), and writescoverage-integration.txt. Integration tests are any test files with//go:build integration, so unit tests in those packages also run there. It keeps the host PATH (Nix inputs first), so tests that run functions can reach the host's Docker; nothing here does, but feat(project): add alpha project simulate on the ported crossplane-diff engine #436's simulate tests need it.testapp and check exportCROSSPLANE_CRDS_DIRfor the untagged CRD helper tests.integration-testsjob runs the app. It caches Go modules and the build cache (outside the Nix sandbox nothing else does), and uploads coverage under the codecov flagintegration.integrationtag./coverage-integration.txt.github.com/shirou/gopsutil/v4(used by the reaper). Tidying also pulled in its indirect dependencies and raisedgo.yaml.in/yaml/v3from v3.0.4 to v3.0.5, which gopsutil requires. The vendor hash was regenerated withnix run .#tidy.How to run the integration tests
Locally:
Arguments after
--go togo test. Nix provides envtest's binaries and Crossplane's CRDs. To use your own, setKUBEBUILDER_ASSETSorCROSSPLANE_CRDS_DIR. Without them,go test -tags integration ./...skips the cluster tests.In CI, the
integration-testsjob in.github/workflows/ci.ymlrunsnix run .#integration-teston every PR and push.To add a test: give its file
//go:build integration(the app runs every package with such a file), callintegration.Startwith aSetup, and callintegration.ReapOrphanedEnvtestfrom the package'sTestMain.Testing
./nix.sh run .#integration-testpasses.TestTraceIntegrationruns (it doesn't skip) and passes../nix.sh run .#test,nix build .#checks.<system>.testand./nix.sh run .#lintpass.CROSSPLANE_CRDS_DIR(plaingo test ./..., IDE runs), the CRD helper tests that need Crossplane's CRDs skip, asStartdoes;nix run .#testand thetestcheck set it, so they run there.TestSelectServerscovers the reaper's selection, including a system etcd in an envtest dir and ak8s_test_framework_dir outside the temp dir.nix store prefetch-file).Related
internal/testutils/integrationand keep their simulate-specific harness and testdata.Setup'sUnestablishedXRDs,FieldManagerApplies,DeleteAfterSetuporRBACRules,Cluster.Config,Cluster.Client,Cluster.Context,Cluster.UserConfig,FieldManagerApply,CompositeReconcilerFieldManager,ReadResourcesFromFile, orAwaitAdmissionDenial. feat(project): add alpha project simulate on the ported crossplane-diff engine #436's simulate tests use them.I have:
./nix.sh flake checkto ensure this PR is ready for review. (./nix.sh run .#test,./nix.sh run .#lintand./nix.sh run .#integration-testpass.)Linked a PR or a docs tracking issue to document this change.(no docs change)Addedbackport release-x.ylabels to auto-backport this PR.Need help with this checklist? See the cheat sheet.
🤖 Generated with Claude Code