jsonnet icon indicating copy to clipboard operation
jsonnet copied to clipboard

std.mergePatch loses hidden fields #2

Open dxlr8r opened this issue 2 years ago • 7 comments

Sorry for resurrecting an old thread. But I came a cross the same issue the other day. I use Jsonnet for Terraform, and the way I create modules using Jsonnet, and want to pass data between the modules (which are merged using std.mergePatch), hidden fields I want to lookup are missing after I merge them.

dxlr8r avatar Dec 02 '22 14:12 dxlr8r

Can't you make them non-hidden? Merge Patch doesn't have a concept of hidden fields because it's a JSON standard.

sparkprime avatar Dec 02 '22 15:12 sparkprime

Terraform is very particular with what fields it accept; so the short answer no. The longer answer is, yes of course there are workarounds. I have one implemented, but the code is far more readable, maintainable less DRY without it. Now I have to add several lines of boilerplate per module.

dxlr8r avatar Dec 02 '22 15:12 dxlr8r

Can you use the language's mixin support instead of std.mergePatch?

sparkprime avatar Dec 28 '22 14:12 sparkprime

That would be very difficult. In this case, I want to merge several sources. Some of those sources are jsonnet, and there mixin can be used. Others are HCL converted to JSON, one could perhaps write some code to edit the JSON and add + where needed, but that seems like a dirty hack.

dxlr8r avatar Jan 20 '23 15:01 dxlr8r

you could write a wrapper that imports the json and uses it to build an object that will mix together nicely

sparkprime avatar Feb 02 '23 15:02 sparkprime

I could, many different workarounds one could think of. Personally I believe people would except std.mergePatch to merge Jsonnet objects. My alternatives for my use case is to either create a recursive function that merges Jsonnet objects, which would work like std.mergePatch but without deleting hidden fields, or wait for std.mergePatch to be updated.

dxlr8r avatar Feb 02 '23 18:02 dxlr8r

i have come up to the function like this to solve import from json to make it a jsonnet object

local main       = import 'lib/main.libsonnet';
local overrides  = std.parseJson(importstr 'etc/config.json'); // for safe import

// reference to the helpful comment because of the missing documentation https://stackoverflow.com/a/76149084
local jsonnet_object(o) = {
    [c.key]+: if std.isObject(c.value) then jsonnet_object(c.value) else c.value
    for c in std.objectKeysValues(o)
    if std.isObject(c.value)
} + {
  [c.key]: c.value
  for c in std.objectKeysValues(o)
  if !std.isObject(c.value)
};

local config     =  main {config+: jsonnet_object(overrides.config)};

serge-salamanka avatar Feb 12 '24 01:02 serge-salamanka