diff --git a/Cargo.toml b/Cargo.toml index 032b25b..02ad159 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ categories = ["command-line-utilities", "parsing"] [[bin]] doc = false -name = "yq" +name = "whyq" path = "yq.rs" [dependencies] diff --git a/README.md b/README.md index 6d1188e..5e772cc 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # whyq - low overhead yq implementation -[![CI](https://github.com/clux/yq/actions/workflows/release.yml/badge.svg)](https://github.com/clux/yq/actions/workflows/release.yml) +[![CI](https://github.com/clux/whyq/actions/workflows/release.yml/badge.svg)](https://github.com/clux/whyq/actions/workflows/release.yml) [![Crates.io](https://img.shields.io/crates/v/whyq.svg)](https://crates.io/crates/whyq) [![dependency status](https://deps.rs/repo/github/clux/whyq/status.svg)](https://deps.rs/repo/github/clux/whyq) @@ -36,7 +36,7 @@ cargo binstall whyq - reads __multidoc yaml__ input, handles [yaml merge keys](https://yaml.org/type/merge.html) (expanding tags) - reads from __stdin xor file__ (file if last arg is a file) - output conversion shortcuts: `-y` (YAML) or `-t` (TOML) -- drop-in replacement to [python-yq](https://kislyuk.github.io/yq/) (`provides: yq`) +- drop-in replacement to [python-yq](https://kislyuk.github.io/yq/) (with `alias yq=whyq`) - ~[1MB](https://github.com/clux/whyq/releases/latest) in binary size (for small cloud CI images / [binstalled ci actions](https://github.com/cargo-bins/cargo-binstall#faq)) ### Limitations @@ -48,15 +48,16 @@ cargo binstall whyq - No XML/CSV support (or other more exotic formats) ## Usage + ### YAML Input Use as [jq](https://jqlang.github.io/jq/tutorial/) either via stdin: ```sh -$ yq '.[3].kind' -r < test/deploy.yaml +$ whyq '.[3].kind' -r < test/deploy.yaml Service -$ yq -y '.[3].metadata' < test/deploy.yaml +$ whyq -y '.[3].metadata' < test/deploy.yaml labels: app: controller name: controller @@ -66,15 +67,17 @@ namespace: default or from a file arg (at the end): ```sh -$ yq '.[3].kind' -r test/deploy.yaml -$ yq -y '.[3].metadata' test/deploy.yaml +$ whyq '.[3].kind' -r test/deploy.yaml +$ whyq -y '.[3].metadata' test/deploy.yaml ``` The default input format is YAML and is what the binary is named for (and the most common primary usage case). +If you want to use it as the top level `yq` executable you can `alias yq=whyq`. This should be compatible with `python-yq`, but have some differences with the go yq. + ### TOML Input -Using say `Cargo.toml` from this repo as input, and aliasing `tq='yq --input=toml'`: +Using say `Cargo.toml` from this repo as input, and aliasing `tq='whyq --input=toml'`: ```sh $ tq '.package.categories[]' -r < Cargo.toml @@ -96,14 +99,14 @@ $ tq '.profile' -c < Cargo.toml {"release":{"lto":true,"panic":"abort","strip":"symbols"}} ``` -Add `alias tq='yq --input=toml'` to your `.bashrc` or `.zshrc` (etc) to make this permanent if you find it useful. +Add `alias tq='whyq --input=toml'` to your `.bashrc` or `.zshrc` (etc) to make this permanent if you find it useful. ### JSON Input If you need to convert json to another format you pass `--input=json`: ```sh -$ yq --input=json '.ingredients | keys' -y < test/guacamole.json +$ whyq --input=json '.ingredients | keys' -y < test/guacamole.json - avocado - coriander - cumin @@ -119,7 +122,7 @@ $ yq --input=json '.ingredients | keys' -y < test/guacamole.json Select with nested query and raw output: ```sh -$ yq '.spec.template.spec.containers[].image' -r < test/grafana.yaml +$ whyq '.spec.template.spec.containers[].image' -r < test/grafana.yaml quay.io/kiwigrid/k8s-sidecar:1.24.6 quay.io/kiwigrid/k8s-sidecar:1.24.6 docker.io/grafana/grafana:10.1.0 @@ -128,20 +131,20 @@ docker.io/grafana/grafana:10.1.0 Select on multidoc: ```sh -$ yq -y '.[] | select(.kind == "Deployment") | .spec.template.spec.containers[0].ports[0].containerPort' test/deploy.yaml +$ whyq -y '.[] | select(.kind == "Deployment") | .spec.template.spec.containers[0].ports[0].containerPort' test/deploy.yaml 8000 ``` Escaping keys with slashes etc in them: ```sh -yq -y '.updates[] | select(.["package-ecosystem"] == "cargo") | .groups' .github/dependabot.yml +whyq -y '.updates[] | select(.["package-ecosystem"] == "cargo") | .groups' .github/dependabot.yml ``` Using helpers from `jq` [modules](https://jqlang.github.io/jq/manual/#modules) e.g. [k.jq](https://github.com/clux/whyq/blob/main/test/modules/k.jq): ```sh -$ yq 'include "k"; .[] | gvk' -r -L$PWD/test/modules < test/deploy.yaml +$ whyq 'include "k"; .[] | gvk' -r -L$PWD/test/modules < test/deploy.yaml v1.ServiceAccount rbac.authorization.k8s.io/v1.ClusterRole rbac.authorization.k8s.io/v1.ClusterRoleBinding @@ -159,7 +162,7 @@ If you pass on `-r`,`-c` or `-c` for raw/compact output, then this will generall The project respects `RUST_LOG` when set, and sends these diagnostic logs to stderr: ```sh -$ RUST_LOG=debug yq '.version' test/circle.yml +$ RUST_LOG=debug whyq '.version' test/circle.yml 2023-09-18T23:17:04.533055Z DEBUG yq: args: Args { input: Yaml, output: Jq, yaml_output: false, toml_output: false, in_place: false, jq_query: ".version", file: Some("test/circle.yml"), compact_output: false, raw_output: false, join_output: false, modules: None } 2023-09-18T23:17:04.533531Z DEBUG yq: found 1 documents 2023-09-18T23:17:04.533563Z DEBUG yq: input decoded as json: {"definitions":{"filters":{"on_every_commit":{"tags":{"only":"/.*/"}},"on_tag":{"branches":{"ignore":"/.*/"},"tags":{"only":"/v[0-9]+(\\.[0-9]+)*/"}}},"steps":[{"step":{"command":"chmod a+w . && cargo build --release","name":"Build binary"}},{"step":{"command":"rustc --version; cargo --version; rustup --version","name":"Version information"}}]},"jobs":{"build":{"docker":[{"image":"clux/muslrust:stable"}],"environment":{"IMAGE_NAME":"whyq"},"resource_class":"xlarge","steps":["checkout",{"run":{"command":"rustc --version; cargo --version; rustup --version","name":"Version information"}},{"run":{"command":"chmod a+w . && cargo build --release","name":"Build binary"}},{"run":"echo versions"}]},"release":{"docker":[{"image":"clux/muslrust:stable"}],"resource_class":"xlarge","steps":["checkout",{"run":{"command":"rustc --version; cargo --version; rustup --version","name":"Version information"}},{"run":{"command":"chmod a+w . && cargo build --release","name":"Build binary"}},{"upload":{"arch":"x86_64-unknown-linux-musl","binary_name":"${IMAGE_NAME}","source":"target/x86_64-unknown-linux-musl/release/${IMAGE_NAME}","version":"${CIRCLE_TAG}"}}]}},"version":2.1,"workflows":{"my_flow":{"jobs":[{"build":{"filters":{"tags":{"only":"/.*/"}}}},{"release":{"filters":{"branches":{"ignore":"/.*/"},"tags":{"only":"/v[0-9]+(\\.[0-9]+)*/"}}}}]},"version":2}} diff --git a/test/yq.test.bats b/test/yq.test.bats index 3b29fc6..f5aa5a6 100644 --- a/test/yq.test.bats +++ b/test/yq.test.bats @@ -1,7 +1,7 @@ #!/usr/bin/env bats @test "stdin" { - run yq -y '.[2].kind' < test/deploy.yaml + run whyq -y '.[2].kind' < test/deploy.yaml echo "$output" && echo "$output" | grep "ClusterRoleBinding" } @@ -9,99 +9,99 @@ if [[ "${CI}" =~ "true" ]]; then skip # isTerminal seems to do the wrong thing on github actions.. fi - yq -y '.[2].kind' test/deploy.yaml - run yq -y '.[2].kind' test/deploy.yaml + whyq -y '.[2].kind' test/deploy.yaml + run whyq -y '.[2].kind' test/deploy.yaml echo "$output" && echo "$output" | grep "ClusterRoleBinding" } @test "compact_json_output" { - run yq '.[2].metadata' -c < test/deploy.yaml + run whyq '.[2].metadata' -c < test/deploy.yaml echo "$output" && echo "$output" | grep '{"name":"controller"}' } @test "nested_select" { - run yq '.[] | select(.kind == "Deployment") | .spec.template.spec.containers[0].ports[0].containerPort' -r < test/deploy.yaml + run whyq '.[] | select(.kind == "Deployment") | .spec.template.spec.containers[0].ports[0].containerPort' -r < test/deploy.yaml echo "$output" && echo "$output" | grep "8000" } @test "nested_select_json" { - run yq '.[] | select(.kind == "Deployment") | .spec.template.spec.containers[0].readinessProbe' -c < test/deploy.yaml + run whyq '.[] | select(.kind == "Deployment") | .spec.template.spec.containers[0].readinessProbe' -c < test/deploy.yaml echo "$output" && echo "$output" | grep '{"httpGet":{"path":"/health","port":"http"},"initialDelaySeconds":5,"periodSeconds":5}' - run yq '.spec.template.spec.containers[].image' -r < test/grafana.yaml + run whyq '.spec.template.spec.containers[].image' -r < test/grafana.yaml } @test "jq_compat" { - cat test/deploy.yaml | yq '.[] | select(.kind == "Deployment") | .spec.template.spec.containers[0].readinessProbe' -c > test/output.json + cat test/deploy.yaml | whyq '.[] | select(.kind == "Deployment") | .spec.template.spec.containers[0].readinessProbe' -c > test/output.json run jq ".httpGet.path" test/output.json echo "$output" && echo "$output" | grep '"/health"' rm test/output.json } -@test "yq_in_place_edit" { - cat test/secret.yaml | yq -i '.metadata.name="updated-name"' > test/output.yaml - cat test/output.yaml | yq '.metadata.name' | grep 'updated-name' +@test "whyq_in_place_edit" { + cat test/secret.yaml | whyq -i '.metadata.name="updated-name"' > test/output.yaml + cat test/output.yaml | whyq '.metadata.name' | grep 'updated-name' rm test/output.yaml } @test "exit_codes" { - run yq -h + run whyq -h [ "$status" -eq 0 ] - run yq --help + run whyq --help [ "$status" -eq 0 ] if [[ "${CI}" =~ "true" ]]; then skip # ci is fun fi - run yq + run whyq [ "$status" -eq 1 ] } @test "toml" { - run yq --input=toml -y '.package.edition' -r < Cargo.toml + run whyq --input=toml -y '.package.edition' -r < Cargo.toml echo "$output" && echo "$output" | grep '2021' - run yq --input=toml '.dependencies.clap.features' -c < Cargo.toml + run whyq --input=toml '.dependencies.clap.features' -c < Cargo.toml echo "$output" && echo "$output" | grep '["cargo","derive"]' } @test "yaml_merge" { - run yq '.workflows.my_flow.jobs[0].build' -c < test/circle.yml + run whyq '.workflows.my_flow.jobs[0].build' -c < test/circle.yml echo "$output" && echo "$output" | grep '{"filters":{"tags":{"only":"/.*/"}}}' - run yq '.jobs.build.steps[1].run.name' -r < test/circle.yml + run whyq '.jobs.build.steps[1].run.name' -r < test/circle.yml echo "$output" && echo "$output" | grep "Version information" } @test "inplace" { - run yq -yi '.kind = "Hahah"' test/grafana.yaml - run yq -r .kind test/grafana.yaml + run whyq -yi '.kind = "Hahah"' test/grafana.yaml + run whyq -r .kind test/grafana.yaml echo "$output" && echo "$output" | grep "Hahah" - yq -yi '.kind = "Deployment"' test/grafana.yaml # undo + whyq -yi '.kind = "Deployment"' test/grafana.yaml # undo } @test "join" { - run yq -j '.spec.template.spec.containers[].image' test/grafana.yaml + run whyq -j '.spec.template.spec.containers[].image' test/grafana.yaml echo "$output" && echo "$output" | grep "quay.io/kiwigrid/k8s-sidecar:1.24.6quay.io/kiwigrid/k8s-sidecar:1.24.6docker.io/grafana/grafana:10.1.0" } @test "json_input" { - run yq --input=json ".ingredients | keys" -c < test/guacamole.json + run whyq --input=json ".ingredients | keys" -c < test/guacamole.json echo "$output" && echo "$output" | grep '["avocado","coriander","cumin","garlic","lime","onions","pepper","salt","tomatoes"]' } @test "jq_modules" { - run yq 'include "k"; . | gvk' -r -L$PWD/test/modules < test/grafana.yaml + run whyq 'include "k"; . | gvk' -r -L$PWD/test/modules < test/grafana.yaml echo "$output" && echo "$output" | grep 'apps/v1.Deployment' } @test "paramless" { - run yq -y <<< '["foo"]' + run whyq -y <<< '["foo"]' echo "$output" && echo "$output" | grep '\- foo' - run yq <<< '"bar"' + run whyq <<< '"bar"' echo "$output" && echo "$output" | grep '"bar"' } @test "multidoc-jq-output-to-yaml" { - run yq '.[].metadata.labels' -y test/deploy.yaml + run whyq '.[].metadata.labels' -y test/deploy.yaml echo "$output" && echo "$output" | rg -U '\- null\n- null\n- null\n- app: controller\n- app: controller' }