goss-org / goss

Quick and Easy server testing/validation
https://goss.rocks
Apache License 2.0
5.6k stars 473 forks source link

Add "structured data" resource #981

Closed sed-i closed 1 month ago

sed-i commented 1 month ago

Describe the feature: Server validation often involves structured data, such as json/yaml/toml. Being able to assert against objects inside some structured data could obviate the need for bespoke goss resources.

Describe the solution you'd like A general purpose resource for poking into structured data and making exact/contains assertions. For example:

structured-data:
  format: json  # another option: yaml
  source:
    command: "juju status --format=json"
    # mutually exclusive option: url
  mode: contains  # another option: exact-match
  assertions:
    ".applications | keys":  # this is a standard jq-style query
      - prom
      - alertmanager
    ".applications.prom.relations | keys":
      - alertmanager
      - prometheus-peers

Describe alternatives you've considered While we can certainly use the command resource for those checks, on a larger scale it may result in checks that are not maintainable.

aelsabbahy commented 1 month ago

Can you provide an example json and checks you're making?

Goss has a gjson matcher, which may meet your needs.

You can use it against the stdout of a command.

sed-i commented 1 month ago

I was not aware of gjson, looks incredible @aelsabbahy. A trimmed down json sample is below.

json sample ```json { "model": { "name": "welcome-k8s" }, "applications": { "am": { "charm": "alertmanager-k8s", "base": { "name": "ubuntu", "channel": "20.04" }, "relations": { "alerting": [ { "related-application": "prom", "interface": "alertmanager_dispatch", "scope": "global" } ], "replicas": [ { "related-application": "am", "interface": "alertmanager_replica", "scope": "global" } ] }, "version": "0.27.0" }, "prom": { "charm": "prometheus-k8s", "base": { "name": "ubuntu", "channel": "20.04" }, "relations": { "alertmanager": [ { "related-application": "am", "interface": "alertmanager_dispatch", "scope": "global" } ], "prometheus-peers": [ { "related-application": "prom", "interface": "prometheus_peers", "scope": "global" } ] }, "version": "2.52.0" } } } } ```

I tried to run the following:

command:
  app-names:
    exec: juju status --format=json
    exit-status: 0
    stdout:
      gjson:
        applications:
          and:
            - {have-key: "prom"}
            - {have-key: "am"}
        application.prom.relations:
          and:
            - {have-key: "alertmanager"}

But got a nil pointer deref.

goss -g check2.yaml validate
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x84e53b]

goroutine 7 [running]:
github.com/goss-org/goss/matchers.(*AndMatcher).FailureResult(0x4119db?, {0x0?, 0x0?})
    /home/travis/gopath/src/github.com/goss-org/goss/matchers/and.go:32 +0x5b
github.com/goss-org/goss/matchers.(*WithSafeTransformMatcher).FailureResult(0xb567f8?, {0xa676c0, 0xc000382110})
    /home/travis/gopath/src/github.com/goss-org/goss/matchers/with_safe_transform.go:45 +0x1bc
github.com/goss-org/goss/matchers.(*AndMatcher).FailureResult(0x0?, {0xa676c0?, 0xc000382110?})
    /home/travis/gopath/src/github.com/goss-org/goss/matchers/and.go:32 +0x62
github.com/goss-org/goss/resource.ValidateGomegaValue({_, _}, {_, _}, {_, _}, {_, _}, _)
    /home/travis/gopath/src/github.com/goss-org/goss/resource/validate.go:199 +0x788
github.com/goss-org/goss/resource.ValidateValue({_, _}, {_, _}, {_, _}, {_, _}, _)
    /home/travis/gopath/src/github.com/goss-org/goss/resource/validate.go:126 +0x174
github.com/goss-org/goss/resource.(*Command).Validate(0xc0000bc380, 0xc0000be0b0)
    /home/travis/gopath/src/github.com/goss-org/goss/resource/command.go:65 +0x3bd
github.com/goss-org/goss.validate.func2()
    /home/travis/gopath/src/github.com/goss-org/goss/validate.go:184 +0x86
created by github.com/goss-org/goss.validate in goroutine 1
    /home/travis/gopath/src/github.com/goss-org/goss/validate.go:181 +0x187

Likely I got the syntax wrong?

sed-i commented 1 month ago

Oops, a typo on my part

-application.prom.relations:
+applications.prom.relations:

This works fine:

command:
  app-names:
    exec: juju status --format=json
    exit-status: 0
    stdout:
      gjson:
        applications:
          and:
            - {have-key: "prom"}
            - {have-key: "am"}
        applications.prom.relations:
          and:
            - {have-key: "alertmanager"}
sed-i commented 1 month ago

Filed #982 with a minimal repro. Closing this issue, as the requested feature already exists.