mirror of
https://github.com/anchore/syft.git
synced 2026-10-12 22:27:22 +02:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
873f6e4037 |
+3
-24
@@ -1,5 +1,4 @@
|
||||
tools:
|
||||
# we want to use a pinned version of binny to manage the toolchain (so binny manages itself!)
|
||||
- name: binny
|
||||
version:
|
||||
want: v0.6.3
|
||||
@@ -7,15 +6,6 @@ tools:
|
||||
with:
|
||||
repo: anchore/binny
|
||||
|
||||
# used to produce SBOMs during release
|
||||
- name: syft
|
||||
version:
|
||||
want: latest
|
||||
method: github-release
|
||||
with:
|
||||
repo: anchore/syft
|
||||
|
||||
# used to sign mac binaries at release
|
||||
- name: quill
|
||||
version:
|
||||
want: v0.4.1
|
||||
@@ -23,7 +13,6 @@ tools:
|
||||
with:
|
||||
repo: anchore/quill
|
||||
|
||||
# used for linting
|
||||
- name: golangci-lint
|
||||
version:
|
||||
want: v1.55.2
|
||||
@@ -31,7 +20,6 @@ tools:
|
||||
with:
|
||||
repo: golangci/golangci-lint
|
||||
|
||||
# used for showing the changelog at release
|
||||
- name: glow
|
||||
version:
|
||||
want: v1.5.1
|
||||
@@ -39,15 +27,13 @@ tools:
|
||||
with:
|
||||
repo: charmbracelet/glow
|
||||
|
||||
# used for signing the checksums file at release
|
||||
- name: cosign
|
||||
version:
|
||||
want: v2.2.3
|
||||
want: v2.2.2
|
||||
method: github-release
|
||||
with:
|
||||
repo: sigstore/cosign
|
||||
|
||||
# used in integration tests to verify JSON schemas
|
||||
- name: yajsv
|
||||
version:
|
||||
want: v1.4.1
|
||||
@@ -55,7 +41,6 @@ tools:
|
||||
with:
|
||||
repo: neilpa/yajsv
|
||||
|
||||
# used to release all artifacts
|
||||
- name: goreleaser
|
||||
version:
|
||||
want: v1.23.0
|
||||
@@ -63,7 +48,6 @@ tools:
|
||||
with:
|
||||
repo: goreleaser/goreleaser
|
||||
|
||||
# used for organizing imports during static analysis
|
||||
- name: gosimports
|
||||
version:
|
||||
want: v0.3.8
|
||||
@@ -71,7 +55,6 @@ tools:
|
||||
with:
|
||||
repo: rinchsan/gosimports
|
||||
|
||||
# used at release to generate the changelog
|
||||
- name: chronicle
|
||||
version:
|
||||
want: v0.8.0
|
||||
@@ -79,7 +62,6 @@ tools:
|
||||
with:
|
||||
repo: anchore/chronicle
|
||||
|
||||
# used during static analysis for license compliance
|
||||
- name: bouncer
|
||||
version:
|
||||
want: v0.4.0
|
||||
@@ -87,7 +69,6 @@ tools:
|
||||
with:
|
||||
repo: wagoodman/go-bouncer
|
||||
|
||||
# used for showing benchmark testing
|
||||
- name: benchstat
|
||||
version:
|
||||
want: latest
|
||||
@@ -100,18 +81,16 @@ tools:
|
||||
entrypoint: cmd/benchstat
|
||||
module: golang.org/x/perf
|
||||
|
||||
# used for running all local and CI tasks
|
||||
- name: task
|
||||
version:
|
||||
want: v3.34.1
|
||||
want: v3.33.1
|
||||
method: github-release
|
||||
with:
|
||||
repo: go-task/task
|
||||
|
||||
# used for triggering a release
|
||||
- name: gh
|
||||
version:
|
||||
want: v2.43.1
|
||||
want: v2.42.0
|
||||
method: github-release
|
||||
with:
|
||||
repo: cli/cli
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Restore base benchmark result
|
||||
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
|
||||
uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c #v3.3.3
|
||||
with:
|
||||
path: test/results/benchmark-main.txt
|
||||
# use base sha for PR or new commit hash for main push in benchmark result key
|
||||
@@ -39,13 +39,13 @@ jobs:
|
||||
OUTPUT="${OUTPUT//$'\r'/'%0D'}" # URL encode all '\r' characters
|
||||
echo "result=$OUTPUT" >> $GITHUB_OUTPUT
|
||||
|
||||
- uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
|
||||
- uses: actions/upload-artifact@1eb3cb2b3e0f29609092a73eb033bb759a334595 # v4.1.0
|
||||
with:
|
||||
name: benchmark-test-results
|
||||
path: test/results/**/*
|
||||
|
||||
- name: Update PR benchmark results comment
|
||||
uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 #v2.9.0
|
||||
uses: marocchino/sticky-pull-request-comment@efaaab3fd41a9c3de579aba759d2552635e590fd #v2.8.0
|
||||
continue-on-error: true
|
||||
with:
|
||||
header: benchmark
|
||||
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 #v3.23.2
|
||||
uses: github/codeql-action/init@e5f05b81d5b6ff8cfa111c80c22c5fd02a384118 #v3.23.0
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 #v3.23.2
|
||||
uses: github/codeql-action/autobuild@e5f05b81d5b6ff8cfa111c80c22c5fd02a384118 #v3.23.0
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -70,4 +70,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@b7bf0a3ed3ecfa44160715d7c442788f65f0f923 #v3.23.2
|
||||
uses: github/codeql-action/analyze@e5f05b81d5b6ff8cfa111c80c22c5fd02a384118 #v3.23.0
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
name: Dependabot Automation
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
run:
|
||||
uses: anchore/workflows/.github/workflows/dependabot-automation.yaml@main
|
||||
@@ -40,7 +40,7 @@ jobs:
|
||||
|
||||
- name: Delete existing comment
|
||||
if: ${{ hashFiles( env.CI_COMMENT_FILE ) == '' }}
|
||||
uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 #v2.9.0
|
||||
uses: marocchino/sticky-pull-request-comment@efaaab3fd41a9c3de579aba759d2552635e590fd #v2.8.0
|
||||
with:
|
||||
header: ${{ env.COMMENT_HEADER }}
|
||||
hide: true
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
|
||||
- name: Add comment
|
||||
if: ${{ hashFiles( env.CI_COMMENT_FILE ) != '' }}
|
||||
uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 #v2.9.0
|
||||
uses: marocchino/sticky-pull-request-comment@efaaab3fd41a9c3de579aba759d2552635e590fd #v2.8.0
|
||||
with:
|
||||
header: ${{ env.COMMENT_HEADER }}
|
||||
path: ${{ env.CI_COMMENT_FILE }}
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
tag: ${{ steps.release_info.outputs.tag_name }}
|
||||
revision: ${{ steps.git_info.outputs.commit }}
|
||||
|
||||
- uses: 8398a7/action-slack@28ba43ae48961b90635b50953d216767a6bea486 #v3.16.2
|
||||
- uses: 8398a7/action-slack@fbd6aa58ba854a740e11a35d0df80cb5d12101d8 #v3.15.1
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
status: ${{ job.status }}
|
||||
|
||||
@@ -94,8 +94,6 @@ jobs:
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
# required for goreleaser signs section with cosign
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 #v4.1.1
|
||||
with:
|
||||
@@ -143,12 +141,12 @@ jobs:
|
||||
AWS_ACCESS_KEY_ID: ${{ secrets.TOOLBOX_AWS_ACCESS_KEY_ID }}
|
||||
AWS_SECRET_ACCESS_KEY: ${{ secrets.TOOLBOX_AWS_SECRET_ACCESS_KEY }}
|
||||
|
||||
- uses: anchore/sbom-action@b6a39da80722a2cb0ef5d197531764a89b5d48c3 #v0.15.8
|
||||
- uses: anchore/sbom-action@c7f031d9249a826a082ea14c79d3b686a51d485a #v0.15.3
|
||||
continue-on-error: true
|
||||
with:
|
||||
artifact-name: sbom.spdx.json
|
||||
|
||||
- uses: 8398a7/action-slack@28ba43ae48961b90635b50953d216767a6bea486 #v3.16.2
|
||||
- uses: 8398a7/action-slack@fbd6aa58ba854a740e11a35d0df80cb5d12101d8 #v3.15.1
|
||||
continue-on-error: true
|
||||
with:
|
||||
status: ${{ job.status }}
|
||||
|
||||
@@ -50,7 +50,7 @@ jobs:
|
||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@b1ddad2c994a25fbc81a28b3ec0e368bb2021c50 #v6.0.0
|
||||
- uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 #v5.0.2
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
|
||||
@@ -33,7 +33,7 @@ jobs:
|
||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@b1ddad2c994a25fbc81a28b3ec0e368bb2021c50 #v6.0.0
|
||||
- uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 #v5.0.2
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
@@ -45,7 +45,7 @@ jobs:
|
||||
Update CPE dictionary index based on the latest available CPE dictionary
|
||||
token: ${{ steps.generate-token.outputs.token }}
|
||||
|
||||
- uses: 8398a7/action-slack@28ba43ae48961b90635b50953d216767a6bea486 #v3.16.2
|
||||
- uses: 8398a7/action-slack@fbd6aa58ba854a740e11a35d0df80cb5d12101d8 #v3.15.1
|
||||
with:
|
||||
status: ${{ job.status }}
|
||||
fields: workflow,eventName,job
|
||||
|
||||
@@ -44,7 +44,7 @@ jobs:
|
||||
app_id: ${{ secrets.TOKEN_APP_ID }}
|
||||
private_key: ${{ secrets.TOKEN_APP_PRIVATE_KEY }}
|
||||
|
||||
- uses: peter-evans/create-pull-request@b1ddad2c994a25fbc81a28b3ec0e368bb2021c50 #v6.0.0
|
||||
- uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 #v5.0.2
|
||||
with:
|
||||
signoff: true
|
||||
delete-branch: true
|
||||
|
||||
@@ -37,31 +37,31 @@ jobs:
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Restore Java test-fixture cache
|
||||
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
|
||||
uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c #v3.3.3
|
||||
with:
|
||||
path: syft/pkg/cataloger/java/test-fixtures/java-builds/packages
|
||||
key: ${{ runner.os }}-unit-java-cache-${{ hashFiles( 'syft/pkg/cataloger/java/test-fixtures/java-builds/cache.fingerprint' ) }}
|
||||
|
||||
- name: Restore RPM test-fixture cache
|
||||
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
|
||||
uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c #v3.3.3
|
||||
with:
|
||||
path: syft/pkg/cataloger/redhat/test-fixtures/rpms
|
||||
key: ${{ runner.os }}-unit-rpm-cache-${{ hashFiles( 'syft/pkg/cataloger/redhat/test-fixtures/rpms.fingerprint' ) }}
|
||||
|
||||
- name: Restore go binary test-fixture cache
|
||||
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
|
||||
uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c #v3.3.3
|
||||
with:
|
||||
path: syft/pkg/cataloger/golang/test-fixtures/archs/binaries
|
||||
key: ${{ runner.os }}-unit-go-binaries-cache-${{ hashFiles( 'syft/pkg/cataloger/golang/test-fixtures/archs/binaries.fingerprint' ) }}
|
||||
|
||||
- name: Restore binary cataloger test-fixture cache
|
||||
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
|
||||
uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c #v3.3.3
|
||||
with:
|
||||
path: syft/pkg/cataloger/binary/test-fixtures/classifiers/bin
|
||||
key: ${{ runner.os }}-unit-binary-cataloger-cache-${{ hashFiles( 'syft/pkg/cataloger/binary/test-fixtures/cache.fingerprint' ) }}
|
||||
|
||||
- name: Restore Kernel test-fixture cache
|
||||
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
|
||||
uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c #v3.3.3
|
||||
with:
|
||||
path: syft/pkg/cataloger/kernel/test-fixtures/cache
|
||||
key: ${{ runner.os }}-unit-kernel-cache-${{ hashFiles( 'syft/pkg/cataloger/kernel/test-fixtures/cache.fingerprint' ) }}
|
||||
@@ -84,10 +84,10 @@ jobs:
|
||||
run: make validate-cyclonedx-schema
|
||||
|
||||
- name: Restore integration test cache
|
||||
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
|
||||
uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c #v3.3.3
|
||||
with:
|
||||
path: ${{ github.workspace }}/cmd/syft/internal/test/integration/test-fixtures/cache
|
||||
key: ${{ runner.os }}-integration-test-cache-${{ hashFiles('/cmd/syft/internal/test/integration/test-fixtures/cache.fingerprint') }}
|
||||
path: ${{ github.workspace }}/test/integration/test-fixtures/cache
|
||||
key: ${{ runner.os }}-integration-test-cache-${{ hashFiles('test/integration/test-fixtures/cache.fingerprint') }}
|
||||
|
||||
- name: Run integration tests
|
||||
run: make integration
|
||||
@@ -110,7 +110,7 @@ jobs:
|
||||
# why not use actions/upload-artifact? It is very slow (3 minutes to upload ~600MB of data, vs 10 seconds with this approach).
|
||||
# see https://github.com/actions/upload-artifact/issues/199 for more info
|
||||
- name: Upload snapshot artifacts
|
||||
uses: actions/cache/save@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
|
||||
uses: actions/cache/save@e12d46a63a90f2fae62d114769bbf2a179198b5c #v3.3.3
|
||||
with:
|
||||
# we need to preserve the snapshot data itself as well as the task data that confirms if the
|
||||
# snapshot build is stale or not. Otherwise the downstream jobs will attempt to rebuild the snapshot
|
||||
@@ -134,7 +134,7 @@ jobs:
|
||||
|
||||
- name: Download snapshot build
|
||||
id: snapshot-cache
|
||||
uses: actions/cache/restore@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
|
||||
uses: actions/cache/restore@e12d46a63a90f2fae62d114769bbf2a179198b5c #v3.3.3
|
||||
with:
|
||||
path: |
|
||||
snapshot
|
||||
@@ -152,7 +152,7 @@ jobs:
|
||||
|
||||
- name: Restore install.sh test image cache
|
||||
id: install-test-image-cache
|
||||
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
|
||||
uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c #v3.3.3
|
||||
with:
|
||||
path: ${{ github.workspace }}/test/install/cache
|
||||
key: ${{ runner.os }}-install-test-image-cache-${{ hashFiles('test/install/cache.fingerprint') }}
|
||||
@@ -187,7 +187,7 @@ jobs:
|
||||
|
||||
- name: Download snapshot build
|
||||
id: snapshot-cache
|
||||
uses: actions/cache/restore@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
|
||||
uses: actions/cache/restore@e12d46a63a90f2fae62d114769bbf2a179198b5c #v3.3.3
|
||||
with:
|
||||
path: |
|
||||
snapshot
|
||||
@@ -202,7 +202,7 @@ jobs:
|
||||
|
||||
- name: Restore docker image cache for compare testing
|
||||
id: mac-compare-testing-cache
|
||||
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
|
||||
uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c #v3.3.3
|
||||
with:
|
||||
path: image.tar
|
||||
key: ${{ runner.os }}-${{ hashFiles('test/compare/mac.sh') }}
|
||||
@@ -226,14 +226,14 @@ jobs:
|
||||
uses: ./.github/actions/bootstrap
|
||||
|
||||
- name: Restore CLI test-fixture cache
|
||||
uses: actions/cache@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
|
||||
uses: actions/cache@e12d46a63a90f2fae62d114769bbf2a179198b5c #v3.3.3
|
||||
with:
|
||||
path: ${{ github.workspace }}/test/cli/test-fixtures/cache
|
||||
key: ${{ runner.os }}-cli-test-cache-${{ hashFiles('test/cli/test-fixtures/cache.fingerprint') }}
|
||||
|
||||
- name: Download snapshot build
|
||||
id: snapshot-cache
|
||||
uses: actions/cache/restore@13aacd865c20de90d75de3b17ebe84f7a17d57d2 #v4.0.0
|
||||
uses: actions/cache/restore@e12d46a63a90f2fae62d114769bbf2a179198b5c #v3.3.3
|
||||
with:
|
||||
path: |
|
||||
snapshot
|
||||
|
||||
@@ -32,6 +32,7 @@ VERSION
|
||||
/test/results
|
||||
coverage.txt
|
||||
*.log
|
||||
test/integration/test-fixtures/**/go.sum
|
||||
|
||||
# probable archives
|
||||
.images
|
||||
|
||||
@@ -247,28 +247,3 @@ docker_manifests:
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-arm64v8
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-ppc64le
|
||||
- ghcr.io/anchore/syft:{{.Tag}}-s390x
|
||||
|
||||
sboms:
|
||||
- artifacts: archive
|
||||
# this is relative to the snapshot/dist directory, not the root of the repo
|
||||
cmd: ../.tool/syft
|
||||
documents:
|
||||
- "{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}.sbom"
|
||||
args:
|
||||
- "scan"
|
||||
- "$artifact"
|
||||
- "--output"
|
||||
- "json=$document"
|
||||
|
||||
signs:
|
||||
- cmd: .tool/cosign
|
||||
signature: "${artifact}.sig"
|
||||
certificate: "${artifact}.pem"
|
||||
args:
|
||||
- "sign-blob"
|
||||
- "--oidc-issuer=https://token.actions.githubusercontent.com"
|
||||
- "--output-certificate=${certificate}"
|
||||
- "--output-signature=${signature}"
|
||||
- "${artifact}"
|
||||
- "--yes"
|
||||
artifacts: checksum
|
||||
|
||||
+1
-1
@@ -234,7 +234,7 @@ rough outline how that works:
|
||||
the `/test` directory. These tests should focus on correctness of functionality in depth. % test coverage metrics
|
||||
only considers unit tests and no other forms of testing.
|
||||
|
||||
- `integration`: located within `cmd/syft/internal/test/integration`, these tests focus on the behavior surfaced by the common library
|
||||
- `integration`: located within `test/integration`, these tests focus on the behavior surfaced by the common library
|
||||
entrypoints from the `syft` package and make light assertions about the results surfaced. Additionally, these tests
|
||||
tend to make diversity assertions for enum-like objects, ensuring that as enum values are added to a definition
|
||||
that integration tests will automatically fail if no test attempts to use that enum value. For more details see
|
||||
|
||||
@@ -502,20 +502,19 @@ Configuration options (example values are the default):
|
||||
|
||||
```yaml
|
||||
# the output format(s) of the SBOM report (options: syft-table, syft-text, syft-json, spdx-json, ...)
|
||||
# same as -o, --output, and SYFT_OUTPUT env var
|
||||
# to specify multiple output files in differing formats, use a list:
|
||||
# output:
|
||||
# - "syft-json=<syft-json-output-file>"
|
||||
# - "spdx-json=<spdx-json-output-file>"
|
||||
# SYFT_OUTPUT env var / -o, --output flags
|
||||
output:
|
||||
- "syft-table"
|
||||
output: "syft-table"
|
||||
|
||||
# suppress all output (except for the SBOM report)
|
||||
# SYFT_QUIET env var / -q flag
|
||||
# same as -q ; SYFT_QUIET env var
|
||||
quiet: false
|
||||
|
||||
# enable/disable checking for application updates on startup
|
||||
# SYFT_CHECK_FOR_APP_UPDATE env var
|
||||
# same as SYFT_CHECK_FOR_APP_UPDATE env var
|
||||
check-for-app-update: true
|
||||
|
||||
# maximum number of workers used to process the list of package catalogers in parallel
|
||||
@@ -525,11 +524,15 @@ parallelism: 1
|
||||
# exclude:
|
||||
# - "/etc/**"
|
||||
# - "./out/**/*.json"
|
||||
# SYFT_EXCLUDE env var / --exclude flag
|
||||
# same as --exclude ; SYFT_EXCLUDE env var
|
||||
exclude: []
|
||||
|
||||
# allows users to exclude synthetic binary packages from the sbom
|
||||
# these packages are removed if an overlap with a non-synthetic package is found
|
||||
exclude-binary-overlap-by-ownership: true
|
||||
|
||||
# os and/or architecture to use when referencing container images (e.g. "windows/armv6" or "arm64")
|
||||
# SYFT_PLATFORM env var / --platform flag
|
||||
# same as --platform; SYFT_PLATFORM env var
|
||||
platform: ""
|
||||
|
||||
# the search space to look for file and package data (options: all-layers, squashed)
|
||||
@@ -538,24 +541,48 @@ scope: "squashed"
|
||||
|
||||
# set the list of package catalogers to use when generating the SBOM
|
||||
# default = empty (cataloger set determined automatically by the source type [image or file/directory])
|
||||
# Use `syft cataloger list` for a list of catalogers you can specify
|
||||
# DEPRECATED: please use default-catalogers and select-catalogers configuration options instead
|
||||
# SYFT_CATALOGERS env var / --catalogers flag
|
||||
# catalogers:
|
||||
# - alpm-db-cataloger
|
||||
# - apkdb-cataloger
|
||||
# - binary-cataloger
|
||||
# - cargo-auditable-binary-cataloger
|
||||
# - cocoapods-cataloger
|
||||
# - conan-cataloger
|
||||
# - dartlang-lock-cataloger
|
||||
# - dotnet-deps-cataloger
|
||||
# - dotnet-portable-executable-cataloger
|
||||
# - dpkg-db-cataloger
|
||||
# - elixir-mix-lock-cataloger
|
||||
# - erlang-rebar-lock-cataloger
|
||||
# - go-module-file-cataloger
|
||||
# - go-module-binary-cataloger
|
||||
# - graalvm-native-image-cataloger
|
||||
# - haskell-cataloger
|
||||
# - java-cataloger
|
||||
# - java-gradle-lockfile-cataloger
|
||||
# - java-pom-cataloger
|
||||
# - javascript-lock-cataloger
|
||||
# - javascript-package-cataloger
|
||||
# - linux-kernel-cataloger
|
||||
# - nix-store-cataloger
|
||||
# - php-composer-installed-cataloger
|
||||
# - php-composer-lock-cataloger
|
||||
# - portage-cataloger
|
||||
# - python-package-cataloger
|
||||
# - python-installed-package-cataloger
|
||||
# - rpm-db-cataloger
|
||||
# - rpm-archive-cataloger
|
||||
# - ruby-gemfile-cataloger
|
||||
# - ruby-installed-gemspec-cataloger
|
||||
# - rust-cargo-lock-cataloger
|
||||
# - sbom-cataloger
|
||||
# - spm-cataloger
|
||||
catalogers:
|
||||
|
||||
# set the base set of catalogers to use (defaults to 'image' or 'directory' depending on the scan source)
|
||||
# SYFT_DEFAULT_CATALOGERS env var / --override-default-catalogers flag
|
||||
default-catalogers: []
|
||||
|
||||
# add, remove, and filter the catalogers to be used
|
||||
# SYFT_SELECT_CATALOGERS env var / --select-catalogers flag;
|
||||
select-catalogers: []
|
||||
|
||||
# all format configuration
|
||||
format:
|
||||
|
||||
# default value for all formats that support the "pretty" option (default is unset)
|
||||
# SYFT_FORMAT_PRETTY env var
|
||||
pretty:
|
||||
|
||||
# all syft-json format options
|
||||
@@ -563,7 +590,6 @@ format:
|
||||
|
||||
# include space indention and newlines (inherits default value from 'format.pretty' or 'false' if parent is unset)
|
||||
# note: inherits default value from 'format.pretty' or 'false' if parent is unset
|
||||
# SYFT_FORMAT_JSON_PRETTY env var
|
||||
pretty: false
|
||||
|
||||
# transform any syft-json output to conform to an approximation of the v11.0.1 schema. This includes:
|
||||
@@ -573,30 +599,21 @@ format:
|
||||
# that output might not strictly be json schema v11 compliant, however, for consumers that require time to port
|
||||
# over to the final syft 1.0 json output this option can be used to ease the transition.
|
||||
#
|
||||
# Note: long term support for this option is not guaranteed (it may change or break at any time).
|
||||
# SYFT_FORMAT_JSON_LEGACY env var
|
||||
# Note: long term support for this option is not guaranteed.
|
||||
legacy: false
|
||||
|
||||
# all template format options
|
||||
template:
|
||||
# path to the template file to use when rendering the output with the `template` output format.
|
||||
# Note that all template paths are based on the current syft-json schema.
|
||||
# SYFT_FORMAT_TEMPLATE_PATH env var / -t flag
|
||||
# same as -t ; SYFT_TEMPLATE_PATH env var
|
||||
path: ""
|
||||
|
||||
# if true, uses the go structs for the syft-json format for templating.
|
||||
# if false, uses the syft-json output for templating (which follows the syft JSON schema exactly).
|
||||
#
|
||||
# Note: long term support for this option is not guaranteed (it may change or break at any time).
|
||||
# SYFT_FORMAT_TEMPLATE_LEGACY env var
|
||||
legacy: false
|
||||
|
||||
# all spdx-json format options
|
||||
spdx-json:
|
||||
|
||||
# include space indention and newlines
|
||||
# note: inherits default value from 'format.pretty' or 'false' if parent is unset
|
||||
# SYFT_FORMAT_SPDX_JSON_PRETTY env var
|
||||
pretty: false
|
||||
|
||||
# all cyclonedx-json format options
|
||||
@@ -604,7 +621,6 @@ format:
|
||||
|
||||
# include space indention and newlines
|
||||
# note: inherits default value from 'format.pretty' or 'false' if parent is unset
|
||||
# SYFT_FORMAT_CYCLONEDX_JSON_PRETTY env var
|
||||
pretty: false
|
||||
|
||||
# all cyclonedx-xml format options
|
||||
@@ -612,7 +628,6 @@ format:
|
||||
|
||||
# include space indention
|
||||
# note: inherits default value from 'format.pretty' or 'false' if parent is unset
|
||||
# SYFT_FORMAT_CYCLONEDX_XML_PRETTY env var
|
||||
pretty: false
|
||||
|
||||
|
||||
@@ -621,17 +636,16 @@ file:
|
||||
metadata:
|
||||
# select which files should be captured by the file-metadata cataloger and included in the SBOM.
|
||||
# Options include:
|
||||
# - "all": capture all files from the search space
|
||||
# - "owned-by-package": capture only files owned by packages
|
||||
# - "none", "": do not capture any files
|
||||
# - "all-files": capture all files from the search space
|
||||
# - "owned-files": capture only files owned by packages
|
||||
# - "unowned-files": capture only files not owned by packages
|
||||
# - "no-files", "": do not capture any files
|
||||
# SYFT_FILE_METADATA_SELECTION env var
|
||||
selection: "owned-by-package"
|
||||
selection: "owned-files"
|
||||
|
||||
# the file digest algorithms to use when cataloging files (options: "md5", "sha1", "sha224", "sha256", "sha384", "sha512")
|
||||
# SYFT_FILE_METADATA_DIGESTS env var
|
||||
digests:
|
||||
- "sha256"
|
||||
- "sha1"
|
||||
digests: ["sha256"]
|
||||
|
||||
# capture the contents of select files in the SBOM
|
||||
content:
|
||||
@@ -660,7 +674,6 @@ package:
|
||||
|
||||
# allows users to exclude synthetic binary packages from the sbom
|
||||
# these packages are removed if an overlap with a non-synthetic package is found
|
||||
# SYFT_PACKAGE_EXCLUDE_BINARY_OVERLAP_BY_OWNERSHIP env var
|
||||
exclude-binary-overlap-by-ownership: true
|
||||
|
||||
|
||||
@@ -719,23 +732,17 @@ javascript:
|
||||
# configuration for the source that the SBOM is generated from (e.g. a file, directory, or container image)
|
||||
source:
|
||||
# alias name for the source
|
||||
# SYFT_SOURCE_NAME env var / --source-name flag
|
||||
# SYFT_SOURCE_NAME env var; --source-name flag
|
||||
name: ""
|
||||
|
||||
# alias version for the source
|
||||
# SYFT_SOURCE_VERSION env var / --source-version flag
|
||||
# SYFT_SOURCE_VERSION env var; --source-version flag
|
||||
version: ""
|
||||
|
||||
# base directory for scanning, no links will be followed above this directory, and all paths will be
|
||||
# reported relative to this directory
|
||||
# SYFT_SOURCE_BASE_PATH env var
|
||||
base-path: ''
|
||||
|
||||
# options affecting the file source type
|
||||
|
||||
# options affecting the file source type
|
||||
file:
|
||||
# the file digest algorithms to use on the scanned file (options: "md5", "sha1", "sha224", "sha256", "sha384", "sha512")
|
||||
digests:
|
||||
- "sha256"
|
||||
digests: ["sha256"]
|
||||
|
||||
image:
|
||||
|
||||
@@ -797,15 +804,15 @@ attest:
|
||||
|
||||
log:
|
||||
# use structured logging
|
||||
# SYFT_LOG_STRUCTURED env var
|
||||
# same as SYFT_LOG_STRUCTURED env var
|
||||
structured: false
|
||||
|
||||
# the log level; note: detailed logging suppress the ETUI
|
||||
# SYFT_LOG_LEVEL env var
|
||||
# same as SYFT_LOG_LEVEL env var
|
||||
level: "error"
|
||||
|
||||
# location to write the log file (default is not to have a log file)
|
||||
# SYFT_LOG_FILE env var
|
||||
# same as SYFT_LOG_FILE env var
|
||||
file: ""
|
||||
```
|
||||
|
||||
|
||||
+5
-5
@@ -185,7 +185,7 @@ tasks:
|
||||
- fixtures
|
||||
vars:
|
||||
TEST_PKGS:
|
||||
sh: "go list ./... | grep -v {{ .OWNER }}/{{ .PROJECT }}/test | grep -v {{ .OWNER }}/{{ .PROJECT }}/cmd/syft/internal/test | tr '\n' ' '"
|
||||
sh: "go list ./... | grep -v {{ .OWNER }}/{{ .PROJECT }}/test | tr '\n' ' '"
|
||||
|
||||
# unit test coverage threshold (in % coverage)
|
||||
COVERAGE_THRESHOLD: 62
|
||||
@@ -197,7 +197,7 @@ tasks:
|
||||
integration:
|
||||
desc: Run integration tests
|
||||
cmds:
|
||||
- "go test -v ./cmd/syft/internal/test/integration"
|
||||
- "go test -v ./test/integration"
|
||||
# exercise most of the CLI with the data race detector
|
||||
- "go run -race cmd/syft/main.go alpine:latest"
|
||||
|
||||
@@ -265,7 +265,7 @@ tasks:
|
||||
fingerprints:
|
||||
desc: Generate test fixture fingerprints
|
||||
generates:
|
||||
- cmd/syft/internal/test/integration/test-fixtures/cache.fingerprint
|
||||
- test/integration/test-fixtures/cache.fingerprint
|
||||
- syft/pkg/cataloger/binary/test-fixtures/cache.fingerprint
|
||||
- syft/pkg/cataloger/java/test-fixtures/java-builds/cache.fingerprint
|
||||
- syft/pkg/cataloger/golang/test-fixtures/archs/binaries.fingerprint
|
||||
@@ -275,7 +275,7 @@ tasks:
|
||||
- test/cli/test-fixtures/cache.fingerprint
|
||||
cmds:
|
||||
# for IMAGE integration test fixtures
|
||||
- "cd cmd/syft/internal/test/integration/test-fixtures && make cache.fingerprint"
|
||||
- "cd test/integration/test-fixtures && make cache.fingerprint"
|
||||
# for BINARY test fixtures
|
||||
- "cd syft/pkg/cataloger/binary/test-fixtures && make cache.fingerprint"
|
||||
# for JAVA BUILD test fixtures
|
||||
@@ -286,7 +286,7 @@ tasks:
|
||||
- "cd syft/pkg/cataloger/redhat/test-fixtures && make rpms.fingerprint"
|
||||
# for Kernel test fixtures
|
||||
- "cd syft/pkg/cataloger/kernel/test-fixtures && make cache.fingerprint"
|
||||
# for INSTALL test fixtures
|
||||
# for INSTALL integration test fixtures
|
||||
- "cd test/install && make cache.fingerprint"
|
||||
# for CLI test fixtures
|
||||
- "cd test/cli/test-fixtures && make cache.fingerprint"
|
||||
|
||||
+45
-4
@@ -8,8 +8,13 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/cmd/syft/internal"
|
||||
"github.com/anchore/syft/cmd/syft/internal/commands"
|
||||
"github.com/anchore/stereoscope"
|
||||
"github.com/anchore/syft/cmd/syft/cli/commands"
|
||||
handler "github.com/anchore/syft/cmd/syft/cli/ui"
|
||||
"github.com/anchore/syft/cmd/syft/internal/ui"
|
||||
"github.com/anchore/syft/internal/bus"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/internal/redact"
|
||||
)
|
||||
|
||||
// Application constructs the `syft packages` command and aliases the root command to `syft packages`.
|
||||
@@ -29,7 +34,44 @@ func Command(id clio.Identification) *cobra.Command {
|
||||
}
|
||||
|
||||
func create(id clio.Identification, out io.Writer) (clio.Application, *cobra.Command) {
|
||||
clioCfg := internal.AppClioSetupConfig(id, out)
|
||||
clioCfg := clio.NewSetupConfig(id).
|
||||
WithGlobalConfigFlag(). // add persistent -c <path> for reading an application config from
|
||||
WithGlobalLoggingFlags(). // add persistent -v and -q flags tied to the logging config
|
||||
WithConfigInRootHelp(). // --help on the root command renders the full application config in the help text
|
||||
WithUIConstructor(
|
||||
// select a UI based on the logging configuration and state of stdin (if stdin is a tty)
|
||||
func(cfg clio.Config) ([]clio.UI, error) {
|
||||
noUI := ui.None(out, cfg.Log.Quiet)
|
||||
if !cfg.Log.AllowUI(os.Stdin) || cfg.Log.Quiet {
|
||||
return []clio.UI{noUI}, nil
|
||||
}
|
||||
|
||||
return []clio.UI{
|
||||
ui.New(out, cfg.Log.Quiet,
|
||||
handler.New(handler.DefaultHandlerConfig()),
|
||||
),
|
||||
noUI,
|
||||
}, nil
|
||||
},
|
||||
).
|
||||
WithInitializers(
|
||||
func(state *clio.State) error {
|
||||
// clio is setting up and providing the bus, redact store, and logger to the application. Once loaded,
|
||||
// we can hoist them into the internal packages for global use.
|
||||
stereoscope.SetBus(state.Bus)
|
||||
bus.Set(state.Bus)
|
||||
|
||||
redact.Set(state.RedactStore)
|
||||
|
||||
log.Set(state.Logger)
|
||||
stereoscope.SetLogger(state.Logger)
|
||||
|
||||
return nil
|
||||
},
|
||||
).
|
||||
WithPostRuns(func(state *clio.State, err error) {
|
||||
stereoscope.Cleanup()
|
||||
})
|
||||
|
||||
app := clio.New(*clioCfg)
|
||||
|
||||
@@ -44,7 +86,6 @@ func create(id clio.Identification, out io.Writer) (clio.Application, *cobra.Com
|
||||
rootCmd.AddCommand(
|
||||
scanCmd,
|
||||
commands.Packages(app, scanCmd), // this is currently an alias for the scan command
|
||||
commands.Cataloger(app),
|
||||
commands.Attest(app),
|
||||
commands.Convert(app),
|
||||
clio.VersionCommand(id),
|
||||
|
||||
@@ -13,7 +13,7 @@ import (
|
||||
"github.com/wagoodman/go-progress"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/cmd/syft/internal/options"
|
||||
"github.com/anchore/syft/cmd/syft/cli/options"
|
||||
"github.com/anchore/syft/cmd/syft/internal/ui"
|
||||
"github.com/anchore/syft/internal"
|
||||
"github.com/anchore/syft/internal/bus"
|
||||
@@ -30,7 +30,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
attestExample = ` {{.appName}} {{.command}} --output [FORMAT] alpine:latest defaults to using images from a Docker daemon. If Docker is not present, the image is pulled directly from the registry
|
||||
attestExample = ` {{.appName}} {{.command}} --output [FORMAT] alpine:latest defaults to using images from a Docker daemon. If Docker is not present, the image is pulled directly from the registry
|
||||
`
|
||||
attestSchemeHelp = "\n " + schemeHelpHeader + "\n" + imageSchemeHelp
|
||||
attestHelp = attestExample + attestSchemeHelp
|
||||
@@ -42,7 +42,7 @@ type attestOptions struct {
|
||||
options.Output `yaml:",inline" mapstructure:",squash"`
|
||||
options.UpdateCheck `yaml:",inline" mapstructure:",squash"`
|
||||
options.Catalog `yaml:",inline" mapstructure:",squash"`
|
||||
Attest options.Attest `yaml:"attest" mapstructure:"attest"`
|
||||
options.Attest `yaml:",inline" mapstructure:",squash"`
|
||||
}
|
||||
|
||||
func Attest(app clio.Application) *cobra.Command {
|
||||
@@ -232,7 +232,7 @@ func attestCommand(sbomFilepath string, opts *attestOptions, userInput string) (
|
||||
}
|
||||
|
||||
func predicateType(outputName string) string {
|
||||
// select the Cosign predicate type based on defined output type
|
||||
// Select Cosign predicate type based on defined output type
|
||||
// As orientation, check: https://github.com/sigstore/cosign/blob/main/pkg/cosign/attestation/attestation.go
|
||||
switch strings.ToLower(outputName) {
|
||||
case "cyclonedx-json":
|
||||
@@ -4,22 +4,17 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/scylladb/go-set/strset"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/clio/cliotestutils"
|
||||
"github.com/anchore/syft/cmd/syft/internal"
|
||||
"github.com/anchore/syft/cmd/syft/internal/options"
|
||||
"github.com/anchore/syft/cmd/syft/cli/options"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
@@ -272,60 +267,3 @@ func Test_buildSBOMForAttestation(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_attestCLIWiring(t *testing.T) {
|
||||
id := clio.Identification{
|
||||
Name: "syft",
|
||||
Version: "testing",
|
||||
}
|
||||
cfg := internal.AppClioSetupConfig(id, io.Discard)
|
||||
tests := []struct {
|
||||
name string
|
||||
assertionFunc func(*testing.T, *cobra.Command, []string, ...any)
|
||||
wantOpts attestOptions
|
||||
args []string
|
||||
env map[string]string
|
||||
}{
|
||||
{
|
||||
name: "key flag is accepted",
|
||||
args: []string{"some-image:some-tag", "--key", "some-cosign-key.key"},
|
||||
assertionFunc: hasAttestOpts(options.Attest{Key: "some-cosign-key.key"}),
|
||||
},
|
||||
{
|
||||
name: "key password is read from env",
|
||||
args: []string{"some-image:some-tag", "--key", "cosign.key"},
|
||||
env: map[string]string{
|
||||
"SYFT_ATTEST_PASSWORD": "some-password",
|
||||
},
|
||||
assertionFunc: hasAttestOpts(options.Attest{
|
||||
Key: "cosign.key",
|
||||
Password: "some-password",
|
||||
}),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.env != nil {
|
||||
for k, v := range tt.env {
|
||||
t.Setenv(k, v)
|
||||
}
|
||||
}
|
||||
app := cliotestutils.NewApplication(t, cfg, tt.assertionFunc)
|
||||
cmd := Attest(app)
|
||||
cmd.SetArgs(tt.args)
|
||||
err := cmd.Execute()
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func hasAttestOpts(wantOpts options.Attest) cliotestutils.AssertionFunc {
|
||||
return func(t *testing.T, _ *cobra.Command, _ []string, cfgs ...any) {
|
||||
assert.Equal(t, len(cfgs), 1)
|
||||
attestOpts, ok := cfgs[0].(*attestOptions)
|
||||
require.True(t, ok)
|
||||
if d := cmp.Diff(wantOpts, attestOpts.Attest); d != "" {
|
||||
t.Errorf("mismatched attest options (-want +got):\n%s", d)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/cmd/syft/internal/options"
|
||||
"github.com/anchore/syft/cmd/syft/cli/options"
|
||||
"github.com/anchore/syft/cmd/syft/internal/ui"
|
||||
"github.com/anchore/syft/internal"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/cmd/syft/internal/ui"
|
||||
"github.com/anchore/syft/internal"
|
||||
)
|
||||
|
||||
func Packages(app clio.Application, scanCmd *cobra.Command) *cobra.Command {
|
||||
@@ -14,14 +13,11 @@ func Packages(app clio.Application, scanCmd *cobra.Command) *cobra.Command {
|
||||
opts := defaultScanOptions()
|
||||
|
||||
cmd := app.SetupCommand(&cobra.Command{
|
||||
Use: "packages [SOURCE]",
|
||||
Short: scanCmd.Short,
|
||||
Long: scanCmd.Long,
|
||||
Args: scanCmd.Args,
|
||||
Example: internal.Tprintf(scanHelp, map[string]interface{}{
|
||||
"appName": id.Name,
|
||||
"command": "packages",
|
||||
}),
|
||||
Use: "packages [SOURCE]",
|
||||
Short: scanCmd.Short,
|
||||
Long: scanCmd.Long,
|
||||
Args: scanCmd.Args,
|
||||
Example: scanCmd.Example,
|
||||
PreRunE: applicationUpdateCheck(id, &opts.UpdateCheck),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
restoreStdout := ui.CaptureStdoutToTraceLog()
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/stereoscope/pkg/image"
|
||||
"github.com/anchore/syft/cmd/syft/internal/options"
|
||||
"github.com/anchore/syft/cmd/syft/cli/options"
|
||||
"github.com/anchore/syft/cmd/syft/internal/ui"
|
||||
"github.com/anchore/syft/internal"
|
||||
"github.com/anchore/syft/internal/bus"
|
||||
@@ -132,7 +132,7 @@ func (o *scanOptions) validateLegacyOptionsNotUsed() error {
|
||||
}
|
||||
|
||||
if legacy.ExcludeBinaryOverlapByOwnership != nil {
|
||||
return fmt.Errorf("the config file option 'exclude-binary-overlap-by-ownership' has been removed, please use 'package.exclude-binary-overlap-by-ownership' instead")
|
||||
return fmt.Errorf("the config file option 'exclude-binary-overlap-by-ownership' has been removed, please use 'relationships.exclude-binary-packages-with-file-ownership-overlap' instead")
|
||||
}
|
||||
|
||||
if legacy.BasePath != nil {
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/anchore/syft/cmd/syft/internal/options"
|
||||
"github.com/anchore/syft/cmd/syft/cli/options"
|
||||
)
|
||||
|
||||
func Test_scanOptions_validateLegacyOptionsNotUsed(t *testing.T) {
|
||||
@@ -29,7 +29,7 @@ func Test_scanOptions_validateLegacyOptionsNotUsed(t *testing.T) {
|
||||
{
|
||||
name: "config file with exclude-binary-overlap-by-ownership legacy option",
|
||||
cfg: "test-fixtures/scan-configs/with-exclude-binary-overlap-by-ownership.yaml",
|
||||
wantErr: assertErrorContains("package.exclude-binary-overlap-by-ownership"),
|
||||
wantErr: assertErrorContains("relationships.exclude-binary-packages-with-file-ownership-overlap"),
|
||||
},
|
||||
{
|
||||
name: "config file with file string legacy option",
|
||||
@@ -11,8 +11,8 @@ import (
|
||||
|
||||
"github.com/anchore/clio"
|
||||
hashiVersion "github.com/anchore/go-version"
|
||||
"github.com/anchore/syft/cmd/syft/cli/options"
|
||||
"github.com/anchore/syft/cmd/syft/internal"
|
||||
"github.com/anchore/syft/cmd/syft/internal/options"
|
||||
"github.com/anchore/syft/internal/bus"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/event"
|
||||
@@ -4,8 +4,6 @@ import (
|
||||
"github.com/anchore/clio"
|
||||
)
|
||||
|
||||
var _ clio.FlagAdder = (*Attest)(nil)
|
||||
|
||||
type Attest struct {
|
||||
// IMPORTANT: do not show the attestation key/password in any YAML/JSON output (sensitive information)
|
||||
Key secret `yaml:"key" json:"key" mapstructure:"key"`
|
||||
@@ -14,6 +12,6 @@ type Attest struct {
|
||||
|
||||
var _ clio.FlagAdder = (*Attest)(nil)
|
||||
|
||||
func (o *Attest) AddFlags(flags clio.FlagSet) {
|
||||
func (o Attest) AddFlags(flags clio.FlagSet) {
|
||||
flags.StringVarP((*string)(&o.Key), "key", "k", "the key to use for the attestation")
|
||||
}
|
||||
@@ -46,6 +46,7 @@ type Catalog struct {
|
||||
// configuration for the source (the subject being analyzed)
|
||||
Registry registryConfig `yaml:"registry" json:"registry" mapstructure:"registry"`
|
||||
Platform string `yaml:"platform" json:"platform" mapstructure:"platform"`
|
||||
Name string `yaml:"name" json:"name" mapstructure:"name"` // deprecated
|
||||
Source sourceConfig `yaml:"source" json:"source" mapstructure:"source"`
|
||||
Exclusions []string `yaml:"exclude" json:"exclude" mapstructure:"exclude"`
|
||||
}
|
||||
@@ -174,6 +175,14 @@ func (cfg *Catalog) AddFlags(flags clio.FlagSet) {
|
||||
flags.StringArrayVarP(&cfg.SelectCatalogers, "select-catalogers", "",
|
||||
"add, remove, and filter the catalogers to be used")
|
||||
|
||||
flags.StringVarP(&cfg.Source.Name, "name", "",
|
||||
"set the name of the target being analyzed")
|
||||
|
||||
if pfp, ok := flags.(fangs.PFlagSetProvider); ok {
|
||||
flagSet := pfp.PFlagSet()
|
||||
flagSet.Lookup("name").Deprecated = "use: source-name"
|
||||
}
|
||||
|
||||
flags.StringVarP(&cfg.Source.Name, "source-name", "",
|
||||
"set the name of the target being analyzed")
|
||||
|
||||
@@ -189,6 +198,13 @@ func (cfg *Catalog) DescribeFields(descriptions fangs.FieldDescriptionSet) {
|
||||
}
|
||||
|
||||
func (cfg *Catalog) PostLoad() error {
|
||||
if cfg.Name != "" {
|
||||
log.Warnf("name parameter is deprecated. please use: source-name. name will be removed in a future version")
|
||||
if cfg.Source.Name == "" {
|
||||
cfg.Source.Name = cfg.Name
|
||||
}
|
||||
}
|
||||
|
||||
usingLegacyCatalogers := len(cfg.Catalogers) > 0
|
||||
usingNewCatalogers := len(cfg.DefaultCatalogers) > 0 || len(cfg.SelectCatalogers) > 0
|
||||
|
||||
@@ -2,9 +2,6 @@ package options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/scylladb/go-set/strset"
|
||||
|
||||
intFile "github.com/anchore/syft/internal/file"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
@@ -38,10 +35,6 @@ func defaultFileConfig() fileConfig {
|
||||
}
|
||||
|
||||
func (c *fileConfig) PostLoad() error {
|
||||
digests := strset.New(c.Metadata.Digests...).List()
|
||||
sort.Strings(digests)
|
||||
c.Metadata.Digests = digests
|
||||
|
||||
switch c.Metadata.Selection {
|
||||
case file.NoFilesSelection, file.FilesOwnedByPackageSelection, file.AllFilesSelection:
|
||||
return nil
|
||||
@@ -0,0 +1,129 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/syft/format/cyclonedxjson"
|
||||
"github.com/anchore/syft/syft/format/cyclonedxxml"
|
||||
"github.com/anchore/syft/syft/format/github"
|
||||
"github.com/anchore/syft/syft/format/spdxjson"
|
||||
"github.com/anchore/syft/syft/format/spdxtagvalue"
|
||||
"github.com/anchore/syft/syft/format/syftjson"
|
||||
"github.com/anchore/syft/syft/format/table"
|
||||
"github.com/anchore/syft/syft/format/template"
|
||||
"github.com/anchore/syft/syft/format/text"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
var _ clio.PostLoader = (*Format)(nil)
|
||||
|
||||
// Format contains all user configuration for output formatting.
|
||||
type Format struct {
|
||||
Pretty *bool `yaml:"pretty" json:"pretty" mapstructure:"pretty"`
|
||||
Template FormatTemplate `yaml:"template" json:"template" mapstructure:"template"`
|
||||
SyftJSON FormatSyftJSON `yaml:"json" json:"json" mapstructure:"json"`
|
||||
SPDXJSON FormatSPDXJSON `yaml:"spdx-json" json:"spdx-json" mapstructure:"spdx-json"`
|
||||
CyclonedxJSON FormatCyclonedxJSON `yaml:"cyclonedx-json" json:"cyclonedx-json" mapstructure:"cyclonedx-json"`
|
||||
CyclonedxXML FormatCyclonedxXML `yaml:"cyclonedx-xml" json:"cyclonedx-xml" mapstructure:"cyclonedx-xml"`
|
||||
}
|
||||
|
||||
func (o *Format) PostLoad() error {
|
||||
o.SyftJSON.Pretty = multiLevelOption[bool](false, o.Pretty, o.SyftJSON.Pretty)
|
||||
o.SPDXJSON.Pretty = multiLevelOption[bool](false, o.Pretty, o.SPDXJSON.Pretty)
|
||||
o.CyclonedxJSON.Pretty = multiLevelOption[bool](false, o.Pretty, o.CyclonedxJSON.Pretty)
|
||||
o.CyclonedxXML.Pretty = multiLevelOption[bool](false, o.Pretty, o.CyclonedxXML.Pretty)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DefaultFormat() Format {
|
||||
return Format{
|
||||
Template: DefaultFormatTemplate(),
|
||||
SyftJSON: DefaultFormatJSON(),
|
||||
SPDXJSON: DefaultFormatSPDXJSON(),
|
||||
CyclonedxJSON: DefaultFormatCyclonedxJSON(),
|
||||
CyclonedxXML: DefaultFormatCyclonedxXML(),
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Format) Encoders() ([]sbom.FormatEncoder, error) {
|
||||
// setup all encoders based on the configuration
|
||||
var list encoderList
|
||||
|
||||
// in the future there will be application configuration options that can be used to set the default output format
|
||||
list.addWithErr(template.ID)(o.Template.formatEncoders())
|
||||
list.addWithErr(syftjson.ID)(o.SyftJSON.formatEncoders())
|
||||
list.add(table.ID)(table.NewFormatEncoder())
|
||||
list.add(text.ID)(text.NewFormatEncoder())
|
||||
list.add(github.ID)(github.NewFormatEncoder())
|
||||
list.addWithErr(cyclonedxxml.ID)(o.CyclonedxXML.formatEncoders())
|
||||
list.addWithErr(cyclonedxjson.ID)(o.CyclonedxJSON.formatEncoders())
|
||||
list.addWithErr(spdxjson.ID)(o.SPDXJSON.formatEncoders())
|
||||
list.addWithErr(spdxtagvalue.ID)(spdxTagValueEncoders())
|
||||
|
||||
return list.encoders, list.err
|
||||
}
|
||||
|
||||
// TODO: when application configuration is made for this format then this should be ported to the options object
|
||||
// that is created for that configuration (as done with the template output option)
|
||||
func spdxTagValueEncoders() ([]sbom.FormatEncoder, error) {
|
||||
var (
|
||||
encs []sbom.FormatEncoder
|
||||
errs error
|
||||
)
|
||||
for _, v := range spdxtagvalue.SupportedVersions() {
|
||||
enc, err := spdxtagvalue.NewFormatEncoderWithConfig(spdxtagvalue.EncoderConfig{Version: v})
|
||||
if err != nil {
|
||||
errs = multierror.Append(errs, err)
|
||||
} else {
|
||||
encs = append(encs, enc)
|
||||
}
|
||||
}
|
||||
return encs, errs
|
||||
}
|
||||
|
||||
type encoderList struct {
|
||||
encoders []sbom.FormatEncoder
|
||||
err error
|
||||
}
|
||||
|
||||
func (l *encoderList) addWithErr(name sbom.FormatID) func([]sbom.FormatEncoder, error) {
|
||||
return func(encs []sbom.FormatEncoder, err error) {
|
||||
if err != nil {
|
||||
l.err = multierror.Append(l.err, fmt.Errorf("unable to configure %q format encoder: %w", name, err))
|
||||
return
|
||||
}
|
||||
for _, enc := range encs {
|
||||
if enc == nil {
|
||||
l.err = multierror.Append(l.err, fmt.Errorf("unable to configure %q format encoder: nil encoder returned", name))
|
||||
continue
|
||||
}
|
||||
l.encoders = append(l.encoders, enc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (l *encoderList) add(name sbom.FormatID) func(...sbom.FormatEncoder) {
|
||||
return func(encs ...sbom.FormatEncoder) {
|
||||
for _, enc := range encs {
|
||||
if enc == nil {
|
||||
l.err = multierror.Append(l.err, fmt.Errorf("unable to configure %q format encoder: nil encoder returned", name))
|
||||
continue
|
||||
}
|
||||
l.encoders = append(l.encoders, enc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func multiLevelOption[T any](defaultValue T, option ...*T) *T {
|
||||
result := defaultValue
|
||||
for _, opt := range option {
|
||||
if opt != nil {
|
||||
result = *opt
|
||||
}
|
||||
}
|
||||
return &result
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/go-multierror"
|
||||
|
||||
"github.com/anchore/syft/syft/format/cyclonedxjson"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
type FormatCyclonedxJSON struct {
|
||||
Pretty *bool `yaml:"pretty" json:"pretty" mapstructure:"pretty"`
|
||||
}
|
||||
|
||||
func DefaultFormatCyclonedxJSON() FormatCyclonedxJSON {
|
||||
return FormatCyclonedxJSON{}
|
||||
}
|
||||
|
||||
func (o FormatCyclonedxJSON) formatEncoders() ([]sbom.FormatEncoder, error) {
|
||||
var (
|
||||
encs []sbom.FormatEncoder
|
||||
errs error
|
||||
)
|
||||
for _, v := range cyclonedxjson.SupportedVersions() {
|
||||
enc, err := cyclonedxjson.NewFormatEncoderWithConfig(o.buildConfig(v))
|
||||
if err != nil {
|
||||
errs = multierror.Append(errs, err)
|
||||
} else {
|
||||
encs = append(encs, enc)
|
||||
}
|
||||
}
|
||||
return encs, errs
|
||||
}
|
||||
|
||||
func (o FormatCyclonedxJSON) buildConfig(version string) cyclonedxjson.EncoderConfig {
|
||||
var pretty bool
|
||||
if o.Pretty != nil {
|
||||
pretty = *o.Pretty
|
||||
}
|
||||
return cyclonedxjson.EncoderConfig{
|
||||
Version: version,
|
||||
Pretty: pretty,
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -13,7 +13,7 @@ func TestFormatCyclonedxJSON_buildConfig(t *testing.T) {
|
||||
ft := &FormatCyclonedxJSON{}
|
||||
ft = setAllToNonZero(t, ft).(*FormatCyclonedxJSON)
|
||||
|
||||
subject := ft.config("Version")
|
||||
subject := ft.buildConfig("Version")
|
||||
assertExpectedValue(t, subject)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/go-multierror"
|
||||
|
||||
"github.com/anchore/syft/syft/format/cyclonedxxml"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
type FormatCyclonedxXML struct {
|
||||
Pretty *bool `yaml:"pretty" json:"pretty" mapstructure:"pretty"`
|
||||
}
|
||||
|
||||
func DefaultFormatCyclonedxXML() FormatCyclonedxXML {
|
||||
return FormatCyclonedxXML{}
|
||||
}
|
||||
|
||||
func (o FormatCyclonedxXML) formatEncoders() ([]sbom.FormatEncoder, error) {
|
||||
var (
|
||||
encs []sbom.FormatEncoder
|
||||
errs error
|
||||
)
|
||||
for _, v := range cyclonedxxml.SupportedVersions() {
|
||||
enc, err := cyclonedxxml.NewFormatEncoderWithConfig(o.buildConfig(v))
|
||||
if err != nil {
|
||||
errs = multierror.Append(errs, err)
|
||||
} else {
|
||||
encs = append(encs, enc)
|
||||
}
|
||||
}
|
||||
return encs, errs
|
||||
}
|
||||
|
||||
func (o FormatCyclonedxXML) buildConfig(version string) cyclonedxxml.EncoderConfig {
|
||||
var pretty bool
|
||||
if o.Pretty != nil {
|
||||
pretty = *o.Pretty
|
||||
}
|
||||
return cyclonedxxml.EncoderConfig{
|
||||
Version: version,
|
||||
Pretty: pretty,
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -10,6 +10,6 @@ func TestFormatCyclonedxXML_buildConfig(t *testing.T) {
|
||||
ft := FormatCyclonedxXML{}
|
||||
ftp := setAllToNonZero(t, &ft).(*FormatCyclonedxXML)
|
||||
|
||||
subject := ftp.config("Version")
|
||||
subject := ftp.buildConfig("Version")
|
||||
assertExpectedValue(t, subject)
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/hashicorp/go-multierror"
|
||||
|
||||
"github.com/anchore/syft/syft/format/spdxjson"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
type FormatSPDXJSON struct {
|
||||
Pretty *bool `yaml:"pretty" json:"pretty" mapstructure:"pretty"`
|
||||
}
|
||||
|
||||
func DefaultFormatSPDXJSON() FormatSPDXJSON {
|
||||
return FormatSPDXJSON{}
|
||||
}
|
||||
|
||||
func (o FormatSPDXJSON) formatEncoders() ([]sbom.FormatEncoder, error) {
|
||||
var (
|
||||
encs []sbom.FormatEncoder
|
||||
errs error
|
||||
)
|
||||
for _, v := range spdxjson.SupportedVersions() {
|
||||
enc, err := spdxjson.NewFormatEncoderWithConfig(o.buildConfig(v))
|
||||
if err != nil {
|
||||
errs = multierror.Append(errs, err)
|
||||
} else {
|
||||
encs = append(encs, enc)
|
||||
}
|
||||
}
|
||||
return encs, errs
|
||||
}
|
||||
|
||||
func (o FormatSPDXJSON) buildConfig(v string) spdxjson.EncoderConfig {
|
||||
var pretty bool
|
||||
if o.Pretty != nil {
|
||||
pretty = *o.Pretty
|
||||
}
|
||||
return spdxjson.EncoderConfig{
|
||||
Version: v,
|
||||
Pretty: pretty,
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -10,6 +10,6 @@ func TestFormatSPDXJSON_buildConfig(t *testing.T) {
|
||||
ft := &FormatSPDXJSON{}
|
||||
ft = setAllToNonZero(t, ft).(*FormatSPDXJSON)
|
||||
|
||||
subject := ft.config("Version")
|
||||
subject := ft.buildConfig("Version")
|
||||
assertExpectedValue(t, subject)
|
||||
}
|
||||
+7
-1
@@ -2,6 +2,7 @@ package options
|
||||
|
||||
import (
|
||||
"github.com/anchore/syft/syft/format/syftjson"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
type FormatSyftJSON struct {
|
||||
@@ -15,7 +16,12 @@ func DefaultFormatJSON() FormatSyftJSON {
|
||||
}
|
||||
}
|
||||
|
||||
func (o FormatSyftJSON) config() syftjson.EncoderConfig {
|
||||
func (o FormatSyftJSON) formatEncoders() ([]sbom.FormatEncoder, error) {
|
||||
enc, err := syftjson.NewFormatEncoderWithConfig(o.buildConfig())
|
||||
return []sbom.FormatEncoder{enc}, err
|
||||
}
|
||||
|
||||
func (o FormatSyftJSON) buildConfig() syftjson.EncoderConfig {
|
||||
var pretty bool
|
||||
if o.Pretty != nil {
|
||||
pretty = *o.Pretty
|
||||
+1
-1
@@ -10,6 +10,6 @@ func TestFormatSyftJSON_buildConfig(t *testing.T) {
|
||||
ft := &FormatSyftJSON{}
|
||||
ft = setAllToNonZero(t, ft).(*FormatSyftJSON)
|
||||
|
||||
subject := ft.config()
|
||||
subject := ft.buildConfig()
|
||||
assertExpectedValue(t, subject)
|
||||
}
|
||||
+8
-5
@@ -3,6 +3,7 @@ package options
|
||||
import (
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/syft/format/template"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
var _ clio.FlagAdder = (*FormatTemplate)(nil)
|
||||
@@ -10,7 +11,6 @@ var _ clio.FlagAdder = (*FormatTemplate)(nil)
|
||||
type FormatTemplate struct {
|
||||
Enabled bool `yaml:"-" json:"-" mapstructure:"-"`
|
||||
Path string `yaml:"path" json:"path" mapstructure:"path"` // -t template file to use for output
|
||||
Legacy bool `yaml:"legacy" json:"legacy" mapstructure:"legacy"`
|
||||
}
|
||||
|
||||
func DefaultFormatTemplate() FormatTemplate {
|
||||
@@ -26,9 +26,12 @@ func (o *FormatTemplate) AddFlags(flags clio.FlagSet) {
|
||||
}
|
||||
}
|
||||
|
||||
func (o FormatTemplate) config() template.EncoderConfig {
|
||||
return template.EncoderConfig{
|
||||
TemplatePath: o.Path,
|
||||
Legacy: o.Legacy,
|
||||
func (o FormatTemplate) formatEncoders() ([]sbom.FormatEncoder, error) {
|
||||
if !o.Enabled {
|
||||
return nil, nil
|
||||
}
|
||||
enc, err := template.NewFormatEncoder(template.EncoderConfig{
|
||||
TemplatePath: o.Path,
|
||||
})
|
||||
return []sbom.FormatEncoder{enc}, err
|
||||
}
|
||||
@@ -2,7 +2,6 @@ package options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/scylladb/go-set/strset"
|
||||
@@ -35,13 +34,6 @@ func defaultSourceConfig() sourceConfig {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *fileSource) PostLoad() error {
|
||||
digests := strset.New(c.Digests...).List()
|
||||
sort.Strings(digests)
|
||||
c.Digests = digests
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c imageSource) PostLoad() error {
|
||||
return checkDefaultSourceValues(c.DefaultPullSource)
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package internal
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/go-logger"
|
||||
gologgerredact "github.com/anchore/go-logger/adapter/redact"
|
||||
"github.com/anchore/stereoscope"
|
||||
handlers "github.com/anchore/syft/cmd/syft/cli/ui"
|
||||
"github.com/anchore/syft/cmd/syft/internal/ui"
|
||||
"github.com/anchore/syft/internal/bus"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/internal/redact"
|
||||
)
|
||||
|
||||
func AppClioSetupConfig(id clio.Identification, out io.Writer) *clio.SetupConfig {
|
||||
clioCfg := clio.NewSetupConfig(id).
|
||||
WithGlobalConfigFlag(). // add persistent -c <path> for reading an application config from
|
||||
WithGlobalLoggingFlags(). // add persistent -v and -q flags tied to the logging config
|
||||
WithConfigInRootHelp(). // --help on the root command renders the full application config in the help text
|
||||
WithLoggerConstructor(
|
||||
func(cfg clio.Config, store gologgerredact.Store) (logger.Logger, error) {
|
||||
if !cfg.Log.AllowUI(os.Stdin) && !cfg.Log.Quiet {
|
||||
// this is a special case where the user has not explicitly disabled the UI, but the UI is not allowed
|
||||
// due to the lack of a tty. In this case, we should default to info level.
|
||||
cfg.Log.Level = logger.InfoLevel
|
||||
cfg.Log.Verbosity = 1
|
||||
}
|
||||
return clio.DefaultLogger(cfg, store)
|
||||
},
|
||||
).
|
||||
WithUIConstructor(
|
||||
// select a UI based on the logging configuration and state of stdin (if stdin is a tty)
|
||||
func(cfg clio.Config) ([]clio.UI, error) {
|
||||
noUI := ui.None(out, cfg.Log.Quiet)
|
||||
if !cfg.Log.AllowUI(os.Stdin) || cfg.Log.Quiet {
|
||||
return []clio.UI{noUI}, nil
|
||||
}
|
||||
|
||||
return []clio.UI{
|
||||
ui.New(out, cfg.Log.Quiet,
|
||||
handlers.New(handlers.DefaultHandlerConfig()),
|
||||
),
|
||||
noUI,
|
||||
}, nil
|
||||
},
|
||||
).
|
||||
WithInitializers(
|
||||
func(state *clio.State) error {
|
||||
// clio is setting up and providing the bus, redact store, and logger to the application. Once loaded,
|
||||
// we can hoist them into the internal packages for global use.
|
||||
stereoscope.SetBus(state.Bus)
|
||||
bus.Set(state.Bus)
|
||||
|
||||
redact.Set(state.RedactStore)
|
||||
|
||||
log.Set(state.Logger)
|
||||
stereoscope.SetLogger(state.Logger)
|
||||
return nil
|
||||
},
|
||||
).
|
||||
WithPostRuns(func(state *clio.State, err error) {
|
||||
stereoscope.Cleanup()
|
||||
})
|
||||
return clioCfg
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
)
|
||||
|
||||
func Cataloger(app clio.Application) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "cataloger",
|
||||
Short: "Show available catalogers and configuration",
|
||||
}
|
||||
|
||||
cmd.AddCommand(
|
||||
CatalogerList(app),
|
||||
)
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -1,267 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
"github.com/scylladb/go-set/strset"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/internal/bus"
|
||||
"github.com/anchore/syft/internal/task"
|
||||
"github.com/anchore/syft/syft/cataloging/pkgcataloging"
|
||||
)
|
||||
|
||||
type catalogerListOptions struct {
|
||||
Output string `yaml:"output" json:"output" mapstructure:"output"`
|
||||
DefaultCatalogers []string `yaml:"default-catalogers" json:"default-catalogers" mapstructure:"default-catalogers"`
|
||||
SelectCatalogers []string `yaml:"select-catalogers" json:"select-catalogers" mapstructure:"select-catalogers"`
|
||||
ShowHidden bool `yaml:"show-hidden" json:"show-hidden" mapstructure:"show-hidden"`
|
||||
}
|
||||
|
||||
func (o *catalogerListOptions) AddFlags(flags clio.FlagSet) {
|
||||
flags.StringVarP(&o.Output, "output", "o", "format to output the cataloger list (available: table, json)")
|
||||
|
||||
flags.StringArrayVarP(&o.DefaultCatalogers, "override-default-catalogers", "", "override the default catalogers with an expression")
|
||||
|
||||
flags.StringArrayVarP(&o.SelectCatalogers, "select-catalogers", "", "select catalogers with an expression")
|
||||
|
||||
flags.BoolVarP(&o.ShowHidden, "show-hidden", "s", "show catalogers that have been de-selected")
|
||||
}
|
||||
|
||||
func defaultCatalogerListOptions() *catalogerListOptions {
|
||||
return &catalogerListOptions{
|
||||
DefaultCatalogers: []string{"all"},
|
||||
}
|
||||
}
|
||||
|
||||
func CatalogerList(app clio.Application) *cobra.Command {
|
||||
opts := defaultCatalogerListOptions()
|
||||
|
||||
return app.SetupCommand(&cobra.Command{
|
||||
Use: "list [OPTIONS]",
|
||||
Short: "List available catalogers",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
return runCatalogerList(opts)
|
||||
},
|
||||
}, opts)
|
||||
}
|
||||
|
||||
func runCatalogerList(opts *catalogerListOptions) error {
|
||||
factories := task.DefaultPackageTaskFactories()
|
||||
allTasks, err := factories.Tasks(task.DefaultCatalogingFactoryConfig())
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to create cataloger tasks: %w", err)
|
||||
}
|
||||
|
||||
report, err := catalogerListReport(opts, allTasks)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to generate cataloger list report: %w", err)
|
||||
}
|
||||
|
||||
bus.Report(report)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func catalogerListReport(opts *catalogerListOptions, allTasks []task.Task) (string, error) {
|
||||
selectedTasks, selectionEvidence, err := task.Select(allTasks,
|
||||
pkgcataloging.NewSelectionRequest().
|
||||
WithDefaults(opts.DefaultCatalogers...).
|
||||
WithExpression(opts.SelectCatalogers...),
|
||||
)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to select catalogers: %w", err)
|
||||
}
|
||||
var report string
|
||||
|
||||
switch opts.Output {
|
||||
case "json":
|
||||
report, err = renderCatalogerListJSON(selectedTasks, selectionEvidence, opts.DefaultCatalogers, opts.SelectCatalogers)
|
||||
case "table", "":
|
||||
if opts.ShowHidden {
|
||||
report = renderCatalogerListTable(allTasks, selectionEvidence, opts.DefaultCatalogers, opts.SelectCatalogers)
|
||||
} else {
|
||||
report = renderCatalogerListTable(selectedTasks, selectionEvidence, opts.DefaultCatalogers, opts.SelectCatalogers)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("unable to render cataloger list: %w", err)
|
||||
}
|
||||
|
||||
return report, nil
|
||||
}
|
||||
|
||||
func renderCatalogerListJSON(tasks []task.Task, selection task.Selection, defaultSelections, selections []string) (string, error) {
|
||||
type node struct {
|
||||
Name string `json:"name"`
|
||||
Tags []string `json:"tags"`
|
||||
}
|
||||
|
||||
names, tagsByName := extractTaskInfo(tasks)
|
||||
|
||||
nodesByName := make(map[string]node)
|
||||
|
||||
for name := range tagsByName {
|
||||
tagsSelected := selection.TokensByTask[name].SelectedOn.List()
|
||||
|
||||
if len(tagsSelected) == 1 && tagsSelected[0] == "all" {
|
||||
tagsSelected = tagsByName[name]
|
||||
}
|
||||
|
||||
sort.Strings(tagsSelected)
|
||||
|
||||
if tagsSelected == nil {
|
||||
// ensure collections are not null
|
||||
tagsSelected = []string{}
|
||||
}
|
||||
|
||||
nodesByName[name] = node{
|
||||
Name: name,
|
||||
Tags: tagsSelected,
|
||||
}
|
||||
}
|
||||
|
||||
type document struct {
|
||||
DefaultSelection []string `json:"default"`
|
||||
Selection []string `json:"selection"`
|
||||
Catalogers []node `json:"catalogers"`
|
||||
}
|
||||
|
||||
if selections == nil {
|
||||
// ensure collections are not null
|
||||
selections = []string{}
|
||||
}
|
||||
|
||||
doc := document{
|
||||
DefaultSelection: defaultSelections,
|
||||
Selection: selections,
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
doc.Catalogers = append(doc.Catalogers, nodesByName[name])
|
||||
}
|
||||
|
||||
by, err := json.Marshal(doc)
|
||||
|
||||
return string(by), err
|
||||
}
|
||||
|
||||
func renderCatalogerListTable(tasks []task.Task, selection task.Selection, defaultSelections, selections []string) string {
|
||||
t := table.NewWriter()
|
||||
t.SetStyle(table.StyleLight)
|
||||
t.AppendHeader(table.Row{"Cataloger", "Tags"})
|
||||
|
||||
names, tagsByName := extractTaskInfo(tasks)
|
||||
|
||||
rowsByName := make(map[string]table.Row)
|
||||
|
||||
for name, tags := range tagsByName {
|
||||
rowsByName[name] = formatRow(name, tags, selection)
|
||||
}
|
||||
|
||||
for _, name := range names {
|
||||
t.AppendRow(rowsByName[name])
|
||||
}
|
||||
|
||||
report := t.Render()
|
||||
|
||||
if len(selections) > 0 {
|
||||
header := "Selected by expressions:\n"
|
||||
for _, expr := range selections {
|
||||
header += fmt.Sprintf(" - %q\n", expr)
|
||||
}
|
||||
report = header + report
|
||||
}
|
||||
|
||||
if len(defaultSelections) > 0 {
|
||||
header := "Default selections:\n"
|
||||
for _, expr := range defaultSelections {
|
||||
header += fmt.Sprintf(" - %q\n", expr)
|
||||
}
|
||||
report = header + report
|
||||
}
|
||||
|
||||
return report
|
||||
}
|
||||
|
||||
func formatRow(name string, tags []string, selection task.Selection) table.Row {
|
||||
isIncluded := selection.Result.Has(name)
|
||||
var selections *task.TokenSelection
|
||||
if s, exists := selection.TokensByTask[name]; exists {
|
||||
selections = &s
|
||||
}
|
||||
|
||||
var formattedTags []string
|
||||
for _, tag := range tags {
|
||||
formattedTags = append(formattedTags, formatToken(tag, selections, isIncluded))
|
||||
}
|
||||
|
||||
var tagStr string
|
||||
if isIncluded {
|
||||
tagStr = strings.Join(formattedTags, ", ")
|
||||
} else {
|
||||
tagStr = strings.Join(formattedTags, grey.Render(", "))
|
||||
}
|
||||
|
||||
// TODO: selection should keep warnings (non-selections) in struct
|
||||
|
||||
return table.Row{
|
||||
formatToken(name, selections, isIncluded),
|
||||
tagStr,
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
green = lipgloss.NewStyle().Foreground(lipgloss.Color("10")) // hi green
|
||||
grey = lipgloss.NewStyle().Foreground(lipgloss.Color("8")) // dark grey
|
||||
red = lipgloss.NewStyle().Foreground(lipgloss.Color("9")) // high red
|
||||
)
|
||||
|
||||
func formatToken(token string, selection *task.TokenSelection, included bool) string {
|
||||
if included && selection != nil {
|
||||
// format all tokens in selection in green
|
||||
if selection.SelectedOn.Has(token) {
|
||||
return green.Render(token)
|
||||
}
|
||||
|
||||
return token
|
||||
}
|
||||
|
||||
// format all tokens in selection in red, all others in grey
|
||||
if selection != nil && selection.DeselectedOn.Has(token) {
|
||||
return red.Render(token)
|
||||
}
|
||||
|
||||
return grey.Render(token)
|
||||
}
|
||||
|
||||
func extractTaskInfo(tasks []task.Task) ([]string, map[string][]string) {
|
||||
tagsByName := make(map[string][]string)
|
||||
var names []string
|
||||
|
||||
for _, tsk := range tasks {
|
||||
var tags []string
|
||||
name := tsk.Name()
|
||||
|
||||
if s, ok := tsk.(task.Selector); ok {
|
||||
set := strset.New(s.Selectors()...)
|
||||
set.Remove(name)
|
||||
tags = set.List()
|
||||
sort.Strings(tags)
|
||||
}
|
||||
|
||||
tagsByName[name] = tags
|
||||
names = append(names, name)
|
||||
}
|
||||
|
||||
sort.Strings(names)
|
||||
|
||||
return names, tagsByName
|
||||
}
|
||||
@@ -1,201 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/scylladb/go-set/strset"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/syft/internal/sbomsync"
|
||||
"github.com/anchore/syft/internal/task"
|
||||
"github.com/anchore/syft/syft/file"
|
||||
)
|
||||
|
||||
var _ interface {
|
||||
task.Task
|
||||
task.Selector
|
||||
} = (*dummyTask)(nil)
|
||||
|
||||
type dummyTask struct {
|
||||
name string
|
||||
selectors []string
|
||||
}
|
||||
|
||||
func (d dummyTask) HasAllSelectors(s ...string) bool {
|
||||
return strset.New(d.selectors...).Has(s...)
|
||||
}
|
||||
|
||||
func (d dummyTask) Selectors() []string {
|
||||
return d.selectors
|
||||
}
|
||||
|
||||
func (d dummyTask) Name() string {
|
||||
return d.name
|
||||
}
|
||||
|
||||
func (d dummyTask) Execute(_ context.Context, _ file.Resolver, _ sbomsync.Builder) error {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func testTasks() []task.Task {
|
||||
return []task.Task{
|
||||
dummyTask{
|
||||
name: "task1",
|
||||
selectors: []string{"image", "a", "b", "1"},
|
||||
},
|
||||
dummyTask{
|
||||
name: "task2",
|
||||
selectors: []string{"image", "b", "c", "2"},
|
||||
},
|
||||
dummyTask{
|
||||
name: "task3",
|
||||
selectors: []string{"directory", "c", "d", "3"},
|
||||
},
|
||||
dummyTask{
|
||||
name: "task4",
|
||||
selectors: []string{"directory", "d", "e", "4"},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func Test_catalogerListReport(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
options *catalogerListOptions
|
||||
want string
|
||||
wantErr require.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "no expressions, table",
|
||||
options: func() *catalogerListOptions {
|
||||
c := defaultCatalogerListOptions()
|
||||
c.Output = "table"
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
Default selections:
|
||||
- "all"
|
||||
┌───────────┬────────────────────┐
|
||||
│ CATALOGER │ TAGS │
|
||||
├───────────┼────────────────────┤
|
||||
│ task1 │ 1, a, b, image │
|
||||
│ task2 │ 2, b, c, image │
|
||||
│ task3 │ 3, c, d, directory │
|
||||
│ task4 │ 4, d, directory, e │
|
||||
└───────────┴────────────────────┘
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "no expressions, json",
|
||||
options: func() *catalogerListOptions {
|
||||
c := defaultCatalogerListOptions()
|
||||
c.Output = "json"
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
{"default":["all"],"selection":[],"catalogers":[{"name":"task1","tags":["1","a","b","image"]},{"name":"task2","tags":["2","b","c","image"]},{"name":"task3","tags":["3","c","d","directory"]},{"name":"task4","tags":["4","d","directory","e"]}]}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "no expressions, default selection, table",
|
||||
options: func() *catalogerListOptions {
|
||||
c := defaultCatalogerListOptions()
|
||||
c.Output = "table"
|
||||
c.DefaultCatalogers = []string{
|
||||
"image",
|
||||
}
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
Default selections:
|
||||
- "image"
|
||||
┌───────────┬────────────────┐
|
||||
│ CATALOGER │ TAGS │
|
||||
├───────────┼────────────────┤
|
||||
│ task1 │ 1, a, b, image │
|
||||
│ task2 │ 2, b, c, image │
|
||||
└───────────┴────────────────┘
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "no expressions, default selection, json",
|
||||
options: func() *catalogerListOptions {
|
||||
c := defaultCatalogerListOptions()
|
||||
c.Output = "json"
|
||||
c.DefaultCatalogers = []string{
|
||||
"image",
|
||||
}
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
{"default":["image"],"selection":[],"catalogers":[{"name":"task1","tags":["image"]},{"name":"task2","tags":["image"]}]}
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "with expressions, default selection, table",
|
||||
options: func() *catalogerListOptions {
|
||||
c := defaultCatalogerListOptions()
|
||||
c.Output = "table"
|
||||
c.DefaultCatalogers = []string{
|
||||
"image",
|
||||
}
|
||||
c.SelectCatalogers = []string{
|
||||
"-directory",
|
||||
"+task3",
|
||||
"-c",
|
||||
"b",
|
||||
}
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
Default selections:
|
||||
- "image"
|
||||
Selected by expressions:
|
||||
- "-directory"
|
||||
- "+task3"
|
||||
- "-c"
|
||||
- "b"
|
||||
┌───────────┬────────────────────┐
|
||||
│ CATALOGER │ TAGS │
|
||||
├───────────┼────────────────────┤
|
||||
│ task1 │ 1, a, b, image │
|
||||
│ task3 │ 3, c, d, directory │
|
||||
└───────────┴────────────────────┘
|
||||
`,
|
||||
},
|
||||
{
|
||||
name: "with expressions, default selection, json",
|
||||
options: func() *catalogerListOptions {
|
||||
c := defaultCatalogerListOptions()
|
||||
c.Output = "json"
|
||||
c.DefaultCatalogers = []string{
|
||||
"image",
|
||||
}
|
||||
c.SelectCatalogers = []string{
|
||||
"-directory",
|
||||
"+task3",
|
||||
"-c",
|
||||
"b",
|
||||
}
|
||||
return c
|
||||
}(),
|
||||
want: `
|
||||
{"default":["image"],"selection":["-directory","+task3","-c","b"],"catalogers":[{"name":"task1","tags":["b","image"]},{"name":"task3","tags":["task3"]}]}
|
||||
`,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.wantErr == nil {
|
||||
tt.wantErr = require.NoError
|
||||
}
|
||||
|
||||
got, err := catalogerListReport(tt.options, testTasks())
|
||||
tt.wantErr(t, err)
|
||||
assert.Equal(t, strings.TrimSpace(tt.want), strings.TrimSpace(got))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
gologgerredact "github.com/anchore/go-logger/adapter/redact"
|
||||
"github.com/anchore/syft/internal/redact"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
// Initialize global state needed to test clio/cobra commands directly
|
||||
// Should be kept minimal.
|
||||
|
||||
// Initialize redact store once for all tests in the commands package
|
||||
// Redact store must be wired up here because syft will panic unless
|
||||
// a redact store is wired up exactly once
|
||||
redact.Set(gologgerredact.NewStore())
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/anchore/syft/syft/file"
|
||||
)
|
||||
|
||||
func Test_fileConfig_PostLoad(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
cfg fileConfig
|
||||
assert func(t *testing.T, cfg fileConfig)
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "deduplicate digests",
|
||||
cfg: fileConfig{
|
||||
Metadata: fileMetadata{
|
||||
Selection: file.NoFilesSelection,
|
||||
Digests: []string{"sha1", "sha1"},
|
||||
},
|
||||
},
|
||||
assert: func(t *testing.T, cfg fileConfig) {
|
||||
assert.Equal(t, []string{"sha1"}, cfg.Metadata.Digests)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "error on invalid selection",
|
||||
cfg: fileConfig{
|
||||
Metadata: fileMetadata{
|
||||
Selection: file.Selection("invalid"),
|
||||
},
|
||||
},
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "error on empty selection",
|
||||
cfg: fileConfig{},
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.wantErr == nil {
|
||||
tt.wantErr = assert.NoError
|
||||
}
|
||||
tt.wantErr(t, tt.cfg.PostLoad())
|
||||
if tt.assert != nil {
|
||||
tt.assert(t, tt.cfg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/syft/format"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
)
|
||||
|
||||
var _ clio.PostLoader = (*Format)(nil)
|
||||
|
||||
// Format contains all user configuration for output formatting.
|
||||
type Format struct {
|
||||
Pretty *bool `yaml:"pretty" json:"pretty" mapstructure:"pretty"`
|
||||
Template FormatTemplate `yaml:"template" json:"template" mapstructure:"template"`
|
||||
SyftJSON FormatSyftJSON `yaml:"json" json:"json" mapstructure:"json"`
|
||||
SPDXJSON FormatSPDXJSON `yaml:"spdx-json" json:"spdx-json" mapstructure:"spdx-json"`
|
||||
CyclonedxJSON FormatCyclonedxJSON `yaml:"cyclonedx-json" json:"cyclonedx-json" mapstructure:"cyclonedx-json"`
|
||||
CyclonedxXML FormatCyclonedxXML `yaml:"cyclonedx-xml" json:"cyclonedx-xml" mapstructure:"cyclonedx-xml"`
|
||||
}
|
||||
|
||||
func (o *Format) PostLoad() error {
|
||||
o.SyftJSON.Pretty = multiLevelOption[bool](false, o.Pretty, o.SyftJSON.Pretty)
|
||||
o.SPDXJSON.Pretty = multiLevelOption[bool](false, o.Pretty, o.SPDXJSON.Pretty)
|
||||
o.CyclonedxJSON.Pretty = multiLevelOption[bool](false, o.Pretty, o.CyclonedxJSON.Pretty)
|
||||
o.CyclonedxXML.Pretty = multiLevelOption[bool](false, o.Pretty, o.CyclonedxXML.Pretty)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func DefaultFormat() Format {
|
||||
return Format{
|
||||
Template: DefaultFormatTemplate(),
|
||||
SyftJSON: DefaultFormatJSON(),
|
||||
SPDXJSON: DefaultFormatSPDXJSON(),
|
||||
CyclonedxJSON: DefaultFormatCyclonedxJSON(),
|
||||
CyclonedxXML: DefaultFormatCyclonedxXML(),
|
||||
}
|
||||
}
|
||||
|
||||
func (o Format) Encoders() ([]sbom.FormatEncoder, error) {
|
||||
return format.EncodersConfig{
|
||||
Template: o.Template.config(),
|
||||
SyftJSON: o.SyftJSON.config(),
|
||||
SPDXJSON: o.SPDXJSON.config(format.AllVersions), // we support multiple versions, not just a single version
|
||||
CyclonedxJSON: o.CyclonedxJSON.config(format.AllVersions), // we support multiple versions, not just a single version
|
||||
CyclonedxXML: o.CyclonedxXML.config(format.AllVersions), // we support multiple versions, not just a single version
|
||||
}.Encoders()
|
||||
}
|
||||
|
||||
func multiLevelOption[T any](defaultValue T, option ...*T) *T {
|
||||
result := defaultValue
|
||||
for _, opt := range option {
|
||||
if opt != nil {
|
||||
result = *opt
|
||||
}
|
||||
}
|
||||
return &result
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/anchore/syft/syft/format/cyclonedxjson"
|
||||
)
|
||||
|
||||
type FormatCyclonedxJSON struct {
|
||||
Pretty *bool `yaml:"pretty" json:"pretty" mapstructure:"pretty"`
|
||||
}
|
||||
|
||||
func DefaultFormatCyclonedxJSON() FormatCyclonedxJSON {
|
||||
return FormatCyclonedxJSON{}
|
||||
}
|
||||
|
||||
func (o FormatCyclonedxJSON) config(version string) cyclonedxjson.EncoderConfig {
|
||||
var pretty bool
|
||||
if o.Pretty != nil {
|
||||
pretty = *o.Pretty
|
||||
}
|
||||
return cyclonedxjson.EncoderConfig{
|
||||
Version: version,
|
||||
Pretty: pretty,
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/anchore/syft/syft/format/cyclonedxxml"
|
||||
)
|
||||
|
||||
type FormatCyclonedxXML struct {
|
||||
Pretty *bool `yaml:"pretty" json:"pretty" mapstructure:"pretty"`
|
||||
}
|
||||
|
||||
func DefaultFormatCyclonedxXML() FormatCyclonedxXML {
|
||||
return FormatCyclonedxXML{}
|
||||
}
|
||||
|
||||
func (o FormatCyclonedxXML) config(version string) cyclonedxxml.EncoderConfig {
|
||||
var pretty bool
|
||||
if o.Pretty != nil {
|
||||
pretty = *o.Pretty
|
||||
}
|
||||
return cyclonedxxml.EncoderConfig{
|
||||
Version: version,
|
||||
Pretty: pretty,
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"github.com/anchore/syft/syft/format/spdxjson"
|
||||
)
|
||||
|
||||
type FormatSPDXJSON struct {
|
||||
Pretty *bool `yaml:"pretty" json:"pretty" mapstructure:"pretty"`
|
||||
}
|
||||
|
||||
func DefaultFormatSPDXJSON() FormatSPDXJSON {
|
||||
return FormatSPDXJSON{}
|
||||
}
|
||||
|
||||
func (o FormatSPDXJSON) config(v string) spdxjson.EncoderConfig {
|
||||
var pretty bool
|
||||
if o.Pretty != nil {
|
||||
pretty = *o.Pretty
|
||||
}
|
||||
return spdxjson.EncoderConfig{
|
||||
Version: v,
|
||||
Pretty: pretty,
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package options
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_fileSource_PostLoad(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
cfg fileSource
|
||||
assert func(t *testing.T, cfg fileSource)
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
}{
|
||||
{
|
||||
name: "deduplicate digests",
|
||||
cfg: fileSource{
|
||||
Digests: []string{"sha1", "sha1"},
|
||||
},
|
||||
assert: func(t *testing.T, cfg fileSource) {
|
||||
assert.Equal(t, []string{"sha1"}, cfg.Digests)
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if tt.wantErr == nil {
|
||||
tt.wantErr = assert.NoError
|
||||
}
|
||||
tt.wantErr(t, tt.cfg.PostLoad())
|
||||
if tt.assert != nil {
|
||||
tt.assert(t, tt.cfg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,350 +0,0 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"go/types"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/bmatcuk/doublestar/v4"
|
||||
"github.com/scylladb/go-set/strset"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_packageCatalogerExports(t *testing.T) {
|
||||
// sanity check that we are actually finding exports
|
||||
|
||||
exports := packageCatalogerExports(t)
|
||||
require.NotEmpty(t, exports)
|
||||
|
||||
expectAtLeast := map[string]*strset.Set{
|
||||
"golang": strset.New("NewGoModuleFileCataloger", "NewGoModuleBinaryCataloger", "CatalogerConfig", "DefaultCatalogerConfig"),
|
||||
}
|
||||
|
||||
for pkg, expected := range expectAtLeast {
|
||||
actual, ok := exports[pkg]
|
||||
require.True(t, ok, pkg)
|
||||
require.True(t, expected.IsSubset(actual.Names()), pkg)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Test_validatePackageCatalogerExport(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
export exportToken
|
||||
wantErr assert.ErrorAssertionFunc
|
||||
}{
|
||||
// valid...
|
||||
{
|
||||
name: "valid constructor",
|
||||
export: exportToken{
|
||||
Name: "NewFooCataloger",
|
||||
Type: "*ast.FuncType",
|
||||
SignatureSize: 1,
|
||||
ReturnTypeNames: []string{
|
||||
"pkg.Cataloger",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid default config",
|
||||
export: exportToken{
|
||||
Name: "DefaultFooConfig",
|
||||
Type: "*ast.FuncType",
|
||||
SignatureSize: 0,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid config",
|
||||
export: exportToken{
|
||||
Name: "FooConfig",
|
||||
Type: "*ast.StructType",
|
||||
},
|
||||
},
|
||||
// invalid...
|
||||
{
|
||||
name: "constructor that returns a concrete type",
|
||||
export: exportToken{
|
||||
Name: "NewFooCataloger",
|
||||
Type: "*ast.FuncType",
|
||||
SignatureSize: 1,
|
||||
ReturnTypeNames: []string{
|
||||
"*generic.Cataloger",
|
||||
},
|
||||
},
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "struct with constructor name",
|
||||
export: exportToken{
|
||||
Name: "NewFooCataloger",
|
||||
Type: "*ast.StructType",
|
||||
},
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "struct with default config fn name",
|
||||
export: exportToken{
|
||||
Name: "DefaultFooConfig",
|
||||
Type: "*ast.StructType",
|
||||
},
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "fn with struct name",
|
||||
export: exportToken{
|
||||
Name: "FooConfig",
|
||||
Type: "*ast.FuncType",
|
||||
},
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
{
|
||||
name: "default config with parameters",
|
||||
export: exportToken{
|
||||
Name: "DefaultFooConfig",
|
||||
Type: "*ast.FuncType",
|
||||
SignatureSize: 1,
|
||||
},
|
||||
wantErr: assert.Error,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
if c.wantErr == nil {
|
||||
c.wantErr = assert.NoError
|
||||
}
|
||||
err := validatePackageCatalogerExport(t, "test", c.export)
|
||||
c.wantErr(t, err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_PackageCatalogerConventions(t *testing.T) {
|
||||
// look at each package in syft/pkg/cataloger...
|
||||
// we want to make certain that only the following things are exported from the package:
|
||||
// - function matching New*Cataloger (e.g. NewAptCataloger)
|
||||
// - function matching Default*Config
|
||||
// - struct matching *Config
|
||||
//
|
||||
// anything else that is exported should result in the test failing.
|
||||
// note: this is meant to apply to things in static space, not methods on structs or within interfaces.
|
||||
//
|
||||
// this additionally ensures that:
|
||||
// - any config struct has a Default*Config function to pair with it.
|
||||
// - all cataloger constructors return pkg.Cataloger interface instead of a concrete type
|
||||
|
||||
exportsPerPackage := packageCatalogerExports(t)
|
||||
|
||||
//for debugging purposes...
|
||||
//for pkg, exports := range exportsPerPackage {
|
||||
// t.Log(pkg)
|
||||
// for _, export := range exports {
|
||||
// t.Logf(" %#v", export)
|
||||
// }
|
||||
//}
|
||||
|
||||
for pkg, exports := range exportsPerPackage {
|
||||
for _, export := range exports.List() {
|
||||
// assert the export name is valid...
|
||||
assert.NoError(t, validatePackageCatalogerExport(t, pkg, export))
|
||||
|
||||
// assert that config structs have a Default*Config functions to pair with them...
|
||||
if strings.Contains(export.Name, "Config") && !strings.Contains(export.Name, "Default") {
|
||||
// this is a config struct, make certain there is a pairing with a Default*Config function
|
||||
assert.True(t, exports.Has("Default"+export.Name), "cataloger config struct %q in pkg %q must have a 'Default%s' function", export.Name, pkg, export.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func validatePackageCatalogerExport(t *testing.T, pkg string, export exportToken) error {
|
||||
|
||||
constructorMatches, err := doublestar.Match("New*Cataloger", export.Name)
|
||||
require.NoError(t, err)
|
||||
|
||||
defaultConfigMatches, err := doublestar.Match("Default*Config", export.Name)
|
||||
require.NoError(t, err)
|
||||
|
||||
configMatches, err := doublestar.Match("*Config", export.Name)
|
||||
require.NoError(t, err)
|
||||
|
||||
switch {
|
||||
case constructorMatches:
|
||||
if !export.isFunction() {
|
||||
return fmt.Errorf("constructor convention used for non-function in pkg=%q: %#v", pkg, export)
|
||||
}
|
||||
|
||||
returnTypes := strset.New(export.ReturnTypeNames...)
|
||||
if !returnTypes.Has("pkg.Cataloger") {
|
||||
return fmt.Errorf("constructor convention is to return pkg.Cataloger and not concrete types. pkg=%q constructor=%q types=%+v", pkg, export.Name, strings.Join(export.ReturnTypeNames, ","))
|
||||
}
|
||||
|
||||
case defaultConfigMatches:
|
||||
if !export.isFunction() {
|
||||
return fmt.Errorf("default config convention used for non-function in pkg=%q: %#v", pkg, export)
|
||||
}
|
||||
if export.SignatureSize != 0 {
|
||||
return fmt.Errorf("default config convention used for non-zero signature size in pkg=%q: %#v", pkg, export)
|
||||
}
|
||||
case configMatches:
|
||||
if !export.isStruct() {
|
||||
return fmt.Errorf("config convention used for non-struct in pkg=%q: %#v", pkg, export)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unexpected export in pkg=%q: %#v", pkg, export)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type exportToken struct {
|
||||
Name string
|
||||
Type string
|
||||
SignatureSize int
|
||||
ReturnTypeNames []string
|
||||
}
|
||||
|
||||
func (e exportToken) isFunction() bool {
|
||||
return strings.Contains(e.Type, "ast.FuncType")
|
||||
}
|
||||
|
||||
func (e exportToken) isStruct() bool {
|
||||
return strings.Contains(e.Type, "ast.StructType")
|
||||
}
|
||||
|
||||
type exportTokenSet map[string]exportToken
|
||||
|
||||
func (s exportTokenSet) Names() *strset.Set {
|
||||
set := strset.New()
|
||||
for k := range s {
|
||||
set.Add(k)
|
||||
}
|
||||
return set
|
||||
}
|
||||
|
||||
func (s exportTokenSet) Has(name string) bool {
|
||||
_, ok := s[name]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (s exportTokenSet) Add(tokens ...exportToken) {
|
||||
for _, t := range tokens {
|
||||
if _, ok := s[t.Name]; ok {
|
||||
panic("duplicate token name: " + t.Name)
|
||||
}
|
||||
s[t.Name] = t
|
||||
}
|
||||
}
|
||||
|
||||
func (s exportTokenSet) Remove(names ...string) {
|
||||
for _, name := range names {
|
||||
delete(s, name)
|
||||
}
|
||||
}
|
||||
|
||||
func (s exportTokenSet) List() []exportToken {
|
||||
var tokens []exportToken
|
||||
for _, t := range s {
|
||||
tokens = append(tokens, t)
|
||||
}
|
||||
return tokens
|
||||
}
|
||||
|
||||
func packageCatalogerExports(t *testing.T) map[string]exportTokenSet {
|
||||
t.Helper()
|
||||
|
||||
catalogerPath := filepath.Join(repoRoot(t), "syft", "pkg", "cataloger")
|
||||
|
||||
ignorePaths := []string{
|
||||
filepath.Join(catalogerPath, "common"),
|
||||
filepath.Join(catalogerPath, "generic"),
|
||||
}
|
||||
|
||||
exportsPerPackage := make(map[string]exportTokenSet)
|
||||
|
||||
err := filepath.Walk(catalogerPath, func(path string, info os.FileInfo, err error) error {
|
||||
require.NoError(t, err)
|
||||
|
||||
if info.IsDir() ||
|
||||
!strings.HasSuffix(info.Name(), ".go") ||
|
||||
strings.HasSuffix(info.Name(), "_test.go") ||
|
||||
strings.Contains(path, "test-fixtures") ||
|
||||
strings.Contains(path, "internal") {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, ignorePath := range ignorePaths {
|
||||
if strings.Contains(path, ignorePath) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
fset := token.NewFileSet()
|
||||
node, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
|
||||
require.NoError(t, err)
|
||||
|
||||
pkg := node.Name.Name
|
||||
for _, f := range node.Decls {
|
||||
switch decl := f.(type) {
|
||||
case *ast.GenDecl:
|
||||
for _, spec := range decl.Specs {
|
||||
switch spec := spec.(type) {
|
||||
case *ast.TypeSpec:
|
||||
if spec.Name.IsExported() {
|
||||
if _, ok := exportsPerPackage[pkg]; !ok {
|
||||
exportsPerPackage[pkg] = make(exportTokenSet)
|
||||
}
|
||||
exportsPerPackage[pkg].Add(exportToken{
|
||||
Name: spec.Name.Name,
|
||||
Type: reflect.TypeOf(spec.Type).String(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
case *ast.FuncDecl:
|
||||
if decl.Recv == nil && decl.Name.IsExported() {
|
||||
var returnTypes []string
|
||||
if decl.Type.Results != nil {
|
||||
for _, field := range decl.Type.Results.List {
|
||||
// TODO: there is probably a better way to extract the specific type name
|
||||
//ty := strings.Join(strings.Split(fmt.Sprint(field.Type), " "), ".")
|
||||
ty := types.ExprString(field.Type)
|
||||
|
||||
returnTypes = append(returnTypes, ty)
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := exportsPerPackage[pkg]; !ok {
|
||||
exportsPerPackage[pkg] = make(exportTokenSet)
|
||||
}
|
||||
exportsPerPackage[pkg].Add(exportToken{
|
||||
Name: decl.Name.Name,
|
||||
Type: reflect.TypeOf(decl.Type).String(),
|
||||
SignatureSize: len(decl.Type.Params.List),
|
||||
ReturnTypeNames: returnTypes,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
// remove exceptions
|
||||
// these are known violations to the common convention that are allowed.
|
||||
if vs, ok := exportsPerPackage["binary"]; ok {
|
||||
vs.Remove("Classifier", "EvidenceMatcher", "FileContentsVersionMatcher", "DefaultClassifiers")
|
||||
}
|
||||
|
||||
return exportsPerPackage
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/scylladb/go-set/strset"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/syft/internal/task"
|
||||
"github.com/anchore/syft/syft/cataloging/pkgcataloging"
|
||||
)
|
||||
|
||||
func TestAllPackageCatalogersReachableInTasks(t *testing.T) {
|
||||
// we want to see if we can get a task for all package catalogers. This is a bit tricky since we
|
||||
// don't have a nice way to find all cataloger names in the codebase. Instead, we'll look at the
|
||||
// count of unique task names from the package task factory set and compare that with the known constructors
|
||||
// from a source analysis... they should match.
|
||||
|
||||
// additionally, at this time they should either have a "directory" or "image" tag as well. If there is no tag
|
||||
// on a cataloger task then the test should fail.
|
||||
|
||||
taskFactories := task.DefaultPackageTaskFactories()
|
||||
taskTagsByName := make(map[string][]string)
|
||||
for _, factory := range taskFactories {
|
||||
tsk := factory(task.DefaultCatalogingFactoryConfig())
|
||||
if taskTagsByName[tsk.Name()] != nil {
|
||||
t.Fatalf("duplicate task name: %q", tsk.Name())
|
||||
}
|
||||
|
||||
require.NotNil(t, tsk)
|
||||
if sel, ok := tsk.(task.Selector); ok {
|
||||
taskTagsByName[tsk.Name()] = sel.Selectors()
|
||||
} else {
|
||||
taskTagsByName[tsk.Name()] = []string{}
|
||||
}
|
||||
}
|
||||
|
||||
var constructorCount int
|
||||
constructorsPerPackage := getCatalogerConstructors(t)
|
||||
for _, constructors := range constructorsPerPackage {
|
||||
constructorCount += constructors.Size()
|
||||
}
|
||||
|
||||
assert.Equal(t, len(taskTagsByName), constructorCount, "mismatch in number of cataloger constructors and task names")
|
||||
|
||||
for taskName, tags := range taskTagsByName {
|
||||
if taskName == "sbom-cataloger" {
|
||||
continue // this is a special case
|
||||
}
|
||||
if !strset.New(tags...).HasAny(pkgcataloging.ImageTag, pkgcataloging.DirectoryTag) {
|
||||
t.Errorf("task %q is missing 'directory' or 'image' a tag", taskName)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestAllPackageCatalogersRepresentedInSource(t *testing.T) {
|
||||
// find all functions in syft/pkg/cataloger/** that either:
|
||||
// - match the name glob "New*Cataloger"
|
||||
// - are in cataloger.go and match the name glob "New*"
|
||||
//
|
||||
// Then:
|
||||
// - keep track of all packages with cataloger constructors
|
||||
// - keep track of all constructors
|
||||
constructorsPerPackage := getCatalogerConstructors(t)
|
||||
|
||||
// look at the source file in internal/task/package_tasks.go:
|
||||
// - ensure all go packages that have constructors are imported
|
||||
// - ensure there is a reference to all package constructors
|
||||
assertAllPackageCatalogersRepresented(t, constructorsPerPackage)
|
||||
}
|
||||
|
||||
func getCatalogerConstructors(t *testing.T) map[string]*strset.Set {
|
||||
t.Helper()
|
||||
root := repoRoot(t)
|
||||
catalogerPath := filepath.Join(root, "syft", "pkg", "cataloger")
|
||||
|
||||
constructorsPerPackage := make(map[string]*strset.Set)
|
||||
|
||||
err := filepath.Walk(catalogerPath, func(path string, info os.FileInfo, err error) error {
|
||||
require.NoError(t, err)
|
||||
|
||||
// ignore directories and test files...
|
||||
if info.IsDir() || strings.HasSuffix(info.Name(), "_test.go") {
|
||||
return nil
|
||||
}
|
||||
|
||||
partialResults := getConstructorsFromExpectedFile(t, path, info)
|
||||
|
||||
constructorsPerPackage = mergeConstructors(constructorsPerPackage, partialResults)
|
||||
|
||||
partialResults = getCatalogerConstructorsFromPackage(t, path, info)
|
||||
|
||||
constructorsPerPackage = mergeConstructors(constructorsPerPackage, partialResults)
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
// remove some exceptions
|
||||
delete(constructorsPerPackage, "generic") // this is not an actual cataloger
|
||||
|
||||
return constructorsPerPackage
|
||||
}
|
||||
|
||||
func getConstructorsFromExpectedFile(t *testing.T, path string, info os.FileInfo) map[string][]string {
|
||||
constructorsPerPackage := make(map[string][]string)
|
||||
|
||||
if !strings.HasSuffix(info.Name(), "cataloger.go") && !strings.HasSuffix(info.Name(), "catalogers.go") {
|
||||
return nil
|
||||
}
|
||||
|
||||
fset := token.NewFileSet()
|
||||
node, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, f := range node.Decls {
|
||||
fn, ok := f.(*ast.FuncDecl)
|
||||
if !ok || fn.Recv != nil || !strings.HasPrefix(fn.Name.Name, "New") {
|
||||
continue
|
||||
}
|
||||
|
||||
pkg := node.Name.Name
|
||||
constructorsPerPackage[pkg] = append(constructorsPerPackage[pkg], fn.Name.Name)
|
||||
}
|
||||
|
||||
return constructorsPerPackage
|
||||
}
|
||||
|
||||
func getCatalogerConstructorsFromPackage(t *testing.T, path string, info os.FileInfo) map[string][]string {
|
||||
constructorsPerPackage := make(map[string][]string)
|
||||
|
||||
if info.IsDir() || !strings.HasSuffix(info.Name(), ".go") {
|
||||
return nil
|
||||
}
|
||||
|
||||
fset := token.NewFileSet()
|
||||
node, err := parser.ParseFile(fset, path, nil, parser.ParseComments)
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, f := range node.Decls {
|
||||
fn, ok := f.(*ast.FuncDecl)
|
||||
if !ok || fn.Recv != nil || !strings.HasPrefix(fn.Name.Name, "New") || !strings.HasSuffix(fn.Name.Name, "Cataloger") {
|
||||
continue
|
||||
}
|
||||
|
||||
pkg := node.Name.Name
|
||||
constructorsPerPackage[pkg] = append(constructorsPerPackage[pkg], fn.Name.Name)
|
||||
}
|
||||
|
||||
return constructorsPerPackage
|
||||
}
|
||||
|
||||
func assertAllPackageCatalogersRepresented(t *testing.T, constructorsPerPackage map[string]*strset.Set) {
|
||||
t.Helper()
|
||||
|
||||
contents, err := os.ReadFile(filepath.Join(repoRoot(t), "internal", "task", "package_tasks.go"))
|
||||
require.NoError(t, err)
|
||||
|
||||
// ensure all packages (keys) are represented in the package_tasks.go file
|
||||
for pkg, constructors := range constructorsPerPackage {
|
||||
if !assert.True(t, bytes.Contains(contents, []byte(pkg)), "missing package %q", pkg) {
|
||||
continue
|
||||
}
|
||||
for _, constructor := range constructors.List() {
|
||||
assert.True(t, bytes.Contains(contents, []byte(constructor)), "missing constructor %q for package %q", constructor, pkg)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func repoRoot(t testing.TB) string {
|
||||
t.Helper()
|
||||
root, err := exec.Command("git", "rev-parse", "--show-toplevel").Output()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find repo root dir: %+v", err)
|
||||
}
|
||||
absRepoRoot, err := filepath.Abs(strings.TrimSpace(string(root)))
|
||||
if err != nil {
|
||||
t.Fatal("unable to get abs path to repo root:", err)
|
||||
}
|
||||
return absRepoRoot
|
||||
}
|
||||
|
||||
func mergeConstructors(constructorsPerPackage map[string]*strset.Set, partialResults map[string][]string) map[string]*strset.Set {
|
||||
for pkg, constructors := range partialResults {
|
||||
if _, ok := constructorsPerPackage[pkg]; !ok {
|
||||
constructorsPerPackage[pkg] = strset.New()
|
||||
}
|
||||
constructorsPerPackage[pkg].Add(constructors...)
|
||||
}
|
||||
|
||||
return constructorsPerPackage
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/scylladb/go-set/strset"
|
||||
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
func TestRelationshipsUnique(t *testing.T) {
|
||||
// This test is to ensure that the relationships are deduplicated in the final SBOM.
|
||||
// It is not a test of the relationships themselves.
|
||||
// This test is a regression test for #syft/2509
|
||||
sbom, _ := catalogFixtureImage(t, "image-pkg-coverage", source.SquashedScope)
|
||||
observedRelationships := strset.New()
|
||||
|
||||
for _, rel := range sbom.Relationships {
|
||||
unique := fmt.Sprintf("%s:%s:%s", rel.From.ID(), rel.To.ID(), rel.Type)
|
||||
if observedRelationships.Has(unique) {
|
||||
t.Errorf("duplicate relationship found: %s", unique)
|
||||
}
|
||||
observedRelationships.Add(unique)
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
"github.com/anchore/syft/syft/sbom"
|
||||
"github.com/anchore/syft/syft/source"
|
||||
)
|
||||
|
||||
func TestSbomCataloger(t *testing.T) {
|
||||
assertCount := func(t *testing.T, sbom sbom.SBOM, expectedGoModCatalogerPkgs int, expectedSbomCatalogerPkgs int) {
|
||||
actualSbomPkgs := 0
|
||||
actualGoModPkgs := 0
|
||||
|
||||
for p := range sbom.Artifacts.Packages.Enumerate(pkg.GoModulePkg) {
|
||||
if p.FoundBy == "go-module-file-cataloger" {
|
||||
actualGoModPkgs += 1
|
||||
} else if p.FoundBy == "sbom-cataloger" {
|
||||
actualSbomPkgs += 1
|
||||
}
|
||||
}
|
||||
|
||||
if actualGoModPkgs != expectedGoModCatalogerPkgs {
|
||||
t.Errorf("unexpected number of packages from go mod cataloger: %d != %d", expectedGoModCatalogerPkgs, actualGoModPkgs)
|
||||
}
|
||||
if actualSbomPkgs != expectedSbomCatalogerPkgs {
|
||||
t.Errorf("unexpected number of packages from sbom cataloger: %d != %d", expectedSbomCatalogerPkgs, actualSbomPkgs)
|
||||
}
|
||||
}
|
||||
|
||||
t.Run("default catalogers", func(t *testing.T) {
|
||||
sbom, _ := catalogFixtureImage(t, "image-sbom-cataloger", source.SquashedScope, "+go-module-file-cataloger")
|
||||
|
||||
expectedSbomCatalogerPkgs := 0
|
||||
expectedGoModCatalogerPkgs := 2
|
||||
assertCount(t, sbom, expectedGoModCatalogerPkgs, expectedSbomCatalogerPkgs)
|
||||
})
|
||||
|
||||
// The image contains a go.mod file with 2 dependencies and an spdx json sbom.
|
||||
// The go.mod file contains 2 dependencies, and the sbom includes a go dependency
|
||||
// that overlaps with the go.mod
|
||||
t.Run("with sbom cataloger", func(t *testing.T) {
|
||||
sbom, _ := catalogFixtureImage(t, "image-sbom-cataloger", source.SquashedScope, "+go-module-file-cataloger", "+sbom-cataloger")
|
||||
|
||||
expectedSbomCatalogerPkgs := 1
|
||||
expectedGoModCatalogerPkgs := 2
|
||||
assertCount(t, sbom, expectedGoModCatalogerPkgs, expectedSbomCatalogerPkgs)
|
||||
})
|
||||
}
|
||||
@@ -1,17 +1,13 @@
|
||||
package ui
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/wagoodman/go-partybus"
|
||||
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/syft/internal/log"
|
||||
"github.com/anchore/syft/syft/event"
|
||||
syftEventParsers "github.com/anchore/syft/syft/event/parsers"
|
||||
)
|
||||
|
||||
var _ clio.UI = (*NoUI)(nil)
|
||||
@@ -22,7 +18,6 @@ type NoUI struct {
|
||||
finalizeEvents []partybus.Event
|
||||
subscription partybus.Unsubscribable
|
||||
quiet bool
|
||||
wg *sync.WaitGroup
|
||||
}
|
||||
|
||||
func None(out io.Writer, quiet bool) *NoUI {
|
||||
@@ -30,7 +25,6 @@ func None(out io.Writer, quiet bool) *NoUI {
|
||||
out: out,
|
||||
err: os.Stderr,
|
||||
quiet: quiet,
|
||||
wg: &sync.WaitGroup{},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,35 +38,10 @@ func (n *NoUI) Handle(e partybus.Event) error {
|
||||
case event.CLIReport, event.CLINotification:
|
||||
// keep these for when the UI is terminated to show to the screen (or perform other events)
|
||||
n.finalizeEvents = append(n.finalizeEvents, e)
|
||||
|
||||
case event.AttestationStarted:
|
||||
n.handleAttestationStarted(e)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (n NoUI) Teardown(force bool) error {
|
||||
if !force {
|
||||
n.wg.Wait()
|
||||
}
|
||||
func (n NoUI) Teardown(_ bool) error {
|
||||
return writeEvents(n.out, n.err, n.quiet, n.finalizeEvents...)
|
||||
}
|
||||
|
||||
func (n *NoUI) handleAttestationStarted(e partybus.Event) {
|
||||
n.wg.Add(1)
|
||||
go func() {
|
||||
defer n.wg.Done()
|
||||
reader, _, _, err := syftEventParsers.ParseAttestationStartedEvent(e)
|
||||
if err != nil {
|
||||
log.WithFields("error", err).Warn("unable to parse event")
|
||||
return
|
||||
}
|
||||
|
||||
s := bufio.NewScanner(reader)
|
||||
|
||||
for s.Scan() {
|
||||
text := s.Text()
|
||||
log.Info("[COSIGN]", text)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -9,42 +9,39 @@ require (
|
||||
github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d
|
||||
github.com/acobaugh/osrelease v0.1.0
|
||||
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9
|
||||
github.com/anchore/clio v0.0.0-20240131202212-9eba61247448
|
||||
github.com/anchore/clio v0.0.0-20231016125544-c98a83e1c7fc
|
||||
github.com/anchore/fangs v0.0.0-20231201140849-5075d28d6d8b
|
||||
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a
|
||||
github.com/anchore/go-macholibre v0.0.0-20220308212642-53e6d0aaf6fb
|
||||
github.com/anchore/go-testutils v0.0.0-20200925183923-d5f45b0d3c04
|
||||
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501
|
||||
github.com/anchore/stereoscope v0.0.2-0.20240201063059-db7a4bedaba6
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be
|
||||
github.com/anchore/stereoscope v0.0.0-20231220161148-590920dabc54
|
||||
// we are hinting brotli to latest due to warning when installing archiver v3:
|
||||
// go: warning: github.com/andybalholm/brotli@v1.0.1: retracted by module author: occasional panics and data corruption
|
||||
github.com/aquasecurity/go-pep440-version v0.0.0-20210121094942-22b2f8951d46
|
||||
github.com/bmatcuk/doublestar/v4 v4.6.1
|
||||
github.com/charmbracelet/bubbles v0.17.1
|
||||
github.com/charmbracelet/bubbletea v0.25.0
|
||||
github.com/charmbracelet/lipgloss v0.9.1
|
||||
github.com/dave/jennifer v1.7.0
|
||||
github.com/deitch/magic v0.0.0-20230404182410-1ff89d7342da
|
||||
github.com/distribution/reference v0.5.0
|
||||
github.com/docker/docker v25.0.2+incompatible
|
||||
github.com/docker/docker v24.0.7+incompatible
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/facebookincubator/nvdtools v0.1.5
|
||||
github.com/github/go-spdx/v2 v2.2.0
|
||||
github.com/gkampitakis/go-snaps v0.5.0
|
||||
github.com/gkampitakis/go-snaps v0.4.12
|
||||
github.com/go-git/go-billy/v5 v5.5.0
|
||||
github.com/go-git/go-git/v5 v5.11.0
|
||||
github.com/go-test/deep v1.1.0
|
||||
github.com/google/go-cmp v0.6.0
|
||||
github.com/google/go-containerregistry v0.19.0
|
||||
github.com/google/go-containerregistry v0.17.0
|
||||
github.com/google/licensecheck v0.3.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/google/uuid v1.5.0
|
||||
github.com/gookit/color v1.5.4
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/iancoleman/strcase v0.3.0
|
||||
github.com/invopop/jsonschema v0.7.0
|
||||
github.com/jedib0t/go-pretty/v6 v6.5.4
|
||||
github.com/jinzhu/copier v0.4.0
|
||||
github.com/kastenhq/goversion v0.0.0-20230811215019-93b2f8823953
|
||||
github.com/knqyf263/go-rpmdb v0.0.0-20230301153543-ba94b245509b
|
||||
@@ -59,7 +56,7 @@ require (
|
||||
github.com/saferwall/pe v1.4.8
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d
|
||||
github.com/sanity-io/litter v1.5.5
|
||||
github.com/sassoftware/go-rpmutils v0.3.0
|
||||
github.com/sassoftware/go-rpmutils v0.2.0
|
||||
// pinned to pull in 386 arch fix: https://github.com/scylladb/go-set/commit/cc7b2070d91ebf40d233207b633e28f5bd8f03a5
|
||||
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e
|
||||
github.com/sergi/go-diff v1.3.1
|
||||
@@ -73,19 +70,24 @@ require (
|
||||
github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0
|
||||
github.com/xeipuuv/gojsonschema v1.2.0
|
||||
github.com/zyedidia/generic v1.2.2-0.20230320175451-4410d2372cb1
|
||||
go.uber.org/goleak v1.3.0
|
||||
golang.org/x/mod v0.14.0
|
||||
golang.org/x/net v0.20.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
modernc.org/sqlite v1.28.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be
|
||||
github.com/charmbracelet/bubbles v0.17.1
|
||||
github.com/jedib0t/go-pretty/v6 v6.5.3
|
||||
)
|
||||
|
||||
require (
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect
|
||||
github.com/AdamKorcz/go-118-fuzz-build v0.0.0-20230306123547-8075edf89bb0 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/DataDog/zstd v1.5.5 // indirect
|
||||
github.com/DataDog/zstd v1.4.5 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.0 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
@@ -99,7 +101,7 @@ require (
|
||||
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
|
||||
github.com/becheran/wildmatch-go v1.0.0 // indirect
|
||||
github.com/charmbracelet/harmonica v0.2.0 // indirect
|
||||
github.com/cloudflare/circl v1.3.7 // indirect
|
||||
github.com/cloudflare/circl v1.3.3 // indirect
|
||||
github.com/containerd/cgroups v1.1.0 // indirect
|
||||
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
|
||||
github.com/containerd/containerd v1.7.11 // indirect
|
||||
@@ -144,14 +146,14 @@ require (
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/kevinburke/ssh_config v1.2.0 // indirect
|
||||
github.com/klauspost/compress v1.17.4 // indirect
|
||||
github.com/klauspost/compress v1.17.0 // indirect
|
||||
github.com/klauspost/pgzip v1.2.5 // indirect
|
||||
github.com/kr/pretty v0.3.1 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/maruel/natural v1.1.1 // indirect
|
||||
github.com/maruel/natural v1.1.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.18 // indirect
|
||||
github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75 // indirect
|
||||
@@ -169,7 +171,7 @@ require (
|
||||
github.com/muesli/termenv v0.15.2 // indirect
|
||||
github.com/nwaples/rardecode v1.1.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0-rc3 // indirect
|
||||
github.com/opencontainers/runc v1.1.12 // indirect
|
||||
github.com/opencontainers/runc v1.1.5 // indirect
|
||||
github.com/opencontainers/runtime-spec v1.1.0-rc.1 // indirect
|
||||
github.com/opencontainers/selinux v1.11.0 // indirect
|
||||
github.com/pborman/indent v1.2.1 // indirect
|
||||
@@ -181,7 +183,7 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rivo/uniseg v0.2.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.12.0 // indirect
|
||||
github.com/rogpeppe/go-internal v1.11.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.3.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sahilm/fuzzy v0.1.1-0.20230530133925-c48e322e2a8f // indirect
|
||||
@@ -200,7 +202,7 @@ require (
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/tidwall/sjson v1.2.5 // indirect
|
||||
github.com/ulikunitz/xz v0.5.11 // indirect
|
||||
github.com/ulikunitz/xz v0.5.10 // indirect
|
||||
github.com/vbatts/tar-split v0.11.3 // indirect
|
||||
github.com/xanzy/ssh-agent v0.3.3 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
@@ -244,5 +246,3 @@ retract (
|
||||
v0.53.2
|
||||
v0.53.1 // Published accidentally with incorrect license in depdencies
|
||||
)
|
||||
|
||||
replace github.com/mholt/archiver/v3 v3.5.1 => github.com/anchore/archiver/v3 v3.5.2
|
||||
|
||||
@@ -61,8 +61,8 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym
|
||||
github.com/CycloneDX/cyclonedx-go v0.8.0 h1:FyWVj6x6hoJrui5uRQdYZcSievw3Z32Z88uYzG/0D6M=
|
||||
github.com/CycloneDX/cyclonedx-go v0.8.0/go.mod h1:K2bA+324+Og0X84fA8HhN2X066K7Bxz4rpMQ4ZhjtSk=
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||
github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ=
|
||||
github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
|
||||
github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
|
||||
github.com/DataDog/zstd v1.4.5/go.mod h1:1jcaCB/ufaK+sKp1NBhlGmpz41jOoPQ35bpF36t7BBo=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||
github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww=
|
||||
@@ -89,12 +89,10 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/anchore/archiver/v3 v3.5.2 h1:Bjemm2NzuRhmHy3m0lRe5tNoClB9A4zYyDV58PaB6aA=
|
||||
github.com/anchore/archiver/v3 v3.5.2/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
||||
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9 h1:p0ZIe0htYOX284Y4axJaGBvXHU0VCCzLN5Wf5XbKStU=
|
||||
github.com/anchore/bubbly v0.0.0-20231115134915-def0aba654a9/go.mod h1:3ZsFB9tzW3vl4gEiUeuSOMDnwroWxIxJelOOHUp8dSw=
|
||||
github.com/anchore/clio v0.0.0-20240131202212-9eba61247448 h1:ZgecmkxhH5im+9jPs7Ra1Thmv/p4IBDsoCFD6W8pENg=
|
||||
github.com/anchore/clio v0.0.0-20240131202212-9eba61247448/go.mod h1:t5Mld8naKcG8RTPjW/2n7bfyBKFl1A6PvtXw+v64gK0=
|
||||
github.com/anchore/clio v0.0.0-20231016125544-c98a83e1c7fc h1:A1KFO+zZZmbNlz1+WKsCF0RKVx6XRoxsAG3lrqH9hUQ=
|
||||
github.com/anchore/clio v0.0.0-20231016125544-c98a83e1c7fc/go.mod h1:QeWvNzxsrUNxcs6haQo3OtISfXUXW0qAuiG4EQiz0GU=
|
||||
github.com/anchore/fangs v0.0.0-20231201140849-5075d28d6d8b h1:L/djgY7ZbZ/38+wUtdkk398W3PIBJLkt1N8nU/7e47A=
|
||||
github.com/anchore/fangs v0.0.0-20231201140849-5075d28d6d8b/go.mod h1:TLcE0RE5+8oIx2/NPWem/dq1DeaMoC+fPEH7hoSzPLo=
|
||||
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a h1:nJ2G8zWKASyVClGVgG7sfM5mwoZlZ2zYpIzN2OhjWkw=
|
||||
@@ -109,8 +107,8 @@ github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZV
|
||||
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E=
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501 h1:AV7qjwMcM4r8wFhJq3jLRztew3ywIyPTRapl2T1s9o8=
|
||||
github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501/go.mod h1:Blo6OgJNiYF41ufcgHKkbCKF2MDOMlrqhXv/ij6ocR4=
|
||||
github.com/anchore/stereoscope v0.0.2-0.20240201063059-db7a4bedaba6 h1:4/tLmbUVcLOp2RnkC7F/Ec8jTv2ES5ph4D6Do719bKY=
|
||||
github.com/anchore/stereoscope v0.0.2-0.20240201063059-db7a4bedaba6/go.mod h1:uydT2ful8TY7Hr1WH1V1ZecSq/2TqXpAsGkMiy7lxD0=
|
||||
github.com/anchore/stereoscope v0.0.0-20231220161148-590920dabc54 h1:i2YK5QEs9H2YB3B2zv+AGR44ves0nmAGOD07lMphH14=
|
||||
github.com/anchore/stereoscope v0.0.0-20231220161148-590920dabc54/go.mod h1:IylG7ofLoUKHwS1XDF6rPhOmaE3GgpAgsMdvvYfooTU=
|
||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||
@@ -144,8 +142,6 @@ github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTS
|
||||
github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M=
|
||||
github.com/bradleyjkemp/cupaloy/v2 v2.8.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0=
|
||||
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
|
||||
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
@@ -159,15 +155,16 @@ github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG
|
||||
github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao=
|
||||
github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1p/u1KWg=
|
||||
github.com/charmbracelet/lipgloss v0.9.1/go.mod h1:1mPmG4cxScwUQALAAnacHaigiiHB9Pmr+v1VEawJl6I=
|
||||
github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA=
|
||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
|
||||
github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
@@ -180,6 +177,7 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
|
||||
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
|
||||
github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw=
|
||||
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
|
||||
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY=
|
||||
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
|
||||
github.com/containerd/containerd v1.7.11 h1:lfGKw3eU35sjV0aG2eYZTiwFEY1pCzxdzicHP3SZILw=
|
||||
@@ -203,6 +201,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/dave/jennifer v1.7.0 h1:uRbSBH9UTS64yXbh4FrMHfgfY762RD+C7bUPKODpSJE=
|
||||
@@ -221,14 +220,15 @@ github.com/docker/cli v24.0.0+incompatible h1:0+1VshNwBQzQAx9lOl+OYCTCEAD8fKs/qe
|
||||
github.com/docker/cli v24.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
|
||||
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
|
||||
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v25.0.2+incompatible h1:/OaKeauroa10K4Nqavw4zlhcDq/WBcPMc5DbjOGgozY=
|
||||
github.com/docker/docker v25.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM=
|
||||
github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
|
||||
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
|
||||
github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c/go.mod h1:Uw6UezgYA44ePAFQYUehOuCzmy5zmg/+nl2ZfMWGkpA=
|
||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
|
||||
@@ -265,6 +265,7 @@ github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
|
||||
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
|
||||
github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
|
||||
github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
|
||||
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
|
||||
github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
|
||||
@@ -279,8 +280,8 @@ github.com/gkampitakis/ciinfo v0.3.0 h1:gWZlOC2+RYYttL0hBqcoQhM7h1qNkVqvRCV1fOvp
|
||||
github.com/gkampitakis/ciinfo v0.3.0/go.mod h1:1NIwaOcFChN4fa/B0hEBdAb6npDlFL8Bwx4dfRLRqAo=
|
||||
github.com/gkampitakis/go-diff v1.3.2 h1:Qyn0J9XJSDTgnsgHRdz9Zp24RaJeKMUHg2+PDZZdC4M=
|
||||
github.com/gkampitakis/go-diff v1.3.2/go.mod h1:LLgOrpqleQe26cte8s36HTWcTmMEur6OPYerdAAS9tk=
|
||||
github.com/gkampitakis/go-snaps v0.5.0 h1:Qpk1+V1WJszsDvYMgrI15XbUvWqpsFvFxgaXKV6RU9Q=
|
||||
github.com/gkampitakis/go-snaps v0.5.0/go.mod h1:gX47VYsnvqHsjBrTrpaXfm1Dm1Xg+nREZPKRT8xifV8=
|
||||
github.com/gkampitakis/go-snaps v0.4.12 h1:YeMgKOm0XW3f/Pt2rYpUlpyF8nG6lYGe9oXFJw5LdME=
|
||||
github.com/gkampitakis/go-snaps v0.4.12/go.mod h1:PpnF1KPXQAHBdb/DHoi/1VmlwE+ZkVHzl+QHmgzMSz8=
|
||||
github.com/glebarez/go-sqlite v1.20.3 h1:89BkqGOXR9oRmG58ZrzgoY/Fhy5x0M+/WV48U5zVrZ4=
|
||||
github.com/glebarez/go-sqlite v1.20.3/go.mod h1:u3N6D/wftiAzIOJtZl6BmedqxmmkDfH3q+ihjqxC9u0=
|
||||
github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY=
|
||||
@@ -312,6 +313,7 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me
|
||||
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
|
||||
github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
@@ -370,8 +372,8 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-containerregistry v0.19.0 h1:uIsMRBV7m/HDkDxE/nXMnv1q+lOOSPlQ/ywc5JbB8Ic=
|
||||
github.com/google/go-containerregistry v0.19.0/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ=
|
||||
github.com/google/go-containerregistry v0.17.0 h1:5p+zYs/R4VGHkhyvgWurWrpJ2hW4Vv9fQI+GzdcwXLk=
|
||||
github.com/google/go-containerregistry v0.17.0/go.mod h1:u0qB2l7mvtWVR5kNcbFIhFY1hLbf8eeGapA+vbFDCtQ=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/licensecheck v0.3.1 h1:QoxgoDkaeC4nFrtGN1jV7IPmDCHFNIVh54e5hSt6sPs=
|
||||
github.com/google/licensecheck v0.3.1/go.mod h1:ORkR35t/JjW+emNKtfJDII0zlciG9JgbT7SmsohlHmY=
|
||||
@@ -399,8 +401,8 @@ github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S3
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
|
||||
@@ -408,10 +410,7 @@ github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0
|
||||
github.com/gookit/color v1.2.5/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg=
|
||||
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
|
||||
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
|
||||
github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
|
||||
github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@@ -467,8 +466,8 @@ github.com/invopop/jsonschema v0.7.0 h1:2vgQcBz1n256N+FpX3Jq7Y17AjYt46Ig3zIWyy77
|
||||
github.com/invopop/jsonschema v0.7.0/go.mod h1:O9uiLokuu0+MGFlyiaqtWxwqJm41/+8Nj0lD7A36YH0=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
|
||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||
github.com/jedib0t/go-pretty/v6 v6.5.4 h1:gOGo0613MoqUcf0xCj+h/V3sHDaZasfv152G6/5l91s=
|
||||
github.com/jedib0t/go-pretty/v6 v6.5.4/go.mod h1:5LQIxa52oJ/DlDSLv0HEkWOFMDGoWkJb9ss5KqPpJBg=
|
||||
github.com/jedib0t/go-pretty/v6 v6.5.3 h1:GIXn6Er/anHTkVUoufs7ptEvxdD6KIhR7Axa2wYCPF0=
|
||||
github.com/jedib0t/go-pretty/v6 v6.5.3/go.mod h1:5LQIxa52oJ/DlDSLv0HEkWOFMDGoWkJb9ss5KqPpJBg=
|
||||
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
|
||||
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
@@ -488,8 +487,9 @@ github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=
|
||||
github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM=
|
||||
github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
|
||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||
@@ -500,6 +500,7 @@ github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
@@ -516,8 +517,8 @@ github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc8
|
||||
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
|
||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/maruel/natural v1.1.1 h1:Hja7XhhmvEFhcByqDoHz9QZbkWey+COd9xWfCfn1ioo=
|
||||
github.com/maruel/natural v1.1.1/go.mod h1:v+Rfd79xlw1AgVBjbO0BEQmptqb5HvL/k9GRHB7ZKEg=
|
||||
github.com/maruel/natural v1.1.0 h1:2z1NgP/Vae+gYrtC0VuvrTJ6U35OuyUqDdfluLqMWuQ=
|
||||
github.com/maruel/natural v1.1.0/go.mod h1:eFVhYCcUOfZFxXoDZam8Ktya72wa79fNC3lc/leA0DQ=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
@@ -545,6 +546,8 @@ github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
|
||||
github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
||||
github.com/microsoft/go-rustaudit v0.0.0-20220730194248-4b17361d90a5 h1:tQRHcLQwnwrPq2j2Qra/NnyjyESBGwdeBeVdAE9kXYg=
|
||||
github.com/microsoft/go-rustaudit v0.0.0-20220730194248-4b17361d90a5/go.mod h1:vYT9HE7WCvL64iVeZylKmCsWKfE+JZ8105iuh2Trk8g=
|
||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||
@@ -569,6 +572,7 @@ github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zx
|
||||
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
|
||||
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
|
||||
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
|
||||
github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU=
|
||||
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
|
||||
github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI=
|
||||
github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc=
|
||||
@@ -584,6 +588,7 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
|
||||
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||
github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ=
|
||||
github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 h1:kMlmsLSbjkikxQJ1IPwaM+7LJ9ltFu/fi8CRzvSnQmA=
|
||||
github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho=
|
||||
github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA=
|
||||
@@ -603,10 +608,12 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8
|
||||
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc3 h1:fzg1mXZFj8YdPeNkRXMg+zb88BFV0Ys52cJydRwBkb8=
|
||||
github.com/opencontainers/image-spec v1.1.0-rc3/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8=
|
||||
github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss=
|
||||
github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8=
|
||||
github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs=
|
||||
github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg=
|
||||
github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/runtime-spec v1.1.0-rc.1 h1:wHa9jroFfKGQqFHj0I1fMRKLl0pfj+ynAqBxo3v6u9w=
|
||||
github.com/opencontainers/runtime-spec v1.1.0-rc.1/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI=
|
||||
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
|
||||
github.com/opencontainers/selinux v1.11.0/go.mod h1:E5dMC3VPuVvVHDYmi78qvhJp8+M586T4DlDRYpFkyec=
|
||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||
@@ -660,8 +667,8 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||
@@ -678,13 +685,14 @@ github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d h1:hrujxIzL1woJ7
|
||||
github.com/saintfish/chardet v0.0.0-20230101081208-5e3ef4b5456d/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU=
|
||||
github.com/sanity-io/litter v1.5.5 h1:iE+sBxPBzoK6uaEP5Lt3fHNgpKcHXc/A2HGETy0uJQo=
|
||||
github.com/sanity-io/litter v1.5.5/go.mod h1:9gzJgR2i4ZpjZHsKvUXIRQVk7P+yM3e+jAF7bU2UI5U=
|
||||
github.com/sassoftware/go-rpmutils v0.3.0 h1:tE4TZ8KcOXay5iIP64P291s6Qxd9MQCYhI7DU+f3gFA=
|
||||
github.com/sassoftware/go-rpmutils v0.3.0/go.mod h1:hM9wdxFsjUFR/tJ6SMsLrJuChcucCa0DsCzE9RMfwMo=
|
||||
github.com/sassoftware/go-rpmutils v0.2.0 h1:pKW0HDYMFWQ5b4JQPiI3WI12hGsVoW0V8+GMoZiI/JE=
|
||||
github.com/sassoftware/go-rpmutils v0.2.0/go.mod h1:TJJQYtLe/BeEmEjelI3b7xNZjzAukEkeWKmoakvaOoI=
|
||||
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e h1:7q6NSFZDeGfvvtIRwBrU/aegEYJYmvev0cHAwo17zZQ=
|
||||
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e/go.mod h1:DkpGd78rljTxKAnTDPFqXSGxvETQnJyuSOQwsHycqfs=
|
||||
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
|
||||
github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624Y=
|
||||
github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
|
||||
github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
@@ -749,6 +757,7 @@ github.com/sylabs/sif/v2 v2.11.5 h1:7ssPH3epSonsTrzbS1YxeJ9KuqAN7ISlSM61a7j/mQM=
|
||||
github.com/sylabs/sif/v2 v2.11.5/go.mod h1:GBoZs9LU3e4yJH1dcZ3Akf/jsqYgy5SeguJQC+zd75Y=
|
||||
github.com/sylabs/squashfs v0.6.1 h1:4hgvHnD9JGlYWwT0bPYNt9zaz23mAV3Js+VEgQoRGYQ=
|
||||
github.com/sylabs/squashfs v0.6.1/go.mod h1:ZwpbPCj0ocIvMy2br6KZmix6Gzh6fsGQcCnydMF+Kx8=
|
||||
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
|
||||
github.com/terminalstatic/go-xsd-validate v0.1.5 h1:RqpJnf6HGE2CB/lZB1A8BYguk8uRtcvYAPLCF15qguo=
|
||||
github.com/terminalstatic/go-xsd-validate v0.1.5/go.mod h1:18lsvYFofBflqCrvo1umpABZ99+GneNTw2kEEc8UPJw=
|
||||
github.com/therootcompany/xz v1.0.1 h1:CmOtsn1CbtmyYiusbfmhmkpAAETj0wBIH6kCYaX+xzw=
|
||||
@@ -766,8 +775,9 @@ github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6
|
||||
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
|
||||
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
|
||||
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
|
||||
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli v1.22.12/go.mod h1:sSBEIC79qR6OvcmsD4U3KABeOTxDqQtdDnaFuUN30b8=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
github.com/vbatts/go-mtree v0.5.3 h1:S/jYlfG8rZ+a0bhZd+RANXejy7M4Js8fq9U+XoWTd5w=
|
||||
@@ -776,6 +786,8 @@ github.com/vbatts/tar-split v0.11.3 h1:hLFqsOLQ1SsppQNTMpkpPXClLDfC2A3Zgy9OUU+RV
|
||||
github.com/vbatts/tar-split v0.11.3/go.mod h1:9QlHN18E+fEH7RdG+QAJJcuya3rqT7eXSTY7wGrAokY=
|
||||
github.com/vifraa/gopom v1.0.0 h1:L9XlKbyvid8PAIK8nr0lihMApJQg/12OBvMA28BcWh0=
|
||||
github.com/vifraa/gopom v1.0.0/go.mod h1:oPa1dcrGrtlO37WPDBm5SqHAT+wTgF8An1Q71Z6Vv4o=
|
||||
github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE=
|
||||
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU=
|
||||
github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 h1:jIVmlAFIqV3d+DOxazTR9v+zgj8+VYuQBzPgBZvWBHA=
|
||||
github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651/go.mod h1:b26F2tHLqaoRQf8DywqzVaV1MQ9yvjb0OMcNl7Nxu20=
|
||||
github.com/wagoodman/go-progress v0.0.0-20230925121702-07e42b3cdba0 h1:0KGbf+0SMg+UFy4e1A/CPVvXn21f1qtWdeJwxZFoQG8=
|
||||
@@ -819,24 +831,17 @@ go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZ
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q=
|
||||
go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
|
||||
go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 h1:Mne5On7VWdx7omSrSSZvM4Kw7cS7NQkOOmLcgscI51U=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0/go.mod h1:IPtUMKL4O3tH5y+iXVyAXqpAwMuzC1IrxVS81rummfE=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0 h1:IeMeyr1aBvBiPVYihXIaeIZba6b8E1bYp7lbdxK8CQg=
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.19.0/go.mod h1:oVdCUtjq9MK9BlS7TtucsQwUcXcymNiEDjgDD2jMtZU=
|
||||
go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE=
|
||||
go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
|
||||
go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o=
|
||||
go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A=
|
||||
go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg=
|
||||
go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
|
||||
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
||||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
|
||||
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
|
||||
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
|
||||
@@ -850,6 +855,7 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
@@ -934,6 +940,7 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
|
||||
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
@@ -994,6 +1001,7 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -1001,6 +1009,7 @@ golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -1042,10 +1051,12 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
@@ -1062,6 +1073,7 @@ golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||
@@ -1104,6 +1116,7 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn
|
||||
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
@@ -1256,8 +1269,6 @@ google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ6
|
||||
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17 h1:wpZ8pe2x1Q3f2KyT5f8oP/fa9rHAKgFPr/HZdNuS+PQ=
|
||||
google.golang.org/genproto v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:J7XzRzVy1+IPwWHZUzoD0IccYZIrXILAQpc+Qy9CMhY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17 h1:JpwMPBpFN3uKhdaekDpiNlImDdkUAyiJ6ez/uxGaUSo=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20231106174013-bbf56f31fb17/go.mod h1:0xJLfVdJqpAPl8tDg1ujOCGzx6LFLttXT5NhllGOXY4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
|
||||
@@ -3,5 +3,5 @@ package internal
|
||||
const (
|
||||
// JSONSchemaVersion is the current schema version output by the JSON encoder
|
||||
// This is roughly following the "SchemaVer" guidelines for versioning the JSON schema. Please see schema/json/README.md for details on how to increment.
|
||||
JSONSchemaVersion = "15.0.0"
|
||||
JSONSchemaVersion = "13.0.0"
|
||||
)
|
||||
|
||||
@@ -22,7 +22,6 @@ func supportedHashAlgorithms() []crypto.Hash {
|
||||
}
|
||||
|
||||
func NewDigestsFromFile(closer io.ReadCloser, hashes []crypto.Hash) ([]file.Digest, error) {
|
||||
hashes = NormalizeHashes(hashes)
|
||||
// create a set of hasher objects tied together with a single writer to feed content into
|
||||
hashers := make([]hash.Hash, len(hashes))
|
||||
writers := make([]io.Writer, len(hashes))
|
||||
@@ -68,7 +67,7 @@ func Hashers(names ...string) ([]crypto.Hash, error) {
|
||||
}
|
||||
hashers = append(hashers, hashObj)
|
||||
}
|
||||
return NormalizeHashes(hashers), nil
|
||||
return hashers, nil
|
||||
}
|
||||
|
||||
func CleanDigestAlgorithmName(name string) string {
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"sort"
|
||||
|
||||
"github.com/scylladb/go-set/uset"
|
||||
)
|
||||
|
||||
func NormalizeHashes(hashes []crypto.Hash) []crypto.Hash {
|
||||
set := uset.New()
|
||||
for _, h := range hashes {
|
||||
set.Add(uint(h))
|
||||
}
|
||||
list := set.List()
|
||||
sort.Slice(list, func(i, j int) bool {
|
||||
return list[i] < list[j]
|
||||
})
|
||||
result := make([]crypto.Hash, len(list))
|
||||
for i, v := range list {
|
||||
result[i] = crypto.Hash(v)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
package file
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNormalizeHashes(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
input []crypto.Hash
|
||||
want []crypto.Hash
|
||||
}{
|
||||
{
|
||||
name: "deduplicate hashes",
|
||||
input: []crypto.Hash{
|
||||
crypto.SHA1,
|
||||
crypto.SHA1,
|
||||
},
|
||||
want: []crypto.Hash{
|
||||
crypto.SHA1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "sort hashes",
|
||||
input: []crypto.Hash{
|
||||
crypto.SHA512,
|
||||
crypto.SHA1,
|
||||
},
|
||||
want: []crypto.Hash{
|
||||
crypto.SHA1,
|
||||
crypto.SHA512,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equal(t, tt.want, NormalizeHashes(tt.input))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package mimetype
|
||||
package internal
|
||||
|
||||
import "github.com/scylladb/go-set/strset"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package mimetype
|
||||
package internal
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -30,7 +30,7 @@ func NewFileDigestCatalogerTask(selection file.Selection, hashers ...crypto.Hash
|
||||
return nil
|
||||
}
|
||||
|
||||
result, err := digestsCataloger.Catalog(ctx, resolver, coordinates...)
|
||||
result, err := digestsCataloger.Catalog(resolver, coordinates...)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to catalog file digests: %w", err)
|
||||
}
|
||||
@@ -60,7 +60,7 @@ func NewFileMetadataCatalogerTask(selection file.Selection) Task {
|
||||
return nil
|
||||
}
|
||||
|
||||
result, err := metadataCataloger.Catalog(ctx, resolver, coordinates...)
|
||||
result, err := metadataCataloger.Catalog(resolver, coordinates...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -85,7 +85,7 @@ func NewFileContentCatalogerTask(cfg filecontent.Config) Task {
|
||||
fn := func(ctx context.Context, resolver file.Resolver, builder sbomsync.Builder) error {
|
||||
accessor := builder.(sbomsync.Accessor)
|
||||
|
||||
result, err := cat.Catalog(ctx, resolver)
|
||||
result, err := cat.Catalog(resolver)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ func NewPackageTask(cfg CatalogingFactoryConfig, c pkg.Cataloger, tags ...string
|
||||
|
||||
t := bus.StartCatalogerTask(info, -1, "")
|
||||
|
||||
pkgs, relationships, err := c.Catalog(ctx, resolver)
|
||||
pkgs, relationships, err := c.Catalog(resolver)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to catalog packages with %q: %w", c.Name(), err)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/haskell"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/java"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/javascript"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/kernel"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/nix"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/php"
|
||||
"github.com/anchore/syft/syft/pkg/cataloger/python"
|
||||
@@ -113,16 +112,9 @@ func DefaultPackageTaskFactories() PackageTaskFactories {
|
||||
func(cfg CatalogingFactoryConfig) pkg.Cataloger {
|
||||
return binary.NewCataloger(cfg.PackagesConfig.Binary)
|
||||
},
|
||||
pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, "binary",
|
||||
),
|
||||
pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, "binary"),
|
||||
newSimplePackageTaskFactory(githubactions.NewActionUsageCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, "github", "github-actions"),
|
||||
newSimplePackageTaskFactory(githubactions.NewWorkflowUsageCataloger, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, "github", "github-actions"),
|
||||
newPackageTaskFactory(
|
||||
func(cfg CatalogingFactoryConfig) pkg.Cataloger {
|
||||
return kernel.NewLinuxKernelCataloger(cfg.PackagesConfig.LinuxKernel)
|
||||
},
|
||||
pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.InstalledTag, pkgcataloging.ImageTag, "linux", "kernel",
|
||||
),
|
||||
newSimplePackageTaskFactory(sbomCataloger.NewCataloger, "sbom"), // note: not evidence of installed packages
|
||||
newSimplePackageTaskFactory(sbomCataloger.NewCataloger, pkgcataloging.ImageTag, pkgcataloging.DeclaredTag, pkgcataloging.DirectoryTag, pkgcataloging.ImageTag, "sbom"), // note: not evidence of installed packages
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -73,6 +73,6 @@ func (cfg Config) WithSelection(selection file.Selection) Config {
|
||||
}
|
||||
|
||||
func (cfg Config) WithHashers(hashers []crypto.Hash) Config {
|
||||
cfg.Hashers = intFile.NormalizeHashes(hashers)
|
||||
cfg.Hashers = hashers
|
||||
return cfg
|
||||
}
|
||||
|
||||
@@ -20,9 +20,8 @@ type Config struct {
|
||||
|
||||
func DefaultConfig() Config {
|
||||
return Config{
|
||||
Binary: binary.DefaultCatalogerConfig(),
|
||||
Golang: golang.DefaultCatalogerConfig(),
|
||||
LinuxKernel: kernel.DefaultLinuxKernelCatalogerConfig(),
|
||||
LinuxKernel: kernel.DefaultLinuxCatalogerConfig(),
|
||||
Python: python.DefaultCatalogerConfig(),
|
||||
JavaArchive: java.DefaultArchiveCatalogerConfig(),
|
||||
}
|
||||
|
||||
@@ -2,11 +2,13 @@ package cpe
|
||||
|
||||
import (
|
||||
"sort"
|
||||
|
||||
"github.com/facebookincubator/nvdtools/wfn"
|
||||
)
|
||||
|
||||
var _ sort.Interface = (*BySpecificity)(nil)
|
||||
|
||||
type BySpecificity []CPE
|
||||
type BySpecificity []wfn.Attributes
|
||||
|
||||
func (c BySpecificity) Len() int { return len(c) }
|
||||
|
||||
@@ -33,17 +35,17 @@ func (c BySpecificity) Less(i, j int) bool {
|
||||
return c[i].BindToFmtString() < c[j].BindToFmtString()
|
||||
}
|
||||
|
||||
func countFieldLength(cpe CPE) int {
|
||||
func countFieldLength(cpe wfn.Attributes) int {
|
||||
return len(cpe.Part + cpe.Vendor + cpe.Product + cpe.Version + cpe.TargetSW)
|
||||
}
|
||||
|
||||
func weightedCountForSpecifiedFields(cpe CPE) int {
|
||||
checksForSpecifiedField := []func(cpe CPE) (bool, int){
|
||||
func(cpe CPE) (bool, int) { return cpe.Part != "", 2 },
|
||||
func(cpe CPE) (bool, int) { return cpe.Vendor != "", 3 },
|
||||
func(cpe CPE) (bool, int) { return cpe.Product != "", 4 },
|
||||
func(cpe CPE) (bool, int) { return cpe.Version != "", 1 },
|
||||
func(cpe CPE) (bool, int) { return cpe.TargetSW != "", 1 },
|
||||
func weightedCountForSpecifiedFields(cpe wfn.Attributes) int {
|
||||
checksForSpecifiedField := []func(cpe wfn.Attributes) (bool, int){
|
||||
func(cpe wfn.Attributes) (bool, int) { return cpe.Part != "", 2 },
|
||||
func(cpe wfn.Attributes) (bool, int) { return cpe.Vendor != "", 3 },
|
||||
func(cpe wfn.Attributes) (bool, int) { return cpe.Product != "", 4 },
|
||||
func(cpe wfn.Attributes) (bool, int) { return cpe.Version != "", 1 },
|
||||
func(cpe wfn.Attributes) (bool, int) { return cpe.TargetSW != "", 1 },
|
||||
}
|
||||
|
||||
weightedCount := 0
|
||||
|
||||
+16
-48
@@ -8,37 +8,7 @@ import (
|
||||
"github.com/facebookincubator/nvdtools/wfn"
|
||||
)
|
||||
|
||||
const Any = ""
|
||||
|
||||
type CPE struct {
|
||||
Part string
|
||||
Vendor string
|
||||
Product string
|
||||
Version string
|
||||
Update string
|
||||
Edition string
|
||||
SWEdition string
|
||||
TargetSW string
|
||||
TargetHW string
|
||||
Other string
|
||||
Language string
|
||||
}
|
||||
|
||||
func (c CPE) asAttributes() wfn.Attributes {
|
||||
return wfn.Attributes(c)
|
||||
}
|
||||
|
||||
func fromAttributes(a wfn.Attributes) CPE {
|
||||
return CPE(a)
|
||||
}
|
||||
|
||||
func (c CPE) BindToFmtString() string {
|
||||
return c.asAttributes().BindToFmtString()
|
||||
}
|
||||
|
||||
func NewWithAny() CPE {
|
||||
return fromAttributes(*(wfn.NewAttributesWithAny()))
|
||||
}
|
||||
type CPE = wfn.Attributes
|
||||
|
||||
const (
|
||||
allowedCPEPunctuation = "-!\"#$%&'()+,./:;<=>@[]^`{|}~"
|
||||
@@ -64,7 +34,7 @@ func New(cpeStr string) (CPE, error) {
|
||||
}
|
||||
|
||||
// ensure that this CPE can be validated after being fully sanitized
|
||||
if ValidateString(c.String()) != nil {
|
||||
if ValidateString(String(c)) != nil {
|
||||
return CPE{}, err
|
||||
}
|
||||
|
||||
@@ -101,22 +71,20 @@ func newWithoutValidation(cpeStr string) (CPE, error) {
|
||||
return CPE{}, fmt.Errorf("failed to parse CPE=%q", cpeStr)
|
||||
}
|
||||
|
||||
syftCPE := fromAttributes(*value)
|
||||
|
||||
// we need to compare the raw data since we are constructing CPEs in other locations
|
||||
syftCPE.Vendor = normalizeField(syftCPE.Vendor)
|
||||
syftCPE.Product = normalizeField(syftCPE.Product)
|
||||
syftCPE.Language = normalizeField(syftCPE.Language)
|
||||
syftCPE.Version = normalizeField(syftCPE.Version)
|
||||
syftCPE.TargetSW = normalizeField(syftCPE.TargetSW)
|
||||
syftCPE.Part = normalizeField(syftCPE.Part)
|
||||
syftCPE.Edition = normalizeField(syftCPE.Edition)
|
||||
syftCPE.Other = normalizeField(syftCPE.Other)
|
||||
syftCPE.SWEdition = normalizeField(syftCPE.SWEdition)
|
||||
syftCPE.TargetHW = normalizeField(syftCPE.TargetHW)
|
||||
syftCPE.Update = normalizeField(syftCPE.Update)
|
||||
value.Vendor = normalizeField(value.Vendor)
|
||||
value.Product = normalizeField(value.Product)
|
||||
value.Language = normalizeField(value.Language)
|
||||
value.Version = normalizeField(value.Version)
|
||||
value.TargetSW = normalizeField(value.TargetSW)
|
||||
value.Part = normalizeField(value.Part)
|
||||
value.Edition = normalizeField(value.Edition)
|
||||
value.Other = normalizeField(value.Other)
|
||||
value.SWEdition = normalizeField(value.SWEdition)
|
||||
value.TargetHW = normalizeField(value.TargetHW)
|
||||
value.Update = normalizeField(value.Update)
|
||||
|
||||
return syftCPE, nil
|
||||
return *value, nil
|
||||
}
|
||||
|
||||
func normalizeField(field string) string {
|
||||
@@ -125,7 +93,7 @@ func normalizeField(field string) string {
|
||||
|
||||
// keep dashes and forward slashes unescaped
|
||||
if field == "*" {
|
||||
return Any
|
||||
return wfn.Any
|
||||
}
|
||||
return stripSlashes(field)
|
||||
}
|
||||
@@ -144,7 +112,7 @@ func stripSlashes(s string) string {
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
func (c CPE) String() string {
|
||||
func String(c CPE) string {
|
||||
output := CPE{}
|
||||
output.Vendor = sanitize(c.Vendor)
|
||||
output.Product = sanitize(c.Product)
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -42,8 +41,8 @@ func Test_New(t *testing.T) {
|
||||
t.Fatalf("got an error while creating CPE: %+v", err)
|
||||
}
|
||||
|
||||
if d := cmp.Diff(actual, test.expected); d != "" {
|
||||
t.Errorf("CPE mismatch (-want +got):\n%s", d)
|
||||
if String(actual) != String(test.expected) {
|
||||
t.Errorf("mismatched entries:\n\texpected:%+v\n\t actual:%+v\n", String(test.expected), String(actual))
|
||||
}
|
||||
|
||||
})
|
||||
@@ -99,7 +98,7 @@ func Test_CPEParser(t *testing.T) {
|
||||
assert.Equal(t, c1, c2)
|
||||
assert.Equal(t, c1, test.WFN)
|
||||
assert.Equal(t, c2, test.WFN)
|
||||
assert.Equal(t, test.WFN.String(), test.CPEString)
|
||||
assert.Equal(t, String(test.WFN), test.CPEString)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -165,12 +164,12 @@ func Test_InvalidCPE(t *testing.T) {
|
||||
if test.expectedErr {
|
||||
assert.Error(t, err)
|
||||
if t.Failed() {
|
||||
t.Logf("got CPE: %q details: %+v", c, c)
|
||||
t.Logf("got CPE: %q details: %+v", String(c), c)
|
||||
}
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, test.expected, c.String())
|
||||
assert.Equal(t, test.expected, String(c))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -216,13 +215,13 @@ func Test_RoundTrip(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
// CPE string must be preserved through a round trip
|
||||
assert.Equal(t, test.cpe, Must(test.cpe).String())
|
||||
assert.Equal(t, test.cpe, String(Must(test.cpe)))
|
||||
// The parsed CPE must be the same after a round trip
|
||||
assert.Equal(t, Must(test.cpe), Must(Must(test.cpe).String()))
|
||||
assert.Equal(t, Must(test.cpe), Must(String(Must(test.cpe))))
|
||||
// The test case parsed CPE must be the same after parsing the input string
|
||||
assert.Equal(t, test.parsedCPE, Must(test.cpe))
|
||||
// The test case parsed CPE must produce the same string as the input cpe
|
||||
assert.Equal(t, test.parsedCPE.String(), test.cpe)
|
||||
assert.Equal(t, String(test.parsedCPE), test.cpe)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"github.com/wagoodman/go-progress"
|
||||
|
||||
"github.com/anchore/syft/internal/bus"
|
||||
"github.com/anchore/syft/internal/relationship"
|
||||
"github.com/anchore/syft/internal/sbomsync"
|
||||
"github.com/anchore/syft/internal/task"
|
||||
"github.com/anchore/syft/syft/artifact"
|
||||
@@ -77,6 +78,8 @@ func CreateSBOM(ctx context.Context, src source.Source, cfg *CreateSBOMConfig) (
|
||||
packageCatalogingProgress.SetCompleted()
|
||||
catalogingProgress.SetCompleted()
|
||||
|
||||
relationship.Finalize(builder, cfg.Relationships, src)
|
||||
|
||||
return &s, nil
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user