diff --git a/Makefile b/Makefile index 6f4632476..fa3c5879e 100644 --- a/Makefile +++ b/Makefile @@ -147,7 +147,7 @@ validate-cyclonedx-schema: .PHONY: unit unit: $(RESULTSDIR) fixtures ## Run unit tests (with coverage) $(call title,Running unit tests) - go test -coverprofile $(COVER_REPORT) $(shell go list ./... | grep -v anchore/syft/test) + go test -coverprofile $(COVER_REPORT) $(shell go list ./... | grep -v anchore/syft/test) @go tool cover -func $(COVER_REPORT) | grep total | awk '{print substr($$3, 1, length($$3)-1)}' > $(COVER_TOTAL) @echo "Coverage: $$(cat $(COVER_TOTAL))" @if [ $$(echo "$$(cat $(COVER_TOTAL)) >= $(COVERAGE_THRESHOLD)" | bc -l) -ne 1 ]; then echo "$(RED)$(BOLD)Failed coverage quality gate (> $(COVERAGE_THRESHOLD)%)$(RESET)" && false; fi @@ -189,10 +189,6 @@ fixtures: generate-json-schema: ## Generate a new json schema cd schema/json && go run generate.go -.PHONY: clear-test-cache -clear-test-cache: ## Delete all test cache (built docker image tars) - find . -type f -wholename "**/test-fixtures/cache/*.tar" -delete - .PHONY: build build: $(SNAPSHOTDIR) ## Build release snapshot binaries and packages @@ -313,7 +309,7 @@ release: clean-dist changelog-release ## Build and publish final binaries and pa .PHONY: clean -clean: clean-dist clean-snapshot ## Remove previous builds and result reports +clean: clean-dist clean-snapshot clean-test-image-cache ## Remove previous builds, result reports, and test cache rm -rf $(RESULTSDIR)/* .PHONY: clean-snapshot @@ -323,3 +319,26 @@ clean-snapshot: .PHONY: clean-dist clean-dist: rm -rf $(DISTDIR) $(TEMPDIR)/goreleaser.yaml + +clean-test-image-cache: clean-test-image-tar-cache clean-test-image-docker-cache + +.PHONY: clear-test-image-tar-cache +clean-test-image-tar-cache: ## Delete all test cache (built docker image tars) + find . -type f -wholename "**/test-fixtures/cache/stereoscope-fixture-*.tar" -delete + +.PHONY: clear-test-image-docker-cache +clean-test-image-docker-cache: ## Purge all test docker images + docker images --format '{{.ID}} {{.Repository}}' | grep stereoscope-fixture- | awk '{print $$1}' | uniq | xargs docker rmi --force + +.PHONY: show-test-image-cache +show-test-image-cache: ## Show all docker and image tar cache + $(call title,Docker daemon cache) + @docker images --format '{{.ID}} {{.Repository}}:{{.Tag}}' | grep stereoscope-fixture- | sort + + $(call title,Tar cache) + @find . -type f -wholename "**/test-fixtures/cache/stereoscope-fixture-*.tar" | sort + +.PHONY: show-test-snapshots +show-test-snapshots: ## Show all test snapshots + $(call title,Test snapshots) + @find . -type f -wholename "**/test-fixtures/snapshot/*" | sort \ No newline at end of file diff --git a/go.mod b/go.mod index 95354b280..5a9ded037 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/anchore/go-rpmdb v0.0.0-20201106153645-0043963c2e12 github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b - github.com/anchore/stereoscope v0.0.0-20210323145922-1f45cd8849b4 + github.com/anchore/stereoscope v0.0.0-20210323182342-47b72675ff65 github.com/antihax/optional v1.0.0 github.com/bmatcuk/doublestar/v2 v2.0.4 github.com/docker/docker v17.12.0-ce-rc1.0.20200309214505-aa6a9891b09c+incompatible diff --git a/go.sum b/go.sum index eecc235eb..3ec96d0c7 100644 --- a/go.sum +++ b/go.sum @@ -115,8 +115,8 @@ github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04 h1:VzprUTpc0v github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04/go.mod h1:6dK64g27Qi1qGQZ67gFmBFvEHScy0/C8qhQhNe5B5pQ= github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZVsCYMrIZBpFxwV26CbsuoEh5muXD5I1Ods= github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E= -github.com/anchore/stereoscope v0.0.0-20210323145922-1f45cd8849b4 h1:Uuvne+/Mgeyu3fR1JCxiFUQQo2Gp5vXTInum3GbhbwM= -github.com/anchore/stereoscope v0.0.0-20210323145922-1f45cd8849b4/go.mod h1:G7tFR0iI9r6AvibmXKA9v010pRS1IIJgd0t6fOMDxCw= +github.com/anchore/stereoscope v0.0.0-20210323182342-47b72675ff65 h1:r3tiir6UCgj/YeTqy4s2bfhZ9SuJYNlXx1Z9e/eLrbI= +github.com/anchore/stereoscope v0.0.0-20210323182342-47b72675ff65/go.mod h1:G7tFR0iI9r6AvibmXKA9v010pRS1IIJgd0t6fOMDxCw= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= diff --git a/internal/presenter/packages/test-fixtures/snapshot/TestJSONImgsPresenter.golden b/internal/presenter/packages/test-fixtures/snapshot/TestJSONImgsPresenter.golden index dbb11f32c..0c27b16d9 100644 --- a/internal/presenter/packages/test-fixtures/snapshot/TestJSONImgsPresenter.golden +++ b/internal/presenter/packages/test-fixtures/snapshot/TestJSONImgsPresenter.golden @@ -9,7 +9,7 @@ "locations": [ { "path": "/somefile-1.txt", - "layerID": "sha256:e158b57d6f5a96ef5fd22f2fe76c70b5ba6ff5b2619f9d83125b2aad0492ac7b" + "layerID": "sha256:3de16c5b8659a2e8d888b8ded8427be7a5686a3c8c4e4dd30de20f362827285b" } ], "licenses": [ @@ -40,7 +40,7 @@ "locations": [ { "path": "/somefile-2.txt", - "layerID": "sha256:da21056e7bf4308ecea0c0836848a7fe92f38fdcf35bc09ee6d98e7ab7beeebf" + "layerID": "sha256:366a3f5653e34673b875891b021647440d0127c2ef041e3b1a22da2a7d4f3703" } ], "licenses": [], @@ -67,27 +67,27 @@ "type": "image", "target": { "userInput": "user-image-input", - "imageID": "sha256:92fbdd71302c666029f11ef5ea49caba6e97daa86cb4dce7874377b26c731d65", + "imageID": "sha256:c2b46b4eb06296933b7cf0722683964e9ecbd93265b9ef6ae9642e3952afbba0", "manifestDigest": "sha256:2731251dc34951c0e50fcc643b4c5f74922dad1a5d98f302b504cf46cd5d9368", "mediaType": "application/vnd.docker.distribution.manifest.v2+json", "tags": [ - "stereoscope-fixture-image-simple:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + "stereoscope-fixture-image-simple:85066c51088bdd274f7a89e99e00490f666c49e72ffc955707cd6e18f0e22c5b" ], "imageSize": 38, "layers": [ { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", - "digest": "sha256:e158b57d6f5a96ef5fd22f2fe76c70b5ba6ff5b2619f9d83125b2aad0492ac7b", + "digest": "sha256:3de16c5b8659a2e8d888b8ded8427be7a5686a3c8c4e4dd30de20f362827285b", "size": 22 }, { "mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip", - "digest": "sha256:da21056e7bf4308ecea0c0836848a7fe92f38fdcf35bc09ee6d98e7ab7beeebf", + "digest": "sha256:366a3f5653e34673b875891b021647440d0127c2ef041e3b1a22da2a7d4f3703", "size": 16 } ], - "manifest": "eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiY29uZmlnIjp7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuY29udGFpbmVyLmltYWdlLnYxK2pzb24iLCJzaXplIjoxNTg2LCJkaWdlc3QiOiJzaGEyNTY6OTJmYmRkNzEzMDJjNjY2MDI5ZjExZWY1ZWE0OWNhYmE2ZTk3ZGFhODZjYjRkY2U3ODc0Mzc3YjI2YzczMWQ2NSJ9LCJsYXllcnMiOlt7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuaW1hZ2Uucm9vdGZzLmRpZmYudGFyLmd6aXAiLCJzaXplIjoyMDQ4LCJkaWdlc3QiOiJzaGEyNTY6ZTE1OGI1N2Q2ZjVhOTZlZjVmZDIyZjJmZTc2YzcwYjViYTZmZjViMjYxOWY5ZDgzMTI1YjJhYWQwNDkyYWM3YiJ9LHsibWVkaWFUeXBlIjoiYXBwbGljYXRpb24vdm5kLmRvY2tlci5pbWFnZS5yb290ZnMuZGlmZi50YXIuZ3ppcCIsInNpemUiOjIwNDgsImRpZ2VzdCI6InNoYTI1NjpkYTIxMDU2ZTdiZjQzMDhlY2VhMGMwODM2ODQ4YTdmZTkyZjM4ZmRjZjM1YmMwOWVlNmQ5OGU3YWI3YmVlZWJmIn1dfQ==", - "config": "eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZpZyI6eyJIb3N0bmFtZSI6IiIsIkRvbWFpbm5hbWUiOiIiLCJVc2VyIjoiIiwiQXR0YWNoU3RkaW4iOmZhbHNlLCJBdHRhY2hTdGRvdXQiOmZhbHNlLCJBdHRhY2hTdGRlcnIiOmZhbHNlLCJUdHkiOmZhbHNlLCJPcGVuU3RkaW4iOmZhbHNlLCJTdGRpbk9uY2UiOmZhbHNlLCJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiQ21kIjpudWxsLCJJbWFnZSI6InNoYTI1Njo3MDRjZGI0ZDViYmNlMDhjNzI1N2I0OTUxMWM5YzBlYTc2N2UwNzdmZDhiOGIzNDUxOGMzNjg3YTdmZjFlNTlkIiwiVm9sdW1lcyI6bnVsbCwiV29ya2luZ0RpciI6IiIsIkVudHJ5cG9pbnQiOm51bGwsIk9uQnVpbGQiOm51bGwsIkxhYmVscyI6bnVsbH0sImNvbnRhaW5lcl9jb25maWciOnsiSG9zdG5hbWUiOiIiLCJEb21haW5uYW1lIjoiIiwiVXNlciI6IiIsIkF0dGFjaFN0ZGluIjpmYWxzZSwiQXR0YWNoU3Rkb3V0IjpmYWxzZSwiQXR0YWNoU3RkZXJyIjpmYWxzZSwiVHR5IjpmYWxzZSwiT3BlblN0ZGluIjpmYWxzZSwiU3RkaW5PbmNlIjpmYWxzZSwiRW52IjpbIlBBVEg9L3Vzci9sb2NhbC9zYmluOi91c3IvbG9jYWwvYmluOi91c3Ivc2JpbjovdXNyL2Jpbjovc2JpbjovYmluIl0sIkNtZCI6WyIvYmluL3NoIiwiLWMiLCIjKG5vcCkgQUREIGZpbGU6ZGYzYjc0NGY1NGE5YjE2YjliOWFlZDQwZTNlOThkOWNhMmI0OWY1YTc3ZDlmYThhOTc2OTBkN2JhZjU4ODgyMCBpbiAvc29tZWZpbGUtMi50eHQgIl0sIkltYWdlIjoic2hhMjU2OjcwNGNkYjRkNWJiY2UwOGM3MjU3YjQ5NTExYzljMGVhNzY3ZTA3N2ZkOGI4YjM0NTE4YzM2ODdhN2ZmMWU1OWQiLCJWb2x1bWVzIjpudWxsLCJXb3JraW5nRGlyIjoiIiwiRW50cnlwb2ludCI6bnVsbCwiT25CdWlsZCI6bnVsbCwiTGFiZWxzIjpudWxsfSwiY3JlYXRlZCI6IjIwMjEtMDMtMTNUMTY6MTU6NTAuMDM2MDAwNloiLCJkb2NrZXJfdmVyc2lvbiI6IjIwLjEwLjIiLCJoaXN0b3J5IjpbeyJjcmVhdGVkIjoiMjAyMS0wMy0xM1QxNjoxNTo0OS44NjA5MDgyWiIsImNyZWF0ZWRfYnkiOiIvYmluL3NoIC1jICMobm9wKSBBREQgZmlsZTphYzMyZGEyM2Q1MWU4MDFmMDJmOTI0MTIzZWQzMDk5MGViM2YwZmVjMWI5ZWQ0ZjBiMDZjMjRlODhiOWMzNjk1IGluIC9zb21lZmlsZS0xLnR4dCAifSx7ImNyZWF0ZWQiOiIyMDIxLTAzLTEzVDE2OjE1OjUwLjAzNjAwMDZaIiwiY3JlYXRlZF9ieSI6Ii9iaW4vc2ggLWMgIyhub3ApIEFERCBmaWxlOmRmM2I3NDRmNTRhOWIxNmI5YjlhZWQ0MGUzZTk4ZDljYTJiNDlmNWE3N2Q5ZmE4YTk3NjkwZDdiYWY1ODg4MjAgaW4gL3NvbWVmaWxlLTIudHh0ICJ9XSwib3MiOiJsaW51eCIsInJvb3RmcyI6eyJ0eXBlIjoibGF5ZXJzIiwiZGlmZl9pZHMiOlsic2hhMjU2OmUxNThiNTdkNmY1YTk2ZWY1ZmQyMmYyZmU3NmM3MGI1YmE2ZmY1YjI2MTlmOWQ4MzEyNWIyYWFkMDQ5MmFjN2IiLCJzaGEyNTY6ZGEyMTA1NmU3YmY0MzA4ZWNlYTBjMDgzNjg0OGE3ZmU5MmYzOGZkY2YzNWJjMDllZTZkOThlN2FiN2JlZWViZiJdfX0=", + "manifest": "eyJzY2hlbWFWZXJzaW9uIjoyLCJtZWRpYVR5cGUiOiJhcHBsaWNhdGlvbi92bmQuZG9ja2VyLmRpc3RyaWJ1dGlvbi5tYW5pZmVzdC52Mitqc29uIiwiY29uZmlnIjp7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuY29udGFpbmVyLmltYWdlLnYxK2pzb24iLCJzaXplIjoxNTg2LCJkaWdlc3QiOiJzaGEyNTY6YzJiNDZiNGViMDYyOTY5MzNiN2NmMDcyMjY4Mzk2NGU5ZWNiZDkzMjY1YjllZjZhZTk2NDJlMzk1MmFmYmJhMCJ9LCJsYXllcnMiOlt7Im1lZGlhVHlwZSI6ImFwcGxpY2F0aW9uL3ZuZC5kb2NrZXIuaW1hZ2Uucm9vdGZzLmRpZmYudGFyLmd6aXAiLCJzaXplIjoyMDQ4LCJkaWdlc3QiOiJzaGEyNTY6M2RlMTZjNWI4NjU5YTJlOGQ4ODhiOGRlZDg0MjdiZTdhNTY4NmEzYzhjNGU0ZGQzMGRlMjBmMzYyODI3Mjg1YiJ9LHsibWVkaWFUeXBlIjoiYXBwbGljYXRpb24vdm5kLmRvY2tlci5pbWFnZS5yb290ZnMuZGlmZi50YXIuZ3ppcCIsInNpemUiOjIwNDgsImRpZ2VzdCI6InNoYTI1NjozNjZhM2Y1NjUzZTM0NjczYjg3NTg5MWIwMjE2NDc0NDBkMDEyN2MyZWYwNDFlM2IxYTIyZGEyYTdkNGYzNzAzIn1dfQ==", + "config": "eyJhcmNoaXRlY3R1cmUiOiJhbWQ2NCIsImNvbmZpZyI6eyJIb3N0bmFtZSI6IiIsIkRvbWFpbm5hbWUiOiIiLCJVc2VyIjoiIiwiQXR0YWNoU3RkaW4iOmZhbHNlLCJBdHRhY2hTdGRvdXQiOmZhbHNlLCJBdHRhY2hTdGRlcnIiOmZhbHNlLCJUdHkiOmZhbHNlLCJPcGVuU3RkaW4iOmZhbHNlLCJTdGRpbk9uY2UiOmZhbHNlLCJFbnYiOlsiUEFUSD0vdXNyL2xvY2FsL3NiaW46L3Vzci9sb2NhbC9iaW46L3Vzci9zYmluOi91c3IvYmluOi9zYmluOi9iaW4iXSwiQ21kIjpudWxsLCJJbWFnZSI6InNoYTI1NjpkYWMyMTUwMzhjMDUwZTM1NzMwNTVlZmU4YTkwM2NkMWY5YmJkZmU0ZjlhZTlkODk5OTFjNTljY2M2OTA1MmU1IiwiVm9sdW1lcyI6bnVsbCwiV29ya2luZ0RpciI6IiIsIkVudHJ5cG9pbnQiOm51bGwsIk9uQnVpbGQiOm51bGwsIkxhYmVscyI6bnVsbH0sImNvbnRhaW5lcl9jb25maWciOnsiSG9zdG5hbWUiOiIiLCJEb21haW5uYW1lIjoiIiwiVXNlciI6IiIsIkF0dGFjaFN0ZGluIjpmYWxzZSwiQXR0YWNoU3Rkb3V0IjpmYWxzZSwiQXR0YWNoU3RkZXJyIjpmYWxzZSwiVHR5IjpmYWxzZSwiT3BlblN0ZGluIjpmYWxzZSwiU3RkaW5PbmNlIjpmYWxzZSwiRW52IjpbIlBBVEg9L3Vzci9sb2NhbC9zYmluOi91c3IvbG9jYWwvYmluOi91c3Ivc2JpbjovdXNyL2Jpbjovc2JpbjovYmluIl0sIkNtZCI6WyIvYmluL3NoIiwiLWMiLCIjKG5vcCkgQUREIGZpbGU6ZGYzYjc0NGY1NGE5YjE2YjliOWFlZDQwZTNlOThkOWNhMmI0OWY1YTc3ZDlmYThhOTc2OTBkN2JhZjU4ODgyMCBpbiAvc29tZWZpbGUtMi50eHQgIl0sIkltYWdlIjoic2hhMjU2OmRhYzIxNTAzOGMwNTBlMzU3MzA1NWVmZThhOTAzY2QxZjliYmRmZTRmOWFlOWQ4OTk5MWM1OWNjYzY5MDUyZTUiLCJWb2x1bWVzIjpudWxsLCJXb3JraW5nRGlyIjoiIiwiRW50cnlwb2ludCI6bnVsbCwiT25CdWlsZCI6bnVsbCwiTGFiZWxzIjpudWxsfSwiY3JlYXRlZCI6IjIwMjEtMDMtMjNUMTg6MTU6NTguODcyMjg5OFoiLCJkb2NrZXJfdmVyc2lvbiI6IjIwLjEwLjIiLCJoaXN0b3J5IjpbeyJjcmVhdGVkIjoiMjAyMS0wMy0yM1QxODoxNTo1OC42MTc3OTU2WiIsImNyZWF0ZWRfYnkiOiIvYmluL3NoIC1jICMobm9wKSBBREQgZmlsZTphYzMyZGEyM2Q1MWU4MDFmMDJmOTI0MTIzZWQzMDk5MGViM2YwZmVjMWI5ZWQ0ZjBiMDZjMjRlODhiOWMzNjk1IGluIC9zb21lZmlsZS0xLnR4dCAifSx7ImNyZWF0ZWQiOiIyMDIxLTAzLTIzVDE4OjE1OjU4Ljg3MjI4OThaIiwiY3JlYXRlZF9ieSI6Ii9iaW4vc2ggLWMgIyhub3ApIEFERCBmaWxlOmRmM2I3NDRmNTRhOWIxNmI5YjlhZWQ0MGUzZTk4ZDljYTJiNDlmNWE3N2Q5ZmE4YTk3NjkwZDdiYWY1ODg4MjAgaW4gL3NvbWVmaWxlLTIudHh0ICJ9XSwib3MiOiJsaW51eCIsInJvb3RmcyI6eyJ0eXBlIjoibGF5ZXJzIiwiZGlmZl9pZHMiOlsic2hhMjU2OjNkZTE2YzViODY1OWEyZThkODg4YjhkZWQ4NDI3YmU3YTU2ODZhM2M4YzRlNGRkMzBkZTIwZjM2MjgyNzI4NWIiLCJzaGEyNTY6MzY2YTNmNTY1M2UzNDY3M2I4NzU4OTFiMDIxNjQ3NDQwZDAxMjdjMmVmMDQxZTNiMWEyMmRhMmE3ZDRmMzcwMyJdfX0=", "scope": "Squashed" } }, diff --git a/internal/presenter/packages/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden b/internal/presenter/packages/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden index 24d879f49..10739912e 100644 Binary files a/internal/presenter/packages/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden and b/internal/presenter/packages/test-fixtures/snapshot/stereoscope-fixture-image-simple.golden differ diff --git a/internal/presenter/packages/test-fixtures/snapshot/stereoscope-fixture-packages-image-simple.golden b/internal/presenter/packages/test-fixtures/snapshot/stereoscope-fixture-packages-image-simple.golden new file mode 100644 index 000000000..b7d3fed18 Binary files /dev/null and b/internal/presenter/packages/test-fixtures/snapshot/stereoscope-fixture-packages-image-simple.golden differ diff --git a/syft/presenter/json/package.go b/syft/presenter/json/package.go deleted file mode 100644 index 456af01ba..000000000 --- a/syft/presenter/json/package.go +++ /dev/null @@ -1,181 +0,0 @@ -package json - -import ( - "encoding/json" - "fmt" - - "github.com/anchore/syft/syft/pkg" - "github.com/anchore/syft/syft/source" -) - -// Package represents a pkg.Package object specialized for JSON marshaling and unmarshaling. -type Package struct { - packageBasicMetadata - packageCustomMetadata -} - -// packageBasicMetadata contains non-ambiguous values (type-wise) from pkg.Package. -type packageBasicMetadata struct { - ID string `json:"id"` - Name string `json:"name"` - Version string `json:"version"` - Type string `json:"type"` - FoundBy string `json:"foundBy"` - Locations []source.Location `json:"locations"` - Licenses []string `json:"licenses"` - Language string `json:"language"` - CPEs []string `json:"cpes"` - PURL string `json:"purl"` -} - -// packageCustomMetadata contains ambiguous values (type-wise) from pkg.Package. -type packageCustomMetadata struct { - MetadataType string `json:"metadataType"` - Metadata interface{} `json:"metadata"` -} - -// packageMetadataUnpacker is all values needed from Package to disambiguate ambiguous fields during json unmarshaling. -type packageMetadataUnpacker struct { - MetadataType string `json:"metadataType"` - Metadata json.RawMessage `json:"metadata"` -} - -// NewPackage crates a new Package from the given pkg.Package. -func NewPackage(p *pkg.Package) (Package, error) { - var cpes = make([]string, len(p.CPEs)) - for i, c := range p.CPEs { - cpes[i] = c.BindToFmtString() - } - - // ensure collections are never nil for presentation reasons - - var locations = make([]source.Location, 0) - if p.Locations != nil { - locations = p.Locations - } - - var licenses = make([]string, 0) - if p.Licenses != nil { - licenses = p.Licenses - } - - return Package{ - packageBasicMetadata: packageBasicMetadata{ - ID: string(p.ID), - Name: p.Name, - Version: p.Version, - Type: string(p.Type), - FoundBy: p.FoundBy, - Locations: locations, - Licenses: licenses, - Language: string(p.Language), - CPEs: cpes, - PURL: p.PURL, - }, - packageCustomMetadata: packageCustomMetadata{ - MetadataType: string(p.MetadataType), - Metadata: p.Metadata, - }, - }, nil -} - -// ToPackage generates a pkg.Package from the current Package. -func (a Package) ToPackage() (pkg.Package, error) { - var cpes = make([]pkg.CPE, len(a.CPEs)) - var err error - for i, c := range a.CPEs { - cpes[i], err = pkg.NewCPE(c) - if err != nil { - return pkg.Package{}, fmt.Errorf("unable to parse CPE from JSON package: %w", err) - } - } - return pkg.Package{ - // does not include found-by and locations - ID: pkg.ID(a.ID), - Name: a.Name, - Version: a.Version, - FoundBy: a.FoundBy, - Licenses: a.Licenses, - Language: pkg.Language(a.Language), - Locations: a.Locations, - CPEs: cpes, - PURL: a.PURL, - Type: pkg.Type(a.Type), - MetadataType: pkg.MetadataType(a.MetadataType), - Metadata: a.Metadata, - }, nil -} - -// UnmarshalJSON is a custom unmarshaller for handling basic values and values with ambiguous types. -// nolint:funlen -func (a *Package) UnmarshalJSON(b []byte) error { - var basic packageBasicMetadata - if err := json.Unmarshal(b, &basic); err != nil { - return err - } - a.packageBasicMetadata = basic - - var unpacker packageMetadataUnpacker - if err := json.Unmarshal(b, &unpacker); err != nil { - return err - } - - a.MetadataType = unpacker.MetadataType - - switch pkg.MetadataType(a.MetadataType) { - case pkg.RpmdbMetadataType: - var payload pkg.RpmdbMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - a.Metadata = payload - case pkg.PythonPackageMetadataType: - var payload pkg.PythonPackageMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - a.Metadata = payload - case pkg.DpkgMetadataType: - var payload pkg.DpkgMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - a.Metadata = payload - case pkg.ApkMetadataType: - var payload pkg.ApkMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - a.Metadata = payload - case pkg.JavaMetadataType: - var payload pkg.JavaMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - a.Metadata = payload - case pkg.NpmPackageJSONMetadataType: - var payload pkg.NpmPackageJSONMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - a.Metadata = payload - case pkg.GemMetadataType: - var payload pkg.GemMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - a.Metadata = payload - case pkg.RustCargoPackageMetadataType: - var payload pkg.CargoPackageMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - a.Metadata = payload - case "": - // there may be packages with no metadata, which is OK - default: - return fmt.Errorf("unsupported package metadata type: %+v", a.MetadataType) - } - - return nil -}