mirror of
https://github.com/anchore/syft.git
synced 2026-10-12 14:17:20 +02:00
Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
206fd8b7d3 | ||
|
|
c348d97fe0 | ||
|
|
30bb7cf992 | ||
|
|
54e0ee4c47 | ||
|
|
c231a9d7cb | ||
|
|
3e27b6e93f | ||
|
|
63ee5ba098 |
+1
-1
@@ -31,7 +31,6 @@ linters:
|
|||||||
- misspell
|
- misspell
|
||||||
- nakedret
|
- nakedret
|
||||||
- nolintlint
|
- nolintlint
|
||||||
- prealloc
|
|
||||||
- rowserrcheck
|
- rowserrcheck
|
||||||
- scopelint
|
- scopelint
|
||||||
- staticcheck
|
- staticcheck
|
||||||
@@ -55,5 +54,6 @@ linters:
|
|||||||
# - lll # without a way to specify per-line exception cases, this is not usable
|
# - lll # without a way to specify per-line exception cases, this is not usable
|
||||||
# - maligned # this is an excellent linter, but tricky to optimize and we are not sensitive to memory layout optimizations
|
# - maligned # this is an excellent linter, but tricky to optimize and we are not sensitive to memory layout optimizations
|
||||||
# - nestif
|
# - nestif
|
||||||
|
# - prealloc # this unnecessarily requires preallocations for slices
|
||||||
# - testpackage
|
# - testpackage
|
||||||
# - wsl
|
# - wsl
|
||||||
@@ -169,6 +169,9 @@ check-pipeline: ## Run local CircleCI pipeline locally (sanity check)
|
|||||||
circleci local execute -c .tmp/circleci.yml --job "Unit & Integration Tests (go-latest)"
|
circleci local execute -c .tmp/circleci.yml --job "Unit & Integration Tests (go-latest)"
|
||||||
@printf '$(SUCCESS)Pipeline checks pass!$(RESET)\n'
|
@printf '$(SUCCESS)Pipeline checks pass!$(RESET)\n'
|
||||||
|
|
||||||
|
proto:
|
||||||
|
protoc -I syft/plugin/proto/ syft/plugin/proto/cataloger.proto --go_out=plugins=grpc:syft/plugin/proto/
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build: $(SNAPSHOTDIR) ## Build release snapshot binaries and packages
|
build: $(SNAPSHOTDIR) ## Build release snapshot binaries and packages
|
||||||
|
|
||||||
|
|||||||
+17
-1
@@ -3,6 +3,10 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
|
|
||||||
|
"github.com/adrg/xdg"
|
||||||
|
"github.com/anchore/syft/internal"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
@@ -78,6 +82,18 @@ func setGlobalCliOptions() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rootCmd.Flags().CountVarP(&cliOpts.Verbosity, "verbose", "v", "increase verbosity (-v = info, -vv = debug)")
|
rootCmd.Flags().CountVarP(&cliOpts.Verbosity, "verbose", "v", "increase verbosity (-v = info, -vv = debug)")
|
||||||
|
|
||||||
|
// plugins
|
||||||
|
defaultPluginDir := path.Join(xdg.CacheHome, internal.ApplicationName, "plugins")
|
||||||
|
flag = "plugins.dir"
|
||||||
|
rootCmd.Flags().String(
|
||||||
|
flag, defaultPluginDir,
|
||||||
|
"plugin storage directory",
|
||||||
|
)
|
||||||
|
if err := viper.BindPFlag(flag, rootCmd.Flags().Lookup(flag)); err != nil {
|
||||||
|
fmt.Printf("unable to bind flag '%s': %+v", flag, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func initAppConfig() {
|
func initAppConfig() {
|
||||||
@@ -101,7 +117,7 @@ func initLogging() {
|
|||||||
logWrapper := logger.NewLogrusLogger(cfg)
|
logWrapper := logger.NewLogrusLogger(cfg)
|
||||||
syft.SetLogger(logWrapper)
|
syft.SetLogger(logWrapper)
|
||||||
stereoscope.SetLogger(&logger.LogrusNestedLogger{
|
stereoscope.SetLogger(&logger.LogrusNestedLogger{
|
||||||
Logger: logWrapper.Logger.WithField("from-lib", "steroscope"),
|
Logger: logWrapper.Logger.WithField("from-lib", "stereoscope"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
-1
@@ -68,7 +68,17 @@ func startWorker(userInput string) <-chan error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
catalog, scope, distro, err := syft.Catalog(userInput, appConfig.ScopeOpt)
|
config := syft.Config{
|
||||||
|
PluginDirectory: appConfig.Plugins.Directory,
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := syft.NewClient(config)
|
||||||
|
if err != nil {
|
||||||
|
errs <- fmt.Errorf("could not initialize syft: %+v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
catalog, scope, distro, err := client.Catalog(userInput, appConfig.ScopeOpt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs <- fmt.Errorf("failed to catalog input: %+v", err)
|
errs <- fmt.Errorf("failed to catalog input: %+v", err)
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -7,16 +7,19 @@ require (
|
|||||||
github.com/anchore/go-rpmdb v0.0.0-20200811175839-cbc751c28e8e
|
github.com/anchore/go-rpmdb v0.0.0-20200811175839-cbc751c28e8e
|
||||||
github.com/anchore/go-testutils v0.0.0-20200624184116-66aa578126db
|
github.com/anchore/go-testutils v0.0.0-20200624184116-66aa578126db
|
||||||
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b
|
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b
|
||||||
github.com/anchore/stereoscope v0.0.0-20200813152757-548b22c8a0b3
|
github.com/anchore/stereoscope v0.0.0-20200903223322-a3806f515470
|
||||||
github.com/bmatcuk/doublestar v1.3.1
|
github.com/bmatcuk/doublestar v1.3.1
|
||||||
github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe // indirect
|
github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe // indirect
|
||||||
github.com/dustin/go-humanize v1.0.0
|
github.com/dustin/go-humanize v1.0.0
|
||||||
github.com/go-test/deep v1.0.6
|
github.com/go-test/deep v1.0.6
|
||||||
|
github.com/golang/protobuf v1.4.2
|
||||||
github.com/google/go-containerregistry v0.1.1 // indirect
|
github.com/google/go-containerregistry v0.1.1 // indirect
|
||||||
github.com/google/uuid v1.1.1
|
github.com/google/uuid v1.1.1
|
||||||
github.com/gookit/color v1.2.7
|
github.com/gookit/color v1.2.7
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 // indirect
|
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 // indirect
|
||||||
|
github.com/hashicorp/go-hclog v0.14.1
|
||||||
github.com/hashicorp/go-multierror v1.1.0
|
github.com/hashicorp/go-multierror v1.1.0
|
||||||
|
github.com/hashicorp/go-plugin v1.3.0
|
||||||
github.com/hashicorp/go-version v1.2.0
|
github.com/hashicorp/go-version v1.2.0
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/mitchellh/mapstructure v1.3.1
|
github.com/mitchellh/mapstructure v1.3.1
|
||||||
@@ -38,6 +41,7 @@ require (
|
|||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 // indirect
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 // indirect
|
||||||
golang.org/x/sys v0.0.0-20200610111108-226ff32320da // indirect
|
golang.org/x/sys v0.0.0-20200610111108-226ff32320da // indirect
|
||||||
google.golang.org/genproto v0.0.0-20200615140333-fd031eab31e7 // indirect
|
google.golang.org/genproto v0.0.0-20200615140333-fd031eab31e7 // indirect
|
||||||
|
google.golang.org/grpc v1.31.1
|
||||||
gopkg.in/ini.v1 v1.57.0 // indirect
|
gopkg.in/ini.v1 v1.57.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.3.0
|
gopkg.in/yaml.v2 v2.3.0
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -131,8 +131,8 @@ github.com/anchore/go-testutils v0.0.0-20200624184116-66aa578126db/go.mod h1:D3r
|
|||||||
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZVsCYMrIZBpFxwV26CbsuoEh5muXD5I1Ods=
|
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b h1:e1bmaoJfZVsCYMrIZBpFxwV26CbsuoEh5muXD5I1Ods=
|
||||||
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E=
|
github.com/anchore/go-version v1.2.2-0.20200701162849-18adb9c92b9b/go.mod h1:Bkc+JYWjMCF8OyZ340IMSIi2Ebf3uwByOk6ho4wne1E=
|
||||||
github.com/anchore/stereoscope v0.0.0-20200520221116-025e07f1c93e/go.mod h1:bkyLl5VITnrmgErv4S1vDfVz/TGAZ5il6161IQo7w2g=
|
github.com/anchore/stereoscope v0.0.0-20200520221116-025e07f1c93e/go.mod h1:bkyLl5VITnrmgErv4S1vDfVz/TGAZ5il6161IQo7w2g=
|
||||||
github.com/anchore/stereoscope v0.0.0-20200813152757-548b22c8a0b3 h1:pl+txuYlhK8Mmio4d+4zQI/1xg8X6BtNErTASrx23Wk=
|
github.com/anchore/stereoscope v0.0.0-20200903223322-a3806f515470 h1:apXyPyfiaL/YQF7VeXRbDDB9TA7dA9rxdq8YbzPk9ko=
|
||||||
github.com/anchore/stereoscope v0.0.0-20200813152757-548b22c8a0b3/go.mod h1:WntReQTI/I27FOQ87UgLVVzWgku6+ZsqfOTLxpIZFCs=
|
github.com/anchore/stereoscope v0.0.0-20200903223322-a3806f515470/go.mod h1:WntReQTI/I27FOQ87UgLVVzWgku6+ZsqfOTLxpIZFCs=
|
||||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||||
github.com/apex/log v1.1.4/go.mod h1:AlpoD9aScyQfJDVHmLMEcx4oU6LqzkWp4Mg9GdAcEvQ=
|
github.com/apex/log v1.1.4/go.mod h1:AlpoD9aScyQfJDVHmLMEcx4oU6LqzkWp4Mg9GdAcEvQ=
|
||||||
github.com/apex/log v1.3.0 h1:1fyfbPvUwD10nMoh3hY6MXzvZShJQn9/ck7ATgAt5pA=
|
github.com/apex/log v1.3.0 h1:1fyfbPvUwD10nMoh3hY6MXzvZShJQn9/ck7ATgAt5pA=
|
||||||
@@ -474,12 +474,18 @@ github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/U
|
|||||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
|
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
|
||||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||||
|
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
|
||||||
|
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
|
||||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||||
|
github.com/hashicorp/go-hclog v0.14.1 h1:nQcJDQwIAGnmoUWp8ubocEX40cCml/17YkF6csQLReU=
|
||||||
|
github.com/hashicorp/go-hclog v0.14.1/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
|
||||||
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
|
||||||
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
|
||||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||||
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
|
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
|
||||||
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
||||||
|
github.com/hashicorp/go-plugin v1.3.0 h1:4d/wJojzvHV1I4i/rrjVaeuyxWrLzDE1mDCyDy8fXS8=
|
||||||
|
github.com/hashicorp/go-plugin v1.3.0/go.mod h1:F9eH4LrE/ZsRdbwhfjs9k9HoDUwAHnYtXdgmf1AVNs0=
|
||||||
github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
github.com/hashicorp/go-retryablehttp v0.6.4/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
||||||
github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM=
|
github.com/hashicorp/go-retryablehttp v0.6.6 h1:HJunrbHTDDbBb/ay4kxa1n+dLmttUlnP3V9oNE4hmsM=
|
||||||
github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
github.com/hashicorp/go-retryablehttp v0.6.6/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER/9wtLZZ8meHqQvEYWY=
|
||||||
@@ -500,6 +506,8 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
|
|||||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||||
|
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb h1:b5rjCoWHc7eqmAS4/qyk21ZsHyb6Mxv/jykxvNTkU4M=
|
||||||
|
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
|
||||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||||
@@ -510,6 +518,8 @@ github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ
|
|||||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
|
github.com/jarcoal/httpmock v1.0.5/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik=
|
||||||
|
github.com/jhump/protoreflect v1.6.0 h1:h5jfMVslIg6l29nsMs0D8Wj17RDVdNYti0vDN/PZZoE=
|
||||||
|
github.com/jhump/protoreflect v1.6.0/go.mod h1:eaTn3RZAmMBcV0fifFvlm6VHNz3wSkYyXYWUh7ymB74=
|
||||||
github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a h1:GmsqmapfzSJkm28dhRoHz2tLRbJmqhU86IPgBtN3mmk=
|
github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a h1:GmsqmapfzSJkm28dhRoHz2tLRbJmqhU86IPgBtN3mmk=
|
||||||
github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a/go.mod h1:xRskid8CManxVta/ALEhJha/pweKBaVG6fWgc0yH25s=
|
github.com/jingyugao/rowserrcheck v0.0.0-20191204022205-72ab7603b68a/go.mod h1:xRskid8CManxVta/ALEhJha/pweKBaVG6fWgc0yH25s=
|
||||||
github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0=
|
github.com/jirfag/go-printf-func-name v0.0.0-20191110105641-45db9963cdd3/go.mod h1:HEWGJkRDzjJY2sqdDwxccsGicWEf9BQOZsq2tV+xzM0=
|
||||||
@@ -589,6 +599,7 @@ github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNx
|
|||||||
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.6/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.6/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
|
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
|
||||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
|
||||||
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
|
||||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
@@ -611,6 +622,8 @@ github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrk
|
|||||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
|
github.com/mitchellh/go-ps v0.0.0-20190716172923-621e5597135b/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
|
||||||
|
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||||
|
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
|
||||||
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
|
||||||
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
|
||||||
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
|
||||||
@@ -639,6 +652,8 @@ github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1
|
|||||||
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
|
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
|
github.com/oklog/run v1.0.0 h1:Ru7dDtJNOyC66gQ5dQmaCa0qIsAUFY3sFpK1Xk8igrw=
|
||||||
|
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||||
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
|
||||||
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
|
github.com/olekukonko/tablewriter v0.0.4 h1:vHD/YYe1Wolo78koG299f7V/VAS08c6IpCLn+Ejf/w8=
|
||||||
@@ -923,6 +938,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||||||
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
@@ -1012,6 +1028,7 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191112214154-59a1497f0cea/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -1148,6 +1165,7 @@ google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww
|
|||||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc=
|
||||||
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||||
|
google.golang.org/genproto v0.0.0-20170818010345-ee236bd376b0/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||||
@@ -1181,6 +1199,7 @@ google.golang.org/genproto v0.0.0-20200604104852-0b0486081ffb h1:ek2py5bOqzR7MR/
|
|||||||
google.golang.org/genproto v0.0.0-20200604104852-0b0486081ffb/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
google.golang.org/genproto v0.0.0-20200604104852-0b0486081ffb/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||||
google.golang.org/genproto v0.0.0-20200615140333-fd031eab31e7 h1:1N7l1PuXZwEK7OhHdmKQROOM75PnUjABGwvVRbLBgFk=
|
google.golang.org/genproto v0.0.0-20200615140333-fd031eab31e7 h1:1N7l1PuXZwEK7OhHdmKQROOM75PnUjABGwvVRbLBgFk=
|
||||||
google.golang.org/genproto v0.0.0-20200615140333-fd031eab31e7/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
google.golang.org/genproto v0.0.0-20200615140333-fd031eab31e7/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
|
||||||
|
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||||
@@ -1195,6 +1214,8 @@ google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
|
|||||||
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||||
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
|
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
|
||||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||||
|
google.golang.org/grpc v1.31.1 h1:SfXqXS5hkufcdZ/mHtYCh53P2b+92WQq/DZcKLgsFRs=
|
||||||
|
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
|
|||||||
@@ -28,7 +28,13 @@ type Application struct {
|
|||||||
Quiet bool `mapstructure:"quiet"`
|
Quiet bool `mapstructure:"quiet"`
|
||||||
Log Logging `mapstructure:"log"`
|
Log Logging `mapstructure:"log"`
|
||||||
CliOptions CliOnlyOptions
|
CliOptions CliOnlyOptions
|
||||||
CheckForAppUpdate bool `mapstructure:"check-for-app-update"`
|
CheckForAppUpdate bool `mapstructure:"check-for-app-update"`
|
||||||
|
Plugins Plugins `mapstructure:"plugins"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Plugins struct {
|
||||||
|
Enabled bool `mapstructure:"enabled"`
|
||||||
|
Directory string `mapstructure:"dir"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Logging struct {
|
type Logging struct {
|
||||||
|
|||||||
+7
-1
@@ -1,6 +1,8 @@
|
|||||||
package log
|
package log
|
||||||
|
|
||||||
import "github.com/anchore/syft/syft/logger"
|
import (
|
||||||
|
"github.com/anchore/syft/syft/logger"
|
||||||
|
)
|
||||||
|
|
||||||
var Log logger.Logger = &nopLogger{}
|
var Log logger.Logger = &nopLogger{}
|
||||||
|
|
||||||
@@ -8,6 +10,10 @@ func Errorf(format string, args ...interface{}) {
|
|||||||
Log.Errorf(format, args...)
|
Log.Errorf(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Error(args ...interface{}) {
|
||||||
|
Log.Error(args...)
|
||||||
|
}
|
||||||
|
|
||||||
func Infof(format string, args ...interface{}) {
|
func Infof(format string, args ...interface{}) {
|
||||||
Log.Infof(format, args...)
|
Log.Infof(format, args...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package log
|
|||||||
type nopLogger struct{}
|
type nopLogger struct{}
|
||||||
|
|
||||||
func (l *nopLogger) Errorf(format string, args ...interface{}) {}
|
func (l *nopLogger) Errorf(format string, args ...interface{}) {}
|
||||||
|
func (l *nopLogger) Error(args ...interface{}) {}
|
||||||
func (l *nopLogger) Infof(format string, args ...interface{}) {}
|
func (l *nopLogger) Infof(format string, args ...interface{}) {}
|
||||||
func (l *nopLogger) Info(args ...interface{}) {}
|
func (l *nopLogger) Info(args ...interface{}) {}
|
||||||
func (l *nopLogger) Debugf(format string, args ...interface{}) {}
|
func (l *nopLogger) Debugf(format string, args ...interface{}) {}
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-hclog"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Source: https://github.com/hashicorp/go-hclog/blob/master/stdlog.go (MIT License)
|
||||||
|
|
||||||
|
// Provides a io.Writer to shim the data out of *log.Logger
|
||||||
|
// and back into our Logger. This is basically the only way to
|
||||||
|
// build upon *log.Logger.
|
||||||
|
type HCLogStdlogAdapter struct {
|
||||||
|
log hclog.Logger
|
||||||
|
inferLevels bool
|
||||||
|
forceLevel hclog.Level
|
||||||
|
}
|
||||||
|
|
||||||
|
// Take the data, infer the levels if configured, and send it through
|
||||||
|
// a regular Logger.
|
||||||
|
func (s *HCLogStdlogAdapter) Write(data []byte) (int, error) {
|
||||||
|
str := string(bytes.TrimRight(data, " \t\n"))
|
||||||
|
|
||||||
|
if s.forceLevel != hclog.NoLevel {
|
||||||
|
// Use pickLevel to strip log levels included in the line since we are
|
||||||
|
// forcing the level
|
||||||
|
_, str := s.pickLevel(str)
|
||||||
|
|
||||||
|
// Log at the forced level
|
||||||
|
s.dispatch(str, s.forceLevel)
|
||||||
|
} else if s.inferLevels {
|
||||||
|
level, str := s.pickLevel(str)
|
||||||
|
s.dispatch(str, level)
|
||||||
|
} else {
|
||||||
|
s.log.Info(str)
|
||||||
|
}
|
||||||
|
|
||||||
|
return len(data), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *HCLogStdlogAdapter) dispatch(str string, level hclog.Level) {
|
||||||
|
switch level {
|
||||||
|
case hclog.Trace:
|
||||||
|
s.log.Trace(str)
|
||||||
|
case hclog.Debug:
|
||||||
|
s.log.Debug(str)
|
||||||
|
case hclog.Info:
|
||||||
|
s.log.Info(str)
|
||||||
|
case hclog.Warn:
|
||||||
|
s.log.Warn(str)
|
||||||
|
case hclog.Error:
|
||||||
|
s.log.Error(str)
|
||||||
|
default:
|
||||||
|
s.log.Info(str)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect, based on conventions, what log level this is.
|
||||||
|
func (s *HCLogStdlogAdapter) pickLevel(str string) (hclog.Level, string) {
|
||||||
|
switch {
|
||||||
|
case strings.HasPrefix(str, "[DEBUG]"):
|
||||||
|
return hclog.Debug, strings.TrimSpace(str[7:])
|
||||||
|
case strings.HasPrefix(str, "[TRACE]"):
|
||||||
|
return hclog.Trace, strings.TrimSpace(str[7:])
|
||||||
|
case strings.HasPrefix(str, "[INFO]"):
|
||||||
|
return hclog.Info, strings.TrimSpace(str[6:])
|
||||||
|
case strings.HasPrefix(str, "[WARN]"):
|
||||||
|
return hclog.Warn, strings.TrimSpace(str[7:])
|
||||||
|
case strings.HasPrefix(str, "[ERROR]"):
|
||||||
|
return hclog.Error, strings.TrimSpace(str[7:])
|
||||||
|
case strings.HasPrefix(str, "[ERR]"):
|
||||||
|
return hclog.Error, strings.TrimSpace(str[5:])
|
||||||
|
default:
|
||||||
|
return hclog.Info, str
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/logger"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-hclog"
|
||||||
|
)
|
||||||
|
|
||||||
|
// integrity check
|
||||||
|
var _ hclog.Logger = &LoggerHCLogAdapter{}
|
||||||
|
|
||||||
|
// LoggerHCLogAdapter is used to (partially) adapt a syft logger.Logger object to the hclog.Logger interface for syft plugins.
|
||||||
|
// Note: this does not implement all functionality required by the hclog.Logger.
|
||||||
|
type LoggerHCLogAdapter struct {
|
||||||
|
Logger logger.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLoggerHCLogAdapter(logger logger.Logger) *LoggerHCLogAdapter {
|
||||||
|
return &LoggerHCLogAdapter{
|
||||||
|
Logger: logger,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Args are alternating key, val pairs
|
||||||
|
// keys must be strings
|
||||||
|
// vals can be any type, but display is implementation specific
|
||||||
|
// Emit a message and key/value pairs at a provided log level
|
||||||
|
func (l *LoggerHCLogAdapter) Log(level hclog.Level, msg string, args ...interface{}) {
|
||||||
|
l.Logger.Info(append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit a message and key/value pairs at the TRACE level
|
||||||
|
func (l *LoggerHCLogAdapter) Trace(msg string, args ...interface{}) {
|
||||||
|
l.Logger.Debug(append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit a message and key/value pairs at the DEBUG level
|
||||||
|
func (l *LoggerHCLogAdapter) Debug(msg string, args ...interface{}) {
|
||||||
|
l.Logger.Debug(append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit a message and key/value pairs at the INFO level
|
||||||
|
func (l *LoggerHCLogAdapter) Info(msg string, args ...interface{}) {
|
||||||
|
l.Logger.Info(append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit a message and key/value pairs at the WARN level
|
||||||
|
func (l *LoggerHCLogAdapter) Warn(msg string, args ...interface{}) {
|
||||||
|
l.Logger.Error(append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit a message and key/value pairs at the ERROR level
|
||||||
|
func (l *LoggerHCLogAdapter) Error(msg string, args ...interface{}) {
|
||||||
|
l.Logger.Error(append([]interface{}{msg}, args...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicate if TRACE logs would be emitted. This and the other Is* guards
|
||||||
|
// are used to elide expensive logging code based on the current level.
|
||||||
|
func (l *LoggerHCLogAdapter) IsTrace() bool {
|
||||||
|
// TODO: not implemented
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicate if DEBUG logs would be emitted. This and the other Is* guards
|
||||||
|
// are used to elide expensive logging code based on the current level.
|
||||||
|
func (l *LoggerHCLogAdapter) IsDebug() bool {
|
||||||
|
// TODO: not implemented
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicate if INFO logs would be emitted. This and the other Is* guards
|
||||||
|
// are used to elide expensive logging code based on the current level.
|
||||||
|
func (l *LoggerHCLogAdapter) IsInfo() bool {
|
||||||
|
// TODO: not implemented
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicate if WARN logs would be emitted. This and the other Is* guards
|
||||||
|
// are used to elide expensive logging code based on the current level.
|
||||||
|
func (l *LoggerHCLogAdapter) IsWarn() bool {
|
||||||
|
// TODO: not implemented
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicate if ERROR logs would be emitted. This and the other Is* guards
|
||||||
|
// are used to elide expensive logging code based on the current level.
|
||||||
|
func (l *LoggerHCLogAdapter) IsError() bool {
|
||||||
|
// TODO: not implemented
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImpliedArgs returns With key/value pairs
|
||||||
|
func (l *LoggerHCLogAdapter) ImpliedArgs() []interface{} {
|
||||||
|
// TODO: not implemented
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a sublogger that will always have the given key/value pairs
|
||||||
|
func (l *LoggerHCLogAdapter) With(args ...interface{}) hclog.Logger {
|
||||||
|
// TODO: not implemented
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the Name of the logger
|
||||||
|
func (l *LoggerHCLogAdapter) Name() string {
|
||||||
|
// TODO: not implemented
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a logger that will prepend the name string on the front of all messages.
|
||||||
|
// If the logger already has a name, the new value will be appended to the current
|
||||||
|
// name. That way, a major subsystem can use this to decorate all it's own logs
|
||||||
|
// without losing context.
|
||||||
|
func (l *LoggerHCLogAdapter) Named(name string) hclog.Logger {
|
||||||
|
// TODO: not implemented
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a logger that will prepend the name string on the front of all messages.
|
||||||
|
// This sets the name of the logger to the value directly, unlike Named which honor
|
||||||
|
// the current name as well.
|
||||||
|
func (l *LoggerHCLogAdapter) ResetNamed(name string) hclog.Logger {
|
||||||
|
// TODO: not implemented
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updates the level. This should affect all sub-loggers as well. If an
|
||||||
|
// implementation cannot update the level on the fly, it should no-op.
|
||||||
|
func (l *LoggerHCLogAdapter) SetLevel(level hclog.Level) {
|
||||||
|
// TODO: not implemented
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a value that conforms to the stdlib log.Logger interface
|
||||||
|
func (l *LoggerHCLogAdapter) StandardLogger(opts *hclog.StandardLoggerOptions) *log.Logger {
|
||||||
|
return log.New(l.StandardWriter(opts), "", log.LstdFlags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a value that conforms to io.Writer, which can be passed into log.SetOutput()
|
||||||
|
func (l *LoggerHCLogAdapter) StandardWriter(opts *hclog.StandardLoggerOptions) io.Writer {
|
||||||
|
return &HCLogStdlogAdapter{
|
||||||
|
log: l,
|
||||||
|
inferLevels: opts.InferLevels,
|
||||||
|
forceLevel: opts.ForceLevel,
|
||||||
|
}
|
||||||
|
}
|
||||||
+25
-12
@@ -6,10 +6,15 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/logger"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
prefixed "github.com/x-cray/logrus-prefixed-formatter"
|
prefixed "github.com/x-cray/logrus-prefixed-formatter"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// integrity check
|
||||||
|
var _ logger.Logger = &LogrusLogger{}
|
||||||
|
var _ logger.Logger = &LogrusNestedLogger{}
|
||||||
|
|
||||||
type LogrusConfig struct {
|
type LogrusConfig struct {
|
||||||
EnableConsole bool
|
EnableConsole bool
|
||||||
EnableFile bool
|
EnableFile bool
|
||||||
@@ -76,42 +81,50 @@ func NewLogrusLogger(cfg LogrusConfig) *LogrusLogger {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LogrusLogger) Debugf(format string, args ...interface{}) {
|
func (l *LogrusLogger) Errorf(format string, args ...interface{}) {
|
||||||
l.Logger.Debugf(format, args...)
|
l.Logger.Errorf(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LogrusLogger) Infof(format string, args ...interface{}) {
|
func (l *LogrusLogger) Infof(format string, args ...interface{}) {
|
||||||
l.Logger.Infof(format, args...)
|
l.Logger.Infof(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LogrusLogger) Debug(args ...interface{}) {
|
func (l *LogrusLogger) Debugf(format string, args ...interface{}) {
|
||||||
l.Logger.Debug(args...)
|
l.Logger.Debugf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LogrusLogger) Error(args ...interface{}) {
|
||||||
|
l.Logger.Error(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LogrusLogger) Info(args ...interface{}) {
|
func (l *LogrusLogger) Info(args ...interface{}) {
|
||||||
l.Logger.Info(args...)
|
l.Logger.Info(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LogrusLogger) Errorf(format string, args ...interface{}) {
|
func (l *LogrusLogger) Debug(args ...interface{}) {
|
||||||
l.Logger.Errorf(format, args...)
|
l.Logger.Debug(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LogrusNestedLogger) Debugf(format string, args ...interface{}) {
|
func (l *LogrusNestedLogger) Errorf(format string, args ...interface{}) {
|
||||||
l.Logger.Debugf(format, args...)
|
l.Logger.Errorf(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LogrusNestedLogger) Infof(format string, args ...interface{}) {
|
func (l *LogrusNestedLogger) Infof(format string, args ...interface{}) {
|
||||||
l.Logger.Infof(format, args...)
|
l.Logger.Infof(format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LogrusNestedLogger) Debug(args ...interface{}) {
|
func (l *LogrusNestedLogger) Debugf(format string, args ...interface{}) {
|
||||||
l.Logger.Debug(args...)
|
l.Logger.Debugf(format, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LogrusNestedLogger) Error(args ...interface{}) {
|
||||||
|
l.Logger.Error(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LogrusNestedLogger) Info(args ...interface{}) {
|
func (l *LogrusNestedLogger) Info(args ...interface{}) {
|
||||||
l.Logger.Info(args...)
|
l.Logger.Info(args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *LogrusNestedLogger) Errorf(format string, args ...interface{}) {
|
func (l *LogrusNestedLogger) Debug(args ...interface{}) {
|
||||||
l.Logger.Errorf(format, args...)
|
l.Logger.Debug(args...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,181 @@
|
|||||||
|
package logger
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-hclog"
|
||||||
|
"github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
// integrity check
|
||||||
|
var _ hclog.Logger = &LogrusHCLogAdapter{}
|
||||||
|
|
||||||
|
var levels = map[hclog.Level]logrus.Level{
|
||||||
|
hclog.NoLevel: logrus.PanicLevel,
|
||||||
|
hclog.Error: logrus.ErrorLevel,
|
||||||
|
hclog.Warn: logrus.WarnLevel,
|
||||||
|
hclog.Info: logrus.InfoLevel,
|
||||||
|
hclog.Debug: logrus.DebugLevel,
|
||||||
|
hclog.Trace: logrus.TraceLevel,
|
||||||
|
}
|
||||||
|
|
||||||
|
// LogrusHCLogAdapter is used to adapt a logrus logger object to the hclog.Logger interface for syft plugins.
|
||||||
|
type LogrusHCLogAdapter struct {
|
||||||
|
logger *logrus.Logger
|
||||||
|
entry *logrus.Entry
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLogrusHCLogAdapter(logger *logrus.Logger, fields map[string]interface{}) *LogrusHCLogAdapter {
|
||||||
|
if fields != nil {
|
||||||
|
return &LogrusHCLogAdapter{
|
||||||
|
logger: logger,
|
||||||
|
entry: logger.WithFields(fields),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &LogrusHCLogAdapter{
|
||||||
|
logger: logger,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *LogrusHCLogAdapter) log(level hclog.Level, msg string, args ...interface{}) {
|
||||||
|
if l.entry != nil {
|
||||||
|
l.entry.WithFields(makeArgFields(args...)).Log(levels[level], msg)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
l.logger.WithFields(makeArgFields(args...)).Log(levels[level], msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Args are alternating key, val pairs
|
||||||
|
// keys must be strings
|
||||||
|
// vals can be any type, but display is implementation specific
|
||||||
|
// Emit a message and key/value pairs at a provided log level
|
||||||
|
func (l *LogrusHCLogAdapter) Log(level hclog.Level, msg string, args ...interface{}) {
|
||||||
|
l.log(level, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit a message and key/value pairs at the TRACE level
|
||||||
|
func (l *LogrusHCLogAdapter) Trace(msg string, args ...interface{}) {
|
||||||
|
l.log(hclog.Trace, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit a message and key/value pairs at the DEBUG level
|
||||||
|
func (l *LogrusHCLogAdapter) Debug(msg string, args ...interface{}) {
|
||||||
|
l.log(hclog.Debug, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit a message and key/value pairs at the INFO level
|
||||||
|
func (l *LogrusHCLogAdapter) Info(msg string, args ...interface{}) {
|
||||||
|
l.log(hclog.Info, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit a message and key/value pairs at the WARN level
|
||||||
|
func (l *LogrusHCLogAdapter) Warn(msg string, args ...interface{}) {
|
||||||
|
l.log(hclog.Warn, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Emit a message and key/value pairs at the ERROR level
|
||||||
|
func (l *LogrusHCLogAdapter) Error(msg string, args ...interface{}) {
|
||||||
|
l.log(hclog.Error, msg, args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicate if TRACE logs would be emitted. This and the other Is* guards
|
||||||
|
// are used to elide expensive logging code based on the current level.
|
||||||
|
func (l *LogrusHCLogAdapter) IsTrace() bool {
|
||||||
|
return l.logger.Level <= logrus.TraceLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicate if DEBUG logs would be emitted. This and the other Is* guards
|
||||||
|
// are used to elide expensive logging code based on the current level.
|
||||||
|
func (l *LogrusHCLogAdapter) IsDebug() bool {
|
||||||
|
return l.logger.Level <= logrus.DebugLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicate if INFO logs would be emitted. This and the other Is* guards
|
||||||
|
// are used to elide expensive logging code based on the current level.
|
||||||
|
func (l *LogrusHCLogAdapter) IsInfo() bool {
|
||||||
|
return l.logger.Level <= logrus.InfoLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicate if WARN logs would be emitted. This and the other Is* guards
|
||||||
|
// are used to elide expensive logging code based on the current level.
|
||||||
|
func (l *LogrusHCLogAdapter) IsWarn() bool {
|
||||||
|
return l.logger.Level <= logrus.WarnLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
// Indicate if ERROR logs would be emitted. This and the other Is* guards
|
||||||
|
// are used to elide expensive logging code based on the current level.
|
||||||
|
func (l *LogrusHCLogAdapter) IsError() bool {
|
||||||
|
return l.logger.Level <= logrus.ErrorLevel
|
||||||
|
}
|
||||||
|
|
||||||
|
// ImpliedArgs returns With key/value pairs
|
||||||
|
func (l *LogrusHCLogAdapter) ImpliedArgs() []interface{} {
|
||||||
|
// TODO: not implemented
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a sublogger that will always have the given key/value pairs
|
||||||
|
func (l *LogrusHCLogAdapter) With(args ...interface{}) hclog.Logger {
|
||||||
|
l.entry = l.logger.WithFields(makeArgFields(args...))
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the Name of the logger
|
||||||
|
func (l *LogrusHCLogAdapter) Name() string {
|
||||||
|
// TODO: not implemented
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a logger that will prepend the name string on the front of all messages.
|
||||||
|
// If the logger already has a name, the new value will be appended to the current
|
||||||
|
// name. That way, a major subsystem can use this to decorate all it's own logs
|
||||||
|
// without losing context.
|
||||||
|
func (l *LogrusHCLogAdapter) Named(name string) hclog.Logger {
|
||||||
|
return NewLogrusHCLogAdapter(l.logger, logrus.Fields{"name": name})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a logger that will prepend the name string on the front of all messages.
|
||||||
|
// This sets the name of the logger to the value directly, unlike Named which honor
|
||||||
|
// the current name as well.
|
||||||
|
func (l *LogrusHCLogAdapter) ResetNamed(name string) hclog.Logger {
|
||||||
|
return NewLogrusHCLogAdapter(l.logger, logrus.Fields{"name": name})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Updates the level. This should affect all sub-loggers as well. If an
|
||||||
|
// implementation cannot update the level on the fly, it should no-op.
|
||||||
|
func (l *LogrusHCLogAdapter) SetLevel(level hclog.Level) {
|
||||||
|
l.logger.SetLevel(levels[level])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a value that conforms to the stdlib log.Logger interface
|
||||||
|
func (l *LogrusHCLogAdapter) StandardLogger(opts *hclog.StandardLoggerOptions) *log.Logger {
|
||||||
|
return log.New(l.StandardWriter(opts), "", log.LstdFlags)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return a value that conforms to io.Writer, which can be passed into log.SetOutput()
|
||||||
|
func (l *LogrusHCLogAdapter) StandardWriter(opts *hclog.StandardLoggerOptions) io.Writer {
|
||||||
|
return &HCLogStdlogAdapter{
|
||||||
|
log: l,
|
||||||
|
inferLevels: opts.InferLevels,
|
||||||
|
forceLevel: opts.ForceLevel,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeArgFields(args ...interface{}) logrus.Fields {
|
||||||
|
if len(args)%2 != 0 {
|
||||||
|
panic(fmt.Errorf("odd number of logger key-value pairs (%d): %+v", len(args), args))
|
||||||
|
}
|
||||||
|
|
||||||
|
var key string
|
||||||
|
var fields = make(logrus.Fields)
|
||||||
|
for i, arg := range args {
|
||||||
|
if i%2 == 0 {
|
||||||
|
key = arg.(string)
|
||||||
|
} else {
|
||||||
|
fields[key] = arg
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fields
|
||||||
|
}
|
||||||
@@ -4,6 +4,8 @@ Package apkdb provides a concrete Cataloger implementation for Alpine DB files.
|
|||||||
package apkdb
|
package apkdb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/anchore/stereoscope/pkg/file"
|
"github.com/anchore/stereoscope/pkg/file"
|
||||||
"github.com/anchore/syft/syft/cataloger/common"
|
"github.com/anchore/syft/syft/cataloger/common"
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
@@ -27,16 +29,16 @@ func New() *Cataloger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Name returns a string that uniquely describes this cataloger.
|
// Name returns a string that uniquely describes this cataloger.
|
||||||
func (a *Cataloger) Name() string {
|
func (c *Cataloger) Name() string {
|
||||||
return "apkdb-cataloger"
|
return "apkdb-cataloger"
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectFiles returns a set of discovered Alpine DB files from the user content source.
|
// SelectFiles returns a set of discovered Alpine DB files from the user content source.
|
||||||
func (a *Cataloger) SelectFiles(resolver scope.FileResolver) []file.Reference {
|
func (c *Cataloger) SelectFiles(resolver scope.FileResolver) []file.Reference {
|
||||||
return a.cataloger.SelectFiles(resolver)
|
return c.cataloger.SelectFiles(resolver)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Catalog returns the Packages indexed from all Alpine DB files discovered.
|
// Catalog returns the Packages indexed from all Alpine DB files discovered.
|
||||||
func (a *Cataloger) Catalog(contents map[file.Reference]string) ([]pkg.Package, error) {
|
func (c *Cataloger) Catalog(contents map[file.Reference]io.Reader) ([]pkg.Package, error) {
|
||||||
return a.cataloger.Catalog(contents, a.Name())
|
return c.cataloger.Catalog(contents)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ Package bundler provides a concrete Cataloger implementation for Ruby Gemfile.lo
|
|||||||
package bundler
|
package bundler
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/anchore/stereoscope/pkg/file"
|
"github.com/anchore/stereoscope/pkg/file"
|
||||||
"github.com/anchore/syft/syft/cataloger/common"
|
"github.com/anchore/syft/syft/cataloger/common"
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
@@ -27,16 +29,16 @@ func New() *Cataloger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Name returns a string that uniquely describes this cataloger.
|
// Name returns a string that uniquely describes this cataloger.
|
||||||
func (a *Cataloger) Name() string {
|
func (c *Cataloger) Name() string {
|
||||||
return "bundler-cataloger"
|
return "bundler-cataloger"
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectFiles returns a set of discovered Gemfile.lock files from the user content source.
|
// SelectFiles returns a set of discovered Gemfile.lock files from the user content source.
|
||||||
func (a *Cataloger) SelectFiles(resolver scope.FileResolver) []file.Reference {
|
func (c *Cataloger) SelectFiles(resolver scope.FileResolver) []file.Reference {
|
||||||
return a.cataloger.SelectFiles(resolver)
|
return c.cataloger.SelectFiles(resolver)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Catalog returns the Packages indexed from all Gemfile.lock files discovered.
|
// Catalog returns the Packages indexed from all Gemfile.lock files discovered.
|
||||||
func (a *Cataloger) Catalog(contents map[file.Reference]string) ([]pkg.Package, error) {
|
func (c *Cataloger) Catalog(contents map[file.Reference]io.Reader) ([]pkg.Package, error) {
|
||||||
return a.cataloger.Catalog(contents, a.Name())
|
return c.cataloger.Catalog(contents)
|
||||||
}
|
}
|
||||||
|
|||||||
+55
-52
@@ -12,6 +12,61 @@ import (
|
|||||||
"github.com/wagoodman/go-progress"
|
"github.com/wagoodman/go-progress"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Catalog a given scope (container image or filesystem) with the given catalogers, returning all discovered packages.
|
||||||
|
// In order to efficiently retrieve contents from a underlying container image the content fetch requests are
|
||||||
|
// done in bulk. Specifically, all files of interest are collected from each catalogers and accumulated into a single
|
||||||
|
// request.
|
||||||
|
func Catalog(resolver scope.Resolver, catalogers ...Cataloger) (*pkg.Catalog, error) {
|
||||||
|
catalog := pkg.NewCatalog()
|
||||||
|
fileSelection := make([]file.Reference, 0)
|
||||||
|
|
||||||
|
filesProcessed, packagesDiscovered := newMonitor()
|
||||||
|
|
||||||
|
// ask catalogers for files to extract from the image tar
|
||||||
|
for _, a := range catalogers {
|
||||||
|
catalogerSelection := a.SelectFiles(resolver)
|
||||||
|
fileSelection = append(fileSelection, catalogerSelection...)
|
||||||
|
log.Debugf("cataloger '%s' selected '%d' files", a.Name(), len(catalogerSelection))
|
||||||
|
filesProcessed.N += int64(len(fileSelection))
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch contents for requested selection by catalogers
|
||||||
|
// TODO: we should consider refactoring to return a set of io.Readers instead of the full contents themselves (allow for optional buffering).
|
||||||
|
contents, err := resolver.MultipleFileContentsByRef(fileSelection...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// perform analysis, accumulating errors for each failed analysis
|
||||||
|
var errs error
|
||||||
|
for _, c := range catalogers {
|
||||||
|
// TODO: check for multiple rounds of analyses by Iterate error
|
||||||
|
packages, err := c.Catalog(contents)
|
||||||
|
if err != nil {
|
||||||
|
errs = multierror.Append(errs, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("cataloger '%s' discovered '%d' packages", c.Name(), len(packages))
|
||||||
|
packagesDiscovered.N += int64(len(packages))
|
||||||
|
|
||||||
|
catalogerName := c.Name()
|
||||||
|
for _, p := range packages {
|
||||||
|
p.FoundBy = catalogerName
|
||||||
|
catalog.Add(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if errs != nil {
|
||||||
|
return nil, errs
|
||||||
|
}
|
||||||
|
|
||||||
|
filesProcessed.SetCompleted()
|
||||||
|
packagesDiscovered.SetCompleted()
|
||||||
|
|
||||||
|
return catalog, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Monitor provides progress-related data for observing the progress of a Catalog() call (published on the event bus).
|
// Monitor provides progress-related data for observing the progress of a Catalog() call (published on the event bus).
|
||||||
type Monitor struct {
|
type Monitor struct {
|
||||||
FilesProcessed progress.Monitorable // the number of files selected and contents analyzed from all registered catalogers
|
FilesProcessed progress.Monitorable // the number of files selected and contents analyzed from all registered catalogers
|
||||||
@@ -32,55 +87,3 @@ func newMonitor() (*progress.Manual, *progress.Manual) {
|
|||||||
})
|
})
|
||||||
return &filesProcessed, &packagesDiscovered
|
return &filesProcessed, &packagesDiscovered
|
||||||
}
|
}
|
||||||
|
|
||||||
// Catalog a given scope (container image or filesystem) with the given catalogers, returning all discovered packages.
|
|
||||||
// In order to efficiently retrieve contents from a underlying container image the content fetch requests are
|
|
||||||
// done in bulk. Specifically, all files of interest are collected from each catalogers and accumulated into a single
|
|
||||||
// request.
|
|
||||||
func Catalog(resolver scope.Resolver, catalogers ...Cataloger) (*pkg.Catalog, error) {
|
|
||||||
catalog := pkg.NewCatalog()
|
|
||||||
fileSelection := make([]file.Reference, 0)
|
|
||||||
|
|
||||||
filesProcessed, packagesDiscovered := newMonitor()
|
|
||||||
|
|
||||||
// ask catalogers for files to extract from the image tar
|
|
||||||
for _, a := range catalogers {
|
|
||||||
fileSelection = append(fileSelection, a.SelectFiles(resolver)...)
|
|
||||||
log.Debugf("cataloger '%s' selected '%d' files", a.Name(), len(fileSelection))
|
|
||||||
filesProcessed.N += int64(len(fileSelection))
|
|
||||||
}
|
|
||||||
|
|
||||||
// fetch contents for requested selection by catalogers
|
|
||||||
// TODO: we should consider refactoring to return a set of io.Readers instead of the full contents themselves (allow for optional buffering).
|
|
||||||
contents, err := resolver.MultipleFileContentsByRef(fileSelection...)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// perform analysis, accumulating errors for each failed analysis
|
|
||||||
var errs error
|
|
||||||
for _, a := range catalogers {
|
|
||||||
// TODO: check for multiple rounds of analyses by Iterate error
|
|
||||||
packages, err := a.Catalog(contents)
|
|
||||||
if err != nil {
|
|
||||||
errs = multierror.Append(errs, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("cataloger '%s' discovered '%d' packages", a.Name(), len(packages))
|
|
||||||
packagesDiscovered.N += int64(len(packages))
|
|
||||||
|
|
||||||
for _, p := range packages {
|
|
||||||
catalog.Add(p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if errs != nil {
|
|
||||||
return nil, errs
|
|
||||||
}
|
|
||||||
|
|
||||||
filesProcessed.SetCompleted()
|
|
||||||
packagesDiscovered.SetCompleted()
|
|
||||||
|
|
||||||
return catalog, nil
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -6,10 +6,13 @@ catalogers defined in child packages as well as the interface definition to impl
|
|||||||
package cataloger
|
package cataloger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/cataloger/dpkg"
|
||||||
|
|
||||||
"github.com/anchore/stereoscope/pkg/file"
|
"github.com/anchore/stereoscope/pkg/file"
|
||||||
"github.com/anchore/syft/syft/cataloger/apkdb"
|
"github.com/anchore/syft/syft/cataloger/apkdb"
|
||||||
"github.com/anchore/syft/syft/cataloger/bundler"
|
"github.com/anchore/syft/syft/cataloger/bundler"
|
||||||
"github.com/anchore/syft/syft/cataloger/dpkg"
|
|
||||||
"github.com/anchore/syft/syft/cataloger/golang"
|
"github.com/anchore/syft/syft/cataloger/golang"
|
||||||
"github.com/anchore/syft/syft/cataloger/java"
|
"github.com/anchore/syft/syft/cataloger/java"
|
||||||
"github.com/anchore/syft/syft/cataloger/javascript"
|
"github.com/anchore/syft/syft/cataloger/javascript"
|
||||||
@@ -28,13 +31,12 @@ type Cataloger interface {
|
|||||||
// SelectFiles discovers and returns specific files that the cataloger would like to inspect the contents of.
|
// SelectFiles discovers and returns specific files that the cataloger would like to inspect the contents of.
|
||||||
SelectFiles(scope.FileResolver) []file.Reference
|
SelectFiles(scope.FileResolver) []file.Reference
|
||||||
// Catalog is given the file contents and should return any discovered Packages after analyzing the contents.
|
// Catalog is given the file contents and should return any discovered Packages after analyzing the contents.
|
||||||
Catalog(map[file.Reference]string) ([]pkg.Package, error)
|
Catalog(map[file.Reference]io.Reader) ([]pkg.Package, error)
|
||||||
// TODO: add "IterationNeeded" error to indicate to the driver to continue with another Select/Catalog pass
|
// TODO: add "IterationNeeded" error to indicate to the driver to continue with another Select/Catalog pass
|
||||||
// TODO: we should consider refactoring to return a set of io.Readers instead of the full contents themselves (allow for optional buffering).
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// All returns a slice of all locally defined catalogers (defined in child packages).
|
// All returns a slice of all locally defined catalogers (defined in child packages).
|
||||||
func All() []Cataloger {
|
func BuiltIn() []Cataloger {
|
||||||
return []Cataloger{
|
return []Cataloger{
|
||||||
dpkg.New(),
|
dpkg.New(),
|
||||||
bundler.New(),
|
bundler.New(),
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ Package common provides generic utilities used by multiple catalogers.
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"io"
|
||||||
|
|
||||||
"github.com/anchore/stereoscope/pkg/file"
|
"github.com/anchore/stereoscope/pkg/file"
|
||||||
"github.com/anchore/syft/internal/log"
|
"github.com/anchore/syft/internal/log"
|
||||||
@@ -73,7 +73,7 @@ func (a *GenericCataloger) SelectFiles(resolver scope.FileResolver) []file.Refer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Catalog takes a set of file contents and uses any configured parser functions to resolve and return discovered packages
|
// Catalog takes a set of file contents and uses any configured parser functions to resolve and return discovered packages
|
||||||
func (a *GenericCataloger) Catalog(contents map[file.Reference]string, upstreamMatcher string) ([]pkg.Package, error) {
|
func (a *GenericCataloger) Catalog(contents map[file.Reference]io.Reader) ([]pkg.Package, error) {
|
||||||
defer a.clear()
|
defer a.clear()
|
||||||
|
|
||||||
packages := make([]pkg.Package, 0)
|
packages := make([]pkg.Package, 0)
|
||||||
@@ -81,19 +81,18 @@ func (a *GenericCataloger) Catalog(contents map[file.Reference]string, upstreamM
|
|||||||
for reference, parser := range a.parsers {
|
for reference, parser := range a.parsers {
|
||||||
content, ok := contents[reference]
|
content, ok := contents[reference]
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Errorf("cataloger '%s' missing file content: %+v", upstreamMatcher, reference)
|
log.Errorf("cataloger missing file content: %+v", reference)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
entries, err := parser(string(reference.Path), strings.NewReader(content))
|
entries, err := parser(string(reference.Path), content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO: should we fail? or only log?
|
// TODO: should we fail? or only log?
|
||||||
log.Errorf("cataloger '%s' failed to parse entries (reference=%+v): %w", upstreamMatcher, reference, err)
|
log.Errorf("cataloger failed to parse entries (reference=%+v): %w", reference, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, entry := range entries {
|
for _, entry := range entries {
|
||||||
entry.FoundBy = upstreamMatcher
|
|
||||||
entry.Source = []file.Reference{reference}
|
entry.Source = []file.Reference{reference}
|
||||||
|
|
||||||
packages = append(packages, entry)
|
packages = append(packages, entry)
|
||||||
|
|||||||
@@ -79,17 +79,15 @@ func TestGenericCataloger(t *testing.T) {
|
|||||||
selectionByPath[string(s.Path)] = s
|
selectionByPath[string(s.Path)] = s
|
||||||
}
|
}
|
||||||
|
|
||||||
upstream := "some-other-cataloger"
|
|
||||||
expectedPkgs := make(map[file.Reference]pkg.Package)
|
expectedPkgs := make(map[file.Reference]pkg.Package)
|
||||||
for path, ref := range selectionByPath {
|
for path, ref := range selectionByPath {
|
||||||
expectedPkgs[ref] = pkg.Package{
|
expectedPkgs[ref] = pkg.Package{
|
||||||
FoundBy: upstream,
|
Source: []file.Reference{ref},
|
||||||
Source: []file.Reference{ref},
|
Name: fmt.Sprintf("%s file contents!", path),
|
||||||
Name: fmt.Sprintf("%s file contents!", path),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
actualPkgs, err := cataloger.Catalog(resolver.contents, upstream)
|
actualPkgs, err := cataloger.Catalog(resolver.contents)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("cataloger catalog action failed: %+v", err)
|
t.Fatalf("cataloger catalog action failed: %+v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ Package dpkg provides a concrete Cataloger implementation for Debian package DB
|
|||||||
package dpkg
|
package dpkg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/anchore/stereoscope/pkg/file"
|
"github.com/anchore/stereoscope/pkg/file"
|
||||||
"github.com/anchore/syft/syft/cataloger/common"
|
"github.com/anchore/syft/syft/cataloger/common"
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
@@ -27,16 +29,16 @@ func New() *Cataloger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Name returns a string that uniquely describes this cataloger.
|
// Name returns a string that uniquely describes this cataloger.
|
||||||
func (a *Cataloger) Name() string {
|
func (c *Cataloger) Name() string {
|
||||||
return "dpkg-cataloger"
|
return "dpkg-cataloger"
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectFiles returns a set of discovered DPKG status files from the user content source.
|
// SelectFiles returns a set of discovered DPKG status files from the user content source.
|
||||||
func (a *Cataloger) SelectFiles(resolver scope.FileResolver) []file.Reference {
|
func (c *Cataloger) SelectFiles(resolver scope.FileResolver) []file.Reference {
|
||||||
return a.cataloger.SelectFiles(resolver)
|
return c.cataloger.SelectFiles(resolver)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Catalog returns the Packages indexed from all DPKG status files discovered.
|
// Catalog returns the Packages indexed from all DPKG status files discovered.
|
||||||
func (a *Cataloger) Catalog(contents map[file.Reference]string) ([]pkg.Package, error) {
|
func (c *Cataloger) Catalog(contents map[file.Reference]io.Reader) ([]pkg.Package, error) {
|
||||||
return a.cataloger.Catalog(contents, a.Name())
|
return c.cataloger.Catalog(contents)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ Package golang provides a concrete Cataloger implementation for go.mod files.
|
|||||||
package golang
|
package golang
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/anchore/stereoscope/pkg/file"
|
"github.com/anchore/stereoscope/pkg/file"
|
||||||
"github.com/anchore/syft/syft/cataloger/common"
|
"github.com/anchore/syft/syft/cataloger/common"
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
@@ -27,16 +29,16 @@ func New() *Cataloger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Name returns a string that uniquely describes this cataloger.
|
// Name returns a string that uniquely describes this cataloger.
|
||||||
func (a *Cataloger) Name() string {
|
func (c *Cataloger) Name() string {
|
||||||
return "go-cataloger"
|
return "go-cataloger"
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectFiles returns a set of discovered go.mod files from the user content source.
|
// SelectFiles returns a set of discovered go.mod files from the user content source.
|
||||||
func (a *Cataloger) SelectFiles(resolver scope.FileResolver) []file.Reference {
|
func (c *Cataloger) SelectFiles(resolver scope.FileResolver) []file.Reference {
|
||||||
return a.cataloger.SelectFiles(resolver)
|
return c.cataloger.SelectFiles(resolver)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Catalog returns the Packages indexed from all go.mod files discovered.
|
// Catalog returns the Packages indexed from all go.mod files discovered.
|
||||||
func (a *Cataloger) Catalog(contents map[file.Reference]string) ([]pkg.Package, error) {
|
func (c *Cataloger) Catalog(contents map[file.Reference]io.Reader) ([]pkg.Package, error) {
|
||||||
return a.cataloger.Catalog(contents, a.Name())
|
return c.cataloger.Catalog(contents)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ Package java provides a concrete Cataloger implementation for Java archives (jar
|
|||||||
package java
|
package java
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/anchore/stereoscope/pkg/file"
|
"github.com/anchore/stereoscope/pkg/file"
|
||||||
"github.com/anchore/syft/syft/cataloger/common"
|
"github.com/anchore/syft/syft/cataloger/common"
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
@@ -28,16 +30,16 @@ func New() *Cataloger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Name returns a string that uniquely describes this cataloger.
|
// Name returns a string that uniquely describes this cataloger.
|
||||||
func (a *Cataloger) Name() string {
|
func (c *Cataloger) Name() string {
|
||||||
return "java-cataloger"
|
return "java-cataloger"
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectFiles returns a set of discovered Java archive files from the user content source.
|
// SelectFiles returns a set of discovered Java archive files from the user content source.
|
||||||
func (a *Cataloger) SelectFiles(resolver scope.FileResolver) []file.Reference {
|
func (c *Cataloger) SelectFiles(resolver scope.FileResolver) []file.Reference {
|
||||||
return a.cataloger.SelectFiles(resolver)
|
return c.cataloger.SelectFiles(resolver)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Catalog returns the Packages indexed from all Java archive files discovered.
|
// Catalog returns the Packages indexed from all Java archive files discovered.
|
||||||
func (a *Cataloger) Catalog(contents map[file.Reference]string) ([]pkg.Package, error) {
|
func (c *Cataloger) Catalog(contents map[file.Reference]io.Reader) ([]pkg.Package, error) {
|
||||||
return a.cataloger.Catalog(contents, a.Name())
|
return c.cataloger.Catalog(contents)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ Package javascript provides a concrete Cataloger implementation for JavaScript e
|
|||||||
package javascript
|
package javascript
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/anchore/stereoscope/pkg/file"
|
"github.com/anchore/stereoscope/pkg/file"
|
||||||
"github.com/anchore/syft/syft/cataloger/common"
|
"github.com/anchore/syft/syft/cataloger/common"
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
@@ -28,16 +30,16 @@ func New() *Cataloger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Name returns a string that uniquely describes this cataloger.
|
// Name returns a string that uniquely describes this cataloger.
|
||||||
func (a *Cataloger) Name() string {
|
func (c *Cataloger) Name() string {
|
||||||
return "javascript-cataloger"
|
return "javascript-cataloger"
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectFiles returns a set of discovered Javascript ecosystem files from the user content source.
|
// SelectFiles returns a set of discovered Javascript ecosystem files from the user content source.
|
||||||
func (a *Cataloger) SelectFiles(resolver scope.FileResolver) []file.Reference {
|
func (c *Cataloger) SelectFiles(resolver scope.FileResolver) []file.Reference {
|
||||||
return a.cataloger.SelectFiles(resolver)
|
return c.cataloger.SelectFiles(resolver)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Catalog returns the Packages indexed from all Javascript ecosystem files discovered.
|
// Catalog returns the Packages indexed from all Javascript ecosystem files discovered.
|
||||||
func (a *Cataloger) Catalog(contents map[file.Reference]string) ([]pkg.Package, error) {
|
func (c *Cataloger) Catalog(contents map[file.Reference]io.Reader) ([]pkg.Package, error) {
|
||||||
return a.cataloger.Catalog(contents, a.Name())
|
return c.cataloger.Catalog(contents)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ Package python provides a concrete Cataloger implementation for Python ecosystem
|
|||||||
package python
|
package python
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/anchore/stereoscope/pkg/file"
|
"github.com/anchore/stereoscope/pkg/file"
|
||||||
"github.com/anchore/syft/syft/cataloger/common"
|
"github.com/anchore/syft/syft/cataloger/common"
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
@@ -31,16 +33,16 @@ func New() *Cataloger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Name returns a string that uniquely describes this cataloger.
|
// Name returns a string that uniquely describes this cataloger.
|
||||||
func (a *Cataloger) Name() string {
|
func (c *Cataloger) Name() string {
|
||||||
return "python-cataloger"
|
return "python-cataloger"
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectFiles returns a set of discovered Python ecosystem files from the user content source.
|
// SelectFiles returns a set of discovered Python ecosystem files from the user content source.
|
||||||
func (a *Cataloger) SelectFiles(resolver scope.FileResolver) []file.Reference {
|
func (c *Cataloger) SelectFiles(resolver scope.FileResolver) []file.Reference {
|
||||||
return a.cataloger.SelectFiles(resolver)
|
return c.cataloger.SelectFiles(resolver)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Catalog returns the Packages indexed from all Python ecosystem files discovered.
|
// Catalog returns the Packages indexed from all Python ecosystem files discovered.
|
||||||
func (a *Cataloger) Catalog(contents map[file.Reference]string) ([]pkg.Package, error) {
|
func (c *Cataloger) Catalog(contents map[file.Reference]io.Reader) ([]pkg.Package, error) {
|
||||||
return a.cataloger.Catalog(contents, a.Name())
|
return c.cataloger.Catalog(contents)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ Package rpmdb provides a concrete Cataloger implementation for RPM "Package" DB
|
|||||||
package rpmdb
|
package rpmdb
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/anchore/stereoscope/pkg/file"
|
"github.com/anchore/stereoscope/pkg/file"
|
||||||
"github.com/anchore/syft/syft/cataloger/common"
|
"github.com/anchore/syft/syft/cataloger/common"
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
@@ -27,16 +29,16 @@ func New() *Cataloger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Name returns a string that uniquely describes this cataloger.
|
// Name returns a string that uniquely describes this cataloger.
|
||||||
func (a *Cataloger) Name() string {
|
func (c *Cataloger) Name() string {
|
||||||
return "rpmdb-cataloger"
|
return "rpmdb-cataloger"
|
||||||
}
|
}
|
||||||
|
|
||||||
// SelectFiles returns a set of discovered RPM DB files from the user content source.
|
// SelectFiles returns a set of discovered RPM DB files from the user content source.
|
||||||
func (a *Cataloger) SelectFiles(resolver scope.FileResolver) []file.Reference {
|
func (c *Cataloger) SelectFiles(resolver scope.FileResolver) []file.Reference {
|
||||||
return a.cataloger.SelectFiles(resolver)
|
return c.cataloger.SelectFiles(resolver)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Catalog returns the Packages indexed from all RPM DB files discovered.
|
// Catalog returns the Packages indexed from all RPM DB files discovered.
|
||||||
func (a *Cataloger) Catalog(contents map[file.Reference]string) ([]pkg.Package, error) {
|
func (c *Cataloger) Catalog(contents map[file.Reference]io.Reader) ([]pkg.Package, error) {
|
||||||
return a.cataloger.Catalog(contents, a.Name())
|
return c.cataloger.Catalog(contents)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,13 +10,35 @@ import (
|
|||||||
"github.com/anchore/syft/syft/distro"
|
"github.com/anchore/syft/syft/distro"
|
||||||
"github.com/anchore/syft/syft/logger"
|
"github.com/anchore/syft/syft/logger"
|
||||||
"github.com/anchore/syft/syft/pkg"
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/plugin"
|
||||||
"github.com/anchore/syft/syft/scope"
|
"github.com/anchore/syft/syft/scope"
|
||||||
"github.com/wagoodman/go-partybus"
|
"github.com/wagoodman/go-partybus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
PluginDirectory string
|
||||||
|
}
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
config Config
|
||||||
|
plugins *plugin.Repository
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewClient(config Config) (Client, error) {
|
||||||
|
plugins, err := plugin.NewRepositoryFromDirectory(config.PluginDirectory)
|
||||||
|
if err != nil {
|
||||||
|
return Client{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return Client{
|
||||||
|
config: config,
|
||||||
|
plugins: plugins,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Catalog the given image from a particular perspective (e.g. squashed scope, all-layers scope). Returns the discovered
|
// Catalog the given image from a particular perspective (e.g. squashed scope, all-layers scope). Returns the discovered
|
||||||
// set of packages, the identified Linux distribution, and the scope object used to wrap the data source.
|
// set of packages, the identified Linux distribution, and the scope object used to wrap the data source.
|
||||||
func Catalog(userInput string, scoptOpt scope.Option) (*pkg.Catalog, *scope.Scope, *distro.Distro, error) {
|
func (c *Client) Catalog(userInput string, scoptOpt scope.Option) (*pkg.Catalog, *scope.Scope, *distro.Distro, error) {
|
||||||
log.Info("cataloging image")
|
log.Info("cataloging image")
|
||||||
s, cleanup, err := scope.NewScope(userInput, scoptOpt)
|
s, cleanup, err := scope.NewScope(userInput, scoptOpt)
|
||||||
defer cleanup()
|
defer cleanup()
|
||||||
@@ -24,9 +46,9 @@ func Catalog(userInput string, scoptOpt scope.Option) (*pkg.Catalog, *scope.Scop
|
|||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
d := IdentifyDistro(s)
|
d := c.IdentifyDistro(s)
|
||||||
|
|
||||||
catalog, err := CatalogFromScope(s)
|
catalog, err := c.CatalogFromScope(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, nil, err
|
return nil, nil, nil, err
|
||||||
}
|
}
|
||||||
@@ -36,7 +58,7 @@ func Catalog(userInput string, scoptOpt scope.Option) (*pkg.Catalog, *scope.Scop
|
|||||||
|
|
||||||
// IdentifyDistro attempts to discover what the underlying Linux distribution may be from the available flat files
|
// IdentifyDistro attempts to discover what the underlying Linux distribution may be from the available flat files
|
||||||
// provided by the given scope object. If results are inconclusive a "UnknownDistro" Type is returned.
|
// provided by the given scope object. If results are inconclusive a "UnknownDistro" Type is returned.
|
||||||
func IdentifyDistro(s scope.Scope) distro.Distro {
|
func (c *Client) IdentifyDistro(s scope.Scope) distro.Distro {
|
||||||
d := distro.Identify(s.Resolver)
|
d := distro.Identify(s.Resolver)
|
||||||
if d.Type != distro.UnknownDistroType {
|
if d.Type != distro.UnknownDistroType {
|
||||||
log.Infof("identified distro: %s", d.String())
|
log.Infof("identified distro: %s", d.String())
|
||||||
@@ -47,9 +69,15 @@ func IdentifyDistro(s scope.Scope) distro.Distro {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Catalog the given scope, which may represent a container image or filesystem. Returns the discovered set of packages.
|
// Catalog the given scope, which may represent a container image or filesystem. Returns the discovered set of packages.
|
||||||
func CatalogFromScope(s scope.Scope) (*pkg.Catalog, error) {
|
func (c *Client) CatalogFromScope(s scope.Scope) (*pkg.Catalog, error) {
|
||||||
log.Info("building the catalog")
|
log.Info("building the catalog")
|
||||||
return cataloger.Catalog(s.Resolver, cataloger.All()...)
|
pluginCatalogers, deactivatePluginsFn, err := c.plugins.ActivateCatalogers()
|
||||||
|
defer deactivatePluginsFn()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return cataloger.Catalog(s.Resolver, append(pluginCatalogers, cataloger.BuiltIn()...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetLogger sets the logger object used for all syft logging calls.
|
// SetLogger sets the logger object used for all syft logging calls.
|
||||||
+13
-2
@@ -1,6 +1,7 @@
|
|||||||
package distro
|
package distro
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -10,6 +11,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// returns a distro or nil
|
// returns a distro or nil
|
||||||
|
// TODO: refactor to io.Reader
|
||||||
type parseFunc func(string) *Distro
|
type parseFunc func(string) *Distro
|
||||||
|
|
||||||
type parseEntry struct {
|
type parseEntry struct {
|
||||||
@@ -17,6 +19,7 @@ type parseEntry struct {
|
|||||||
fn parseFunc
|
fn parseFunc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nolint: funlen
|
||||||
// Identify parses distro-specific files to determine distro metadata like version and release.
|
// Identify parses distro-specific files to determine distro metadata like version and release.
|
||||||
func Identify(resolver scope.Resolver) Distro {
|
func Identify(resolver scope.Resolver) Distro {
|
||||||
distro := NewUnknownDistro()
|
distro := NewUnknownDistro()
|
||||||
@@ -52,8 +55,8 @@ identifyLoop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, ref := range refs {
|
for _, ref := range refs {
|
||||||
contents, err := resolver.MultipleFileContentsByRef(ref)
|
contentReaders, err := resolver.MultipleFileContentsByRef(ref)
|
||||||
content, ok := contents[ref]
|
contentReader, ok := contentReaders[ref]
|
||||||
|
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Infof("no content present for ref: %s", ref)
|
log.Infof("no content present for ref: %s", ref)
|
||||||
@@ -65,6 +68,14 @@ identifyLoop:
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bytes, err := ioutil.ReadAll(contentReader)
|
||||||
|
if err != nil {
|
||||||
|
log.Debugf("unable to read contents from %s: %s", entry.path, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
content := string(bytes)
|
||||||
|
|
||||||
if content == "" {
|
if content == "" {
|
||||||
log.Debugf("no contents in file, skipping: %s", entry.path)
|
log.Debugf("no contents in file, skipping: %s", entry.path)
|
||||||
continue
|
continue
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package logger
|
|||||||
|
|
||||||
type Logger interface {
|
type Logger interface {
|
||||||
Errorf(format string, args ...interface{})
|
Errorf(format string, args ...interface{})
|
||||||
|
Error(args ...interface{})
|
||||||
Infof(format string, args ...interface{})
|
Infof(format string, args ...interface{})
|
||||||
Info(args ...interface{})
|
Info(args ...interface{})
|
||||||
Debugf(format string, args ...interface{})
|
Debugf(format string, args ...interface{})
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/cataloger"
|
||||||
|
syftPluginGrpc "github.com/anchore/syft/syft/plugin/grpc"
|
||||||
|
"github.com/anchore/syft/syft/plugin/proto"
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
// integrity check
|
||||||
|
var _ plugin.GRPCPlugin = &CatalogerPlugin{}
|
||||||
|
|
||||||
|
// CatalogerPlugin is the implementation of plugin.Plugin that is served/consumed.
|
||||||
|
type CatalogerPlugin struct {
|
||||||
|
plugin.NetRPCUnsupportedPlugin
|
||||||
|
Impl cataloger.Cataloger
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CatalogerPlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Server) error {
|
||||||
|
proto.RegisterCatalogerServer(s, syftPluginGrpc.NewCatalogServer(p.Impl, broker))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CatalogerPlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
|
||||||
|
return syftPluginGrpc.NewCatalogerClient(proto.NewCatalogerClient(c), broker), nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package plugin
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Name string
|
||||||
|
Type Type
|
||||||
|
Command string
|
||||||
|
Args []string
|
||||||
|
Env []string
|
||||||
|
Sha256 []byte
|
||||||
|
}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
package grpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/syft/cataloger"
|
||||||
|
|
||||||
|
"github.com/anchore/stereoscope/pkg/file"
|
||||||
|
"github.com/anchore/syft/syft/pkg"
|
||||||
|
"github.com/anchore/syft/syft/plugin/proto"
|
||||||
|
"github.com/anchore/syft/syft/scope"
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
"google.golang.org/grpc"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ cataloger.Cataloger = &CatalogerClient{}
|
||||||
|
|
||||||
|
type CatalogerClient struct {
|
||||||
|
broker *plugin.GRPCBroker
|
||||||
|
client proto.CatalogerClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCatalogerClient(client proto.CatalogerClient, broker *plugin.GRPCBroker) *CatalogerClient {
|
||||||
|
return &CatalogerClient{
|
||||||
|
broker: broker,
|
||||||
|
client: client,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CatalogerClient) Name() string {
|
||||||
|
resp, err := c.client.Name(context.Background(), &proto.Empty{})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Sprintf("error (%s)", err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CatalogerClient) SelectFiles(resolver scope.FileResolver) []file.Reference {
|
||||||
|
fileResolverServer := &FileResolverServer{Impl: resolver}
|
||||||
|
|
||||||
|
var s *grpc.Server
|
||||||
|
serverFunc := func(opts []grpc.ServerOption) *grpc.Server {
|
||||||
|
s = grpc.NewServer(opts...)
|
||||||
|
proto.RegisterFileResolverServer(s, fileResolverServer)
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
brokerID := c.broker.NextId()
|
||||||
|
go c.broker.AcceptAndServe(brokerID, serverFunc)
|
||||||
|
|
||||||
|
resp, err := c.client.SelectFiles(context.Background(), &proto.SelectFilesRequest{
|
||||||
|
FileResolverBrokerId: brokerID,
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
// TODO: nope
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Stop()
|
||||||
|
|
||||||
|
var result []file.Reference
|
||||||
|
for _, f := range resp.Files {
|
||||||
|
result = append(result, file.NewFileReferenceWithID(file.Path(f.Path), uint64(f.Id)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *CatalogerClient) Catalog(contents map[file.Reference]io.Reader) ([]pkg.Package, error) {
|
||||||
|
var fileRefContents []*proto.FileReferenceContents
|
||||||
|
for ref, reader := range contents {
|
||||||
|
readerContents, err := ioutil.ReadAll(reader)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not read %+v contents: %+v", ref, err)
|
||||||
|
}
|
||||||
|
fileRefContents = append(fileRefContents, &proto.FileReferenceContents{
|
||||||
|
Id: int64(ref.ID()),
|
||||||
|
Path: string(ref.Path),
|
||||||
|
Contents: string(readerContents),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
resp, err := c.client.Catalog(context.Background(), &proto.CatalogRequest{
|
||||||
|
Contents: fileRefContents,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result []pkg.Package
|
||||||
|
for _, p := range resp.Package {
|
||||||
|
if p != nil {
|
||||||
|
var sources []file.Reference
|
||||||
|
for _, s := range p.Source {
|
||||||
|
sources = append(sources, file.NewFileReferenceWithID(file.Path(s.Path), uint64(s.Id)))
|
||||||
|
}
|
||||||
|
// TODO: this is potentially brittle
|
||||||
|
result = append(result, pkg.Package{
|
||||||
|
Name: p.Name,
|
||||||
|
Version: p.Version,
|
||||||
|
FoundBy: p.FoundBy,
|
||||||
|
Source: sources,
|
||||||
|
Licenses: p.Licenses,
|
||||||
|
Language: pkg.Language(p.Language),
|
||||||
|
Type: pkg.Type(p.Type),
|
||||||
|
Metadata: p.Metadata,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
package grpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/anchore/stereoscope/pkg/file"
|
||||||
|
"github.com/anchore/syft/syft/cataloger"
|
||||||
|
"github.com/anchore/syft/syft/plugin/proto"
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CatalogerServer struct {
|
||||||
|
Impl cataloger.Cataloger
|
||||||
|
broker *plugin.GRPCBroker
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCatalogServer(impl cataloger.Cataloger, broker *plugin.GRPCBroker) *CatalogerServer {
|
||||||
|
return &CatalogerServer{
|
||||||
|
Impl: impl,
|
||||||
|
broker: broker,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CatalogerServer) Name(ctx context.Context, req *proto.Empty) (*proto.NameResponse, error) {
|
||||||
|
name := s.Impl.Name()
|
||||||
|
return &proto.NameResponse{
|
||||||
|
Name: name,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CatalogerServer) SelectFiles(ctx context.Context, req *proto.SelectFilesRequest) (*proto.SelectFilesResponse, error) {
|
||||||
|
conn, err := s.broker.Dial(req.FileResolverBrokerId)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
fileResolverClient := &FileResolverClient{proto.NewFileResolverClient(conn)}
|
||||||
|
|
||||||
|
fileRefs := s.Impl.SelectFiles(fileResolverClient)
|
||||||
|
|
||||||
|
var refs []*proto.FileReference
|
||||||
|
for _, ref := range fileRefs {
|
||||||
|
refs = append(refs, &proto.FileReference{
|
||||||
|
Id: int64(ref.ID()),
|
||||||
|
Path: string(ref.Path),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &proto.SelectFilesResponse{
|
||||||
|
Files: refs,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *CatalogerServer) Catalog(ctx context.Context, req *proto.CatalogRequest) (*proto.CatalogResponse, error) {
|
||||||
|
contents := make(map[file.Reference]io.Reader)
|
||||||
|
for _, f := range req.Contents {
|
||||||
|
contents[file.NewFileReferenceWithID(file.Path(f.Path), uint64(f.Id))] = strings.NewReader(f.Contents)
|
||||||
|
}
|
||||||
|
packages, err := s.Impl.Catalog(contents)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var results []*proto.Package
|
||||||
|
for _, p := range packages {
|
||||||
|
var sources []*proto.FileReference
|
||||||
|
for _, s := range p.Source {
|
||||||
|
sources = append(sources, &proto.FileReference{
|
||||||
|
Id: int64(s.ID()),
|
||||||
|
Path: string(s.Path),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var metadata map[string]string
|
||||||
|
if v, ok := p.Metadata.(map[string]string); ok {
|
||||||
|
metadata = v
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: this is potentially brittle
|
||||||
|
results = append(results, &proto.Package{
|
||||||
|
Name: p.Name,
|
||||||
|
Version: p.Version,
|
||||||
|
FoundBy: p.FoundBy,
|
||||||
|
Source: sources,
|
||||||
|
Licenses: p.Licenses,
|
||||||
|
Language: uint64(p.Language),
|
||||||
|
Type: string(p.Type),
|
||||||
|
// TODO: metadata needs to be more thoroughly thought through
|
||||||
|
Metadata: metadata,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &proto.CatalogResponse{
|
||||||
|
Package: results,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package grpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/internal/log"
|
||||||
|
|
||||||
|
"github.com/anchore/stereoscope/pkg/file"
|
||||||
|
"github.com/anchore/syft/syft/plugin/proto"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FileResolverClient struct{ client proto.FileResolverClient }
|
||||||
|
|
||||||
|
func (m *FileResolverClient) FilesByPath(paths ...file.Path) ([]file.Reference, error) {
|
||||||
|
var pathStrs []string
|
||||||
|
for _, p := range paths {
|
||||||
|
pathStrs = append(pathStrs, string(p))
|
||||||
|
}
|
||||||
|
resp, err := m.client.FilesByPath(context.Background(), &proto.FileResolverRequest{
|
||||||
|
Paths: pathStrs,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var result []file.Reference
|
||||||
|
for _, ref := range resp.Files {
|
||||||
|
result = append(result, file.NewFileReferenceWithID(file.Path(ref.Path), uint64(ref.Id)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FileResolverClient) FilesByGlob(patterns ...string) ([]file.Reference, error) {
|
||||||
|
resp, err := m.client.FilesByGlob(context.Background(), &proto.FileResolverRequest{
|
||||||
|
Paths: patterns,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debugf("FilesByGlob Response: %+v", resp)
|
||||||
|
|
||||||
|
var result []file.Reference
|
||||||
|
for _, ref := range resp.Files {
|
||||||
|
result = append(result, file.NewFileReferenceWithID(file.Path(ref.Path), uint64(ref.Id)))
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, err
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package grpc
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/anchore/stereoscope/pkg/file"
|
||||||
|
"github.com/anchore/syft/syft/plugin/proto"
|
||||||
|
"github.com/anchore/syft/syft/scope"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FileResolverServer struct {
|
||||||
|
Impl scope.FileResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FileResolverServer) FilesByPath(ctx context.Context, req *proto.FileResolverRequest) (resp *proto.FileResolverResponse, err error) {
|
||||||
|
var paths []file.Path
|
||||||
|
for _, p := range req.Paths {
|
||||||
|
paths = append(paths, file.Path(p))
|
||||||
|
}
|
||||||
|
r, err := m.Impl.FilesByPath(paths...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var refs []*proto.FileReference
|
||||||
|
for _, ref := range r {
|
||||||
|
refs = append(refs, &proto.FileReference{
|
||||||
|
Id: int64(ref.ID()),
|
||||||
|
Path: string(ref.Path),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &proto.FileResolverResponse{
|
||||||
|
Files: refs,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FileResolverServer) FilesByGlob(ctx context.Context, req *proto.FileResolverRequest) (resp *proto.FileResolverResponse, err error) {
|
||||||
|
r, err := m.Impl.FilesByGlob(req.Paths...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var refs []*proto.FileReference
|
||||||
|
for _, ref := range r {
|
||||||
|
refs = append(refs, &proto.FileReference{
|
||||||
|
Id: int64(ref.ID()),
|
||||||
|
Path: string(ref.Path),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return &proto.FileResolverResponse{
|
||||||
|
Files: refs,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"fmt"
|
||||||
|
"os/exec"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/internal/log"
|
||||||
|
"github.com/anchore/syft/internal/logger"
|
||||||
|
"github.com/hashicorp/go-hclog"
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var versionedPlugins = map[int]plugin.PluginSet{
|
||||||
|
1: {
|
||||||
|
TypeCataloger.String(): &CatalogerPlugin{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
type Plugin struct {
|
||||||
|
Config Config
|
||||||
|
clientConfig plugin.ClientConfig
|
||||||
|
client *plugin.Client
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: type should be in the name like with terraform "terraform-<TYPE>-<NAME>"
|
||||||
|
|
||||||
|
func NewPlugin(config Config) Plugin {
|
||||||
|
//cmd := exec.Command("sh", "-c", config.Command) //, config.Args...)
|
||||||
|
cmd := exec.Command(config.Command)
|
||||||
|
cmd.Env = append(cmd.Env, config.Env...)
|
||||||
|
|
||||||
|
var secureConfig *plugin.SecureConfig
|
||||||
|
if len(config.Sha256) > 0 {
|
||||||
|
secureConfig = &plugin.SecureConfig{
|
||||||
|
Checksum: config.Sha256,
|
||||||
|
Hash: sha256.New(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var pluginLogger hclog.Logger
|
||||||
|
if logrusLogger, ok := log.Log.(*logger.LogrusLogger); ok {
|
||||||
|
pluginLogger = logger.NewLogrusHCLogAdapter(logrusLogger.Logger, map[string]interface{}{"plugin": config.Name})
|
||||||
|
} else {
|
||||||
|
// TODO: this does not fully map features, thus logging will be awkward
|
||||||
|
// TODO: find a better way to map loggers (expand our interface?)
|
||||||
|
pluginLogger = logger.NewLoggerHCLogAdapter(log.Log)
|
||||||
|
}
|
||||||
|
|
||||||
|
clientConfig := plugin.ClientConfig{
|
||||||
|
HandshakeConfig: config.Type.HandshakeConfig(),
|
||||||
|
VersionedPlugins: versionedPlugins,
|
||||||
|
SecureConfig: secureConfig,
|
||||||
|
Cmd: cmd,
|
||||||
|
Logger: pluginLogger,
|
||||||
|
AllowedProtocols: []plugin.Protocol{
|
||||||
|
plugin.ProtocolGRPC,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return Plugin{
|
||||||
|
Config: config,
|
||||||
|
clientConfig: clientConfig,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) Start() (interface{}, error) {
|
||||||
|
if p.client != nil {
|
||||||
|
return nil, fmt.Errorf("plugin already started")
|
||||||
|
}
|
||||||
|
|
||||||
|
// start the plugin in a sub process
|
||||||
|
p.client = plugin.NewClient(&p.clientConfig)
|
||||||
|
|
||||||
|
// connect to the sub process via RPC
|
||||||
|
rpcClient, err := p.client.Client()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// fetch the plugin object meeting the requested interface
|
||||||
|
raw, err := rpcClient.Dispense(p.Config.Type.String())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return raw, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Plugin) Stop() error {
|
||||||
|
if p.client == nil {
|
||||||
|
return fmt.Errorf("plugin has not been started")
|
||||||
|
}
|
||||||
|
p.client.Kill()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,841 @@
|
|||||||
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
|
// source: cataloger.proto
|
||||||
|
|
||||||
|
package proto
|
||||||
|
|
||||||
|
import (
|
||||||
|
context "context"
|
||||||
|
fmt "fmt"
|
||||||
|
proto "github.com/golang/protobuf/proto"
|
||||||
|
grpc "google.golang.org/grpc"
|
||||||
|
codes "google.golang.org/grpc/codes"
|
||||||
|
status "google.golang.org/grpc/status"
|
||||||
|
math "math"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var _ = proto.Marshal
|
||||||
|
var _ = fmt.Errorf
|
||||||
|
var _ = math.Inf
|
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the proto package it is being compiled against.
|
||||||
|
// A compilation error at this line likely means your copy of the
|
||||||
|
// proto package needs to be updated.
|
||||||
|
const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package
|
||||||
|
|
||||||
|
type FileReference struct {
|
||||||
|
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||||
|
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FileReference) Reset() { *m = FileReference{} }
|
||||||
|
func (m *FileReference) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*FileReference) ProtoMessage() {}
|
||||||
|
func (*FileReference) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_346aaad5d7f2c092, []int{0}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FileReference) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_FileReference.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *FileReference) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_FileReference.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (m *FileReference) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_FileReference.Merge(m, src)
|
||||||
|
}
|
||||||
|
func (m *FileReference) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_FileReference.Size(m)
|
||||||
|
}
|
||||||
|
func (m *FileReference) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_FileReference.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_FileReference proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *FileReference) GetId() int64 {
|
||||||
|
if m != nil {
|
||||||
|
return m.Id
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FileReference) GetPath() string {
|
||||||
|
if m != nil {
|
||||||
|
return m.Path
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileReferenceContents struct {
|
||||||
|
Id int64 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||||
|
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
|
||||||
|
Contents string `protobuf:"bytes,3,opt,name=contents,proto3" json:"contents,omitempty"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FileReferenceContents) Reset() { *m = FileReferenceContents{} }
|
||||||
|
func (m *FileReferenceContents) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*FileReferenceContents) ProtoMessage() {}
|
||||||
|
func (*FileReferenceContents) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_346aaad5d7f2c092, []int{1}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FileReferenceContents) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_FileReferenceContents.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *FileReferenceContents) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_FileReferenceContents.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (m *FileReferenceContents) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_FileReferenceContents.Merge(m, src)
|
||||||
|
}
|
||||||
|
func (m *FileReferenceContents) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_FileReferenceContents.Size(m)
|
||||||
|
}
|
||||||
|
func (m *FileReferenceContents) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_FileReferenceContents.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_FileReferenceContents proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *FileReferenceContents) GetId() int64 {
|
||||||
|
if m != nil {
|
||||||
|
return m.Id
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FileReferenceContents) GetPath() string {
|
||||||
|
if m != nil {
|
||||||
|
return m.Path
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FileReferenceContents) GetContents() string {
|
||||||
|
if m != nil {
|
||||||
|
return m.Contents
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type Empty struct {
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Empty) Reset() { *m = Empty{} }
|
||||||
|
func (m *Empty) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*Empty) ProtoMessage() {}
|
||||||
|
func (*Empty) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_346aaad5d7f2c092, []int{2}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Empty) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_Empty.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *Empty) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_Empty.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (m *Empty) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_Empty.Merge(m, src)
|
||||||
|
}
|
||||||
|
func (m *Empty) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_Empty.Size(m)
|
||||||
|
}
|
||||||
|
func (m *Empty) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_Empty.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_Empty proto.InternalMessageInfo
|
||||||
|
|
||||||
|
type FileResolverRequest struct {
|
||||||
|
Paths []string `protobuf:"bytes,1,rep,name=paths,proto3" json:"paths,omitempty"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FileResolverRequest) Reset() { *m = FileResolverRequest{} }
|
||||||
|
func (m *FileResolverRequest) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*FileResolverRequest) ProtoMessage() {}
|
||||||
|
func (*FileResolverRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_346aaad5d7f2c092, []int{3}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FileResolverRequest) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_FileResolverRequest.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *FileResolverRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_FileResolverRequest.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (m *FileResolverRequest) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_FileResolverRequest.Merge(m, src)
|
||||||
|
}
|
||||||
|
func (m *FileResolverRequest) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_FileResolverRequest.Size(m)
|
||||||
|
}
|
||||||
|
func (m *FileResolverRequest) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_FileResolverRequest.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_FileResolverRequest proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *FileResolverRequest) GetPaths() []string {
|
||||||
|
if m != nil {
|
||||||
|
return m.Paths
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileResolverResponse struct {
|
||||||
|
Files []*FileReference `protobuf:"bytes,1,rep,name=files,proto3" json:"files,omitempty"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FileResolverResponse) Reset() { *m = FileResolverResponse{} }
|
||||||
|
func (m *FileResolverResponse) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*FileResolverResponse) ProtoMessage() {}
|
||||||
|
func (*FileResolverResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_346aaad5d7f2c092, []int{4}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *FileResolverResponse) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_FileResolverResponse.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *FileResolverResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_FileResolverResponse.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (m *FileResolverResponse) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_FileResolverResponse.Merge(m, src)
|
||||||
|
}
|
||||||
|
func (m *FileResolverResponse) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_FileResolverResponse.Size(m)
|
||||||
|
}
|
||||||
|
func (m *FileResolverResponse) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_FileResolverResponse.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_FileResolverResponse proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *FileResolverResponse) GetFiles() []*FileReference {
|
||||||
|
if m != nil {
|
||||||
|
return m.Files
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type NameResponse struct {
|
||||||
|
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *NameResponse) Reset() { *m = NameResponse{} }
|
||||||
|
func (m *NameResponse) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*NameResponse) ProtoMessage() {}
|
||||||
|
func (*NameResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_346aaad5d7f2c092, []int{5}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *NameResponse) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_NameResponse.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *NameResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_NameResponse.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (m *NameResponse) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_NameResponse.Merge(m, src)
|
||||||
|
}
|
||||||
|
func (m *NameResponse) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_NameResponse.Size(m)
|
||||||
|
}
|
||||||
|
func (m *NameResponse) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_NameResponse.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_NameResponse proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *NameResponse) GetName() string {
|
||||||
|
if m != nil {
|
||||||
|
return m.Name
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
type SelectFilesRequest struct {
|
||||||
|
FileResolverBrokerId uint32 `protobuf:"varint,1,opt,name=fileResolverBrokerId,proto3" json:"fileResolverBrokerId,omitempty"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SelectFilesRequest) Reset() { *m = SelectFilesRequest{} }
|
||||||
|
func (m *SelectFilesRequest) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*SelectFilesRequest) ProtoMessage() {}
|
||||||
|
func (*SelectFilesRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_346aaad5d7f2c092, []int{6}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SelectFilesRequest) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_SelectFilesRequest.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *SelectFilesRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_SelectFilesRequest.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (m *SelectFilesRequest) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_SelectFilesRequest.Merge(m, src)
|
||||||
|
}
|
||||||
|
func (m *SelectFilesRequest) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_SelectFilesRequest.Size(m)
|
||||||
|
}
|
||||||
|
func (m *SelectFilesRequest) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_SelectFilesRequest.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_SelectFilesRequest proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *SelectFilesRequest) GetFileResolverBrokerId() uint32 {
|
||||||
|
if m != nil {
|
||||||
|
return m.FileResolverBrokerId
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
type SelectFilesResponse struct {
|
||||||
|
Files []*FileReference `protobuf:"bytes,1,rep,name=files,proto3" json:"files,omitempty"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SelectFilesResponse) Reset() { *m = SelectFilesResponse{} }
|
||||||
|
func (m *SelectFilesResponse) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*SelectFilesResponse) ProtoMessage() {}
|
||||||
|
func (*SelectFilesResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_346aaad5d7f2c092, []int{7}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *SelectFilesResponse) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_SelectFilesResponse.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *SelectFilesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_SelectFilesResponse.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (m *SelectFilesResponse) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_SelectFilesResponse.Merge(m, src)
|
||||||
|
}
|
||||||
|
func (m *SelectFilesResponse) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_SelectFilesResponse.Size(m)
|
||||||
|
}
|
||||||
|
func (m *SelectFilesResponse) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_SelectFilesResponse.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_SelectFilesResponse proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *SelectFilesResponse) GetFiles() []*FileReference {
|
||||||
|
if m != nil {
|
||||||
|
return m.Files
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Package struct {
|
||||||
|
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||||
|
Version string `protobuf:"bytes,2,opt,name=version,proto3" json:"version,omitempty"`
|
||||||
|
FoundBy string `protobuf:"bytes,3,opt,name=foundBy,proto3" json:"foundBy,omitempty"`
|
||||||
|
Source []*FileReference `protobuf:"bytes,4,rep,name=source,proto3" json:"source,omitempty"`
|
||||||
|
Licenses []string `protobuf:"bytes,5,rep,name=licenses,proto3" json:"licenses,omitempty"`
|
||||||
|
Language uint64 `protobuf:"varint,6,opt,name=language,proto3" json:"language,omitempty"`
|
||||||
|
Type string `protobuf:"bytes,7,opt,name=type,proto3" json:"type,omitempty"`
|
||||||
|
Metadata map[string]string `protobuf:"bytes,8,rep,name=metadata,proto3" json:"metadata,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Package) Reset() { *m = Package{} }
|
||||||
|
func (m *Package) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*Package) ProtoMessage() {}
|
||||||
|
func (*Package) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_346aaad5d7f2c092, []int{8}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Package) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_Package.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *Package) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_Package.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (m *Package) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_Package.Merge(m, src)
|
||||||
|
}
|
||||||
|
func (m *Package) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_Package.Size(m)
|
||||||
|
}
|
||||||
|
func (m *Package) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_Package.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_Package proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *Package) GetName() string {
|
||||||
|
if m != nil {
|
||||||
|
return m.Name
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Package) GetVersion() string {
|
||||||
|
if m != nil {
|
||||||
|
return m.Version
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Package) GetFoundBy() string {
|
||||||
|
if m != nil {
|
||||||
|
return m.FoundBy
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Package) GetSource() []*FileReference {
|
||||||
|
if m != nil {
|
||||||
|
return m.Source
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Package) GetLicenses() []string {
|
||||||
|
if m != nil {
|
||||||
|
return m.Licenses
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Package) GetLanguage() uint64 {
|
||||||
|
if m != nil {
|
||||||
|
return m.Language
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Package) GetType() string {
|
||||||
|
if m != nil {
|
||||||
|
return m.Type
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Package) GetMetadata() map[string]string {
|
||||||
|
if m != nil {
|
||||||
|
return m.Metadata
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type CatalogRequest struct {
|
||||||
|
Contents []*FileReferenceContents `protobuf:"bytes,1,rep,name=contents,proto3" json:"contents,omitempty"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *CatalogRequest) Reset() { *m = CatalogRequest{} }
|
||||||
|
func (m *CatalogRequest) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*CatalogRequest) ProtoMessage() {}
|
||||||
|
func (*CatalogRequest) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_346aaad5d7f2c092, []int{9}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *CatalogRequest) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_CatalogRequest.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *CatalogRequest) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_CatalogRequest.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (m *CatalogRequest) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_CatalogRequest.Merge(m, src)
|
||||||
|
}
|
||||||
|
func (m *CatalogRequest) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_CatalogRequest.Size(m)
|
||||||
|
}
|
||||||
|
func (m *CatalogRequest) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_CatalogRequest.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_CatalogRequest proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *CatalogRequest) GetContents() []*FileReferenceContents {
|
||||||
|
if m != nil {
|
||||||
|
return m.Contents
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type CatalogResponse struct {
|
||||||
|
Package []*Package `protobuf:"bytes,1,rep,name=package,proto3" json:"package,omitempty"`
|
||||||
|
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||||
|
XXX_unrecognized []byte `json:"-"`
|
||||||
|
XXX_sizecache int32 `json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *CatalogResponse) Reset() { *m = CatalogResponse{} }
|
||||||
|
func (m *CatalogResponse) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*CatalogResponse) ProtoMessage() {}
|
||||||
|
func (*CatalogResponse) Descriptor() ([]byte, []int) {
|
||||||
|
return fileDescriptor_346aaad5d7f2c092, []int{10}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *CatalogResponse) XXX_Unmarshal(b []byte) error {
|
||||||
|
return xxx_messageInfo_CatalogResponse.Unmarshal(m, b)
|
||||||
|
}
|
||||||
|
func (m *CatalogResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||||
|
return xxx_messageInfo_CatalogResponse.Marshal(b, m, deterministic)
|
||||||
|
}
|
||||||
|
func (m *CatalogResponse) XXX_Merge(src proto.Message) {
|
||||||
|
xxx_messageInfo_CatalogResponse.Merge(m, src)
|
||||||
|
}
|
||||||
|
func (m *CatalogResponse) XXX_Size() int {
|
||||||
|
return xxx_messageInfo_CatalogResponse.Size(m)
|
||||||
|
}
|
||||||
|
func (m *CatalogResponse) XXX_DiscardUnknown() {
|
||||||
|
xxx_messageInfo_CatalogResponse.DiscardUnknown(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
var xxx_messageInfo_CatalogResponse proto.InternalMessageInfo
|
||||||
|
|
||||||
|
func (m *CatalogResponse) GetPackage() []*Package {
|
||||||
|
if m != nil {
|
||||||
|
return m.Package
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
proto.RegisterType((*FileReference)(nil), "proto.FileReference")
|
||||||
|
proto.RegisterType((*FileReferenceContents)(nil), "proto.FileReferenceContents")
|
||||||
|
proto.RegisterType((*Empty)(nil), "proto.Empty")
|
||||||
|
proto.RegisterType((*FileResolverRequest)(nil), "proto.FileResolverRequest")
|
||||||
|
proto.RegisterType((*FileResolverResponse)(nil), "proto.FileResolverResponse")
|
||||||
|
proto.RegisterType((*NameResponse)(nil), "proto.NameResponse")
|
||||||
|
proto.RegisterType((*SelectFilesRequest)(nil), "proto.SelectFilesRequest")
|
||||||
|
proto.RegisterType((*SelectFilesResponse)(nil), "proto.SelectFilesResponse")
|
||||||
|
proto.RegisterType((*Package)(nil), "proto.Package")
|
||||||
|
proto.RegisterMapType((map[string]string)(nil), "proto.Package.MetadataEntry")
|
||||||
|
proto.RegisterType((*CatalogRequest)(nil), "proto.CatalogRequest")
|
||||||
|
proto.RegisterType((*CatalogResponse)(nil), "proto.CatalogResponse")
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() { proto.RegisterFile("cataloger.proto", fileDescriptor_346aaad5d7f2c092) }
|
||||||
|
|
||||||
|
var fileDescriptor_346aaad5d7f2c092 = []byte{
|
||||||
|
// 541 bytes of a gzipped FileDescriptorProto
|
||||||
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x53, 0xcb, 0x8e, 0xd3, 0x3c,
|
||||||
|
0x14, 0x56, 0x7a, 0x4b, 0x7b, 0x7a, 0x99, 0x5f, 0x6e, 0xe7, 0x57, 0x08, 0x2c, 0xaa, 0xac, 0xca,
|
||||||
|
0x45, 0x5d, 0x74, 0x36, 0x15, 0xb3, 0xa2, 0x65, 0x86, 0x8b, 0x04, 0x1a, 0x99, 0x05, 0x6b, 0x4f,
|
||||||
|
0x7a, 0x5a, 0xa2, 0xa6, 0x71, 0x88, 0xdd, 0x4a, 0x79, 0x19, 0x1e, 0x83, 0x07, 0xe0, 0xc9, 0x50,
|
||||||
|
0x6c, 0x27, 0xd4, 0x10, 0x21, 0x34, 0xab, 0xf8, 0xe4, 0xfb, 0xfc, 0x9d, 0xcf, 0xe7, 0x02, 0x17,
|
||||||
|
0x21, 0x93, 0x2c, 0xe6, 0x3b, 0xcc, 0xe6, 0x69, 0xc6, 0x25, 0x27, 0x6d, 0xf5, 0x09, 0xae, 0x60,
|
||||||
|
0x78, 0x1b, 0xc5, 0x48, 0x71, 0x8b, 0x19, 0x26, 0x21, 0x92, 0x11, 0x34, 0xa2, 0x8d, 0xe7, 0x4c,
|
||||||
|
0x9d, 0x59, 0x93, 0x36, 0xa2, 0x0d, 0x21, 0xd0, 0x4a, 0x99, 0xfc, 0xe2, 0x35, 0xa6, 0xce, 0xac,
|
||||||
|
0x47, 0xd5, 0x39, 0xf8, 0x0c, 0x97, 0xd6, 0xa5, 0x35, 0x4f, 0x24, 0x26, 0x52, 0xfc, 0xcb, 0x65,
|
||||||
|
0xe2, 0x43, 0x37, 0x34, 0x7c, 0xaf, 0xa9, 0xfe, 0x57, 0x71, 0xe0, 0x42, 0xfb, 0xe6, 0x90, 0xca,
|
||||||
|
0x3c, 0x78, 0x0e, 0x63, 0x9d, 0x41, 0xf0, 0xf8, 0x84, 0x19, 0xc5, 0xaf, 0x47, 0x14, 0x92, 0x4c,
|
||||||
|
0xa0, 0x5d, 0x68, 0x08, 0xcf, 0x99, 0x36, 0x67, 0x3d, 0xaa, 0x83, 0x60, 0x05, 0x13, 0x9b, 0x2c,
|
||||||
|
0x52, 0x9e, 0x08, 0x24, 0xcf, 0xa0, 0xbd, 0x8d, 0x62, 0xd4, 0xec, 0xfe, 0x62, 0xa2, 0x5f, 0x3e,
|
||||||
|
0xb7, 0xac, 0x53, 0x4d, 0x09, 0x02, 0x18, 0x7c, 0x64, 0x07, 0xac, 0xee, 0x12, 0x68, 0x25, 0xec,
|
||||||
|
0x80, 0xea, 0x2d, 0x3d, 0xaa, 0xce, 0xc1, 0x5b, 0x20, 0x9f, 0x30, 0xc6, 0x50, 0x16, 0x0a, 0xa2,
|
||||||
|
0xf4, 0xb4, 0x80, 0xc9, 0xf6, 0x2c, 0xfb, 0x2a, 0xe3, 0x7b, 0xcc, 0xde, 0xe9, 0x2a, 0x0c, 0x69,
|
||||||
|
0x2d, 0x16, 0xbc, 0x82, 0xb1, 0xa5, 0xf4, 0x00, 0xc3, 0x3f, 0x1a, 0xe0, 0xde, 0xb1, 0x70, 0xcf,
|
||||||
|
0x76, 0xb5, 0x66, 0x89, 0x07, 0xee, 0x09, 0x33, 0x11, 0xf1, 0xc4, 0x54, 0xbf, 0x0c, 0x0b, 0x64,
|
||||||
|
0xcb, 0x8f, 0xc9, 0x66, 0x95, 0x9b, 0xfa, 0x97, 0x21, 0x79, 0x01, 0x1d, 0xc1, 0x8f, 0x59, 0x88,
|
||||||
|
0x5e, 0xeb, 0x2f, 0x06, 0x0c, 0xa7, 0x68, 0x64, 0x1c, 0x85, 0x98, 0x08, 0x14, 0x5e, 0x5b, 0xf5,
|
||||||
|
0xa3, 0x8a, 0x15, 0xc6, 0x92, 0xdd, 0x91, 0xed, 0xd0, 0xeb, 0x4c, 0x9d, 0x59, 0x8b, 0x56, 0x71,
|
||||||
|
0xe1, 0x56, 0xe6, 0x29, 0x7a, 0xae, 0x76, 0x5b, 0x9c, 0xc9, 0x12, 0xba, 0x07, 0x94, 0x6c, 0xc3,
|
||||||
|
0x24, 0xf3, 0xba, 0x2a, 0xf7, 0x13, 0x93, 0xdb, 0xbc, 0x71, 0xfe, 0xc1, 0xc0, 0x37, 0x89, 0xcc,
|
||||||
|
0x72, 0x5a, 0xb1, 0xfd, 0x6b, 0x18, 0x5a, 0x10, 0xf9, 0x0f, 0x9a, 0x7b, 0xcc, 0x4d, 0x2d, 0x8a,
|
||||||
|
0x63, 0x31, 0x35, 0x27, 0x16, 0x1f, 0xd1, 0x14, 0x42, 0x07, 0x2f, 0x1b, 0x4b, 0x27, 0x78, 0x0f,
|
||||||
|
0xa3, 0xb5, 0xde, 0x8b, 0xb2, 0x9b, 0xcb, 0xb3, 0xe9, 0x74, 0x2c, 0x23, 0xb5, 0x13, 0x7f, 0x36,
|
||||||
|
0xbb, 0xd7, 0x70, 0x51, 0x69, 0x99, 0x7e, 0xce, 0xc0, 0x4d, 0xb5, 0x7d, 0xa3, 0x35, 0xb2, 0x1f,
|
||||||
|
0x45, 0x4b, 0x78, 0xf1, 0xdd, 0x81, 0xde, 0xba, 0xdc, 0x50, 0xf2, 0x14, 0x5a, 0xc5, 0x30, 0x92,
|
||||||
|
0x81, 0xa1, 0xab, 0x9d, 0xf0, 0xc7, 0x26, 0xb2, 0xe6, 0xf4, 0x35, 0xf4, 0xcf, 0x26, 0x89, 0x3c,
|
||||||
|
0x32, 0x9c, 0x3f, 0xe7, 0xd4, 0xf7, 0xeb, 0x20, 0xa3, 0xb2, 0x04, 0xd7, 0x64, 0x27, 0x97, 0x86,
|
||||||
|
0x66, 0xd7, 0xc5, 0xff, 0xff, 0xf7, 0xdf, 0xfa, 0xe6, 0xe2, 0x9b, 0x03, 0x83, 0xf3, 0xe5, 0x23,
|
||||||
|
0xb7, 0xd0, 0x57, 0xda, 0xab, 0xfc, 0x4e, 0x6d, 0xbb, 0x55, 0x3d, 0x6b, 0x9b, 0xfd, 0xc7, 0xb5,
|
||||||
|
0x98, 0xb1, 0xf4, 0x4b, 0xe7, 0x4d, 0xcc, 0xef, 0x1f, 0xac, 0x73, 0xdf, 0x51, 0xd8, 0xd5, 0xcf,
|
||||||
|
0x00, 0x00, 0x00, 0xff, 0xff, 0x6e, 0xfe, 0x04, 0x3e, 0x01, 0x05, 0x00, 0x00,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reference imports to suppress errors if they are not otherwise used.
|
||||||
|
var _ context.Context
|
||||||
|
var _ grpc.ClientConnInterface
|
||||||
|
|
||||||
|
// This is a compile-time assertion to ensure that this generated file
|
||||||
|
// is compatible with the grpc package it is being compiled against.
|
||||||
|
const _ = grpc.SupportPackageIsVersion6
|
||||||
|
|
||||||
|
// CatalogerClient is the client API for Cataloger service.
|
||||||
|
//
|
||||||
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||||
|
type CatalogerClient interface {
|
||||||
|
Name(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*NameResponse, error)
|
||||||
|
SelectFiles(ctx context.Context, in *SelectFilesRequest, opts ...grpc.CallOption) (*SelectFilesResponse, error)
|
||||||
|
Catalog(ctx context.Context, in *CatalogRequest, opts ...grpc.CallOption) (*CatalogResponse, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type catalogerClient struct {
|
||||||
|
cc grpc.ClientConnInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCatalogerClient(cc grpc.ClientConnInterface) CatalogerClient {
|
||||||
|
return &catalogerClient{cc}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *catalogerClient) Name(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*NameResponse, error) {
|
||||||
|
out := new(NameResponse)
|
||||||
|
err := c.cc.Invoke(ctx, "/proto.Cataloger/Name", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *catalogerClient) SelectFiles(ctx context.Context, in *SelectFilesRequest, opts ...grpc.CallOption) (*SelectFilesResponse, error) {
|
||||||
|
out := new(SelectFilesResponse)
|
||||||
|
err := c.cc.Invoke(ctx, "/proto.Cataloger/SelectFiles", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *catalogerClient) Catalog(ctx context.Context, in *CatalogRequest, opts ...grpc.CallOption) (*CatalogResponse, error) {
|
||||||
|
out := new(CatalogResponse)
|
||||||
|
err := c.cc.Invoke(ctx, "/proto.Cataloger/Catalog", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// CatalogerServer is the server API for Cataloger service.
|
||||||
|
type CatalogerServer interface {
|
||||||
|
Name(context.Context, *Empty) (*NameResponse, error)
|
||||||
|
SelectFiles(context.Context, *SelectFilesRequest) (*SelectFilesResponse, error)
|
||||||
|
Catalog(context.Context, *CatalogRequest) (*CatalogResponse, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnimplementedCatalogerServer can be embedded to have forward compatible implementations.
|
||||||
|
type UnimplementedCatalogerServer struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*UnimplementedCatalogerServer) Name(ctx context.Context, req *Empty) (*NameResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method Name not implemented")
|
||||||
|
}
|
||||||
|
func (*UnimplementedCatalogerServer) SelectFiles(ctx context.Context, req *SelectFilesRequest) (*SelectFilesResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method SelectFiles not implemented")
|
||||||
|
}
|
||||||
|
func (*UnimplementedCatalogerServer) Catalog(ctx context.Context, req *CatalogRequest) (*CatalogResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method Catalog not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterCatalogerServer(s *grpc.Server, srv CatalogerServer) {
|
||||||
|
s.RegisterService(&_Cataloger_serviceDesc, srv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Cataloger_Name_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(Empty)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(CatalogerServer).Name(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/proto.Cataloger/Name",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(CatalogerServer).Name(ctx, req.(*Empty))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Cataloger_SelectFiles_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(SelectFilesRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(CatalogerServer).SelectFiles(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/proto.Cataloger/SelectFiles",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(CatalogerServer).SelectFiles(ctx, req.(*SelectFilesRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _Cataloger_Catalog_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(CatalogRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(CatalogerServer).Catalog(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/proto.Cataloger/Catalog",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(CatalogerServer).Catalog(ctx, req.(*CatalogRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _Cataloger_serviceDesc = grpc.ServiceDesc{
|
||||||
|
ServiceName: "proto.Cataloger",
|
||||||
|
HandlerType: (*CatalogerServer)(nil),
|
||||||
|
Methods: []grpc.MethodDesc{
|
||||||
|
{
|
||||||
|
MethodName: "Name",
|
||||||
|
Handler: _Cataloger_Name_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "SelectFiles",
|
||||||
|
Handler: _Cataloger_SelectFiles_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "Catalog",
|
||||||
|
Handler: _Cataloger_Catalog_Handler,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Streams: []grpc.StreamDesc{},
|
||||||
|
Metadata: "cataloger.proto",
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileResolverClient is the client API for FileResolver service.
|
||||||
|
//
|
||||||
|
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
|
||||||
|
type FileResolverClient interface {
|
||||||
|
FilesByPath(ctx context.Context, in *FileResolverRequest, opts ...grpc.CallOption) (*FileResolverResponse, error)
|
||||||
|
FilesByGlob(ctx context.Context, in *FileResolverRequest, opts ...grpc.CallOption) (*FileResolverResponse, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type fileResolverClient struct {
|
||||||
|
cc grpc.ClientConnInterface
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFileResolverClient(cc grpc.ClientConnInterface) FileResolverClient {
|
||||||
|
return &fileResolverClient{cc}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fileResolverClient) FilesByPath(ctx context.Context, in *FileResolverRequest, opts ...grpc.CallOption) (*FileResolverResponse, error) {
|
||||||
|
out := new(FileResolverResponse)
|
||||||
|
err := c.cc.Invoke(ctx, "/proto.FileResolver/FilesByPath", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *fileResolverClient) FilesByGlob(ctx context.Context, in *FileResolverRequest, opts ...grpc.CallOption) (*FileResolverResponse, error) {
|
||||||
|
out := new(FileResolverResponse)
|
||||||
|
err := c.cc.Invoke(ctx, "/proto.FileResolver/FilesByGlob", in, out, opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return out, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FileResolverServer is the server API for FileResolver service.
|
||||||
|
type FileResolverServer interface {
|
||||||
|
FilesByPath(context.Context, *FileResolverRequest) (*FileResolverResponse, error)
|
||||||
|
FilesByGlob(context.Context, *FileResolverRequest) (*FileResolverResponse, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnimplementedFileResolverServer can be embedded to have forward compatible implementations.
|
||||||
|
type UnimplementedFileResolverServer struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*UnimplementedFileResolverServer) FilesByPath(ctx context.Context, req *FileResolverRequest) (*FileResolverResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method FilesByPath not implemented")
|
||||||
|
}
|
||||||
|
func (*UnimplementedFileResolverServer) FilesByGlob(ctx context.Context, req *FileResolverRequest) (*FileResolverResponse, error) {
|
||||||
|
return nil, status.Errorf(codes.Unimplemented, "method FilesByGlob not implemented")
|
||||||
|
}
|
||||||
|
|
||||||
|
func RegisterFileResolverServer(s *grpc.Server, srv FileResolverServer) {
|
||||||
|
s.RegisterService(&_FileResolver_serviceDesc, srv)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _FileResolver_FilesByPath_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(FileResolverRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(FileResolverServer).FilesByPath(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/proto.FileResolver/FilesByPath",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(FileResolverServer).FilesByPath(ctx, req.(*FileResolverRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
func _FileResolver_FilesByGlob_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
|
in := new(FileResolverRequest)
|
||||||
|
if err := dec(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if interceptor == nil {
|
||||||
|
return srv.(FileResolverServer).FilesByGlob(ctx, in)
|
||||||
|
}
|
||||||
|
info := &grpc.UnaryServerInfo{
|
||||||
|
Server: srv,
|
||||||
|
FullMethod: "/proto.FileResolver/FilesByGlob",
|
||||||
|
}
|
||||||
|
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||||
|
return srv.(FileResolverServer).FilesByGlob(ctx, req.(*FileResolverRequest))
|
||||||
|
}
|
||||||
|
return interceptor(ctx, in, info, handler)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _FileResolver_serviceDesc = grpc.ServiceDesc{
|
||||||
|
ServiceName: "proto.FileResolver",
|
||||||
|
HandlerType: (*FileResolverServer)(nil),
|
||||||
|
Methods: []grpc.MethodDesc{
|
||||||
|
{
|
||||||
|
MethodName: "FilesByPath",
|
||||||
|
Handler: _FileResolver_FilesByPath_Handler,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
MethodName: "FilesByGlob",
|
||||||
|
Handler: _FileResolver_FilesByGlob_Handler,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Streams: []grpc.StreamDesc{},
|
||||||
|
Metadata: "cataloger.proto",
|
||||||
|
}
|
||||||
Executable
+67
@@ -0,0 +1,67 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
package proto;
|
||||||
|
|
||||||
|
message FileReference {
|
||||||
|
int64 id = 1;
|
||||||
|
string path = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FileReferenceContents {
|
||||||
|
int64 id = 1;
|
||||||
|
string path = 2;
|
||||||
|
string contents = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Empty {
|
||||||
|
}
|
||||||
|
|
||||||
|
message FileResolverRequest {
|
||||||
|
repeated string paths = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message FileResolverResponse {
|
||||||
|
repeated FileReference files = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message NameResponse {
|
||||||
|
string name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SelectFilesRequest {
|
||||||
|
uint32 fileResolverBrokerId = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message SelectFilesResponse {
|
||||||
|
repeated FileReference files = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message Package {
|
||||||
|
string name = 1;
|
||||||
|
string version = 2;
|
||||||
|
string foundBy = 3;
|
||||||
|
repeated FileReference source = 4;
|
||||||
|
repeated string licenses = 5;
|
||||||
|
uint64 language = 6;
|
||||||
|
string type = 7;
|
||||||
|
map<string, string> metadata = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CatalogRequest {
|
||||||
|
repeated FileReferenceContents contents = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CatalogResponse {
|
||||||
|
repeated Package package = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
service Cataloger {
|
||||||
|
rpc Name(Empty) returns (NameResponse);
|
||||||
|
rpc SelectFiles(SelectFilesRequest) returns (SelectFilesResponse);
|
||||||
|
rpc Catalog(CatalogRequest) returns (CatalogResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
service FileResolver {
|
||||||
|
rpc FilesByPath(FileResolverRequest) returns (FileResolverResponse);
|
||||||
|
rpc FilesByGlob(FileResolverRequest) returns (FileResolverResponse);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/anchore/syft/internal/log"
|
||||||
|
"github.com/anchore/syft/syft/cataloger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Repository struct {
|
||||||
|
byType map[Type][]Plugin
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRepository() *Repository {
|
||||||
|
return &Repository{
|
||||||
|
byType: make(map[Type][]Plugin),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRepositoryFromDirectory(dir string) (*Repository, error) {
|
||||||
|
repo := NewRepository()
|
||||||
|
if dir == "" {
|
||||||
|
return repo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return repo, repo.AddFromDirectory(dir)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Repository) Add(plugin Plugin) {
|
||||||
|
c.byType[plugin.Config.Type] = append(c.byType[plugin.Config.Type], plugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Repository) AddFromDirectory(dir string, pluginTypes ...Type) error {
|
||||||
|
plugins, err := Discover(dir, pluginTypes...)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, plugin := range plugins {
|
||||||
|
log.Debugf("added plugin: %q", plugin.Config.Name)
|
||||||
|
c.Add(plugin)
|
||||||
|
}
|
||||||
|
log.Debugf("%d plugins added", len(plugins))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Repository) Get(pluginType Type) []Plugin {
|
||||||
|
return c.byType[pluginType]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Repository) ActivateCatalogers() ([]cataloger.Cataloger, func(), error) {
|
||||||
|
var result []cataloger.Cataloger
|
||||||
|
var plugins []Plugin
|
||||||
|
var deactivateFn = func() {
|
||||||
|
for _, plugin := range plugins {
|
||||||
|
if err := plugin.Stop(); err != nil {
|
||||||
|
log.Errorf("failed to stop plugin: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, plugin := range c.Get(TypeCataloger) {
|
||||||
|
raw, err := plugin.Start()
|
||||||
|
if err != nil {
|
||||||
|
return nil, deactivateFn, err
|
||||||
|
}
|
||||||
|
plugins = append(plugins, plugin)
|
||||||
|
|
||||||
|
theCataloger, ok := raw.(cataloger.Cataloger)
|
||||||
|
if !ok {
|
||||||
|
return nil, deactivateFn, fmt.Errorf("activation of cataloger did not return a cataloger object (name=%s type=%T)", plugin.Config.Name, theCataloger)
|
||||||
|
}
|
||||||
|
|
||||||
|
result = append(result, theCataloger)
|
||||||
|
}
|
||||||
|
return result, deactivateFn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func Discover(dir string, pluginTypes ...Type) ([]Plugin, error) {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
if len(pluginTypes) == 0 {
|
||||||
|
pluginTypes = AllTypes
|
||||||
|
}
|
||||||
|
|
||||||
|
if !filepath.IsAbs(dir) {
|
||||||
|
dir, err = filepath.Abs(dir)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var plugins []Plugin
|
||||||
|
|
||||||
|
for _, pluginType := range pluginTypes {
|
||||||
|
pluginPrefix := pluginType.String()
|
||||||
|
pluginGlob := fmt.Sprintf("%s-*", pluginPrefix)
|
||||||
|
paths, err := filepath.Glob(filepath.Join(dir, pluginGlob))
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, path := range paths {
|
||||||
|
// TODO: should we use a config for some of this?
|
||||||
|
plugins = append(plugins, NewPlugin(Config{
|
||||||
|
// TODO: should the name be org/name instead of just name? this implies changing the dir storage too
|
||||||
|
Name: strings.TrimPrefix(filepath.Base(path), pluginPrefix+"-"),
|
||||||
|
Type: pluginType,
|
||||||
|
Command: path,
|
||||||
|
Args: nil, // TODO
|
||||||
|
Env: nil, // TODO
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return plugins, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package plugin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/hashicorp/go-plugin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var AllTypes = []Type{
|
||||||
|
TypeCataloger,
|
||||||
|
}
|
||||||
|
|
||||||
|
type Type uint64
|
||||||
|
|
||||||
|
const (
|
||||||
|
TypeUnknown Type = iota
|
||||||
|
TypeCataloger
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p Type) String() string {
|
||||||
|
switch p {
|
||||||
|
case TypeCataloger:
|
||||||
|
return "cataloger"
|
||||||
|
default:
|
||||||
|
return "unknown"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Type) HandshakeConfig() plugin.HandshakeConfig {
|
||||||
|
switch p {
|
||||||
|
case TypeCataloger:
|
||||||
|
return plugin.HandshakeConfig{
|
||||||
|
ProtocolVersion: 1,
|
||||||
|
MagicCookieKey: "SYFT_PLUGIN_MAGIC_COOKIE",
|
||||||
|
MagicCookieValue: "0f86cc7f-6f97-410e-a844-087cd12e36e3",
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic(fmt.Errorf("plugin type unsupported"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseType(pluginType string) Type {
|
||||||
|
switch pluginType {
|
||||||
|
case "cataloger":
|
||||||
|
return TypeCataloger
|
||||||
|
default:
|
||||||
|
return TypeUnknown
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package scope
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/anchore/stereoscope/pkg/file"
|
"github.com/anchore/stereoscope/pkg/file"
|
||||||
"github.com/anchore/stereoscope/pkg/image"
|
"github.com/anchore/stereoscope/pkg/image"
|
||||||
@@ -16,7 +17,7 @@ type Resolver interface {
|
|||||||
|
|
||||||
// ContentResolver knows how to get file content for given file.References
|
// ContentResolver knows how to get file content for given file.References
|
||||||
type ContentResolver interface {
|
type ContentResolver interface {
|
||||||
MultipleFileContentsByRef(f ...file.Reference) (map[file.Reference]string, error)
|
MultipleFileContentsByRef(f ...file.Reference) (map[file.Reference]io.Reader, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// FileResolver knows how to get file.References for given string paths and globs
|
// FileResolver knows how to get file.References for given string paths and globs
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package resolvers
|
|||||||
import (
|
import (
|
||||||
"archive/tar"
|
"archive/tar"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/anchore/stereoscope/pkg/file"
|
"github.com/anchore/stereoscope/pkg/file"
|
||||||
"github.com/anchore/stereoscope/pkg/image"
|
"github.com/anchore/stereoscope/pkg/image"
|
||||||
@@ -111,6 +112,6 @@ func (r *AllLayersResolver) FilesByGlob(patterns ...string) ([]file.Reference, e
|
|||||||
|
|
||||||
// MultipleFileContentsByRef returns the file contents for all file.References relative to the image. Note that a
|
// MultipleFileContentsByRef returns the file contents for all file.References relative to the image. Note that a
|
||||||
// file.Reference is a path relative to a particular layer.
|
// file.Reference is a path relative to a particular layer.
|
||||||
func (r *AllLayersResolver) MultipleFileContentsByRef(f ...file.Reference) (map[file.Reference]string, error) {
|
func (r *AllLayersResolver) MultipleFileContentsByRef(f ...file.Reference) (map[file.Reference]io.Reader, error) {
|
||||||
return r.img.MultipleFileContentsByRef(f...)
|
return r.img.MultipleFileContentsByRef(f...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package resolvers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
@@ -40,15 +40,6 @@ func (s DirectoryResolver) FilesByPath(userPaths ...file.Path) ([]file.Reference
|
|||||||
return references, nil
|
return references, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileContents(path file.Path) ([]byte, error) {
|
|
||||||
contents, err := ioutil.ReadFile(string(path))
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return contents, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// FilesByGlob returns all file.References that match the given path glob pattern from any layer in the image.
|
// FilesByGlob returns all file.References that match the given path glob pattern from any layer in the image.
|
||||||
func (s DirectoryResolver) FilesByGlob(patterns ...string) ([]file.Reference, error) {
|
func (s DirectoryResolver) FilesByGlob(patterns ...string) ([]file.Reference, error) {
|
||||||
result := make([]file.Reference, 0)
|
result := make([]file.Reference, 0)
|
||||||
@@ -76,15 +67,15 @@ func (s DirectoryResolver) FilesByGlob(patterns ...string) ([]file.Reference, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MultipleFileContentsByRef returns the file contents for all file.References relative a directory.
|
// MultipleFileContentsByRef returns the file contents for all file.References relative a directory.
|
||||||
func (s DirectoryResolver) MultipleFileContentsByRef(f ...file.Reference) (map[file.Reference]string, error) {
|
func (s DirectoryResolver) MultipleFileContentsByRef(f ...file.Reference) (map[file.Reference]io.Reader, error) {
|
||||||
refContents := make(map[file.Reference]string)
|
refContents := make(map[file.Reference]io.Reader)
|
||||||
for _, fileRef := range f {
|
for _, fileRef := range f {
|
||||||
contents, err := fileContents(fileRef.Path)
|
targetFile, err := os.Open(string(fileRef.Path))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return refContents, fmt.Errorf("could not read contents of file: %s", fileRef.Path)
|
return refContents, fmt.Errorf("could not open file=%q: %w", fileRef.Path, err)
|
||||||
}
|
}
|
||||||
refContents[fileRef] = string(contents)
|
|
||||||
|
refContents[fileRef] = targetFile
|
||||||
}
|
}
|
||||||
return refContents, nil
|
return refContents, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package resolvers
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
"github.com/anchore/stereoscope/pkg/file"
|
"github.com/anchore/stereoscope/pkg/file"
|
||||||
"github.com/anchore/stereoscope/pkg/image"
|
"github.com/anchore/stereoscope/pkg/image"
|
||||||
@@ -75,6 +76,6 @@ func (r *ImageSquashResolver) FilesByGlob(patterns ...string) ([]file.Reference,
|
|||||||
|
|
||||||
// MultipleFileContentsByRef returns the file contents for all file.References relative to the image. Note that a
|
// MultipleFileContentsByRef returns the file contents for all file.References relative to the image. Note that a
|
||||||
// file.Reference is a path relative to a particular layer, in this case only from the squashed representation.
|
// file.Reference is a path relative to a particular layer, in this case only from the squashed representation.
|
||||||
func (r *ImageSquashResolver) MultipleFileContentsByRef(f ...file.Reference) (map[file.Reference]string, error) {
|
func (r *ImageSquashResolver) MultipleFileContentsByRef(f ...file.Reference) (map[file.Reference]io.Reader, error) {
|
||||||
return r.img.MultipleFileContentsByRef(f...)
|
return r.img.MultipleFileContentsByRef(f...)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user