Skip to content

Commit 2006cde

Browse files
authored
Merge pull request #8 from ticketmaster/fix-opa-library-deps-paths
Correct context for generated files and transitive deps
2 parents c6f5ace + 110758d commit 2006cde

File tree

12 files changed

+228
-67
lines changed

12 files changed

+228
-67
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
load("@rules_opa//opa:defs.bzl", "opa_library")
2+
3+
genrule(
4+
name = "data",
5+
outs = ["data.json"],
6+
cmd = "echo '{\"hello\": \"world\"}' > $@",
7+
)
8+
9+
opa_library(
10+
name = "bundle",
11+
data = [":data"],
12+
deps = ["//examples/simple"],
13+
)

examples/simple/BUILD.bazel

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
1-
load("@rules_opa//opa:defs.bzl", "opa_check", "opa_eval_binary", "opa_library", "opa_test")
1+
load("@rules_opa//opa:defs.bzl", "opa_binary", "opa_check", "opa_eval_binary", "opa_library", "opa_test")
22

33
opa_library(
44
name = "simple",
55
srcs = ["main.rego"],
66
data = ["data.json"],
77
strip_prefix = package_name(),
8+
visibility = ["//examples:__subpackages__"],
9+
)
10+
11+
opa_binary(
12+
name = "simple_bin",
13+
deps = [":simple"],
814
)
915

1016
opa_library(
1117
name = "simple_wasm",
1218
entrypoints = ["main/allow"],
1319
signing_alg = "HS256",
1420
signing_key = "mysecret",
15-
strip_prefix = package_name(),
1621
target = "wasm",
1722
deps = [":simple"],
1823
)
@@ -21,7 +26,7 @@ opa_test(
2126
name = "simple_test",
2227
size = "small",
2328
srcs = ["main_test.rego"],
24-
bundle = ":simple",
29+
deps = [":simple"],
2530
)
2631

2732
opa_check(
@@ -34,7 +39,7 @@ opa_check(
3439

3540
opa_eval_binary(
3641
name = "check_bob",
37-
bundle = ":simple",
3842
input = '{"name":"bob"}',
3943
query = "data.main.allow",
44+
deps = [":simple"],
4045
)

examples/simple/main.rego

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ import future.keywords
99
allow if {
1010
input.name in data.admins
1111
}
12+
13+
#

opa/defs.bzl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ load("//opa/private:opa_library.bzl", _OpaInfo = "OpaInfo", _opa_library = "opa_
33
load("//opa/private:opa_test.bzl", _opa_test = "opa_test")
44
load("//opa/private:opa_check.bzl", _opa_check = "opa_check")
55
load("//opa/private:opa_eval_binary.bzl", _opa_eval_binary = "opa_eval_binary")
6+
load("//opa/private:opa_binary.bzl", _opa_binary = "opa_binary")
67

78
opa_toolchain = _opa_toolchain
89
opa_library = _opa_library
910
opa_test = _opa_test
1011
opa_check = _opa_check
1112
opa_eval_binary = _opa_eval_binary
13+
opa_binary = _opa_binary
1214
OpaInfo = _OpaInfo
1315
OpacInfo = _OpacInfo

opa/private/opa_binary.bzl

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
load(":opa_library.bzl", "OpaInfo")
2+
3+
def _opa_binary_impl(ctx):
4+
toolchain = ctx.toolchains["//tools:toolchain_type"].opacinfo
5+
binary_file = ctx.actions.declare_file("%s_binary.sh" % (ctx.label.name))
6+
7+
if len(ctx.attr.deps) != 1:
8+
fail("opa_binary only allow a single deps")
9+
10+
bundle = ctx.attr.deps[0][OpaInfo].bundle
11+
12+
runfiles = ctx.runfiles(files = [toolchain.opa, bundle])
13+
14+
ctx.actions.write(
15+
output = binary_file,
16+
content = "%s run -b %s" % (toolchain.opa.short_path, bundle.short_path),
17+
is_executable = True,
18+
)
19+
20+
return [
21+
DefaultInfo(
22+
executable = binary_file,
23+
runfiles = runfiles,
24+
),
25+
]
26+
27+
opa_binary = rule(
28+
implementation = _opa_binary_impl,
29+
attrs = {
30+
"deps": attr.label_list(
31+
providers = [OpaInfo],
32+
),
33+
},
34+
executable = True,
35+
toolchains = ["//tools:toolchain_type"],
36+
)

opa/private/opa_eval.sh.tpl

Lines changed: 0 additions & 12 deletions
This file was deleted.

opa/private/opa_eval_binary.bzl

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,32 +3,34 @@ load(":opa_library.bzl", "OpaInfo")
33
def _opa_eval_binary_impl(ctx):
44
exec_file = ctx.actions.declare_file("%s_exec.sh" % (ctx.label.name))
55
toolchain = ctx.toolchains["//tools:toolchain_type"].opacinfo
6-
runfiles = ctx.runfiles(files = [toolchain.opa] + ctx.attr.bundle[OpaInfo].file_deps.to_list())
76

8-
args = []
7+
if len(ctx.attr.deps) != 1:
8+
fail("opa_binary only allow a single deps")
9+
10+
bundle = ctx.attr.deps[0][OpaInfo].bundle
11+
12+
runfiles = ctx.runfiles(files = [toolchain.opa, bundle])
13+
14+
args = ["eval", "-b", bundle.short_path]
15+
suffix = ""
916

1017
if ctx.attr.partial:
1118
args.append("--partial")
1219
if ctx.file.input_file:
1320
args.append("--input %s" % (ctx.file.input_file.short_path))
1421
if ctx.attr.input:
1522
args.append("--stdin-input")
23+
suffix = "<< 'EOF'\n%s\nEOF" % (ctx.attr.input)
1624
if ctx.attr.unknowns:
1725
args.append("--unknowns %s" % (",".join(ctx.attr.unknowns)))
1826

1927
args.append("--format=%s" % (ctx.attr.format))
2028
args.append(ctx.attr.query)
2129

22-
ctx.actions.expand_template(
30+
ctx.actions.write(
2331
output = exec_file,
24-
template = ctx.file._template,
32+
content = "%s %s %s" % (toolchain.opa.short_path, " ".join(args), suffix),
2533
is_executable = True,
26-
substitutions = {
27-
"{OPA_SHORTPATH}": toolchain.opa.short_path,
28-
"{STDIN}": ctx.attr.input,
29-
"{STRIP_PREFIX}": ctx.attr.bundle[OpaInfo].strip_prefix,
30-
"{ARGS}": " ".join(args),
31-
},
3234
)
3335

3436
return [
@@ -42,7 +44,7 @@ opa_eval_binary = rule(
4244
implementation = _opa_eval_binary_impl,
4345
executable = True,
4446
attrs = {
45-
"bundle": attr.label(
47+
"deps": attr.label_list(
4648
providers = [OpaInfo],
4749
mandatory = True,
4850
doc = "The bundle to evaluate",

opa/private/opa_library.bzl

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1-
load("@bazel_skylib//lib:paths.bzl", "paths")
2-
3-
OpaInfo = provider("opa", fields = ["bundle", "target", "file_deps", "strip_prefix"])
1+
OpaInfo = provider("opa", fields = {
2+
"bundle": "The bundle file",
3+
"target": "The bundle target (wasm, rego or plan)",
4+
"file_deps": "A depset containing all the source files",
5+
"file_aliases": "A flat list of all the files with their alias in the bundle",
6+
})
47

58
def _opa_toolchain(ctx):
69
return ctx.toolchains["//tools:toolchain_type"].opacinfo
@@ -40,53 +43,56 @@ def _run_opa_signer(ctx, bundle_file, signed_bundle_file):
4043
executable = ctx.executable._opa_signer,
4144
)
4245

46+
def _file_alias(file, strip_prefix):
47+
return "%s:%s" % (file.path, file.short_path.removeprefix(strip_prefix).removeprefix("/"))
48+
4349
def _run_opa_build(ctx, bundle_file):
4450
toolchain = _opa_toolchain(ctx)
51+
wd = ctx.actions.declare_directory("%s_work" % (ctx.label.name))
4552
args = ctx.actions.args()
4653

47-
strip_prefix = paths.normalize(ctx.attr.strip_prefix)
48-
opa_relative_path = toolchain.opa.path
49-
bundle_relative_path = bundle_file.path
54+
srcs = ctx.files.srcs or []
55+
data = ctx.files.data or []
56+
57+
file_aliases = [_file_alias(file, ctx.attr.strip_prefix or "") for file in srcs + data]
5058

51-
if strip_prefix != ".":
52-
rel = [".." for _ in strip_prefix.split("/")]
53-
opa_relative_path = paths.normalize("/".join(rel + [toolchain.opa.path]))
54-
bundle_relative_path = paths.normalize("/".join(rel + [bundle_file.path]))
59+
for dep in ctx.attr.deps:
60+
file_aliases.extend(dep[OpaInfo].file_aliases)
5561

56-
args.add("build")
57-
args.add("-t")
58-
args.add(ctx.attr.target)
59-
args.add("-o")
60-
args.add("%s" % (bundle_relative_path))
62+
args.add("-d").add(wd.path)
63+
args.add("-o").add(bundle_file, format = "%s:bundle.tar.gz")
64+
args.add("-i").add_all(file_aliases).add("--")
65+
args.add(toolchain.opa).add("build")
66+
args.add("-t").add(ctx.attr.target)
67+
args.add("-o").add("bundle.tar.gz")
6168

6269
if ctx.attr.optimize:
6370
args.add(ctx.attr.optimize, format = "--optimize=%s")
6471

6572
for entrypoint in ctx.attr.entrypoints:
66-
args.add(entrypoint, format = "-e %s")
73+
args.add("-e").add(entrypoint)
6774

6875
args.add(".")
6976

70-
srcs = ctx.files.srcs if ctx.files.srcs else []
71-
data = ctx.files.data if ctx.files.data else []
72-
73-
ctx.actions.run_shell(
77+
ctx.actions.run(
78+
executable = ctx.executable._opa_ctx,
7479
inputs = depset(srcs + data, transitive = [d[OpaInfo].file_deps for d in ctx.attr.deps]),
75-
outputs = [bundle_file],
80+
outputs = [bundle_file, wd],
7681
arguments = [args],
7782
tools = [toolchain.opa],
7883
progress_message = "Bundling policies",
7984
mnemonic = "OpaBuild",
80-
command = "cd %s && %s $@" % (strip_prefix, opa_relative_path),
8185
)
8286

87+
return file_aliases
88+
8389
def _opa_library_impl(ctx):
8490
if ctx.attr.target == "wasm" and len(ctx.attr.entrypoints) == 0:
8591
fail("At least one entrypoint is required for a wasm target")
8692

8793
bundle_file = ctx.actions.declare_file("%s.tar.gz" % (ctx.attr.name))
8894

89-
_run_opa_build(ctx, bundle_file)
95+
file_aliases = _run_opa_build(ctx, bundle_file)
9096

9197
output_files = [bundle_file]
9298

@@ -97,13 +103,13 @@ def _opa_library_impl(ctx):
97103
_run_opa_signer(ctx, bundle_file, signed_bundle_file)
98104
output_files = [signed_bundle_file] + output_files
99105

100-
srcs = ctx.files.srcs if ctx.files.srcs else []
101-
data = ctx.files.data if ctx.files.data else []
106+
srcs = ctx.files.srcs or []
107+
data = ctx.files.data or []
102108

103109
return [
104110
OpaInfo(
105111
bundle = bundle_file,
106-
strip_prefix = paths.normalize(ctx.attr.strip_prefix),
112+
file_aliases = file_aliases,
107113
target = ctx.attr.target,
108114
file_deps = depset(srcs + data, transitive = [d[OpaInfo].file_deps for d in ctx.attr.deps]),
109115
),
@@ -172,6 +178,11 @@ wasm The wasm target emits a bundle containing a WebAssembly module compiled
172178
executable = True,
173179
cfg = "exec",
174180
),
181+
"_opa_ctx": attr.label(
182+
default = "//tools:opa_ctx",
183+
executable = True,
184+
cfg = "exec",
185+
),
175186
},
176187
toolchains = ["//tools:toolchain_type"],
177188
)

opa/private/opa_test.bzl

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,24 @@ load(":opa_library.bzl", "OpaInfo")
22

33
def _opa_test_impl(ctx):
44
toolchain = ctx.toolchains["//tools:toolchain_type"].opacinfo
5-
tester_file = ctx.actions.declare_file("%s_tester.sh" % (ctx.label.name))
6-
bundle = ctx.attr.bundle[OpaInfo]
7-
runfiles = ctx.runfiles(files = ctx.files.srcs + [toolchain.opa] + bundle.file_deps.to_list())
5+
test_file = ctx.actions.declare_file("%s_test.sh" % (ctx.label.name))
6+
7+
if len(ctx.attr.deps) != 1:
8+
fail("opa_test only allow a single deps")
9+
10+
bundle = ctx.attr.deps[0][OpaInfo].bundle
11+
12+
runfiles = ctx.runfiles(files = [toolchain.opa, bundle] + ctx.files.srcs)
813

914
ctx.actions.write(
10-
output = tester_file,
11-
content = "%s test -v %s" % (toolchain.opa.short_path, bundle.strip_prefix),
15+
output = test_file,
16+
content = "%s test %s %s" % (toolchain.opa.short_path, bundle.short_path, " ".join([f.short_path for f in ctx.files.srcs])),
17+
is_executable = True,
1218
)
1319

1420
return [
1521
DefaultInfo(
16-
executable = tester_file,
22+
executable = test_file,
1723
runfiles = runfiles,
1824
),
1925
]
@@ -27,7 +33,7 @@ opa_test = rule(
2733
mandatory = True,
2834
doc = "Rego files to test",
2935
),
30-
"bundle": attr.label(
36+
"deps": attr.label_list(
3137
providers = [OpaInfo],
3238
doc = "The bundle to test",
3339
),

opa/private/opa_toolchain.bzl

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,13 @@ opa_toolchain = rule(
3333
),
3434
"opa_signer": attr.label(
3535
executable = True,
36-
# allow_single_file = True,
37-
mandatory = True,
3836
cfg = "exec",
37+
default = "//tools:opa_signer",
38+
),
39+
"opa_ctx": attr.label(
40+
executable = True,
41+
cfg = "exec",
42+
default = "//tools:opa_ctx",
3943
),
4044
},
4145
)

0 commit comments

Comments
 (0)