Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle empty and null sources correctly #93

Merged
merged 3 commits into from Jul 6, 2018
Merged

Handle empty and null sources correctly #93

merged 3 commits into from Jul 6, 2018

Conversation

akshayjshah
Copy link
Contributor

We're currently handling empty (or comment-only) and null YAML sources
incorrectly. This diff fixes both by simplifying the configuration
provider even further.

These sources are problematic for two reasons. First, we're not
special-casing io.EOF errors when we use yaml.Decoder. More
insidiously, when we unmarshal sources, we're not distinguishing between
nil values caused by empty (or comment-only) sources and explicit
top-level nulls. The latter is particularly problematic because an
explicit null should be higher-priority than all defaults provided via
WithDefault, even if that null is itself overriden by another YAML
source. (For example, if base.yaml is just ~ and production.yaml
is foo: bar, the explicit top-level null in base.yaml should trump
any data supplied by WithDefault.)

This commit fixes these issues by making three interrelated changes:

  1. It changes all YAML options to eagerly consume io.Readers, and
    changes the internal representation of YAML sources to byte slices
    instead of readers. This simplifies later changes, since we'll be
    consuming each source multiple times.
  2. It special-cases io.EOF errors where appropriate, taking care to
    distinguish empty sources and explicit nulls.
  3. It changes WithDefault's internals to match the documentation: the
    implementation literally uses the user-supplied value as the
    lowest-priority search and deep-merges it with all other sources.

We're currently handling empty (or comment-only) and null YAML sources
incorrectly. This diff fixes both by simplifying the configuration
provider even further.

These sources are problematic for two reasons. First, we're not
special-casing `io.EOF` errors when we use `yaml.Decoder`. More
insidiously, when we unmarshal sources, we're not distinguishing between
nil values caused by empty (or comment-only) sources and explicit
top-level nulls. The latter is particularly problematic because an
explicit null should be higher-priority than all defaults provided via
`WithDefault`, even if that null is itself overriden by another YAML
source. (For example, if `base.yaml` is just `~` and `production.yaml`
is `foo: bar`, the explicit top-level null in `base.yaml` should trump
any data supplied by `WithDefault`.)

This commit fixes these issues by making three interrelated changes:

1. It changes all YAML options to eagerly consume `io.Reader`s, and
   changes the internal representation of YAML sources to byte slices
   instead of readers. This simplifies later changes, since we'll be
   consuming each source multiple times.
2. It special-cases `io.EOF` errors where appropriate, taking care to
   distinguish empty sources and explicit nulls.
3. It changes `WithDefault`'s internals to match the documentation: the
   implementation literally uses the user-supplied value as the
   lowest-priority search and deep-merges it with all other sources.
@codecov
Copy link

codecov bot commented Jul 6, 2018

Codecov Report

Merging #93 into master will decrease coverage by 1.19%.
The diff coverage is 77.41%.

Impacted file tree graph

@@            Coverage Diff            @@
##           master      #93     +/-   ##
=========================================
- Coverage   95.54%   94.35%   -1.2%     
=========================================
  Files           8        8             
  Lines         382      390      +8     
=========================================
+ Hits          365      368      +3     
- Misses         11       14      +3     
- Partials        6        8      +2
Impacted Files Coverage Δ
internal/merge/merge.go 96.72% <100%> (+0.35%) ⬆️
option.go 88.63% <64.28%> (-11.37%) ⬇️
config.go 89.92% <75%> (-0.23%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e2c8245...2d1536f. Read the comment docs.

option.go Outdated
all, err := ioutil.ReadAll(f)
if err != nil {
return failed(err)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we close the file here after reading from it instead of relying on the closers?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great point, will fix.

Since we're eagerly reading configuration files now, we don't need to
keep a slice of `io.Closers`. This also simplifies `NewYAML`.
@akshayjshah akshayjshah merged commit 0cbcc7b into master Jul 6, 2018
@akshayjshah akshayjshah deleted the ajs/eof branch July 6, 2018 20:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants