Skip to content

added unit and mock tests for export coverage#229

Merged
stillalearner merged 1 commit intomigtools:mainfrom
stillalearner:improve_export_coverage
Apr 8, 2026
Merged

added unit and mock tests for export coverage#229
stillalearner merged 1 commit intomigtools:mainfrom
stillalearner:improve_export_coverage

Conversation

@stillalearner
Copy link
Copy Markdown
Contributor

@stillalearner stillalearner commented Apr 3, 2026

Summary

Adds unit and integration tests under cmd/export for discovery, cluster-scoped RBAC/SCC filtering, and export I/O. Improves coverage and regression safety.

Changes

discover_test.go

  • testDiscovery mock (discovery.DiscoveryInterface) for discoverPreferredResources (verbs, partial discovery, errors, post-filter empty lists).
  • getObjects / resourceToExtract (ConfigMaps, ClusterRoles, imagestreamtags/imagetags, Forbidden/NotFound, bad GroupVersion, Events, non-admitted cluster kinds, empty verbs/API lists).
  • prepareClusterResourceDir, prepareFailuresDir, writeResources, writeErrors — happy paths and failure cases (bad paths, permissions, marshal/create errors).
  • resourceToExtract: MethodNotSupported, generic list error, empty list (skip, no error).
  • getObjects: label selector propagation; imagestreamtags when Get fails after List.
  • iterateItemsInList / iterateItemsByGet: non-*unstructured.Unstructured list items.
  • GVK fixes on unstructured test objects where handlers branch on GroupVersionKind.

cluster_test.go

  • filterRbacResources integration (SA + CRB + ClusterRole, group subjects, multiple CRBs, drop unmatched cluster RBAC, wrong APIGroup pass-through).
  • clusterRoleToUnstructured sets GVK for acceptClusterRole.
  • SCC: users, CRB RoleRef to SCC / system:openshift:scc:<name>, malformed filtered CRB, name mismatch; filterRbacResources + SCC.
  • Broader cluster.go edge coverage: isClusterScopedResource, exportedSANamespaces, CRB/CR/SCC conversion and subject branches, NA CRB placeholder, etc.
  • clusterRoleBindingUnstructuredThatFailsConversion for real FromUnstructured failures.

How to test

go test ./cmd/export/... -count=1
go test ./cmd/export/... -count=1 -coverprofile=coverage.out
go tool cover -func=coverage.out

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

* **Tests**
  * Expanded test coverage for cluster resource export functionality, including validation of role-based access control (RBAC) filtering, error handling scenarios, and resource discovery behavior.
  * Added comprehensive test cases for edge cases and error paths to improve reliability of the export feature.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 3, 2026

📝 Walkthrough

Walkthrough

Two test files are significantly expanded with new fixtures, helper utilities, and comprehensive test cases. cluster_test.go adds ~770 lines covering RBAC filtering and acceptance logic across cluster-scoped resources (ClusterRole, ClusterRoleBinding, SecurityContextConstraints). discover_test.go adds ~777 lines exercising error paths in directory/resource operations and resource discovery behaviors.

Changes

Cohort / File(s) Summary
RBAC Filtering Tests
cmd/export/cluster_test.go
Added test helpers for converting Kubernetes objects to unstructured representations with explicit GroupVersionKind settings. Introduced comprehensive unit tests validating isClusterScopedResource, exported service-account namespace computation, and acceptance logic for ClusterRoleBinding, ClusterRole, and SecurityContextConstraints across various input states (malformed, empty subjects, namespace mismatches, unknown kinds). Added end-to-end filterRbacResources tests covering orphan handling, multi-CRB filtering, and namespace-scoped resource preservation.
Resource Discovery Tests
cmd/export/discover_test.go
Expanded test coverage for directory preparation and output writing error paths (nested paths, read-only directories, invalid destinations). Added mock discovery.DiscoveryInterface implementation and tests for discoverPreferredResources verb filtering and error handling. Introduced resource extraction and listing tests validating kind-specific fetching, label selector propagation, ImageStreamTag special handling, and various error scenarios (Forbidden, NotFound, MethodNotSupported).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • aufi

Poem

🐰 Tests multiply like burrow nests,
RBAC pathways now pass their tests,
Discovery flows through mock and wire,
A thousand cases lift us higher,
Quality springs from well-laid checks!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.95% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main change: additions of unit and mock tests to improve export code coverage, which directly corresponds to the substantial test additions in discover_test.go and cluster_test.go.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 3, 2026

Test Coverage Report

Total: 21.2%

Per-package coverage

  • github.com/konveyor/crane — 0.0%
  • github.com/konveyor/crane/cmd/apply — 0.0%
  • github.com/konveyor/crane/cmd/convert — 0.0%
  • github.com/konveyor/crane/cmd/export — 93.6%
  • github.com/konveyor/crane/cmd/plugin-manager — 0.0%
  • github.com/konveyor/crane/cmd/plugin-manager/add — 0.0%
  • github.com/konveyor/crane/cmd/plugin-manager/list — 0.0%
  • github.com/konveyor/crane/cmd/plugin-manager/remove — 0.0%
  • github.com/konveyor/crane/cmd/runfn — 0.0%
  • github.com/konveyor/crane/cmd/skopeo-sync-gen — 0.0%
  • github.com/konveyor/crane/cmd/transfer-pvc — 9.2%
  • github.com/konveyor/crane/cmd/transform — 0.0%
  • github.com/konveyor/crane/cmd/transform/listplugins — 0.0%
  • github.com/konveyor/crane/cmd/transform/optionals — 0.0%
  • github.com/konveyor/crane/cmd/tunnel-api — 0.0%
  • github.com/konveyor/crane/cmd/version — 0.0%
  • github.com/konveyor/crane/e2e-tests/framework — 0.0%
  • github.com/konveyor/crane/e2e-tests/utils — 0.0%
  • github.com/konveyor/crane/internal/file — 76.0%
  • github.com/konveyor/crane/internal/flags — 0.0%
  • github.com/konveyor/crane/internal/plugin — 32.9%
Full function-level details
github.com/konveyor/crane/cmd/apply/apply.go:36:			Complete				0.0%
github.com/konveyor/crane/cmd/apply/apply.go:41:			Validate				0.0%
github.com/konveyor/crane/cmd/apply/apply.go:46:			Run					0.0%
github.com/konveyor/crane/cmd/apply/apply.go:50:			NewApplyCommand				0.0%
github.com/konveyor/crane/cmd/apply/apply.go:82:			addFlagsForOptions			0.0%
github.com/konveyor/crane/cmd/apply/apply.go:88:			run					0.0%
github.com/konveyor/crane/cmd/convert/convert.go:30:			NewConvertOptions			0.0%
github.com/konveyor/crane/cmd/convert/convert.go:63:			addFlagsForConvertOptions		0.0%
github.com/konveyor/crane/cmd/convert/convert.go:74:			Complete				0.0%
github.com/konveyor/crane/cmd/convert/convert.go:83:			Run					0.0%
github.com/konveyor/crane/cmd/convert/convert.go:87:			run					0.0%
github.com/konveyor/crane/cmd/convert/convert.go:112:			getClientFromContext			0.0%
github.com/konveyor/crane/cmd/convert/convert.go:134:			getRestConfigFromContext		0.0%
github.com/konveyor/crane/cmd/export/cluster.go:29:			NewClusterScopeHandler			100.0%
github.com/konveyor/crane/cmd/export/cluster.go:35:			isClusterScopedResource			100.0%
github.com/konveyor/crane/cmd/export/cluster.go:44:			filterRbacResources			100.0%
github.com/konveyor/crane/cmd/export/cluster.go:102:			NewClusterScopedRbacHandler		100.0%
github.com/konveyor/crane/cmd/export/cluster.go:113:			exportedSANamespaces			100.0%
github.com/konveyor/crane/cmd/export/cluster.go:126:			groupMatchesExportedSANamespaces	100.0%
github.com/konveyor/crane/cmd/export/cluster.go:143:			parseServiceAccountUserSubject		100.0%
github.com/konveyor/crane/cmd/export/cluster.go:154:			prepareForFiltering			100.0%
github.com/konveyor/crane/cmd/export/cluster.go:187:			filteredResourcesOfKind			100.0%
github.com/konveyor/crane/cmd/export/cluster.go:213:			accept					100.0%
github.com/konveyor/crane/cmd/export/cluster.go:223:			acceptClusterRoleBinding		100.0%
github.com/konveyor/crane/cmd/export/cluster.go:260:			acceptClusterRole			100.0%
github.com/konveyor/crane/cmd/export/cluster.go:284:			acceptSecurityContextConstraints	100.0%
github.com/konveyor/crane/cmd/export/cluster.go:336:			anyServiceAccountInNamespace		100.0%
github.com/konveyor/crane/cmd/export/crd.go:17:				normalizeGroupSet			85.7%
github.com/konveyor/crane/cmd/export/crd.go:29:				shouldSkipCRDGroup			100.0%
github.com/konveyor/crane/cmd/export/crd.go:50:				crdFailureAPIResourceName		100.0%
github.com/konveyor/crane/cmd/export/crd.go:58:				collectRelatedCRDs			89.7%
github.com/konveyor/crane/cmd/export/discover.go:39:			hasClusterScopedManifests		100.0%
github.com/konveyor/crane/cmd/export/discover.go:57:			prepareClusterResourceDir		100.0%
github.com/konveyor/crane/cmd/export/discover.go:73:			prepareFailuresDir			100.0%
github.com/konveyor/crane/cmd/export/discover.go:85:			writeResources				85.7%
github.com/konveyor/crane/cmd/export/discover.go:133:			writeErrors				83.3%
github.com/konveyor/crane/cmd/export/discover.go:174:			getFilePath				100.0%
github.com/konveyor/crane/cmd/export/discover.go:185:			discoverPreferredResources		100.0%
github.com/konveyor/crane/cmd/export/discover.go:214:			resourceToExtract			100.0%
github.com/konveyor/crane/cmd/export/discover.go:283:			isAdmittedResource			100.0%
github.com/konveyor/crane/cmd/export/discover.go:292:			getObjects				100.0%
github.com/konveyor/crane/cmd/export/discover.go:326:			iterateItemsByGet			100.0%
github.com/konveyor/crane/cmd/export/discover.go:349:			iterateItemsInList			100.0%
github.com/konveyor/crane/cmd/export/export.go:46:			Complete				87.5%
github.com/konveyor/crane/cmd/export/export.go:75:			Validate				100.0%
github.com/konveyor/crane/cmd/export/export.go:84:			Run					0.0%
github.com/konveyor/crane/cmd/export/export.go:173:			NewExportCommand			50.0%
github.com/konveyor/crane/cmd/plugin-manager/add/add.go:42:		Complete				0.0%
github.com/konveyor/crane/cmd/plugin-manager/add/add.go:47:		Validate				0.0%
github.com/konveyor/crane/cmd/plugin-manager/add/add.go:90:		Run					0.0%
github.com/konveyor/crane/cmd/plugin-manager/add/add.go:94:		NewAddCommand				0.0%
github.com/konveyor/crane/cmd/plugin-manager/add/add.go:126:		addFlagsForOptions			0.0%
github.com/konveyor/crane/cmd/plugin-manager/add/add.go:131:		run					0.0%
github.com/konveyor/crane/cmd/plugin-manager/add/add.go:195:		downloadBinary				0.0%
github.com/konveyor/crane/cmd/plugin-manager/list/list.go:46:		Complete				0.0%
github.com/konveyor/crane/cmd/plugin-manager/list/list.go:51:		Validate				0.0%
github.com/konveyor/crane/cmd/plugin-manager/list/list.go:56:		Run					0.0%
github.com/konveyor/crane/cmd/plugin-manager/list/list.go:60:		NewListCommand				0.0%
github.com/konveyor/crane/cmd/plugin-manager/list/list.go:90:		addFlagsForOptions			0.0%
github.com/konveyor/crane/cmd/plugin-manager/list/list.go:98:		run					0.0%
github.com/konveyor/crane/cmd/plugin-manager/list/list.go:167:		printInstalledInformation		0.0%
github.com/konveyor/crane/cmd/plugin-manager/list/list.go:177:		groupInformationForPlugins		0.0%
github.com/konveyor/crane/cmd/plugin-manager/list/list.go:196:		printInformation			0.0%
github.com/konveyor/crane/cmd/plugin-manager/list/list.go:208:		printParamsInformation			0.0%
github.com/konveyor/crane/cmd/plugin-manager/list/list.go:222:		getOptionalFields			0.0%
github.com/konveyor/crane/cmd/plugin-manager/list/list.go:247:		printTable				0.0%
github.com/konveyor/crane/cmd/plugin-manager/plugin-manager.go:33:	Complete				0.0%
github.com/konveyor/crane/cmd/plugin-manager/plugin-manager.go:38:	Validate				0.0%
github.com/konveyor/crane/cmd/plugin-manager/plugin-manager.go:43:	Run					0.0%
github.com/konveyor/crane/cmd/plugin-manager/plugin-manager.go:47:	NewPluginManagerCommand			0.0%
github.com/konveyor/crane/cmd/plugin-manager/plugin-manager.go:78:	addFlagsForOptions			0.0%
github.com/konveyor/crane/cmd/plugin-manager/plugin-manager.go:86:	run					0.0%
github.com/konveyor/crane/cmd/plugin-manager/remove/remove.go:33:	Complete				0.0%
github.com/konveyor/crane/cmd/plugin-manager/remove/remove.go:38:	Validate				0.0%
github.com/konveyor/crane/cmd/plugin-manager/remove/remove.go:43:	Run					0.0%
github.com/konveyor/crane/cmd/plugin-manager/remove/remove.go:47:	NewRemoveCommand			0.0%
github.com/konveyor/crane/cmd/plugin-manager/remove/remove.go:77:	run					0.0%
github.com/konveyor/crane/cmd/runfn/runfn.go:33:			NewFnRunCommand				0.0%
github.com/konveyor/crane/cmd/runfn/runfn.go:49:			addFlagsForOptions			0.0%
github.com/konveyor/crane/cmd/runfn/runfn.go:59:			runE					0.0%
github.com/konveyor/crane/cmd/runfn/runfn.go:70:			preRunE					0.0%
github.com/konveyor/crane/cmd/runfn/runfn.go:112:			getFunctionImage			0.0%
github.com/konveyor/crane/cmd/runfn/runfn.go:124:			getContainerFunctions			0.0%
github.com/konveyor/crane/cmd/runfn/runfn.go:151:			getFunctionAnnotation			0.0%
github.com/konveyor/crane/cmd/runfn/runfn.go:170:			getFunctionConfig			0.0%
github.com/konveyor/crane/cmd/runfn/util.go:14:				WriteOutput				0.0%
github.com/konveyor/crane/cmd/runfn/util.go:31:				GetDestinationDir			0.0%
github.com/konveyor/crane/cmd/runfn/util.go:58:				ValidateFunctionImageURL		0.0%
github.com/konveyor/crane/cmd/runfn/util.go:80:				checkIfDirExists			0.0%
github.com/konveyor/crane/cmd/skopeo-sync-gen/skopeo-sync-gen.go:61:	Complete				0.0%
github.com/konveyor/crane/cmd/skopeo-sync-gen/skopeo-sync-gen.go:65:	Validate				0.0%
github.com/konveyor/crane/cmd/skopeo-sync-gen/skopeo-sync-gen.go:69:	NewSkopeoSyncGenCommand			0.0%
github.com/konveyor/crane/cmd/skopeo-sync-gen/skopeo-sync-gen.go:103:	shouldAddImageStream			0.0%
github.com/konveyor/crane/cmd/skopeo-sync-gen/skopeo-sync-gen.go:114:	Run					0.0%
github.com/konveyor/crane/cmd/transfer-pvc/progress.go:37:		NewRsyncLogStream			0.0%
github.com/konveyor/crane/cmd/transfer-pvc/progress.go:50:		Init					0.0%
github.com/konveyor/crane/cmd/transfer-pvc/progress.go:138:		writeProgressToFile			0.0%
github.com/konveyor/crane/cmd/transfer-pvc/progress.go:148:		Close					0.0%
github.com/konveyor/crane/cmd/transfer-pvc/progress.go:154:		Streams					0.0%
github.com/konveyor/crane/cmd/transfer-pvc/progress.go:190:		addDataSize				0.0%
github.com/konveyor/crane/cmd/transfer-pvc/progress.go:215:		String					100.0%
github.com/konveyor/crane/cmd/transfer-pvc/progress.go:219:		MarshalJSON				0.0%
github.com/konveyor/crane/cmd/transfer-pvc/progress.go:223:		AsString				0.0%
github.com/konveyor/crane/cmd/transfer-pvc/progress.go:271:		NewProgress				100.0%
github.com/konveyor/crane/cmd/transfer-pvc/progress.go:291:		Completed				0.0%
github.com/konveyor/crane/cmd/transfer-pvc/progress.go:296:		Status					38.5%
github.com/konveyor/crane/cmd/transfer-pvc/progress.go:321:		Merge					0.0%
github.com/konveyor/crane/cmd/transfer-pvc/progress.go:376:		newDataSize				72.7%
github.com/konveyor/crane/cmd/transfer-pvc/progress.go:399:		parseRsyncLogs				76.1%
github.com/konveyor/crane/cmd/transfer-pvc/progress.go:479:		waitForPodRunning			0.0%
github.com/konveyor/crane/cmd/transfer-pvc/progress.go:513:		getFinalPodStatus			0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:89:		Validate				0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:117:		Validate				0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:133:		NewTransferPVCCommand			0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:169:		addFlagsToTransferPVCCommand		0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:189:		Complete				0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:220:		Validate				0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:246:		Run					0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:250:		getClientFromContext			0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:271:		getRestConfigFromContext		0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:278:		run					0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:485:		getValidatedResourceName		0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:495:		getNodeNameForPVC			0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:515:		getIDsForNamespace			0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:541:		getRsyncClientPodSecurityContext	0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:553:		getRsyncServerPodSecurityContext	0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:565:		garbageCollect				0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:602:		deleteResourcesIteratively		0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:628:		deleteResourcesForGVK			0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:649:		followClientLogs			0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:678:		waitForEndpoint				0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:690:		createEndpoint				0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:735:		getRouteHostName			0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:752:		buildDestinationPVC			0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:773:		ApplyTo					0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:793:		ApplyTo					0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:805:		ApplyTo					0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:821:		String					0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:825:		Set					0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:835:		Type					0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:841:		parseSourceDestinationMapping		100.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:863:		String					0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:867:		Set					0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:876:		Type					0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:880:		String					0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:884:		Set					0.0%
github.com/konveyor/crane/cmd/transfer-pvc/transfer-pvc.go:894:		Type					0.0%
github.com/konveyor/crane/cmd/transform/listplugins/listplugins.go:31:	Complete				0.0%
github.com/konveyor/crane/cmd/transform/listplugins/listplugins.go:36:	Validate				0.0%
github.com/konveyor/crane/cmd/transform/listplugins/listplugins.go:41:	Run					0.0%
github.com/konveyor/crane/cmd/transform/listplugins/listplugins.go:45:	NewListPluginsCommand			0.0%
github.com/konveyor/crane/cmd/transform/listplugins/listplugins.go:77:	run					0.0%
github.com/konveyor/crane/cmd/transform/optionals/optionals.go:31:	Complete				0.0%
github.com/konveyor/crane/cmd/transform/optionals/optionals.go:36:	Validate				0.0%
github.com/konveyor/crane/cmd/transform/optionals/optionals.go:41:	Run					0.0%
github.com/konveyor/crane/cmd/transform/optionals/optionals.go:45:	NewOptionalsCommand			0.0%
github.com/konveyor/crane/cmd/transform/optionals/optionals.go:77:	run					0.0%
github.com/konveyor/crane/cmd/transform/transform.go:43:		Complete				0.0%
github.com/konveyor/crane/cmd/transform/transform.go:48:		Validate				0.0%
github.com/konveyor/crane/cmd/transform/transform.go:53:		Run					0.0%
github.com/konveyor/crane/cmd/transform/transform.go:57:		NewTransformCommand			0.0%
github.com/konveyor/crane/cmd/transform/transform.go:91:		addFlagsForOptions			0.0%
github.com/konveyor/crane/cmd/transform/transform.go:105:		run					0.0%
github.com/konveyor/crane/cmd/transform/transform.go:237:		getPluginPrioritiesMap			0.0%
github.com/konveyor/crane/cmd/transform/transform.go:249:		optionalFlagsToLower			0.0%
github.com/konveyor/crane/cmd/tunnel-api/tunnel-api.go:35:		NewTunnelAPIOptions			0.0%
github.com/konveyor/crane/cmd/tunnel-api/tunnel-api.go:65:		addFlagsForTunnelAPIOptions		0.0%
github.com/konveyor/crane/cmd/tunnel-api/tunnel-api.go:77:		Complete				0.0%
github.com/konveyor/crane/cmd/tunnel-api/tunnel-api.go:100:		Validate				0.0%
github.com/konveyor/crane/cmd/tunnel-api/tunnel-api.go:116:		Run					0.0%
github.com/konveyor/crane/cmd/tunnel-api/tunnel-api.go:120:		getClientFromContext			0.0%
github.com/konveyor/crane/cmd/tunnel-api/tunnel-api.go:129:		getRestConfigFromContext		0.0%
github.com/konveyor/crane/cmd/tunnel-api/tunnel-api.go:136:		run					0.0%
github.com/konveyor/crane/cmd/version/version.go:20:			Complete				0.0%
github.com/konveyor/crane/cmd/version/version.go:25:			Validate				0.0%
github.com/konveyor/crane/cmd/version/version.go:30:			Run					0.0%
github.com/konveyor/crane/cmd/version/version.go:34:			NewVersionCommand			0.0%
github.com/konveyor/crane/cmd/version/version.go:60:			run					0.0%
github.com/konveyor/crane/e2e-tests/framework/app.go:27:		Deploy					0.0%
github.com/konveyor/crane/e2e-tests/framework/app.go:49:		Validate				0.0%
github.com/konveyor/crane/e2e-tests/framework/app.go:71:		Cleanup					0.0%
github.com/konveyor/crane/e2e-tests/framework/app.go:93:		buildCommand				0.0%
github.com/konveyor/crane/e2e-tests/framework/app.go:100:		envWithBinDir				0.0%
github.com/konveyor/crane/e2e-tests/framework/app.go:116:		withExtraVars				0.0%
github.com/konveyor/crane/e2e-tests/framework/client.go:15:		ListPVCs				0.0%
github.com/konveyor/crane/e2e-tests/framework/client.go:37:		NewClientSetForContext			0.0%
github.com/konveyor/crane/e2e-tests/framework/client.go:62:		GetClusterNodeIP			0.0%
github.com/konveyor/crane/e2e-tests/framework/crane.go:27:		Export					0.0%
github.com/konveyor/crane/e2e-tests/framework/crane.go:41:		Transform				0.0%
github.com/konveyor/crane/e2e-tests/framework/crane.go:55:		Apply					0.0%
github.com/konveyor/crane/e2e-tests/framework/crane.go:69:		TransferPVC				0.0%
github.com/konveyor/crane/e2e-tests/framework/kubectl.go:18:		Run					0.0%
github.com/konveyor/crane/e2e-tests/framework/kubectl.go:24:		RunWithStdin				0.0%
github.com/konveyor/crane/e2e-tests/framework/kubectl.go:29:		executeWithStdin			0.0%
github.com/konveyor/crane/e2e-tests/framework/kubectl.go:50:		normalizeKubectlArgs			0.0%
github.com/konveyor/crane/e2e-tests/framework/kubectl.go:58:		CreateNamespace				0.0%
github.com/konveyor/crane/e2e-tests/framework/kubectl.go:77:		ApplyDir				0.0%
github.com/konveyor/crane/e2e-tests/framework/kubectl.go:93:		ApplyYAMLSpec				0.0%
github.com/konveyor/crane/e2e-tests/framework/kubectl.go:102:		ValidateApplyDir			0.0%
github.com/konveyor/crane/e2e-tests/framework/kubectl.go:118:		ScaleDeployment				0.0%
github.com/konveyor/crane/e2e-tests/framework/kubectl.go:176:		ScaleDeploymentIfPresent		0.0%
github.com/konveyor/crane/e2e-tests/framework/logging.go:11:		logVerboseCommand			0.0%
github.com/konveyor/crane/e2e-tests/framework/logging.go:19:		logVerboseOutput			0.0%
github.com/konveyor/crane/e2e-tests/framework/pipeline.go:11:		RunCranePipeline			0.0%
github.com/konveyor/crane/e2e-tests/framework/pipeline.go:25:		RunCranePipelineWithChecks		0.0%
github.com/konveyor/crane/e2e-tests/framework/pipeline.go:43:		PrepareSourceApp			0.0%
github.com/konveyor/crane/e2e-tests/framework/pipeline.go:57:		ApplyOutputToTarget			0.0%
github.com/konveyor/crane/e2e-tests/framework/pipeline.go:71:		checkAndLogStageFiles			0.0%
github.com/konveyor/crane/e2e-tests/framework/scenario.go:23:		NewMigrationScenario			0.0%
github.com/konveyor/crane/e2e-tests/framework/scenario.go:56:		NewScenarioPaths			0.0%
github.com/konveyor/crane/e2e-tests/framework/scenario.go:73:		CleanupScenario				0.0%
github.com/konveyor/crane/e2e-tests/utils/utils.go:13:			CreateTempDir				0.0%
github.com/konveyor/crane/e2e-tests/utils/utils.go:18:			ListFilesRecursively			0.0%
github.com/konveyor/crane/e2e-tests/utils/utils.go:40:			ListFilesRecursivelyAsList		0.0%
github.com/konveyor/crane/e2e-tests/utils/utils.go:64:			HasFilesRecursively			0.0%
github.com/konveyor/crane/e2e-tests/utils/utils.go:74:			ReadTestdataFile			0.0%
github.com/konveyor/crane/internal/file/file_helper.go:22:		ReadFiles				100.0%
github.com/konveyor/crane/internal/file/file_helper.go:32:		readFiles				84.0%
github.com/konveyor/crane/internal/file/file_helper.go:83:		GetWhiteOutFilePath			100.0%
github.com/konveyor/crane/internal/file/file_helper.go:87:		GetTransformPath			100.0%
github.com/konveyor/crane/internal/file/file_helper.go:91:		GetIgnoredPatchesPath			0.0%
github.com/konveyor/crane/internal/file/file_helper.go:95:		updateTransformDirPath			100.0%
github.com/konveyor/crane/internal/file/file_helper.go:99:		updateIgnoredPatchesDirPath		0.0%
github.com/konveyor/crane/internal/file/file_helper.go:106:		updatePath				100.0%
github.com/konveyor/crane/internal/file/file_helper.go:113:		GetOutputFilePath			100.0%
github.com/konveyor/crane/internal/flags/global_flags.go:14:		ApplyFlags				0.0%
github.com/konveyor/crane/internal/flags/global_flags.go:21:		GetLogger				0.0%
github.com/konveyor/crane/internal/flags/global_flags.go:29:		initConfig				0.0%
github.com/konveyor/crane/internal/plugin/plugin_helper.go:21:		GetPlugins				0.0%
github.com/konveyor/crane/internal/plugin/plugin_helper.go:38:		getBinaryPlugins			0.0%
github.com/konveyor/crane/internal/plugin/plugin_helper.go:63:		IsExecAny				0.0%
github.com/konveyor/crane/internal/plugin/plugin_helper.go:67:		GetFilteredPlugins			0.0%
github.com/konveyor/crane/internal/plugin/plugin_helper.go:106:		isPluginInList				0.0%
github.com/konveyor/crane/internal/plugin/plugin_manager_helper.go:24:	BuildManifestMap			0.0%
github.com/konveyor/crane/internal/plugin/plugin_manager_helper.go:68:	GetYamlFromUrl				75.0%
github.com/konveyor/crane/internal/plugin/plugin_manager_helper.go:82:	YamlToManifest				72.7%
github.com/konveyor/crane/internal/plugin/plugin_manager_helper.go:104:	FilterPluginForOsArch			100.0%
github.com/konveyor/crane/internal/plugin/plugin_manager_helper.go:122:	GetDefaultSource			0.0%
github.com/konveyor/crane/internal/plugin/plugin_manager_helper.go:131:	LocateBinaryInPluginDir			0.0%
github.com/konveyor/crane/internal/plugin/plugin_manager_helper.go:143:	IsUrl					100.0%
github.com/konveyor/crane/internal/plugin/plugin_manager_helper.go:149:	getData					80.0%
github.com/konveyor/crane/main.go:21:					main					0.0%
total:									(statements)				21.2%

Posted by CI

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@cmd/export/discover_test.go`:
- Around line 684-714: The test
TestWriteResources_createFailsWhenDestinationFileNotWritable relies on POSIX
file permissions but doesn't skip when run as root; update the test to detect
root (os.Geteuid() == 0) and call t.Skip("skipping test when run as root") at
the start of the test so it behaves like the other permission-based tests;
ensure you add the check near the top of
TestWriteResources_createFailsWhenDestinationFileNotWritable before creating
files/directories and leave references to writeResources and testLogger
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e5e794f6-5035-4997-8abf-3ea2fa02366b

📥 Commits

Reviewing files that changed from the base of the PR and between c6ca79d and 323a40f.

📒 Files selected for processing (2)
  • cmd/export/cluster_test.go
  • cmd/export/discover_test.go

Comment on lines +684 to +714
func TestWriteResources_createFailsWhenDestinationFileNotWritable(t *testing.T) {
log := testLogger()
tmp := t.TempDir()
resourceDir := filepath.Join(tmp, "out")
clusterDir := filepath.Join(tmp, "_cluster")
if err := os.MkdirAll(resourceDir, 0700); err != nil {
t.Fatal(err)
}
if err := os.MkdirAll(clusterDir, 0700); err != nil {
t.Fatal(err)
}

nsObj := namespacedObj("ns", "pod-a")
nsObj.SetKind("Pod")
nsObj.SetGroupVersionKind(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"})
path := filepath.Join(resourceDir, getFilePath(nsObj))
if err := os.WriteFile(path, []byte("seed"), 0400); err != nil {
t.Fatal(err)
}

resources := []*groupResource{
{
APIResource: metav1.APIResource{Name: "pods", Kind: "Pod"},
objects: &unstructured.UnstructuredList{Items: []unstructured.Unstructured{nsObj}},
},
}
errs := writeResources(resources, clusterDir, resourceDir, log)
if len(errs) != 1 {
t.Fatalf("want 1 error opening/truncating read-only destination file, got %v", errs)
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing root user skip for permission-based test.

This test relies on file permissions (0400) to cause a write failure, but root can write to any file regardless of permissions. Other permission-based tests in this file (e.g., lines 476-478, 540-542, 594-596) properly skip when running as root.

Proposed fix
 func TestWriteResources_createFailsWhenDestinationFileNotWritable(t *testing.T) {
+	if os.Geteuid() == 0 {
+		t.Skip("root can write to any file regardless of permissions")
+	}
 	log := testLogger()
 	tmp := t.TempDir()
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func TestWriteResources_createFailsWhenDestinationFileNotWritable(t *testing.T) {
log := testLogger()
tmp := t.TempDir()
resourceDir := filepath.Join(tmp, "out")
clusterDir := filepath.Join(tmp, "_cluster")
if err := os.MkdirAll(resourceDir, 0700); err != nil {
t.Fatal(err)
}
if err := os.MkdirAll(clusterDir, 0700); err != nil {
t.Fatal(err)
}
nsObj := namespacedObj("ns", "pod-a")
nsObj.SetKind("Pod")
nsObj.SetGroupVersionKind(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"})
path := filepath.Join(resourceDir, getFilePath(nsObj))
if err := os.WriteFile(path, []byte("seed"), 0400); err != nil {
t.Fatal(err)
}
resources := []*groupResource{
{
APIResource: metav1.APIResource{Name: "pods", Kind: "Pod"},
objects: &unstructured.UnstructuredList{Items: []unstructured.Unstructured{nsObj}},
},
}
errs := writeResources(resources, clusterDir, resourceDir, log)
if len(errs) != 1 {
t.Fatalf("want 1 error opening/truncating read-only destination file, got %v", errs)
}
}
func TestWriteResources_createFailsWhenDestinationFileNotWritable(t *testing.T) {
if os.Geteuid() == 0 {
t.Skip("root can write to any file regardless of permissions")
}
log := testLogger()
tmp := t.TempDir()
resourceDir := filepath.Join(tmp, "out")
clusterDir := filepath.Join(tmp, "_cluster")
if err := os.MkdirAll(resourceDir, 0700); err != nil {
t.Fatal(err)
}
if err := os.MkdirAll(clusterDir, 0700); err != nil {
t.Fatal(err)
}
nsObj := namespacedObj("ns", "pod-a")
nsObj.SetKind("Pod")
nsObj.SetGroupVersionKind(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"})
path := filepath.Join(resourceDir, getFilePath(nsObj))
if err := os.WriteFile(path, []byte("seed"), 0400); err != nil {
t.Fatal(err)
}
resources := []*groupResource{
{
APIResource: metav1.APIResource{Name: "pods", Kind: "Pod"},
objects: &unstructured.UnstructuredList{Items: []unstructured.Unstructured{nsObj}},
},
}
errs := writeResources(resources, clusterDir, resourceDir, log)
if len(errs) != 1 {
t.Fatalf("want 1 error opening/truncating read-only destination file, got %v", errs)
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@cmd/export/discover_test.go` around lines 684 - 714, The test
TestWriteResources_createFailsWhenDestinationFileNotWritable relies on POSIX
file permissions but doesn't skip when run as root; update the test to detect
root (os.Geteuid() == 0) and call t.Skip("skipping test when run as root") at
the start of the test so it behaves like the other permission-based tests;
ensure you add the check near the top of
TestWriteResources_createFailsWhenDestinationFileNotWritable before creating
files/directories and leave references to writeResources and testLogger
unchanged.

Copy link
Copy Markdown
Contributor

@aufi aufi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From a quick look, LGTM.

@stillalearner stillalearner merged commit 0eef277 into migtools:main Apr 8, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants