Search code examples
inheritanceimportjsonnet

Inheritance with jsonnet libraries


I have a question about the import functionality of JSONNet. What I would like is to be able to import one master libsonnet file, which itself is composed of multiple imports, and be able to access everything from that one import.

I have the following example structure:

.
├── library_one
│   └── init.libsonnet
├── library_two
│   └── init.libsonnet
├── init.libsonnet
└── test.jsonnet

With the following contents for each file:

library_one/init.libsonnet

{
  local LibraryOne = self,

  some_function(some_argument='default'):: [
    'echo "The argument was %s"' % some_argument,
  ],
}

library_two/init.libsonnet

{
  local LibraryTwo = self,

  some_other_function(some_other_argument='another_default'):: [
    'echo "The other argument was %s"' % some_other_argument,
  ],
}

And finally, the "master" file init.libsonnet at the root:

local library_one = import 'library_one/init.libsonnet';
local library_two = import 'library_two/init.libsonnet';

{}

However, when I run the file test.jsonnnet with the following contents:

local master = import 'init.libsonnet';

{
  some_key: master.library_one.some_function,
  some_other_key: master.library_two.some_other_function,
}

I get the error:

RUNTIME ERROR: field does not exist: library_one
    test.jsonnet:4:13-31    object <anonymous>
    During manifestation

Is this kind of inheritance not possible?


Solution

  • Please take a look at @jjo's answer first.

    I just wanted to add that it is possible and reasonable to structure your library, so that you have local "declarations" and then have it "exported" using an object, which I believe is similar to what you are describing.

    library.libsonnet:

    local sqr(x) = x * x;
    
    local cube(x): x * x * x;
    
    {
        sqr: sqr,
        cube: cube,
    }
    

    And then you can use like this:

    local lib = import 'library.libsonnet';
    
    [
        lib.sqr(2),
        lib.cube(3) + lib.sqr(4),
    ]
    

    This style can also be quite good for performance. You can take a look at a real world example here: https://github.com/sbarzowski/jsonnet-modifiers/blob/master/modifiers.libsonnet.

    And as for "master library", you can actually add the parts together in your init.libsonnet:

    local library_one = import 'library_one/init.libsonnet';
    local library_two = import 'library_two/init.libsonnet';
    
    library_one + library_two
    

    If library_one and library_two contain the same field, library_two will take precedence. You can read more about inheritance rules in Jsonnet on the official website: https://jsonnet.org/learning/tutorial.html#oo.