kontena / mortar

The manifest shooter for Kubernetes
Apache License 2.0
145 stars 14 forks source link

Fix --var variables merging into config file variables #97

Closed KevinFUA closed 5 years ago

KevinFUA commented 5 years ago

Context

Note: Run with ruby 2.5.3

We're planning to have a series of configuration files (shot.yaml, shot-prod.yaml, etc.) and then override some values at deploy time using the --var option.

So trying this out with:

mortar --fire -c shot.yaml --var components.server.image.tag=finalfinalv4

# shot.yaml
variables:
  components:
    server:
      replicaCount: 3
      image:
        ..
        tag: finalfinalv3
        ..

What we would expect is that the tag value gets updated to finalfinalv4 while other values stay the same

However what we get is:

ERROR: NoMethodError : undefined method `replicaCount' for nil:NilClass (...yaml:14)

See: 'mortar fire --help'

Issue

This seems to be a bug caused by a discrepancy in between the outputs of YAML.safe_load and variables_hash

YAML outputs a hash of string keys variables_hash outputs a hash with symbol keys

Which means in Config.variables when it runs deep_merge! we get:

yaml_vars = { 'a' => { 'b' => 3 } }
var_vars = { :a => { :c => 3 } }
merged_vars = yaml_vars.dup.deep_merge!(var_vars)
# { 'a' => { 'b' => 3 }, :a => { :c => 3 } }

When finally passed to RecursiveOpenStruct, it'll read from either the string or symbol version (typically the latter it seems like) which means it drops the values from the other.

Fix

This PR forces variables_hash to use string keys so the keys match with YAML.safe_load. This will result in deep_merge! properly merging the keys.