2021-08-13 02:27:09 +00:00
# Salty Dog
2019-06-15 23:07:46 +00:00
2021-08-13 04:00:05 +00:00
`salty-dog` is a tool to validate JSON and YAML data using JSON schema rules. It can filter elements and validate
select parts of the document, supports multiple documents in the same stream or file, and can insert defaults during
validation.
2019-06-25 03:32:39 +00:00
2022-04-24 23:12:05 +00:00
[Check out the getting started guide ](./docs/getting-started.md ).
2019-06-30 21:35:22 +00:00
2019-11-11 01:04:07 +00:00
## Contents
2021-08-13 02:27:09 +00:00
- [Salty Dog ](#salty-dog )
2019-11-11 01:04:07 +00:00
- [Contents ](#contents )
- [Status ](#status )
- [Releases ](#releases )
- [Build ](#build )
- [Usage ](#usage )
2021-08-13 04:00:05 +00:00
- [Using The Container ](#using-the-container )
- [Using The Package ](#using-the-package )
- [Project Package ](#project-package )
- [Global Package ](#global-package )
- [Usage Modes ](#usage-modes )
2019-11-11 01:04:07 +00:00
- [Check Mode ](#check-mode )
- [Fix Mode ](#fix-mode )
- [Default Values ](#default-values )
- [Coercing Values ](#coercing-values )
- [List Mode ](#list-mode )
2021-08-13 04:00:05 +00:00
- [Formatting Logs ](#formatting-logs )
- [Rules ](#rules )
- [Loading Rule Sources ](#loading-rule-sources )
- [Using Rule Tags ](#using-rule-tags )
- [Validating Rules ](#validating-rules )
2019-11-11 01:04:07 +00:00
- [License ](#license )
2019-06-30 18:40:02 +00:00
## Status
[![Pipeline status ](https://img.shields.io/gitlab/pipeline/ssube/salty-dog.svg?gitlab_url=https%3A%2F%2Fgit.apextoaster.com&logo=gitlab )](https://git.apextoaster.com/ssube/salty-dog/commits/master)
2019-11-01 11:03:44 +00:00
[![MIT license ](https://img.shields.io/github/license/ssube/salty-dog.svg )](https://github.com/ssube/salty-dog/blob/master/LICENSE.md)
2022-07-13 13:29:35 +00:00
[![Renovate badge ](https://img.shields.io/badge/renovate-enabled-brightgreen.svg )](https://renovatebot.com)
[![Known vulnerabilities ](https://snyk.io/test/github/ssube/salty-dog/badge.svg )](https://snyk.io/test/github/ssube/salty-dog)
2019-06-30 18:40:02 +00:00
[![Open bug count ](https://img.shields.io/github/issues-raw/ssube/salty-dog/type-bug.svg )](https://github.com/ssube/salty-dog/issues?q=is%3Aopen+is%3Aissue+label%3Atype%2Fbug)
[![Open issue count ](https://img.shields.io/github/issues-raw/ssube/salty-dog.svg )](https://github.com/ssube/salty-dog/issues?q=is%3Aopen+is%3Aissue)
[![Closed issue count ](https://img.shields.io/github/issues-closed-raw/ssube/salty-dog.svg )](https://github.com/ssube/salty-dog/issues?q=is%3Aissue+is%3Aclosed)
2022-07-13 13:29:35 +00:00
[![Lines of Code ](https://sonarcloud.io/api/project_badges/measure?project=ssube_salty-dog&metric=ncloc )](https://sonarcloud.io/dashboard?id=ssube_salty-dog)
[![Test coverage ](https://codecov.io/gh/ssube/salty-dog/branch/master/graph/badge.svg )](https://codecov.io/gh/ssube/salty-dog)
2019-06-30 18:40:02 +00:00
[![Technical debt ratio ](https://img.shields.io/codeclimate/tech-debt/ssube/salty-dog.svg )](https://codeclimate.com/github/ssube/salty-dog/trends/technical_debt)
2022-07-13 13:29:35 +00:00
[![Maintainability score ](https://api.codeclimate.com/v1/badges/5d4326d6f68a2fa137cd/maintainability )](https://codeclimate.com/github/ssube/salty-dog/maintainability)
2019-06-30 18:40:02 +00:00
[![Language grade: JavaScript ](https://img.shields.io/lgtm/grade/javascript/g/ssube/salty-dog.svg?logo=lgtm )](https://lgtm.com/projects/g/ssube/salty-dog/context:javascript)
2022-07-13 13:29:35 +00:00
[![Quality issues ](https://img.shields.io/codeclimate/issues/ssube/salty-dog.svg )](https://codeclimate.com/github/ssube/salty-dog/issues)
2019-06-30 18:40:02 +00:00
[![Total alerts ](https://img.shields.io/lgtm/alerts/g/ssube/salty-dog.svg )](https://lgtm.com/projects/g/ssube/salty-dog/alerts/)
2022-07-13 13:29:35 +00:00
[![FOSSA Status ](https://app.fossa.com/api/projects/git%2Bgithub.com%2Fssube%2Fsalty-dog.svg?type=shield )](https://app.fossa.com/projects/git%2Bgithub.com%2Fssube%2Fsalty-dog?ref=badge_shield)
2019-06-30 18:40:02 +00:00
## Releases
2019-11-11 00:17:53 +00:00
[![github release link ](https://img.shields.io/badge/github-release-blue?logo=github )](https://github.com/ssube/salty-dog/releases)
[![github release version ](https://img.shields.io/github/tag/ssube/salty-dog.svg )](https://github.com/ssube/salty-dog/releases)
2022-04-24 23:13:17 +00:00
[![github commits since release ](https://img.shields.io/github/commits-since/ssube/salty-dog/v0.9.1.svg )](https://github.com/ssube/salty-dog/compare/v0.8.0...master)
2019-06-30 18:40:02 +00:00
2019-11-11 00:17:53 +00:00
[![npm package link ](https://img.shields.io/badge/npm-package-blue?logo=npm )](https://www.npmjs.com/package/salty-dog)
2019-06-30 18:40:02 +00:00
[![npm release version ](https://img.shields.io/npm/v/salty-dog.svg )](https://www.npmjs.com/package/salty-dog)
2019-11-11 00:17:53 +00:00
[![Typescript definitions ](https://img.shields.io/npm/types/salty-dog.svg )](https://www.npmjs.com/package/salty-dog)
[![docker image link ](https://img.shields.io/badge/docker-image-blue?logo=docker )](https://hub.docker.com/r/ssube/salty-dog)
2021-08-13 02:39:03 +00:00
[![docker image size ](https://img.shields.io/docker/image-size/ssube/salty-dog?sort=semver )](https://microbadger.com/images/ssube/salty-dog:master)
2019-06-30 18:40:02 +00:00
2019-06-30 18:44:52 +00:00
## Build
2021-08-13 04:00:05 +00:00
`salty-dog` is written in Typescript and requires `make` , `node` , and `yarn` to build. It can be built locally or in
a container.
2019-10-31 12:35:01 +00:00
2021-08-13 04:00:05 +00:00
[Please see the build docs ](./docs/index.md#build ) for more details.
2019-06-30 18:44:52 +00:00
2021-08-13 04:00:05 +00:00
## Usage
2019-06-17 14:11:26 +00:00
2021-08-13 04:00:05 +00:00
`salty-dog` is distributed as a docker container and an npm package.
2019-06-29 22:21:22 +00:00
2021-08-13 04:00:05 +00:00
While the container is the preferred way of running `salty-dog` , it has one limitation: `docker run` combines
`stdout` and `stderr` , making it impossible to separate logs and the output document. Writing either the logs or dest
to a file works around this.
2019-06-17 14:11:26 +00:00
2021-08-13 04:00:05 +00:00
### Using The Container
2019-06-17 14:11:26 +00:00
2021-08-13 04:00:05 +00:00
To run the Docker container: `docker run --rm ssube/salty-dog:master`
2019-06-16 00:57:31 +00:00
2021-08-13 04:00:05 +00:00
The latest semi-stable image is published to `ssube/salty-dog:master` . Containers are published based on both Alpine
Linux and Debian (currently Stretch). All of the [available tags are listed here ](https://hub.docker.com/r/ssube/salty-dog/tags ).
2019-06-30 18:40:02 +00:00
2021-08-13 04:00:05 +00:00
Rules are provided in the image at `/salty-dog/rules` . To use custom rules in the container, mount them with
`-v $(pwd)/rules:/salty-dog/rules:ro` and load them with `--rules /rules/foo.yml` .
2019-06-30 18:40:02 +00:00
2021-08-13 04:00:05 +00:00
The `ssube/salty-dog` container image can be run normally or interactively.
2019-06-30 18:40:02 +00:00
2021-08-13 04:00:05 +00:00
To validate a file or input normally:
2019-06-30 18:40:02 +00:00
```shell
2021-08-13 04:00:05 +00:00
> docker run --rm ssube/salty-dog:master --help
2019-06-30 18:40:02 +00:00
```
2021-08-13 04:00:05 +00:00
You can also launch a shell within the container, using local rules:
2019-06-30 18:40:02 +00:00
```shell
2021-08-13 04:00:05 +00:00
> docker run \
--rm \
-it \
--entrypoint bash \
ssube/salty-dog:master
2019-06-30 18:40:02 +00:00
```
2021-08-13 04:00:05 +00:00
### Using The Package
2019-06-30 18:44:52 +00:00
2021-08-13 04:00:05 +00:00
`salty-dog` is also published as [an npm package ](https://www.npmjs.com/package/salty-dog ) with a binary, so it can
be used as a CLI command or programmatically.
2019-11-02 16:25:12 +00:00
2021-08-13 04:00:05 +00:00
#### Project Package
2019-11-02 16:25:12 +00:00
2021-08-13 04:00:05 +00:00
To install `salty-dog` for the current project:
2019-11-02 16:25:12 +00:00
2021-08-13 04:00:05 +00:00
```shell
> yarn add -D salty-dog
> $(yarn bin)/salty-dog --help
2019-11-02 16:25:12 +00:00
```
2021-08-13 04:00:05 +00:00
#### Global Package
2019-11-02 19:58:49 +00:00
2021-08-13 04:00:05 +00:00
It is also possible to install `salty-dog` globally, rather than within a project. However, this is
not recommended.
2019-11-02 19:58:49 +00:00
```shell
2021-08-13 04:00:05 +00:00
> yarn global add salty-dog
> export PATH="${PATH}:$(yarn global bin)"
> salty-dog --help
2019-11-02 19:58:49 +00:00
```
2019-11-02 16:25:12 +00:00
2021-08-13 04:00:05 +00:00
### Usage Modes
2019-06-30 18:40:02 +00:00
`salty-dog` can run in a few different modes: `check` mode will report errors, `fix` mode will attempt to modify the
input document, and `list` mode will print the active set of rules.
2019-06-30 18:44:52 +00:00
#### Check Mode
2019-06-16 02:08:21 +00:00
2019-06-25 03:32:39 +00:00
By default, `salty-dog` will validate the structure and contents of the `--source` document. If all rules pass, the
document will be printed to `--dest` .
2019-06-16 00:57:31 +00:00
2019-06-15 23:07:46 +00:00
```shell
2019-06-16 02:21:42 +00:00
> cat examples/kubernetes-resources-pass.yml | salty-dog \
2019-06-16 02:08:21 +00:00
--rules rules/kubernetes.yml \
2019-07-01 00:26:35 +00:00
--tag kubernetes
2019-06-15 23:56:42 +00:00
2019-06-16 02:08:21 +00:00
...
2019-06-15 23:56:42 +00:00
[2019-06-15T23:53:34.223Z] INFO: salty-dog/19839 on cerberus: all rules passed
2019-06-16 02:08:21 +00:00
2019-06-25 03:32:39 +00:00
> cat examples/kubernetes-resources-fail.yml | salty-dog \
2019-06-16 02:08:21 +00:00
--rules rules/kubernetes.yml \
2019-07-01 00:26:35 +00:00
--tag kubernetes
2019-06-16 02:08:21 +00:00
...
2019-06-25 03:32:39 +00:00
[2019-06-15T23:56:04.764Z] ERROR: salty-dog/22211 on cerberus: some rules failed (errors=1)
2019-06-16 02:08:21 +00:00
2019-06-25 03:32:39 +00:00
```
2019-06-16 02:08:21 +00:00
2019-06-25 03:32:39 +00:00
The `--source` and `--dest` default to stdin and stdout, respectively, but a path may be provided:
2019-06-16 02:08:21 +00:00
```shell
2019-06-25 03:32:39 +00:00
> salty-dog \
--rules rules/kubernetes.yml \
2019-07-01 00:26:35 +00:00
--tag kubernetes \
2019-06-25 03:32:39 +00:00
--source examples/kubernetes-resources-pass.yml \
--dest /tmp/kubernetes-resource.yml
2019-06-16 02:08:21 +00:00
...
2019-06-25 03:32:39 +00:00
[2019-06-15T23:53:34.223Z] INFO: salty-dog/19839 on cerberus: all rules passed
2019-06-16 02:08:21 +00:00
```
2019-06-30 18:44:52 +00:00
#### Fix Mode
2019-06-15 23:58:06 +00:00
2019-07-04 14:49:53 +00:00
`salty-dog` can also add default values to missing properties in `fix` mode. If a rule does not immediately pass
2019-06-25 03:32:39 +00:00
with the `--source` document, but defaults are provided in the schema, the defaults will be inserted before printing to
`--dest` .
2019-06-15 23:58:06 +00:00
2019-07-04 14:49:53 +00:00
```shell
> salty-dog fix \
--source examples/kubernetes-resources-some.yml \
--rules rules/kubernetes.yml \
--tag kubernetes
```
2019-06-30 18:44:52 +00:00
##### Default Values
2019-06-15 23:07:46 +00:00
2019-06-25 03:32:39 +00:00
Properties that appear in the schema with a `default` provided will be added to each element as it is checked. Rules
apply in order, as do their defaults.
2019-06-15 23:07:46 +00:00
2019-06-30 18:44:52 +00:00
##### Coercing Values
2019-06-15 23:07:46 +00:00
2019-06-25 03:32:39 +00:00
Properties that appear in the document with a different `type` than they have in the schema may be coerced, if the
value is compatible with the schema type. [The full matrix of valid type coercions ](https://ajv.js.org/coercion.html )
is documented by Ajv.
2019-06-15 23:07:46 +00:00
2019-06-30 18:44:52 +00:00
#### List Mode
2019-06-30 18:40:02 +00:00
2019-07-04 14:49:53 +00:00
`salty-dog` can list the active set of rules, to help debug tags and inclusion. Both `--source` and `--dest` are
ignored in `list` mode.
2019-06-30 18:40:02 +00:00
```shell
2019-07-04 14:49:53 +00:00
> salty-dog list \
2019-06-30 18:40:02 +00:00
--rules rules/kubernetes.yml \
2019-07-04 14:49:53 +00:00
--tag kubernetes
2019-06-30 18:40:02 +00:00
...
[2019-06-30T18:39:11.930Z] INFO: salty-dog/26330 on cerberus: listing active rules
rules: [
{
"desc": "resource limits are too low",
"level": "debug",
"name": "kubernetes-resources-minimum-cpu",
...
]
```
2021-08-13 04:00:05 +00:00
### Formatting Logs
2019-06-15 23:07:46 +00:00
2021-08-13 04:00:05 +00:00
`salty-dog` uses [node-bunyan ](https://github.com/trentm/node-bunyan ) for logging and prints structured JSON output.
Logs can be pretty-printed by redirecting `stderr` through `bunyan` itself or `jq` , both of which are installed in
the `salty-dog` container:
2019-06-15 23:07:46 +00:00
2021-08-13 04:00:05 +00:00
```shell
> cat resource.yml | salty-dog --rules rules/kubernetes.yml --tag kubernetes 2> >(bunyan)
2019-06-15 23:58:06 +00:00
2021-08-13 04:00:05 +00:00
...
[2019-06-15T23:53:34.223Z] INFO: salty-dog/19839 on cerberus: all rules passed
2019-06-15 23:07:46 +00:00
2021-08-13 04:00:05 +00:00
> cat resource.yml | salty-dog --rules rules/kubernetes.yml --tag kubernetes 2> >(jq)
2019-06-15 23:07:46 +00:00
2021-08-13 04:00:05 +00:00
...
{
"name": "salty-dog",
"hostname": "cerberus",
"pid": 19839,
"level": 30,
"msg": "all rules passed",
"time": "2019-06-15T23:53:34.223Z",
"v": 0
}
```
2019-06-15 23:07:46 +00:00
2021-08-13 04:00:05 +00:00
Using `jq` allows for additional filtering and formatting. For example, `jq 'select(.level > 30)'` will only print
warnings and errors (the minimum log level to print can be set in the configuration file).
2019-06-15 23:07:46 +00:00
2021-08-13 04:00:05 +00:00
To print the last line's message and error messages: `tail -1 | jq '[.msg, try (.errors[] | .msg)]'`
2019-06-25 23:46:05 +00:00
2021-08-13 04:00:05 +00:00
```shell
> cat test/examples/kubernetes-resources-high.yml | salty-dog \
--rules rules/kubernetes.yml \
--tag kubernetes 2> >(tail -1 | jq '[.msg, try (.errors[] | .msg)]')
2019-06-15 23:07:46 +00:00
2021-08-13 04:00:05 +00:00
[
"all rules passed"
]
> cat test/examples/kubernetes-resources-some.yml | salty-dog \
--rules rules/kubernetes.yml \
--tag kubernetes 2> >(tail -1 | jq '[.msg, try (.errors[] | .msg)]')
[
"some rules failed",
".resources.limits should have required property 'memory' at $.spec.template.spec.containers[*] for kubernetes-resources",
".metadata should have required property 'labels' at $ for kubernetes-labels"
]
```
## Rules
Rules combine a jsonpath expression and JSON schema to select and validate the document.
The rule's `select` expression is used to select nodes that should be validated, which are `filter` ed, then `check` ed.
The structure of rule files and the rules within them [are documented here ](docs/rules.md ).
### Loading Rule Sources
2019-11-10 04:48:15 +00:00
Rules can be loaded from a file, module, or path.
To load a file by name, `--rule-file foo.yml` . This will accept any extension.
To load a module, `--rule-module foo` . The required module exports [are documented here ](./docs/rules.md#from-module ).
To load a path, `--rule-path foo/` . This will recursively load any files matching `*.+(json|yaml|yml)` .
2021-08-13 04:00:05 +00:00
### Using Rule Tags
All rules are disabled by default and must be enabled by name, level, or tag.
To enable a single rule by name, `--include-name foo-rule` .
To enable a group of rules by level, `--include-level warn` .
To enable a group of rules by tag, `--include-tag foo` .
### Validating Rules
2019-06-15 23:07:46 +00:00
2019-06-25 03:32:39 +00:00
To validate the rules in the `rules/` directory using the meta-rules:
2019-06-15 23:07:46 +00:00
2019-06-25 03:32:39 +00:00
```shell
2019-07-02 13:42:48 +00:00
> make test-rules
2019-06-15 23:07:46 +00:00
2019-06-25 03:32:39 +00:00
...
{"name":"salty-dog","hostname":"cerberus","pid":29403,"level":30,"msg":"all rules passed","time":"2019-06-16T00:56:55.132Z","v":0}
2019-08-30 04:40:52 +00:00
```
2019-08-22 21:34:25 +00:00
## License
2019-11-11 01:04:07 +00:00
2019-08-30 04:40:52 +00:00
[![FOSSA Status ](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fssube%2Fsalty-dog.svg?type=large )](https://app.fossa.io/projects/git%2Bgithub.com%2Fssube%2Fsalty-dog?ref=badge_large)