jsonnet
jsonnet copied to clipboard
jsonnet file argument does not use the importer (and doesn't respect jpath).
jsonnet v0.15.0 does not scan library folders.
When folder specified using -J | --jpath
, only current working directory is searched for the given filename.
I have found in the code that also /usr/local/share/jsonnet-<version>
and /usr/share/jsonnet-<version>
should be scanned for jsonnet "libraries". https://github.com/google/jsonnet/blob/v0.15.0/core/libjsonnet.cpp#L184
root@e99caf4f0657:/tmp# jsonnet -v
Jsonnet commandline interpreter v0.15.0
root@e99caf4f0657:/tmp# mkdir /usr/local/share/jsonnet-0.15.0
root@e99caf4f0657:/tmp# touch /usr/local/share/jsonnet-0.15.0/somefileinfoobarbaz
root@e99caf4f0657:/tmp# strace -s 2048 -f -E JSONNET_PATH=./foobarbaz jsonnet --jpath ./foobarbaz -J ./foobarbaz -- somefileinfoobarbaz |& grep foobarbaz
execve("/go/bin/jsonnet", ["jsonnet", "--jpath", "./foobarbaz", "-J", "./foobarbaz", "--", "somefileinfoobarbaz"], 0x558d1eb83340 /* 11 vars */) = 0
[pid 694] openat(AT_FDCWD, "somefileinfoobarbaz", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
[pid 694] write(2, "Opening input file: somefileinfoobarbaz: no such file or directory\n", 67 <unfinished ...>
Opening input file: somefileinfoobarbaz: no such file or directory
Hmmm... Thanks for reporting, but it works on my machine™. Could you say more about your setup and the exact steps to reproduce?
Well I tried it in some container I found on the web...
docker run -ti quay.io/coreos/jsonnet-ci bash
And run the following inside the container, but you can try the same command on your machine, just replace apt with your package manager if you don't have strace already installed.
apt update && apt install -y strace
jsonnet --version
mkdir /usr/local/share/jsonnet-0.15.0
touch /usr/local/share/jsonnet-0.15.0/somefileinfoobarbaz
cd /tmp/ && mkdir ./foobarbaz && touch somefileinfoobarbaz
strace -s 2048 -f -E JSONNET_PATH=./foobarbaz jsonnet --jpath ./foobarbaz -J ./foobarbaz -- somefileinfoobarbaz |& grep foobarbaz
The invocation
jsonnet --jpath ./foobarbaz -J ./foobarbaz -- somefileinfoobarbaz
Should mean that jsonnet searches for file in library ./foobarbaz with both argument variant from help:
-J / --jpath
Specify an additional library search dir (right-most wins)
Also, the strace sets up the environment variable JSONNET_PATH which is another way to define directories to search in.
The jsonnet program should then open the file somefileinfoobarbaz
in ./foobarbaz
or /usr/local/share/jsonnet-0.15.0
, but as seen from the strace output, none of the locations is searched.
The only path which is searched for somefileinfoobarbaz
is current directory
[pid 235809] openat(AT_FDCWD, "somefileinfoobarbaz", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory)
I was able to reproduce the behavior also my machine with jsonnet v0.17.0 :-(
Ah, I get it now.
This will work:
jsonnet --jpath ./foobarbaz -e 'import "somefileinfoobarbaz"'
This won't: `jsonnet --jpath ./foobarbaz somefileinfoobarbaz
JSONNET_PATH
and --jpath
are relevant for imported paths. The command does a direct filesystem lookup for the starting file.
I think always using the imports would make more sense, but it may also break some people. Maybe we can change that behavior, but it's not on top of my list. In the meantime you can easily work around it by using -e 'import "$YOUR_FILE"'
Thank you for the insight. I have checked the -e 'import "somefileinfoobarbaz"'
and I see the --jpath/-J works well, but all paths are tried, not the right-most as claimed in the usage ;-)
But I don't see the program try to open the file the at standard library path as defined in constructor at:
https://github.com/google/jsonnet/blob/v0.17.0/core/libjsonnet.cpp#L184
Perhaps I just do not understand well the C++ code :-) but the default_import_callback
should iterate all available paths but there is also some cpython_import_callback
which maybe overrides it's function.
Thank you for the insight. I have checked the -e 'import "somefileinfoobarbaz"' and I see the --jpath/-J works well, but all paths are tried, not the right-most as claimed in the usage ;-)
All of the paths are tried until a match is found (unless I'm missing something). If you get a match on first try, there will be no lookup in the remaining paths. So, yeah potentially all of them, but the leftmost component of JSONNET_PATH is tried first. Each --jpath
prepends to JSONNET_PATH, so the rightmost jpath is the leftmost JSONNET_PATH component.
AFAICT tt checks these global paths. Here's what I get when stracing trying to import a nonexistent file:
openat(AT_FDCWD, "foobar.libsonnet", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/local/share/jsonnet-v0.17.0/foobar.libsonnet", O_RDONLY) = -1 ENOENT (No such file or directory)
openat(AT_FDCWD, "/usr/share/jsonnet-v0.17.0/foobar.libsonnet", O_RDONLY) = -1 ENOENT (No such file or directory)
And when I actually put it at any of these paths, it works.
This has never been documented and people don't seem to depend on that. The Go implementation doesn't perform these global lookups (mostly because I was unaware of them until recently) and so far no one complained. For me personally, an explicitly defined JSONNET_PATH makes more sense for the kind of things Jsonnet is good at (i.e. when you are actively trying to eliminate dependence on the environment).