Skip to content

Commit

Permalink
Update specs and README
Browse files Browse the repository at this point in the history
  • Loading branch information
m-o-e committed Oct 8, 2023
1 parent e9d20fb commit 788c8e6
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 99 deletions.
37 changes: 15 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,36 +128,29 @@ Python expressions are **not** supported.
## Layering data from multiple sources

By default envcat reads variables only from your shell environment.
With `-i` you can additionally source data from YAML, JSON or TOML files.
With `-i` you can additionally source data from YAML, JSON or TOML files.
With `-s` you can override variables directly on the command line.

**Example:**
Both flags can be given multiple times.

**Examples:**

```bash
# Override an env-var via YAML file
$ export FOO=bar
$ echo "foo: batz" >demo.yaml
# Override vars with YAML file
$ export FOO=from_env
$ echo "foo: from_file" >demo.yaml
$ envcat -i env -i yaml:demo.yaml FOO
{"FOO":"batz"}

# We can also ignore the environment
# altogether and use only file sources.
$ envcat -i yaml:foo.yaml -i json:bar.json FOO
{"FOO":"batz"}
```

With `-s` you can overwrite values directly.
{"FOO":"from_file"}

**Example:**
# Override a var with `-s`
$ envcat -i env -i yaml:demo.yaml -s FOO=from_arg FOO
{"FOO":"from_arg"}

```bash
$ export FOO=bar
$ envcat -s FOO=batz HELLO
batz
# Layer data from foo.yaml, the environment,
# JSON from stdin and lastly override FOO
$ envcat -i yaml:foo.yaml -i env -i json:- -s FOO=bar [..]
```

`-s` takes precedence over all other data sources.


### Input normalization

envcat flattens the structure of data sourced via `-i` as follows.
Expand Down
37 changes: 15 additions & 22 deletions docs/templates/README.md.j2
Original file line number Diff line number Diff line change
Expand Up @@ -131,36 +131,29 @@ Python expressions are **not** supported.
## Layering data from multiple sources

By default envcat reads variables only from your shell environment.
With `-i` you can additionally source data from YAML, JSON or TOML files.
With `-i` you can additionally source data from YAML, JSON or TOML files.
With `-s` you can override variables directly on the command line.

**Example:**
Both flags can be given multiple times.

**Examples:**

```bash
# Override an env-var via YAML file
$ export FOO=bar
$ echo "foo: batz" >demo.yaml
# Override vars with YAML file
$ export FOO=from_env
$ echo "foo: from_file" >demo.yaml
$ envcat -i env -i yaml:demo.yaml FOO
{"FOO":"batz"}

# We can also ignore the environment
# altogether and use only file sources.
$ envcat -i yaml:foo.yaml -i json:bar.json FOO
{"FOO":"batz"}
```

With `-s` you can overwrite values directly.
{"FOO":"from_file"}

**Example:**
# Override a var with `-s`
$ envcat -i env -i yaml:demo.yaml -s FOO=from_arg FOO
{"FOO":"from_arg"}

```bash
$ export FOO=bar
$ envcat -s FOO=batz HELLO
batz
# Layer data from foo.yaml, the environment,
# JSON from stdin and lastly override FOO
$ envcat -i yaml:foo.yaml -i env -i json:- -s FOO=bar [..]
```

`-s` takes precedence over all other data sources.


### Input normalization

envcat flattens the structure of data sourced via `-i` as follows.
Expand Down
43 changes: 43 additions & 0 deletions fixtures/input/test_normalized.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
NAME: John Doe
AGE: "30"
CITY: New York
HOBBIES_0: Reading
HOBBIES_1: Hiking
HOBBIES_2: Cooking
MATRIX_0_0: "1"
MATRIX_0_1: "2"
MATRIX_0_2: "3"
MATRIX_1_0: "4"
MATRIX_1_1: "5"
MATRIX_1_2: "6"
MATRIX_2_0: "7"
MATRIX_2_1: "8"
MATRIX_2_2: "9"
PEOPLE_0_NAME: Alice
PEOPLE_0_AGE: "25"
PEOPLE_1_NAME: Bob
PEOPLE_1_AGE: "28"
ADDRESS_STREET: 123 Main St
ADDRESS_CITY: Springfield
ADDRESS_ZIP: "12345"
EMPLOYEE_NAME: Jane Smith
EMPLOYEE_DEPARTMENT: HR
EMPLOYEE_CONTACT_EMAIL: [email protected]
EMPLOYEE_CONTACT_PHONE: 555-123-4567
EMPLOYEE_PROJECTS_0: Project A
EMPLOYEE_PROJECTS_1: Project B
EMPLOYEE_SKILLS_0: Skill 1
EMPLOYEE_SKILLS_1: Skill 2
COLORS_0: Red
COLORS_1: Green
COLORS_2: Blue
PERSON_FIRST_NAME: Mary
PERSON_LAST_NAME: Johnson
DESCRIPTION: 'This is a multi-line
description in YAML.
It can span multiple lines.
'
56 changes: 47 additions & 9 deletions spec/envcat/cli/input_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,59 @@ require "../../../src/envcat/cli"
require "digest/sha256"

describe Envcat::Cli do
describe "-i json:fixtures/input/test.json -s AGE=42" do
it "overwrites value from json" do
{% for fmt in %w[json yaml toml] %}
describe "-i {{fmt.id}}:fixtures/input/test.{{fmt.id}}" do
it "parses and normalizes {{fmt.id}}" do
expect_output(nil, nil) { |o, e, i|
Envcat::Cli.invoke(%w[-f kv -i json:fixtures/input/test.json -s AGE=42 AGE], o, e, i)
o.to_s.should eq("AGE=42\n")
Envcat::Cli.invoke(%w[-f yaml -i {{fmt.id}}:fixtures/input/test.{{fmt.id}} *], o, e, i)
fixture = YAML.parse(File.read("fixtures/input/test_normalized.yaml"))
YAML.parse(o.to_s).should eq(fixture)
}
end
end

describe "-s AGE=42 -i json:fixtures/input/test.json" do
it "overwrites value from json" do
expect_output(nil, nil) { |o, e, i|
Envcat::Cli.invoke(%w[-f kv -s AGE=42 -i json:fixtures/input/test.json AGE], o, e, i)
o.to_s.should eq("AGE=42\n")
describe "-i {{fmt.id}}:fixtures/input/test.invalid" do
it "prints error and exits with code 11 if parsing fails" do
expect_output(nil, /Malformed input.*is not valid {{fmt.id.upcase}}/) { |o, e, i|
expect_raises(Exit, "11") {
Envcat::Cli.invoke(%w[-f yaml -i {{fmt.id}}:fixtures/input/test.invalid *], o, e, i)
}
}
end
end

describe "-i {{fmt.id}}:fixtures/input/test.notfound" do
it "prints error and exits with code 7 if input file doesn't exist" do
expect_output(nil, /No such file or directory/) { |o, e, i|
expect_raises(Exit, "7") {
Envcat::Cli.invoke(%w[-f yaml -i {{fmt.id}}:fixtures/input/test.notfound *], o, e, i)
}
}
end
end
{% end %}

{% for fmt in %w[env- derp] %}
describe "-i {{fmt.id}}" do
it "prints error and exits with code 3 if argument to -i is invalid" do
expect_output(nil, /Unknown input type/) { |o, e, i|
expect_raises(Exit, "3") {
Envcat::Cli.invoke(%w[-i {{fmt.id}} *], o, e, i)
}
}
end
end
{% end %}

{% for fmt in %w[yaml yaml: json json: toml toml:] %}
describe "-i {{fmt.id}}" do
it "prints error and exits with code 3 if argument to -i misses path" do
expect_output(nil, /Path is required/) { |o, e, i|
expect_raises(Exit, "3") {
Envcat::Cli.invoke(%w[-i {{fmt.id}} *], o, e, i)
}
}
end
end
{% end %}
end
55 changes: 9 additions & 46 deletions spec/envcat/cli/set_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -3,58 +3,21 @@ require "../../../src/envcat/cli"
require "digest/sha256"

describe Envcat::Cli do
{% for fmt in %w[json yaml toml] %}
describe "-i {{fmt.id}}:fixtures/input/test.{{fmt.id}}" do
it "parses and normalizes {{fmt.id}}" do
describe "-i json:fixtures/input/test.json -s AGE=42" do
it "overwrites value from json" do
expect_output(nil, nil) { |o, e, i|
Envcat::Cli.invoke(%w[-f yaml -i {{fmt.id}}:fixtures/input/test.{{fmt.id}} *], o, e, i)
Digest::SHA256.hexdigest(o.to_s.split("\n").sort.join("\n")).should eq("66dc73717712ef4ed7ac7fa0cd1ccad48c67b718c038fb9c2f852c10e52e77d6")
Envcat::Cli.invoke(%w[-f kv -i json:fixtures/input/test.json -s AGE=42 AGE], o, e, i)
o.to_s.should eq("AGE=42\n")
}
end
end

describe "-i {{fmt.id}}:fixtures/input/test.invalid" do
it "prints error and exits with code 11 if parsing fails" do
expect_output(nil, /Malformed input.*is not valid {{fmt.id.upcase}}/) { |o, e, i|
expect_raises(Exit, "11") {
Envcat::Cli.invoke(%w[-f yaml -i {{fmt.id}}:fixtures/input/test.invalid *], o, e, i)
}
}
end
end

describe "-i {{fmt.id}}:fixtures/input/test.notfound" do
it "prints error and exits with code 7 if input file doesn't exist" do
expect_output(nil, /No such file or directory/) { |o, e, i|
expect_raises(Exit, "7") {
Envcat::Cli.invoke(%w[-f yaml -i {{fmt.id}}:fixtures/input/test.notfound *], o, e, i)
}
}
end
end
{% end %}

{% for fmt in %w[env- derp] %}
describe "-i {{fmt.id}}" do
it "prints error and exits with code 3 if argument to -i is invalid" do
expect_output(nil, /Unknown input type/) { |o, e, i|
expect_raises(Exit, "3") {
Envcat::Cli.invoke(%w[-i {{fmt.id}} *], o, e, i)
}
}
end
end
{% end %}

{% for fmt in %w[yaml yaml: json json: toml toml:] %}
describe "-i {{fmt.id}}" do
it "prints error and exits with code 3 if argument to -i misses path" do
expect_output(nil, /Path is required/) { |o, e, i|
expect_raises(Exit, "3") {
Envcat::Cli.invoke(%w[-i {{fmt.id}} *], o, e, i)
}
describe "-s AGE=42 -i json:fixtures/input/test.json" do
it "overwrites value from json" do
expect_output(nil, nil) { |o, e, i|
Envcat::Cli.invoke(%w[-f kv -s AGE=42 -i json:fixtures/input/test.json AGE], o, e, i)
o.to_s.should eq("AGE=42\n")
}
end
end
{% end %}
end

0 comments on commit 788c8e6

Please sign in to comment.