Skip to content

Commit

Permalink
[goss-org#355] Pivot to pure semver Matcher
Browse files Browse the repository at this point in the history
  • Loading branch information
pedroMMM committed Dec 10, 2019
1 parent 45519a7 commit 7eea531
Show file tree
Hide file tree
Showing 12 changed files with 500 additions and 722 deletions.
15 changes: 8 additions & 7 deletions docs/manual.md
Expand Up @@ -852,20 +852,21 @@ package:
contain-element: "4.1.0"
```

Custom version matcher are available `version-(eq|gt|ge|lt|le)`:
Custom semver matcher is available under `semver-constraint`:

```yaml
package:
kernel:
installed: true
versions:
version-gt: "4.0.0"
example:
content:
- 1.0.1
- 1.9.9
matches:
semver-constraint: ">1.0.0 <2.0.0 !=1.5.0"
```

For more information see:
* [gomega_test.go](https://github.com/aelsabbahy/goss/blob/master/resource/gomega_test.go) - For a complete set of supported json -> Gomega mapping
* [gomega](https://onsi.github.io/gomega/) - Gomega matchers reference
* [go-version](https://github.com/hashicorp/go-version) - Go Version syntax reference
* [semver](https://github.com/blang/semver#ranges) - Semver constraint (or range) syntax

## Templates

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -4,12 +4,12 @@ require (
github.com/achanda/go-sysctl v0.0.0-20160222034550-6be7678c45d2
github.com/aelsabbahy/GOnetstat v0.0.0-20160428114218-edf89f784e08
github.com/aelsabbahy/go-ps v0.0.0-20170721000941-443386855ca1
github.com/blang/semver v3.5.1+incompatible
github.com/cheekybits/genny v0.0.0-20160824153601-e8e29e67948b
github.com/docker/docker v0.0.0-20161109014415-383a2f046b16
github.com/fatih/color v0.0.0-20161025120501-bf82308e8c85
github.com/fsnotify/fsnotify v1.4.7 // indirect
github.com/golang/protobuf v1.3.2 // indirect
github.com/hashicorp/go-version v1.2.0
github.com/hpcloud/tail v1.0.0 // indirect
github.com/kr/pretty v0.1.0 // indirect
github.com/mattn/go-colorable v0.0.9 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Expand Up @@ -4,6 +4,8 @@ github.com/aelsabbahy/GOnetstat v0.0.0-20160428114218-edf89f784e08 h1:oD15ssIOuF
github.com/aelsabbahy/GOnetstat v0.0.0-20160428114218-edf89f784e08/go.mod h1:FETZSu2VGNDJbGfeRExaz/SNbX0TTaqJEMo1yvsKoZ8=
github.com/aelsabbahy/go-ps v0.0.0-20170721000941-443386855ca1 h1:s4dvLggvQOov0YFdv8XQvX+72TAFzfJg+6SgoXiIaq4=
github.com/aelsabbahy/go-ps v0.0.0-20170721000941-443386855ca1/go.mod h1:70tSBushy/POz6cCR294bKno4BNAC7XWVdkkxWQ1N6E=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/cheekybits/genny v0.0.0-20160824153601-e8e29e67948b h1:EaV7ZKUbpQK3eErRkV5GKl7s6SZU30dEB6gimH5BLLk=
github.com/cheekybits/genny v0.0.0-20160824153601-e8e29e67948b/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
Expand All @@ -16,8 +18,6 @@ github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
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/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
Expand Down
14 changes: 7 additions & 7 deletions integration-tests/goss/goss-shared.yaml
Expand Up @@ -55,18 +55,12 @@ file:
package:
foobar:
installed: false
{{- range $name, $ver := index .Vars .Env.OS "packages_apache"}}
{{- range $name, $ver := index .Vars .Env.OS "packages"}}
{{$name}}:
installed: true
versions:
- {{$ver}}
{{end}}
{{- range $name, $k := index .Vars .Env.OS "packages_bash"}}
{{$name}}:
installed: true
versions:
version-gt: 4.0.0
{{end}}
addr:
tcp://google.com:22:
reachable: false
Expand Down Expand Up @@ -217,3 +211,9 @@ matching:
- have-key-with-value:
foo: bar
- have-key: baz
semver:
content:
- 1.0.1
- 1.9.9
matches:
semver-constraint: ">1.0.0 <2.0.0 !=1.5.0"
19 changes: 5 additions & 14 deletions integration-tests/goss/vars.yaml
@@ -1,24 +1,15 @@
---
alpine3:
packages_bash:
bash: null
packages_apache:
packages:
apache2: "2.4.27-r1"
arch:
packages_bash:
bash: null
packages_apache:
packages:
centos7:
packages_bash:
bash: null
packages_apache:
packages:
httpd: "2.4.6"
precise:
packages_bash:
bash: null
packages_apache:
packages:
apache2: "2.2.22-1ubuntu1.11"
wheezy:
packages_bash:
packages_apache:
packages:
apache2: "2.2.22-13+deb7u13"
16 changes: 5 additions & 11 deletions integration-tests/test.sh
Expand Up @@ -43,17 +43,11 @@ trap "rv=\$?; docker rm -vf $id; exit \$rv" INT TERM EXIT
out=$(docker_exec "/goss/$os/goss-linux-$arch" --vars "/goss/vars.yaml" -g "/goss/$os/goss.yaml" validate)
echo "$out"

case $os in
"arch")
egrep -q 'Count: 83, Failed: 0, Skipped: 3' <<<"$out"
;;
"wheezy")
egrep -q 'Count: 97, Failed: 0, Skipped: 5' <<<"$out"
;;
*)
egrep -q 'Count: 99, Failed: 0, Skipped: 5' <<<"$out"
;;
esac
if [[ $os == "arch" ]]; then
egrep -q 'Count: 82, Failed: 0, Skipped: 3' <<<"$out"
else
egrep -q 'Count: 98, Failed: 0, Skipped: 5' <<<"$out"
fi

if [[ ! $os == "arch" ]]; then
docker_exec /goss/generate_goss.sh "$os" "$arch"
Expand Down
104 changes: 104 additions & 0 deletions matchers/semver_constraint.go
@@ -0,0 +1,104 @@
package matchers

import (
"fmt"
"reflect"

"github.com/blang/semver"
"github.com/onsi/gomega/format"
"github.com/onsi/gomega/types"
)

func BeSemverConstraint(constraint interface{}) types.GomegaMatcher {
return &BeSemverConstraintMatcher{
Constraint: constraint,
}
}

type BeSemverConstraintMatcher struct {
Constraint interface{}
}

func (matcher *BeSemverConstraintMatcher) Match(actual interface{}) (success bool, err error) {
constraint, ok := toConstraint(matcher.Constraint)
if !ok {
return false, fmt.Errorf("Expected a valid semver constraint. Got:\n%s", format.Object(matcher.Constraint, 1))
}

actualSlice, ok := toVersions(actual)
if !ok {
return false, fmt.Errorf("Expected a single or list of semver valid version(s). Got:\n%s", format.Object(actual, 1))
}

for _, v := range actualSlice {
if !constraint(*v) {
return false, nil
}
}

return true, nil
}

func (matcher *BeSemverConstraintMatcher) FailureMessage(actual interface{}) (message string) {
return format.Message(actual, fmt.Sprintf("to be %s", matcher.Constraint))
}

func (matcher *BeSemverConstraintMatcher) NegatedFailureMessage(actual interface{}) (message string) {
return format.Message(actual, fmt.Sprintf("not to be %s", matcher.Constraint))
}

func toConstraint(in interface{}) (semver.Range, bool) {
str, ok := in.(string)
if !ok {
return nil, false
}

out, err := semver.ParseRange(str)
return out, err == nil
}

func toVersion(in interface{}) (*semver.Version, bool) {
str, ok := in.(string)
if !ok {
return nil, false
}

v, err := semver.Parse(str)
if err != nil {
return nil, false
}

return &v, true
}

func toVersions(in interface{}) ([]*semver.Version, bool) {
if v, ok := toVersion(in); ok {
return []*semver.Version{v}, ok
}

if reflect.ValueOf(in).Kind() != reflect.Slice {
return nil, false
}

out := make([]*semver.Version, 0)

if slice, ok := in.([]interface{}); ok {
for _, ele := range slice {
if v, ok := toVersion(ele); ok {
out = append(out, v)
} else {
return nil, false
}
}
} else if slice, ok := in.([]string); ok {
for _, ele := range slice {
if v, ok := toVersion(ele); ok {
out = append(out, v)
} else {
return nil, false
}
}
}

return out, len(out) > 0
}

0 comments on commit 7eea531

Please sign in to comment.