sync vulnscan db changes

This commit is contained in:
Alex Goodman 2020-06-28 07:22:27 -04:00
parent 0eb5faff32
commit 92cf98ab12
No known key found for this signature in database
GPG key ID: 86E2870463D5E890
17 changed files with 92 additions and 632 deletions

View file

@ -13,7 +13,7 @@ endif
.PHONY: all boostrap lint lint-fix unit coverage integration build-release
all: lint unit integration
all: lint unit # integration
@printf '$(SUCCESS)All checks pass!$(RESET)\n'
bootstrap:
@ -49,9 +49,10 @@ coverage:
# TODO: add benchmarks
integration:
@printf '$(TITLE)Running integration tests...$(RESET)\n'
go test -tags=integration ./integration
# TODO: add me back in when there are integration tests
#integration:
# @printf '$(TITLE)Running integration tests...$(RESET)\n'
# go test -tags=integration ./integration
build-release:
go build -s -w -X main.version="$(git describe --tags --dirty --always)" \

9
go.mod
View file

@ -4,21 +4,24 @@ go 1.14
require (
github.com/adrg/xdg v0.2.1
github.com/anchore/go-feeds-client v0.0.0-20200624184141-4aef10511b59 // indirect
github.com/anchore/go-testutils v0.0.0-20200520222037-edc2bf1864fe
github.com/anchore/imgbom v0.0.0-20200616171024-2cb7dad96784
github.com/anchore/stereoscope v0.0.0-20200616152009-189722bdb61b
github.com/anchore/vulnscan-db v0.0.0-20200604185950-6a9f5a2c9ddf
github.com/go-test/deep v1.0.6
github.com/anchore/vulnscan-db v0.0.0-20200628111346-8c1d0888ed4c
github.com/go-test/deep v1.0.6 // indirect
github.com/hashicorp/go-getter v1.4.1
github.com/hashicorp/go-version v1.2.0
github.com/hashicorp/go-version v1.2.1
github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a
github.com/knqyf263/go-deb-version v0.0.0-20190517075300-09fca494f03d
github.com/knqyf263/go-version v1.1.1
github.com/lib/pq v1.7.0 // indirect
github.com/mitchellh/go-homedir v1.1.0
github.com/sergi/go-diff v1.1.0
github.com/spf13/afero v1.3.0
github.com/spf13/cobra v1.0.0
github.com/spf13/viper v1.7.0
go.etcd.io/bbolt v1.3.4 // indirect
go.uber.org/zap v1.15.0
gopkg.in/yaml.v2 v2.3.0
)

32
go.sum
View file

@ -108,6 +108,10 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/anchore/go-feeds-client v0.0.0-20200608121036-d9c3f68622a7 h1:IpwJkSqsmdZHN6CmUYNKKx5J25J3g/6yzwRmpvERqhQ=
github.com/anchore/go-feeds-client v0.0.0-20200608121036-d9c3f68622a7/go.mod h1:sugnhPPnoDCFWKzmQxSj444vF3T6UTiCdMLn8YZLyVg=
github.com/anchore/go-feeds-client v0.0.0-20200624184141-4aef10511b59 h1:5JcA8PnPVAiXo9M71HjnHncmUfI1ZnAeb0Dq+i/K2i8=
github.com/anchore/go-feeds-client v0.0.0-20200624184141-4aef10511b59/go.mod h1:sugnhPPnoDCFWKzmQxSj444vF3T6UTiCdMLn8YZLyVg=
github.com/anchore/go-testutils v0.0.0-20200520222037-edc2bf1864fe h1:YMXe4RA3qy4Ri5fmGQii/Gn+Pxv3oBfiS/LqzeOVuwo=
github.com/anchore/go-testutils v0.0.0-20200520222037-edc2bf1864fe/go.mod h1:D3rc2L/q4Hcp9eeX6AIJH4Q+kPjOtJCFhG9za90j+nU=
github.com/anchore/imgbom v0.0.0-20200616171024-2cb7dad96784 h1:s9zoF5uqN8rvp6TBtFgwIoBsP6gwhqaCw43XfELh3C4=
@ -116,8 +120,15 @@ github.com/anchore/stereoscope v0.0.0-20200520221116-025e07f1c93e h1:QBwtrM0MXi0
github.com/anchore/stereoscope v0.0.0-20200520221116-025e07f1c93e/go.mod h1:bkyLl5VITnrmgErv4S1vDfVz/TGAZ5il6161IQo7w2g=
github.com/anchore/stereoscope v0.0.0-20200616152009-189722bdb61b h1:LmFKsQi4oj2VJjch7JhQNzJg1A56FjwHqWZz1ZZKgIw=
github.com/anchore/stereoscope v0.0.0-20200616152009-189722bdb61b/go.mod h1:eQ2/Al6XDA7RFk3FVfpjyGRErITRjNciUPIWixHc7kQ=
github.com/anchore/vulnscan v0.0.0-20200624185207-0eb5faff321b/go.mod h1:q/wqDUtsNxQrES8leqrgd9Oz5+tGXiFl6W2VCUdlOmI=
github.com/anchore/vulnscan-db v0.0.0-20200604185950-6a9f5a2c9ddf h1:U1KgI8Lk6acUjjmtBLWOCoL9U7AV8tFmHnqAtFikJ7E=
github.com/anchore/vulnscan-db v0.0.0-20200604185950-6a9f5a2c9ddf/go.mod h1:OVROq5+BT+g+ES+heRewy7NU2f147o2QyMortckSXek=
github.com/anchore/vulnscan-db v0.0.0-20200624185237-d8f13b221624/go.mod h1:3uEIvOc8ikZOp1ztNu9fGqmF3fmZFg04W4BYcFViXwA=
github.com/anchore/vulnscan-db v0.0.0-20200628111346-8c1d0888ed4c h1:luiggQQg6sj5QcLbmT8XejcdYDZGXaK1eQbnWh5ydwU=
github.com/anchore/vulnscan-db v0.0.0-20200628111346-8c1d0888ed4c/go.mod h1:dYygVCcr2YyhYCRjI85oDVnppbC5nIjA6YVTNOi473g=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apex/log v1.1.4/go.mod h1:AlpoD9aScyQfJDVHmLMEcx4oU6LqzkWp4Mg9GdAcEvQ=
github.com/apex/log v1.3.0/go.mod h1:jd8Vpsr46WAe3EZSQ/IUMs2qQD/GOycT5rPWCO1yGcs=
github.com/apex/logs v0.0.4/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo=
@ -383,6 +394,8 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.2.2/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gookit/color v1.2.4/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg=
github.com/gookit/color v1.2.5 h1:s1gzb/fg3HhkSLKyWVUsZcVBUo+R1TwEYTmmxH8gGFg=
github.com/gookit/color v1.2.5/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 h1:twflg0XRTjwKpxb/jFExr4HGq6on2dEOmnL6FV+fgPw=
@ -432,6 +445,8 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.2.1 h1:zEfKbn2+PDgroKdiOzqiE8rsmLqU2uwi5PB5pBJ3TkI=
github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
@ -475,6 +490,8 @@ github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/X
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 h1:qGQQKEcAR99REcMpsXCp3lJ03zYT1PkRd3kQGPn9GVg=
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
@ -505,6 +522,7 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.5.2/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381 h1:bqDmpDG49ZRnB5PcgP0RXtQvnMSgIF14M7CBd2shtXs=
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
@ -528,6 +546,7 @@ github.com/mattn/go-ieproxy v0.0.1/go.mod h1:pYabZ6IHcRpFh7vIaLfK7rdcWgFEb3SFJ6/
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
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.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
@ -669,6 +688,7 @@ github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOms
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.5.0/go.mod h1:+F7Ogzej0PZc/94MaYx/nvG9jOFMD2osvC3s+Squfpo=
@ -761,6 +781,16 @@ github.com/valyala/quicktemplate v1.2.0/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOV
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
github.com/vdemeester/k8s-pkg-credentialprovider v1.17.4/go.mod h1:inCTmtUdr5KJbreVojo06krnTgaeAz/Z7lynpPk/Q2c=
github.com/vmware/govmomi v0.20.3/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
github.com/wagoodman/go-partybus v0.0.0-20200526224238-eb215533f07d h1:KOxOL6qpmqwoPloNwi+CEgc1ayjHNOFNrvoOmeDOjDg=
github.com/wagoodman/go-partybus v0.0.0-20200526224238-eb215533f07d/go.mod h1:JPirS5jde/CF5qIjcK4WX+eQmKXdPc6vcZkJ/P0hfPw=
github.com/wagoodman/go-progress v0.0.0-20200526224006-dd1404d54b0b h1:UDJoympq2F2QqhIu0wF6PtI+Apq1sW3TobBoZOrUTa8=
github.com/wagoodman/go-progress v0.0.0-20200526224006-dd1404d54b0b/go.mod h1:jLXFoL31zFaHKAAyZUh+sxiTDFe1L1ZHrcK2T1itVKA=
github.com/wagoodman/go-progress v0.0.0-20200621153512-2778c704bf22 h1:GYaiTP0ywrCjJ4qMxxCg+YKPSDMeFJg6i1X9X55LJCA=
github.com/wagoodman/go-progress v0.0.0-20200621153512-2778c704bf22/go.mod h1:jLXFoL31zFaHKAAyZUh+sxiTDFe1L1ZHrcK2T1itVKA=
github.com/wagoodman/jotframe v0.0.0-20200610174534-353b72d58795 h1:x8d69ZxmiQB58l+bg7Oxy7Vc3eazx5KWgZW2pxXDsBI=
github.com/wagoodman/jotframe v0.0.0-20200610174534-353b72d58795/go.mod h1:DzXZ1wfRedNhC3KQTick8Gf3CEPMFHsP5k4R/ldjKtw=
github.com/wagoodman/jotframe v0.0.0-20200622123948-2995cbd43525 h1:fGlwSBQrl9/axciK2+gJ9q86SeQYJpbPx4vOrExvZXY=
github.com/wagoodman/jotframe v0.0.0-20200622123948-2995cbd43525/go.mod h1:DzXZ1wfRedNhC3KQTick8Gf3CEPMFHsP5k4R/ldjKtw=
github.com/xanzy/go-gitlab v0.31.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug=
github.com/xanzy/go-gitlab v0.32.0/go.mod h1:sPLojNBn68fMUWSxIJtdVVIP8uSBYqesTfDUseX11Ug=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
@ -797,6 +827,7 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@ -915,6 +946,7 @@ golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190302025703-b6889370fb10/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View file

@ -55,9 +55,10 @@ func setNonCliDefaultValues(v *viper.Viper) {
v.SetDefault("log.structured", false)
// e.g. ~/.cache/appname/db
v.SetDefault("db.cache-dir", path.Join(xdg.CacheHome, internal.ApplicationName, "db"))
// TODO: change me to the production URL at release
// TODO: change me to the production URL before release
v.SetDefault("db.update-url", "http://localhost:5000/listing.json")
v.SetDefault("db.update-on-startup", true)
// TODO: set this to true before release
v.SetDefault("db.update-on-startup", false)
}
func LoadConfigFromFile(v *viper.Viper, cliOpts *CliOnlyOptions) (*Application, error) {

View file

@ -7,7 +7,8 @@ import (
"path"
"github.com/anchore/vulnscan-db/pkg/db"
"github.com/anchore/vulnscan-db/pkg/sqlite"
"github.com/anchore/vulnscan-db/pkg/db/curation"
"github.com/anchore/vulnscan-db/pkg/store/sqlite"
"github.com/anchore/vulnscan/internal/file"
"github.com/anchore/vulnscan/internal/log"
"github.com/hashicorp/go-version"
@ -16,7 +17,7 @@ import (
const (
supportedVersion = ">=1.0.0, <2.0.0"
dbFileName = "vulnerability.db"
FileName = db.StoreFileName
)
type Config struct {
@ -45,7 +46,7 @@ func NewCurator(cfg Config) (Curator, error) {
}, nil
}
func (c *Curator) GetStore() (db.VulnStore, error) {
func (c *Curator) GetStore() (db.VulnerabilityStoreReader, error) {
// ensure the DB is ok
err := c.Validate()
if err != nil {
@ -54,7 +55,7 @@ func (c *Curator) GetStore() (db.VulnStore, error) {
// provide an abstraction for the underlying store
connectOptions := sqlite.Options{
FilePath: path.Join(c.config.DbDir, dbFileName),
FilePath: path.Join(c.config.DbDir, FileName),
}
store, _, err := sqlite.NewStore(&connectOptions)
if err != nil {
@ -67,27 +68,27 @@ func (c *Curator) Delete() error {
return c.fs.RemoveAll(c.config.DbDir)
}
func (c *Curator) IsUpdateAvailable() (bool, *ListingEntry, error) {
func (c *Curator) IsUpdateAvailable() (bool, *curation.ListingEntry, error) {
log.Debugf("checking for available database updates")
listing, err := newListingFromURL(c.fs, c.client, c.config.ListingURL)
listing, err := curation.NewListingFromURL(c.fs, c.client, c.config.ListingURL)
if err != nil {
return false, nil, fmt.Errorf("failed to get listing file: %w", err)
}
updateEntry := listing.bestUpdate(c.versionConstraint)
updateEntry := listing.BestUpdate(c.versionConstraint)
if updateEntry == nil {
return false, nil, fmt.Errorf("no db candidates with correct version available (maybe there is an application update available?)")
}
log.Debugf("found database update candidate: %s", updateEntry)
// compare created data to current db date
current, err := newMetadataFromDir(c.fs, c.config.DbDir)
current, err := curation.NewMetadataFromDir(c.fs, c.config.DbDir)
if err != nil {
return false, nil, fmt.Errorf("current metadata corrupt: %w", err)
}
if current.isSupercededBy(updateEntry) {
if current.IsSupercededBy(updateEntry) {
log.Debugf("database update available: %s", updateEntry)
return true, updateEntry, nil
}
@ -113,7 +114,7 @@ func (c *Curator) Validate() error {
// return nil
// }
func (c *Curator) UpdateTo(listing *ListingEntry) error {
func (c *Curator) UpdateTo(listing *curation.ListingEntry) error {
// note: the temp directory is persisted upon download/validation/activation failure to allow for investigation
tempDir, err := c.download(listing)
if err != nil {
@ -133,7 +134,7 @@ func (c *Curator) UpdateTo(listing *ListingEntry) error {
return c.fs.RemoveAll(tempDir)
}
func (c *Curator) download(listing *ListingEntry) (string, error) {
func (c *Curator) download(listing *curation.ListingEntry) (string, error) {
// get a temp dir
tempDir, err := ioutil.TempDir("", "vulnscan-scratch")
if err != nil {
@ -160,7 +161,7 @@ func (c *Curator) download(listing *ListingEntry) (string, error) {
func (c *Curator) validate(dbDirPath string) error {
// check that the disk checksum still matches the db payload
metadata, err := newMetadataFromDir(c.fs, dbDirPath)
metadata, err := curation.NewMetadataFromDir(c.fs, dbDirPath)
if err != nil {
return fmt.Errorf("failed to parse database metadata (%s): %w", dbDirPath, err)
}
@ -168,7 +169,7 @@ func (c *Curator) validate(dbDirPath string) error {
return fmt.Errorf("database metadata not found: %s", dbDirPath)
}
dbPath := path.Join(dbDirPath, dbFileName)
dbPath := path.Join(dbDirPath, FileName)
valid, err := file.ValidateByHash(c.fs, dbPath, metadata.Checksum)
if err != nil {
return err

View file

@ -6,12 +6,20 @@ import (
"testing"
"time"
"github.com/anchore/vulnscan-db/pkg/db/curation"
"github.com/anchore/vulnscan/internal"
"github.com/anchore/vulnscan/internal/file"
"github.com/hashicorp/go-version"
"github.com/spf13/afero"
)
func mustUrl(u *url.URL, err error) *url.URL {
if err != nil {
panic(err)
}
return u
}
type testGetter struct {
file map[string]string
dir map[string]string
@ -60,13 +68,13 @@ func newTestCurator(fs afero.Fs, getter file.Getter, dbDir, metadataUrl string)
func TestCuratorDownload(t *testing.T) {
tests := []struct {
name string
entry *ListingEntry
entry *curation.ListingEntry
expectedURL string
err bool
}{
{
name: "download populates returned tempdir",
entry: &ListingEntry{
entry: &curation.ListingEntry{
Built: time.Date(2020, 06, 13, 17, 13, 13, 0, time.UTC),
URL: mustUrl(url.Parse("http://a-url/payload.tar.gz")),
Checksum: "sha256:deadbeefcafe",

View file

@ -1,82 +0,0 @@
package db
import (
"encoding/json"
"fmt"
"github.com/anchore/vulnscan/internal/file"
"github.com/anchore/vulnscan/internal/log"
"github.com/hashicorp/go-version"
"github.com/spf13/afero"
)
// TODO: move all of this to vulnscan-db
type Listing struct {
Latest ListingEntry `json:"latest"`
Available []ListingEntry `json:"available"`
}
func newListingFromPath(fs afero.Fs, path string) (Listing, error) {
f, err := fs.Open(path)
if err != nil {
return Listing{}, fmt.Errorf("unable to open DB listing path: %w", err)
}
defer f.Close()
var l Listing
err = json.NewDecoder(f).Decode(&l)
if err != nil {
return Listing{}, fmt.Errorf("unable to parse DB listing: %w", err)
}
return l, nil
}
func newListingFromURL(fs afero.Fs, getter file.Getter, listingURL string) (Listing, error) {
tempFile, err := afero.TempFile(fs, "", "vulnscan-listing")
if err != nil {
return Listing{}, fmt.Errorf("unable to create listing temp file: %w", err)
}
defer func() {
err := fs.RemoveAll(tempFile.Name())
if err != nil {
log.Errorf("failed to remove file (%s): %w", tempFile.Name(), err)
}
}()
// download the listing file
err = getter.GetFile(tempFile.Name(), listingURL)
if err != nil {
return Listing{}, fmt.Errorf("unable to download listing: %w", err)
}
// parse the listing file
listing, err := newListingFromPath(fs, tempFile.Name())
if err != nil {
return Listing{}, err
}
return listing, nil
}
func (l *Listing) bestUpdate(constraint version.Constraints) *ListingEntry {
// extract the latest available db
candidates := []ListingEntry{l.Latest}
candidates = append(candidates, l.Available...)
// TODO: sort candidates by version and built date
for _, candidate := range candidates {
log.Debugf("found update: %s", candidate)
}
var updateEntry *ListingEntry
for _, candidate := range candidates {
if constraint.Check(candidate.Version) {
copy := candidate
updateEntry = &copy
break
}
}
return updateEntry
}

View file

@ -1,67 +0,0 @@
package db
import (
"encoding/json"
"fmt"
"net/url"
"time"
"github.com/hashicorp/go-version"
)
// TODO: move all of this to vulnscan-db
type ListingEntry struct {
Built time.Time // RFC 3339
Version *version.Version
URL *url.URL
Checksum string
}
type ListingEntryJSON struct {
Built string `json:"built"`
Version string `json:"version"`
URL string `json:"url"`
Checksum string `json:"checksum"`
}
func (l ListingEntryJSON) ToListingEntry() (ListingEntry, error) {
build, err := time.Parse(time.RFC3339, l.Built)
if err != nil {
return ListingEntry{}, fmt.Errorf("cannot convert built time (%s): %+v", l.Built, err)
}
ver, err := version.NewVersion(l.Version)
if err != nil {
return ListingEntry{}, fmt.Errorf("cannot parse version (%s): %+v", l.Version, err)
}
u, err := url.Parse(l.URL)
if err != nil {
return ListingEntry{}, fmt.Errorf("cannot parse url (%s): %+v", l.URL, err)
}
return ListingEntry{
Built: build.UTC(),
Version: ver,
URL: u,
Checksum: l.Checksum,
}, nil
}
func (l *ListingEntry) UnmarshalJSON(data []byte) error {
var lej ListingEntryJSON
if err := json.Unmarshal(data, &lej); err != nil {
return err
}
le, err := lej.ToListingEntry()
if err != nil {
return err
}
*l = le
return nil
}
func (l ListingEntry) String() string {
return fmt.Sprintf("Listing(url=%s)", l.URL)
}

View file

@ -1,115 +0,0 @@
package db
import (
"net/url"
"testing"
"time"
"github.com/go-test/deep"
"github.com/hashicorp/go-version"
"github.com/spf13/afero"
)
func mustUrl(u *url.URL, err error) *url.URL {
if err != nil {
panic(err)
}
return u
}
func mustConst(u version.Constraints, err error) version.Constraints {
if err != nil {
panic(err)
}
return u
}
func TestNewListingFromPath(t *testing.T) {
tests := []struct {
fixture string
expected Listing
err bool
}{
{
fixture: "test-fixtures/listing.json",
expected: Listing{
Latest: ListingEntry{
Built: time.Date(2020, 06, 13, 17, 13, 13, 0, time.UTC),
URL: mustUrl(url.Parse("http://localhost:5000/vulnerability-db-v1.1.0+2020-6-13.tar.gz")),
Version: version.Must(version.NewVersion("1.1.0")),
Checksum: "sha256:dcd6a285c839a7c65939e20c251202912f64826be68609dfc6e48df7f853ddc8",
},
Available: []ListingEntry{
{
Built: time.Date(2020, 06, 12, 16, 12, 12, 0, time.UTC),
URL: mustUrl(url.Parse("http://localhost:5000/vulnerability-db-v0.2.0+2020-6-12.tar.gz")),
Version: version.Must(version.NewVersion("0.2.0")),
Checksum: "sha256:e20c251202948df7f853ddc812f64826bdcd6a285c839a7c65939e68609dfc6e",
},
},
},
},
}
for _, test := range tests {
t.Run(test.fixture, func(t *testing.T) {
listing, err := newListingFromPath(afero.NewOsFs(), test.fixture)
if err != nil && !test.err {
t.Fatalf("failed to get metadata: %+v", err)
} else if err == nil && test.err {
t.Fatalf("expected errer but got none")
}
for _, diff := range deep.Equal(listing, test.expected) {
t.Errorf("listing difference: %s", diff)
}
})
}
}
func TestListingBestUpdate(t *testing.T) {
tests := []struct {
fixture string
constraint version.Constraints
expected *ListingEntry
}{
{
fixture: "test-fixtures/listing.json",
constraint: mustConst(version.NewConstraint("> 1.0.0, < 2.0.0")),
expected: &ListingEntry{
Built: time.Date(2020, 06, 13, 17, 13, 13, 0, time.UTC),
URL: mustUrl(url.Parse("http://localhost:5000/vulnerability-db-v1.1.0+2020-6-13.tar.gz")),
Version: version.Must(version.NewVersion("1.1.0")),
Checksum: "sha256:dcd6a285c839a7c65939e20c251202912f64826be68609dfc6e48df7f853ddc8",
},
},
{
fixture: "test-fixtures/listing.json",
constraint: mustConst(version.NewConstraint("> 0.0.0, < 1.0.0")),
expected: &ListingEntry{
Built: time.Date(2020, 06, 12, 16, 12, 12, 0, time.UTC),
URL: mustUrl(url.Parse("http://localhost:5000/vulnerability-db-v0.2.0+2020-6-12.tar.gz")),
Version: version.Must(version.NewVersion("0.2.0")),
Checksum: "sha256:e20c251202948df7f853ddc812f64826bdcd6a285c839a7c65939e68609dfc6e",
},
},
}
for _, test := range tests {
t.Run(test.constraint.String(), func(t *testing.T) {
listing, err := newListingFromPath(afero.NewOsFs(), test.fixture)
if err != nil {
t.Fatalf("failed to get metadata: %+v", err)
}
actual := listing.bestUpdate(test.constraint)
if actual == nil && test.expected != nil || actual != nil && test.expected == nil {
t.Fatalf("mismatched best candidate expectations")
}
for _, diff := range deep.Equal(actual, test.expected) {
t.Errorf("listing entry difference: %s", diff)
}
})
}
}

View file

@ -1,110 +0,0 @@
package db
import (
"encoding/json"
"fmt"
"path"
"time"
"github.com/anchore/vulnscan/internal/file"
"github.com/anchore/vulnscan/internal/log"
"github.com/hashicorp/go-version"
"github.com/spf13/afero"
)
const metadataFileName = "metadata.json"
type Metadata struct {
Built time.Time
Version *version.Version
Checksum string
}
type MetadataJSON struct {
Built string `json:"built"` // RFC 3339
Version string `json:"version"`
Checksum string `json:"checksum"`
}
func (m MetadataJSON) ToMetadata() (Metadata, error) {
build, err := time.Parse(time.RFC3339, m.Built)
if err != nil {
return Metadata{}, fmt.Errorf("cannot convert built time (%s): %+v", m.Built, err)
}
ver, err := version.NewVersion(m.Version)
if err != nil {
return Metadata{}, fmt.Errorf("cannot parse version (%s): %+v", m.Version, err)
}
metadata := Metadata{
Built: build.UTC(),
Version: ver,
Checksum: m.Checksum,
}
return metadata, nil
}
func metadataPath(dir string) string {
return path.Join(dir, metadataFileName)
}
func newMetadataFromDir(fs afero.Fs, dir string) (*Metadata, error) {
metadataFilePath := metadataPath(dir)
if !file.Exists(fs, metadataFilePath) {
return nil, nil
}
f, err := fs.Open(metadataFilePath)
if err != nil {
return nil, fmt.Errorf("unable to open DB metadata path (%s): %w", metadataFilePath, err)
}
defer f.Close()
var m Metadata
err = json.NewDecoder(f).Decode(&m)
if err != nil {
return nil, fmt.Errorf("unable to parse DB metadata (%s): %w", metadataFilePath, err)
}
return &m, nil
}
func (m *Metadata) UnmarshalJSON(data []byte) error {
var mj MetadataJSON
if err := json.Unmarshal(data, &mj); err != nil {
return err
}
me, err := mj.ToMetadata()
if err != nil {
return err
}
*m = me
return nil
}
func (m *Metadata) isSupercededBy(entry *ListingEntry) bool {
if m == nil {
log.Debugf("cannot find existing metadata, using update...")
// any valid update beats no database, use it!
return true
}
if entry.Version.GreaterThan(m.Version) {
log.Debugf("update is a newer version than the current database, using update...")
// the listing is newer than the existing db, use it!
return true
}
if entry.Built.After(m.Built) {
log.Debugf("existing database (%s) is older than candidate update (%s), using update...", m.Built.String(), entry.Built.String())
// the listing is newer than the existing db, use it!
return true
}
log.Debugf("existing database is already up to date")
return false
}
func (m Metadata) String() string {
return fmt.Sprintf("Metadata(built=%s version=%s checksum=%s)", m.Built, m.Version, m.Checksum)
}

View file

@ -1,107 +0,0 @@
package db
import (
"testing"
"time"
"github.com/go-test/deep"
"github.com/hashicorp/go-version"
"github.com/spf13/afero"
)
func TestMetadataParse(t *testing.T) {
tests := []struct {
fixture string
expected Metadata
err bool
}{
{
fixture: "test-fixtures/metadata-gocase",
expected: Metadata{
Built: time.Date(2020, 06, 15, 14, 02, 36, 0, time.UTC),
Version: version.Must(version.NewVersion("0.2.0")),
Checksum: "sha256:dcd6a285c839a7c65939e20c251202912f64826be68609dfc6e48df7f853ddc8",
},
},
{
fixture: "test-fixtures/metadata-edt-timezone",
expected: Metadata{
Built: time.Date(2020, 06, 15, 18, 02, 36, 0, time.UTC),
Version: version.Must(version.NewVersion("0.2.0")),
Checksum: "sha256:dcd6a285c839a7c65939e20c251202912f64826be68609dfc6e48df7f853ddc8",
},
},
}
for _, test := range tests {
t.Run(test.fixture, func(t *testing.T) {
metadata, err := newMetadataFromDir(afero.NewOsFs(), test.fixture)
if err != nil && !test.err {
t.Fatalf("failed to get metadata: %+v", err)
} else if err == nil && test.err {
t.Fatalf("expected errer but got none")
}
if metadata == nil {
t.Fatalf("metadata not found: %+v", test.fixture)
}
for _, diff := range deep.Equal(*metadata, test.expected) {
t.Errorf("metadata difference: %s", diff)
}
})
}
}
func TestMetadataIsSupercededBy(t *testing.T) {
tests := []struct {
name string
current *Metadata
update *ListingEntry
expectedToSupercede bool
}{
{
name: "prefer updated versions over later dates",
expectedToSupercede: true,
current: &Metadata{
Built: time.Date(2020, 06, 15, 14, 02, 36, 0, time.UTC),
Version: version.Must(version.NewVersion("0.2.0")),
},
update: &ListingEntry{
Built: time.Date(2020, 06, 13, 17, 13, 13, 0, time.UTC),
Version: version.Must(version.NewVersion("0.3.0")),
},
},
{
name: "prefer later dates when version is the same",
expectedToSupercede: false,
current: &Metadata{
Built: time.Date(2020, 06, 15, 14, 02, 36, 0, time.UTC),
Version: version.Must(version.NewVersion("1.1.0")),
},
update: &ListingEntry{
Built: time.Date(2020, 06, 13, 17, 13, 13, 0, time.UTC),
Version: version.Must(version.NewVersion("1.1.0")),
},
},
{
name: "prefer something over nothing",
expectedToSupercede: true,
current: nil,
update: &ListingEntry{
Built: time.Date(2020, 06, 13, 17, 13, 13, 0, time.UTC),
Version: version.Must(version.NewVersion("1.1.0")),
},
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
actual := test.current.isSupercededBy(test.update)
if test.expectedToSupercede != actual {
t.Errorf("failed supercede assertion: got %+v", actual)
}
})
}
}

View file

@ -1,16 +0,0 @@
{
"latest": {
"built": "2020-06-13T13:13:13-04:00",
"version": "1.1.0",
"url": "http://localhost:5000/vulnerability-db-v1.1.0+2020-6-13.tar.gz",
"checksum": "sha256:dcd6a285c839a7c65939e20c251202912f64826be68609dfc6e48df7f853ddc8"
},
"available": [
{
"built": "2020-06-12T12:12:12-04:00",
"version": "0.2.0",
"url": "http://localhost:5000/vulnerability-db-v0.2.0+2020-6-12.tar.gz",
"checksum": "sha256:e20c251202948df7f853ddc812f64826bdcd6a285c839a7c65939e68609dfc6e"
}
]
}

View file

@ -1,7 +0,0 @@
{
"built": "2020-06-15T14:02:36-04:00",
"updated": "2020-06-15T14:02:36-04:00",
"last-check": "2020-06-15T14:02:36-04:00",
"version": "0.2.0",
"checksum": "sha256:dcd6a285c839a7c65939e20c251202912f64826be68609dfc6e48df7f853ddc8"
}

View file

@ -1,5 +0,0 @@
{
"built": "2020-06-15T14:02:36Z",
"version": "0.2.0",
"checksum": "sha256:dcd6a285c839a7c65939e20c251202912f64826be68609dfc6e48df7f853ddc8"
}

View file

@ -2,8 +2,6 @@ package vulnerability
import (
"fmt"
"regexp"
"strings"
"github.com/anchore/imgbom/imgbom/distro"
"github.com/anchore/imgbom/imgbom/pkg"
@ -12,12 +10,12 @@ import (
)
type StoreProvider struct {
store db.VulnStore
store db.VulnerabilityStoreReader
// TODO: allows the ability to have a db cache for keeping rich objects around
// or to have a sync.Pool of warm objects
}
func NewProviderFromStore(store db.VulnStore) *StoreProvider {
func NewProviderFromStore(store db.VulnerabilityStoreReader) *StoreProvider {
return &StoreProvider{
store: store,
}
@ -27,7 +25,7 @@ func (pr *StoreProvider) GetByDistro(d distro.Distro, p *pkg.Package) ([]*Vulner
vulns := make([]*Vulnerability, 0)
namespace := distroNamespace(d)
allPkgVulns, err := pr.store.Get(namespace, p.Name)
allPkgVulns, err := pr.store.GetVulnerability(namespace, p.Name)
if err != nil {
return nil, fmt.Errorf("provider failed to fetch namespace='%s' pkg='%s': %w", namespace, p.Name, err)
}
@ -35,24 +33,14 @@ func (pr *StoreProvider) GetByDistro(d distro.Distro, p *pkg.Package) ([]*Vulner
for _, vuln := range allPkgVulns {
format := version.ParseFormat(vuln.VersionFormat)
// TODO: delete me, this should be implemented in the vulnscan-db repo
var prefix string
if vuln.Version == "None" {
vuln.Version = ""
}
if format == version.DpkgFormat && vuln.Version != "" {
prefix = "< "
}
// </TODO>
constraint, err := version.GetConstraint(prefix+vuln.Version, format)
constraint, err := version.GetConstraint(vuln.VersionConstraint, format)
if err != nil {
return nil, fmt.Errorf("provider failed to parse distro='%s' constraint='%s' format='%s': %w", d, vuln.Version, format, err)
return nil, fmt.Errorf("provider failed to parse distro='%s' constraint='%s' format='%s': %w", d, vuln.VersionConstraint, format, err)
}
vulns = append(vulns, &Vulnerability{
Constraint: constraint,
ID: vuln.VulnerabilityID,
ID: vuln.ID,
})
}
@ -68,7 +56,7 @@ func (pr *StoreProvider) GetByLanguage(l pkg.Language, p *pkg.Package) ([]*Vulne
}
for _, namespace := range namespaces {
allPkgVulns, err := pr.store.Get(namespace, p.Name)
allPkgVulns, err := pr.store.GetVulnerability(namespace, p.Name)
if err != nil {
return nil, fmt.Errorf("provider failed to fetch namespace='%s' pkg='%s': %w", namespace, p.Name, err)
}
@ -76,38 +64,17 @@ func (pr *StoreProvider) GetByLanguage(l pkg.Language, p *pkg.Package) ([]*Vulne
for _, vuln := range allPkgVulns {
format := version.ParseFormat(vuln.VersionFormat)
// TODO: delete me, this should be implemented in the vulnscan-db repo
if format == version.SemanticFormat && vuln.Version != "" {
vuln.Version = forceSemVerConstraint(vuln.Version)
}
// </TODO>
constraint, err := version.GetConstraint(vuln.Version, format)
constraint, err := version.GetConstraint(vuln.VersionConstraint, format)
if err != nil {
return nil, fmt.Errorf("provider failed to parse language='%s' constraint='%s' format='%s': %w", l, vuln.Version, format, err)
return nil, fmt.Errorf("provider failed to parse language='%s' constraint='%s' format='%s': %w", l, vuln.VersionConstraint, format, err)
}
vulns = append(vulns, &Vulnerability{
Constraint: constraint,
ID: vuln.VulnerabilityID,
ID: vuln.ID,
})
}
}
return vulns, nil
}
// match examples:
// >= 5.0.0
// <= 6.1.2.beta
// >= 5.0.0
// < 6.1
// > 5.0.0
// >=5
// <6
var forceSemVerPattern = regexp.MustCompile(`[><=]+\s*[^<>=]+`)
// TODO: delete me once implemented in vulnscan-db
func forceSemVerConstraint(ver string) string {
return strings.Join(forceSemVerPattern.FindAllString(ver, -1), ", ")
}

View file

@ -18,27 +18,27 @@ func (d *mockStore) stub() {
d.data["debian:8"] = map[string][]db.Vulnerability{
"neutron": {
{
Name: "neutron",
NamespaceName: "debian:8",
Version: "2014.1.3-6",
VulnerabilityID: "CVE-2014-fake-1",
VersionFormat: "dpkg",
PackageName: "neutron",
Namespace: "debian:8",
VersionConstraint: "< 2014.1.3-6",
ID: "CVE-2014-fake-1",
VersionFormat: "dpkg",
},
{
Name: "neutron",
NamespaceName: "debian:8",
Version: "2013.0.2-1",
VulnerabilityID: "CVE-2013-fake-2",
VersionFormat: "dpkg",
PackageName: "neutron",
Namespace: "debian:8",
VersionConstraint: "< 2013.0.2-1",
ID: "CVE-2013-fake-2",
VersionFormat: "dpkg",
},
},
}
}
func (d *mockStore) Add(v *db.Vulnerability) error {
func (d *mockStore) AddVulnerability(v *db.Vulnerability) error {
return nil
}
func (d *mockStore) Get(namespace, name string) ([]db.Vulnerability, error) {
func (d *mockStore) GetVulnerability(namespace, name string) ([]db.Vulnerability, error) {
return d.data[namespace][name], nil
}

View file

@ -1,7 +1,6 @@
package vulnerability
import (
"fmt"
"testing"
"github.com/anchore/imgbom/imgbom/distro"
@ -51,46 +50,3 @@ func TestGetByDistro(t *testing.T) {
}
}
// TODO: delete me once implemented in vulnscan-db
func TestForceSemVerConstraint(t *testing.T) {
tests := []struct {
input string
expected string
}{
{
input: "> 5.0.0",
expected: "> 5.0.0",
},
{
input: ">= 5.0.0",
expected: ">= 5.0.0",
},
{
input: ">= 5.0.0 < 6.1",
expected: ">= 5.0.0 , < 6.1",
},
{
input: ">= 5.0.0 < 6.1.2",
expected: ">= 5.0.0 , < 6.1.2",
},
{
input: ">= 5 <= 6",
expected: ">= 5 , <= 6",
},
{
input: ">=5<6",
expected: ">=5, <6",
},
}
for _, test := range tests {
name := fmt.Sprintf("'%s'->'%s'", test.input, test.expected)
t.Run(name, func(t *testing.T) {
actual := forceSemVerConstraint(test.input)
if actual != test.expected {
t.Errorf("failed to force semver constraint: input='%s': '%s'!='%s'", test.input, test.expected, actual)
}
})
}
}