diff options
Diffstat (limited to 'tools/build_defs/jsonnet')
-rw-r--r-- | tools/build_defs/jsonnet/BUILD | 16 | ||||
-rw-r--r-- | tools/build_defs/jsonnet/README.md | 553 | ||||
-rw-r--r-- | tools/build_defs/jsonnet/jsonnet.bzl | 248 |
3 files changed, 0 insertions, 817 deletions
diff --git a/tools/build_defs/jsonnet/BUILD b/tools/build_defs/jsonnet/BUILD deleted file mode 100644 index 7f38b97020..0000000000 --- a/tools/build_defs/jsonnet/BUILD +++ /dev/null @@ -1,16 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -filegroup( - name = "srcs", - srcs = glob(["**"]), -) - -filegroup( - name = "jsonnet", - srcs = ["@jsonnet//:jsonnet"], -) - -filegroup( - name = "std", - srcs = ["@jsonnet//:std"], -) diff --git a/tools/build_defs/jsonnet/README.md b/tools/build_defs/jsonnet/README.md deleted file mode 100644 index 59db1888c8..0000000000 --- a/tools/build_defs/jsonnet/README.md +++ /dev/null @@ -1,553 +0,0 @@ -# Jsonnet Rules - -<div class="toc"> - <h2>Rules</h2> - <ul> - <li><a href="#jsonnet_library">jsonnet_library</a></li> - <li><a href="#jsonnet_to_json">jsonnet_to_json</a></li> - <li><a href="#jsonnet_to_json_test">jsonnet_to_json_test</a></li> - </ul> -</div> - -## Overview - -These are build rules for working with [Jsonnet][jsonnet] files with Bazel. - -[jsonnet]: http://google.github.io/jsonnet/doc/ - -## Setup - -To use the Jsonnet rules, add the following to your `WORKSPACE` file to add the -external repositories for Jsonnet: - -```python -load("@bazel_tools//tools/build_defs/jsonnet:jsonnet.bzl", "jsonnet_repositories") - -jsonnet_repositories() -``` - -<a name="#jsonnet_library"></a> -## jsonnet_library - -```python -jsonnet_library(name, srcs, deps, imports) -``` - -<table class="table table-condensed table-bordered table-params"> - <colgroup> - <col class="col-param" /> - <col class="param-description" /> - </colgroup> - <thead> - <tr> - <th colspan="2">Attributes</th> - </tr> - </thead> - <tbody> - <tr> - <td><code>name</code></td> - <td> - <code>Name, required</code> - <p>A unique name for this rule.</p> - </td> - </tr> - <tr> - <td><code>srcs</code></td> - <td> - <code>List of Labels, required</code> - <p> - List of <code>.jsonnet</code> files that comprises this Jsonnet - library. - </p> - </td> - </tr> - <tr> - <td><code>deps</code></td> - <td> - <code>List of labels, optional</code> - <p> - List of targets that are required by the <code>srcs</code> Jsonnet - files. - </p> - </td> - </tr> - <tr> - <td><code>imports</code></td> - <td> - <code>List of strings, optional</code> - <p> - List of import <code>-J</code> flags to be passed to the - <code>jsonnet</code> compiler. - </p> - </td> - </tr> - </tbody> -</table> - -### Example - -Suppose you have the following directory structure: - -``` -[workspace]/ - WORKSPACE - configs/ - BUILD - backend.jsonnet - frontend.jsonnet -``` - -You can use the `jsonnet_library` rule to build a collection of `.jsonnet` -files that can be imported by other `.jsonnet` files as dependencies: - -`configs/BUILD`: - -```python -load("@bazel_tools//tools/build_defs/jsonnet:jsonnet.bzl", "jsonnet_library") - -jsonnet_library( - name = "configs", - srcs = [ - "backend.jsonnet", - "frontend.jsonnet", - ], -) -``` - -<a name="#jsonnet_to_json"></a> -## jsonnet\_to\_json - -```python -jsonnet_to_json(name, src, deps, outs, multiple_outputs, imports, vars, code_vars) -``` - -<table class="table table-condensed table-bordered table-params"> - <colgroup> - <col class="col-param" /> - <col class="param-description" /> - </colgroup> - <thead> - <tr> - <th colspan="2">Attributes</th> - </tr> - </thead> - <tbody> - <tr> - <td><code>name</code></td> - <td> - <code>Name, required</code> - <p>A unique name for this rule.</p> - <p> - This name will be used as the name of the JSON file generated by this - rule. - </p> - </td> - </tr> - <tr> - <td><code>src</code></td> - <td> - <code>Label, required</code> - <p> - The <code>.jsonnet</code> file to convert to JSON. - </p> - </td> - </tr> - <tr> - <td><code>deps</code></td> - <td> - <code>List of labels, optional</code> - <p> - List of targets that are required by the <code>src</code> Jsonnet - file. - </p> - </td> - </tr> - <tr> - <td><code>outs</code></td> - <td> - <code>List of Filenames, optional</code> - <p> - Names of the output .json files to be generated by this rule. - </p> - <p> - If you are generating only a single JSON file and are not using - jsonnet multiple output files, then this attribute should only - contain the file name of the JSON file you are generating. - </p> - <p> - If you are generating multiple JSON files using jsonnet multiple file - output (<code>jsonnet -m</code>), then list the file names of all the - JSON files to be generated. The file names specified here must match - the file names specified in your <code>src</code> Jsonnet file. - </p> - <p> - For the case where multiple file output is used but only for - generating one output file, set the <code>multiple_outputs</code> - attribute to 1 to explicitly enable the <code>-m</code> flag for - multiple file output. - </p> - </td> - </tr> - <tr> - <td><code>multiple_outputs</code></td> - <td> - <code>bool, optional, default 0</code> - <p> - Set to 1 to explicitly enable multiple file output via the - <code>jsonnet -m</code> flag. - </p> - <p> - This is used for the case where multiple file output is used but only - for generating a single output file. For example: - </p> -<pre> -local foo = import "foo.jsonnet"; - -{ - "foo.json": foo, -} -</pre> - </p> - </td> - </tr> - <tr> - <td><code>imports</code></td> - <td> - <code>List of strings, optional</code> - <p> - List of import <code>-J</code> flags to be passed to the - <code>jsonnet</code> compiler. - </p> - </td> - </tr> - <tr> - <td><code>vars</code></td> - <td> - <code>String dict, optional</code> - <p> - Map of variables to pass to jsonnet via <code>--var key=value</code>. - </p> - </td> - </tr> - <tr> - <td><code>code_vars</code></td> - <td> - <code>String dict, optional</code> - <p> - Map of code variables to pass to jsonnet via - <code>--code-var key=value</code>. - </p> - </td> - </tr> - </tbody> -</table> - -### Example - -Suppose you have the following directory structure: - -``` -[workspace]/ - WORKSPACE - workflows/ - BUILD - workflow.jsonnet - wordcount.jsonnet - intersection.jsonnet -``` - -Say that `workflow.jsonnet` is a base configuration library for a workflow -scheduling system and `wordcount.jsonnet` and `intersection.jsonnet` both -import `workflow.jsonnet` to define workflows for performing a wordcount and -intersection of two files, respectively. - -First, create a `jsonnet_library` target with `workflow.jsonnet`: - -`workflows/BUILD`: - -```python -load("@bazel_tools//tools/build_defs/jsonnet:jsonnet.bzl", "jsonnet_library") - -jsonnet_library( - name = "workflow", - srcs = ["workflow.jsonnet"], -) -``` - -To compile `wordcount.jsonnet` and `intersection.jsonnet` to JSON, define two -`jsonnet_to_json` targets: - -```python -jsonnet_to_json( - name = "wordcount", - src = "wordcount.jsonnet", - outs = ["wordcount.json"], - deps = [":workflow"], -) - -jsonnet_to_json( - name = "intersection", - src = "intersection.jsonnet", - outs = ["intersection.json"], - deps = [":workflow"], -) -``` - -### Example: Multiple output files - -To use Jsonnet's [multiple output files][multiple-output-files], suppose you -add a file `shell-workflows.jsonnet` that imports `wordcount.jsonnet` and -`intersection.jsonnet`: - -`workflows/shell-workflows.jsonnet`: - -``` -local wordcount = import "workflows/wordcount.jsonnet"; -local intersection = import "workflows/intersection.jsonnet"; - -{ - "wordcount-workflow.json": wordcount, - "intersection-workflow.json": intersection, -} -``` - -To compile `shell-workflows.jsonnet` into the two JSON files, -`wordcount-workflow.json` and `intersection-workflow.json`, first create a -`jsonnet_library` target containing the two files that -`shell-workflows.jsonnet` depends on: - -```python -jsonnet_library( - name = "shell-workflows-lib", - srcs = [ - "wordcount.jsonnet", - "intersection.jsonnet", - ], - deps = [":workflow"], -) -``` - -Then, create a `jsonnet_to_json` target and set `outs` to the list of output -files to indicate that multiple output JSON files are generated: - -```python -jsonnet_to_json( - name = "shell-workflows", - src = "shell-workflows.jsonnet", - deps = [":shell-workflows-lib"], - outs = [ - "wordcount-workflow.jsonnet", - "intersection-workflow.jsonnet", - ], -) -``` - -[multiple-output-files]: http://google.github.io/jsonnet/doc/commandline.html - -<a name="#jsonnet_to_json_test"></a> -## jsonnet\_to\_json\_test - -```python -jsonnet_to_json_test(name, src, deps, imports, golden, error=0, regex=False) -``` - -<table class="table table-condensed table-bordered table-params"> - <colgroup> - <col class="col-param" /> - <col class="param-description" /> - </colgroup> - <thead> - <tr> - <th colspan="2">Attributes</th> - </tr> - </thead> - <tbody> - <tr> - <td><code>name</code></td> - <td> - <code>Name, required</code> - <p>A unique name for this rule.</p> - <p> - This name will be used as the name of the JSON file generated by this - rule. - </p> - </td> - </tr> - <tr> - <td><code>src</code></td> - <td> - <code>Label, required</code> - <p> - The <code>.jsonnet</code> file to convert to JSON. - </p> - </td> - </tr> - <tr> - <td><code>deps</code></td> - <td> - <code>List of labels, optional</code> - <p> - List of targets that are required by the <code>src</code> Jsonnet - file. - </p> - </td> - </tr> - <tr> - <td><code>imports</code></td> - <td> - <code>List of strings, optional</code> - <p> - List of import <code>-J</code> flags to be passed to the - <code>jsonnet</code> compiler. - </p> - </td> - </tr> - <tr> - <td><code>vars</code></td> - <td> - <code>String dict, optional</code> - <p> - Map of variables to pass to jsonnet via <code>--var key=value</code>. - </p> - </td> - </tr> - <tr> - <td><code>code_vars</code></td> - <td> - <code>String dict, optional</code> - <p> - Map of code variables to pass to jsonnet via - <code>--code-var key=value</code>. - </p> - </td> - </tr> - <tr> - <td><code>golden</code></td> - <td> - <code>Label, optional</code> - <p> - The expected (combined stdout and stderr) output to compare to the - output of running <code>jsonnet</code> on <code>src</code>. - </p> - </td> - </tr> - <tr> - <td><code>error</code></td> - <td> - <code>Integer, optional, default is 0</code> - <p> - The expected error code from running <code>jsonnet</code> on - <code>src</code>. - </p> - </td> - </tr> - <tr> - <td><code>regex</code></td> - <td> - <code>bool, optional, default is False</code> - <p> - Set to 1 if <code>golden</code> contains a regex used to match - the output of running <code>jsonnet</code> on <code>src</code>. - </p> - </td> - </tr> - </tbody> -</table> - -### Example - -Suppose you have the following directory structure: - -``` -[workspace]/ - WORKSPACE - config/ - BUILD - base_config.jsonnet - test_config.jsonnet - test_config.json -``` - -Suppose that `base_config.jsonnet` is a library Jsonnet file, containing the -base configuration for a service. Suppose that `test_config.jsonnet` is a test -configuration file that is used to test `base_config.jsonnet`, and -`test_config.json` is the expected JSON output from compiling -`test_config.jsonnet`. - -The `jsonnet_to_json_test` rule can be used to verify that compiling a Jsonnet -file produces the expected JSON output. Simply define a `jsonnet_to_json_test` -target and provide the input test Jsonnet file and the `golden` file containing -the expected JSON output: - -`config/BUILD`: - -```python -load( - "@bazel_tools//tools/build_defs/jsonnet:jsonnet.bzl", - "jsonnet_library", - "jsonnet_to_json_test", -) - -jsonnet_library( - name = "base_config", - srcs = ["base_config.jsonnet"], -) - -jsonnet_to_json_test( - name = "test_config_test", - src = "test_config", - deps = [":base_config"], - golden = "test_config.json", -) -``` - -To run the test: `bazel test //config:test_config_test` - -### Example: Negative tests - -Suppose you have the following directory structure: - -``` -[workspace]/ - WORKSPACE - config/ - BUILD - base_config.jsonnet - invalid_config.jsonnet - invalid_config.output -``` - -Suppose that `invalid_config.jsonnet` is a Jsonnet file used to verify that -an invalid config triggers an assertion in `base_config.jsonnet`, and -`invalid_config.output` is the expected error output. - -The `jsonnet_to_json_test` rule can be used to verify that compiling a Jsonnet -file results in an expected error code and error output. Simply define a -`jsonnet_to_json_test` target and provide the input test Jsonnet file, the -expected error code in the `error` attribute, and the `golden` file containing -the expected error output: - -`config/BUILD`: - -```python -load( - "@bazel_tools//tools/build_defs/jsonnet:jsonnet.bzl", - "jsonnet_library", - "jsonnet_to_json_test", -) - -jsonnet_library( - name = "base_config", - srcs = ["base_config.jsonnet"], -) - -jsonnet_to_json_test( - name = "invalid_config_test", - src = "invalid_config", - deps = [":base_config"], - golden = "invalid_config.output", - error = 1, -) -``` - -To run the test: `bazel test //config:invalid_config_test` diff --git a/tools/build_defs/jsonnet/jsonnet.bzl b/tools/build_defs/jsonnet/jsonnet.bzl deleted file mode 100644 index 23b9a9914d..0000000000 --- a/tools/build_defs/jsonnet/jsonnet.bzl +++ /dev/null @@ -1,248 +0,0 @@ -# Copyright 2015 The Bazel Authors. All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Jsonnet rules for Bazel.""" - -_JSONNET_FILETYPE = FileType([".jsonnet"]) - -def _setup_deps(deps): - """Collects source files and import flags of transitive dependencies. - - Args: - deps: List of deps labels from ctx.attr.deps. - - Returns: - Returns a struct containing the following fields: - transitive_sources: List of Files containing sources of transitive - dependencies - imports: List of Strings containing import flags set by transitive - dependency targets. - """ - transitive_sources = set(order="compile") - imports = set() - for dep in deps: - transitive_sources += dep.transitive_jsonnet_files - imports += ["%s/%s" % (dep.label.package, im) for im in dep.imports] - - return struct( - transitive_sources = transitive_sources, - imports = imports) - -def _jsonnet_library_impl(ctx): - """Implementation of the jsonnet_library rule.""" - depinfo = _setup_deps(ctx.attr.deps) - sources = depinfo.transitive_sources + ctx.files.srcs - imports = depinfo.imports + ctx.attr.imports - return struct(files = set(), - transitive_jsonnet_files = sources, - imports = imports) - -def _jsonnet_toolchain(ctx): - return struct( - jsonnet_path = ctx.file.jsonnet.path, - imports = ["-J %s" % ctx.file.std.dirname]) - -def _jsonnet_to_json_impl(ctx): - """Implementation of the jsonnet_to_json rule.""" - depinfo = _setup_deps(ctx.attr.deps) - toolchain = _jsonnet_toolchain(ctx) - jsonnet_vars = ctx.attr.vars - jsonnet_code_vars = ctx.attr.code_vars - command = ( - [ - "set -e;", - toolchain.jsonnet_path, - ] + - ["-J %s/%s" % (ctx.label.package, im) for im in ctx.attr.imports] + - ["-J %s" % im for im in depinfo.imports] + - toolchain.imports + - ["-J ."] + - ["--var '%s'='%s'" - % (var, jsonnet_vars[var]) for var in jsonnet_vars.keys()] + - ["--code-var '%s'='%s'" - % (var, jsonnet_code_vars[var]) for var in jsonnet_code_vars.keys()]) - - outputs = [] - # If multiple_outputs is set to true, then jsonnet will be invoked with the - # -m flag for multiple outputs. Otherwise, jsonnet will write the resulting - # JSON to stdout, which is redirected into a single JSON output file. - if len(ctx.attr.outs) > 1 or ctx.attr.multiple_outputs: - output_json_files = [ctx.new_file(ctx.configuration.bin_dir, out.name) - for out in ctx.attr.outs] - outputs += output_json_files - command += ["-m", output_json_files[0].dirname, ctx.file.src.path] - else: - if len(ctx.attr.outs) > 1: - fail("Only one file can be specified in outs if multiple_outputs is " + - "not set.") - - compiled_json = ctx.new_file(ctx.configuration.bin_dir, - ctx.attr.outs[0].name) - outputs += [compiled_json] - command += [ctx.file.src.path, "-o", compiled_json.path] - - compile_inputs = ( - [ctx.file.src, ctx.file.jsonnet, ctx.file.std] + - list(depinfo.transitive_sources)) - - ctx.action( - inputs = compile_inputs, - outputs = outputs, - mnemonic = "Jsonnet", - command = " ".join(command), - use_default_shell_env = True, - progress_message = "Compiling Jsonnet to JSON for " + ctx.label.name); - -_EXIT_CODE_COMPARE_COMMAND = """ -EXIT_CODE=$? -EXPECTED_EXIT_CODE=%d -if [ $EXIT_CODE -ne $EXPECTED_EXIT_CODE ] ; then - echo "FAIL (exit code): %s" - echo "Expected: $EXPECTED_EXIT_CODE" - echo "Actual: $EXIT_CODE" - echo "Output: $OUTPUT" - exit 1 -fi -""" - -_DIFF_COMMAND = """ -GOLDEN=$(cat %s) -if [ "$OUTPUT" != "$GOLDEN" ]; then - echo "FAIL (output mismatch): %s" - echo "Diff:" - diff <(echo $GOLDEN) <(echo $OUTPUT) - echo "Expected: $GOLDEN" - echo "Actual: $OUTPUT" - exit 1 -fi -""" - -_REGEX_DIFF_COMMAND = """ -GOLDEN_REGEX=$(cat %s) -if [[ ! "$OUTPUT" =~ $GOLDEN_REGEX ]]; then - echo "FAIL (regex mismatch): %s" - echo "Output: $OUTPUT" - exit 1 -fi -""" - -def _jsonnet_to_json_test_impl(ctx): - """Implementation of the jsonnet_to_json_test rule.""" - depinfo = _setup_deps(ctx.attr.deps) - toolchain = _jsonnet_toolchain(ctx) - - golden_files = [] - if ctx.file.golden: - golden_files += [ctx.file.golden] - if ctx.attr.regex: - diff_command = _REGEX_DIFF_COMMAND % (ctx.file.golden.short_path, - ctx.label.name) - else: - diff_command = _DIFF_COMMAND % (ctx.file.golden.short_path, - ctx.label.name) - - jsonnet_vars = ctx.attr.vars - jsonnet_code_vars = ctx.attr.code_vars - jsonnet_command = " ".join( - ["OUTPUT=$(%s" % ctx.file.jsonnet.short_path] + - ["-J %s/%s" % (ctx.label.package, im) for im in ctx.attr.imports] + - ["-J %s" % im for im in depinfo.imports] + - toolchain.imports + - ["-J ."] + - ["--var %s=%s" - % (var, jsonnet_vars[var]) for var in jsonnet_vars.keys()] + - ["--code-var %s=%s" - % (var, jsonnet_code_vars[var]) for var in jsonnet_code_vars.keys()] + - [ - ctx.file.src.path, - "2>&1)", - ]) - - command = "\n".join([ - "#!/bin/bash", - jsonnet_command, - _EXIT_CODE_COMPARE_COMMAND % (ctx.attr.error, ctx.label.name), - diff_command]) - - ctx.file_action(output = ctx.outputs.executable, - content = command, - executable = True); - - test_inputs = ( - [ctx.file.src, ctx.file.jsonnet, ctx.file.std] + - golden_files + - list(depinfo.transitive_sources)) - - return struct( - runfiles = ctx.runfiles(files = test_inputs, collect_data = True)) - -_jsonnet_common_attrs = { - "deps": attr.label_list(providers = ["transitive_jsonnet_files"], - allow_files = False), - "imports": attr.string_list(), - "jsonnet": attr.label( - default = Label("@bazel_tools//tools/build_defs/jsonnet:jsonnet"), - cfg = HOST_CFG, - executable = True, - single_file = True), - "std": attr.label( - default = Label("@bazel_tools//tools/build_defs/jsonnet:std"), - single_file = True), -} - -_jsonnet_library_attrs = { - "srcs": attr.label_list(allow_files = _JSONNET_FILETYPE), -} - -jsonnet_library = rule( - _jsonnet_library_impl, - attrs = _jsonnet_library_attrs + _jsonnet_common_attrs, -) - -_jsonnet_compile_attrs = { - "src": attr.label(allow_files = _JSONNET_FILETYPE, - single_file = True), - "vars": attr.string_dict(), - "code_vars": attr.string_dict(), -} - -_jsonnet_to_json_attrs = _jsonnet_compile_attrs + { - "outs": attr.output_list(mandatory = True), - "multiple_outputs": attr.bool(), -} - -jsonnet_to_json = rule( - _jsonnet_to_json_impl, - attrs = _jsonnet_to_json_attrs + _jsonnet_common_attrs, -) - -_jsonnet_to_json_test_attrs = _jsonnet_compile_attrs + { - "golden": attr.label(allow_files = True, single_file = True), - "error": attr.int(), - "regex": attr.bool(), -} - -jsonnet_to_json_test = rule( - _jsonnet_to_json_test_impl, - attrs = _jsonnet_to_json_test_attrs + _jsonnet_common_attrs, - executable = True, - test = True, -) - -def jsonnet_repositories(): - native.git_repository( - name = "jsonnet", - remote = "https://github.com/google/jsonnet.git", - tag = "v0.8.1", - ) |