blob: 7d431effa3be6caf11b7e377ab48e9f760ee7f08 [file] [log] [blame]
Serge Bazanski7353e172021-03-31 22:09:22 +02001# Copyright 2020 The Monogon Project Authors.
2#
3# SPDX-License-Identifier: Apache-2.0
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17# Bazel rules for generating Kubernetes-style API types using
18# github.com/kubernetes/code-generator.
19#
20# k8s.io/code-gen generators target a peculiar filesystem/package structure for
21# generated code:
22#
23# example.com/project/apis/goodbye/v1/doc.go - hand written
24# /types.go - hand written
25# /zz_generated.go - generated
26# example.com/project/apis/hello/v1/doc.go - hand written
27# /types.go - hand written
28# /zz_generated.go - generated
29# example.com/project/generated/clientset/... - generated
30# example.com/project/generated/informers/... - generated
31# example.com/project/generated/listers/... - generated
32#
33# This means, that usually the generated files are both colocated directly
34# with the package (for zz_generated.deepcopy.go, generated by deepcopy)
35# and have their own package (for files generated by clientset, informers,
36# listers).
37#
38# Most importantly, however, multiple Go packages (in the above example,
39# goodbye/v1 and hello/v1) are used to in turn generate multiple output Go
40# packages. This proves problematic when generating code for Bazel, as we have
41# to consume the result of code generation from multiple Bazel targets (each
42# representing a different generated Go package).
43#
44# To handle this, we split up the code generation into four main steps. These
45# need to be manually instantiated by any use who wants to consume these rules.
46#
47# 1. Create a rules_go go_path that contains all hand-written API packages.
48# 2. Parse hand written API packages using go_kubernetes_resource_bundle, via
49# the generated go_path. This prepares outputs (ie., 'runs' generators),
50# and creates an internal provider (KubeResourceBundle) that contains
51# informations about generated Go packages.
52# 3. For every output package, create a go_kubernetes_library target,
53# specifying the bundle from which it's supposed to be created, and which
54# particular library from that bundle should be used.
55# 4. Next to every go_kubernetes_library, create a go_library with the same
56# importpath which embeds the go_kubernetes_library. The split between
57# go_kubernetes_library and go_library is required to let Gazelle know
58# about the availability of given importpaths at given Bazel targets
59# (unfortunately, it seems like Gazelle is unable to parse rules that emit
60# the same providers as go_library does, instead requiring us to use a full
61# go_library rule instead).
62#
63# Point 3. is somwhat different for the generated deepcopy code, which has to
64# live alongside (in the same importpath) as the hand-written API go_library,
65# and needs to be embedded into that. Special care has to be taken to not cause
66# a cycle (handwritten API -> go_path -> bundle -> kubernetes_library ->
67# go_library) in this case. This is done via a select() which selectively
68# enables the inclusion of the generated deepcopy code within the hand-written
69# API library, only enabling it for the target build, not the preprocessing
70# done by go_kubernetes_resource_bundle.
71#
72# Or, in graphical form:
73#
74# .------------. .------------.
75# | go_library | | go_library |
76# |------------| |------------|
77# | goodbye/v1 | | hello/v2 |
78# '------------' '------------'
79# '------. .--------'
80# .---------.
81# | go_path |
82# '---------'
83# | (preprocessing transition)
84# .-------------------------------.
85# | go_kubernetes_resource_bundle |
86# '-------------------------------'
87# | '--------------------------.
Lorenz Brun4e0dba62021-05-17 15:25:15 +020088# .---------------------------. .--------------------------.
Serge Bazanski7353e172021-03-31 22:09:22 +020089# | go_kubernetes_library | | go_kubernetes_library |
90# |---------------------------| |--------------------------| ... others ...
91# | clientset/verioned/typed | | clientset/verioned/fake |
92# '---------------------------' '--------------------------'
93# | |
Lorenz Brun4e0dba62021-05-17 15:25:15 +020094# .---------------------------. .--------------------------.
Serge Bazanski7353e172021-03-31 22:09:22 +020095# | go_library | | go_library |
96# |---------------------------| |--------------------------| ... others ...
97# | clientset/versioned/typed | | clientset/versioned/fake |
98# '---------------------------' '--------------------------'
99#
100
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200101load("@io_bazel_rules_go//go:def.bzl", "GoLibrary", "GoPath", "go_context")
Serge Bazanski7353e172021-03-31 22:09:22 +0200102
103def _preprocessing_transition_impl(settings, attr):
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200104 return {"//metropolis/build/kube-code-generator:preprocessing": "yes"}
Serge Bazanski7353e172021-03-31 22:09:22 +0200105
106# preprocessing_transition is attached to the incoming go_path in
107# go_kubernetes_resource_bundle, unsets the
108# //metropolis/build/kube-code-generator:embed_deepcopy config setting.
109# This allows go_libraries that make up the handwritten API libraries to only
110# embed the generated deepcopy when they are pulled in for build reasons, not
111# when the graph is being traversed in order to generate the deepcopy itself.
112# This breaks up the cycle that would happen otherwise.
113preprocessing_transition = transition(
114 implementation = _preprocessing_transition_impl,
115 inputs = [],
116 outputs = ["//metropolis/build/kube-code-generator:preprocessing"],
117)
118
119# KubeResourceBundle is emitted by go_kubernetes_resource_bundle and contains
120# informations about libraries generated by the kubernetes code-generators.
121KubeResourceBundle = provider(
122 "Information about the generated Go sources of a k8s.io/code-generator-built library.",
123 fields = {
124 "libraries": "Map from Go importpath to list of Files that make up this importpath.",
125 },
126)
127
128def _go_kubernetes_library_impl(ctx):
129 go = go_context(ctx)
130 bundle = ctx.attr.bundle[KubeResourceBundle]
131 libraries = bundle.libraries
132
133 found_importpaths = [l.importpath for l in libraries]
134
135 libraries = [l for l in libraries if l.importpath == ctx.attr.importpath]
136 if len(libraries) < 1:
137 fail("importpath {} not found in bundle (have {})".format(ctx.attr.importpath, ", ".join(found_importpaths)))
138 if len(libraries) > 1:
139 fail("internal error: multiple libraries with importpath {} found in bundle".format(ctx.attr.importpath))
140 library = libraries[0]
141
142 source = go.library_to_source(go, ctx.attr, library, ctx.coverage_instrumented())
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200143 return [library, source, OutputGroupInfo(go_generated_srcs = depset(library.srcs))]
Serge Bazanski7353e172021-03-31 22:09:22 +0200144
145# go_kubernetes_library picks a single Go library from a kube_resource_bundle
146# and prepares it for being embedded into a go_library.
147go_kubernetes_library = rule(
148 implementation = _go_kubernetes_library_impl,
149 attrs = {
150 "bundle": attr.label(
151 mandatory = True,
152 providers = [KubeResourceBundle],
153 doc = "A go_kubernetes_resource_bundle that contains the result of a kubernetes code-generation run.",
154 ),
155 "importpath": attr.string(
156 mandatory = True,
157 doc = "The importpath of the library picked from the bundle, same as the importpath of the go_library that embeds it.",
158 ),
159 "deps": attr.label_list(
160 providers = [GoLibrary],
161 doc = "All build dependencies of this library.",
162 ),
Serge Bazanski7353e172021-03-31 22:09:22 +0200163 "_go_context_data": attr.label(
164 default = "@io_bazel_rules_go//:go_context_data",
165 ),
Serge Bazanski7353e172021-03-31 22:09:22 +0200166 },
167 toolchains = ["@io_bazel_rules_go//go:toolchain"],
168)
169
170# _gotool_run is a helper function which runs an executable under
171# //metropolis/build/gotoolwrap, effectively setting up everything required to
172# use standard Go tooling on the monogon workspace (ie. GOPATH/GOROOT). This is
173# required by generators to run 'go fmt'.
Tim Windelschmidtddc5e6a2024-04-23 23:44:34 +0200174#
175# The optional `copyout` argument configures which files to copy out from the
176# GOPATH into declared files. The contents of the list should be strings that
177# refer to a file within GOPATH/src, eg. source.monogon.dev/foo/bar/baz.go. The
178# files is then going to be copied into the path corresponding to a declared
179# file of the same basename.
180def _gotool_run(cg, executable, arguments, copyout=[], **kwargs):
181 ctx = cg.ctx
Serge Bazanski7353e172021-03-31 22:09:22 +0200182 go = go_context(ctx)
183 gopath = ctx.attr.gopath[0][GoPath]
184
185 inputs = [
186 gopath.gopath_file,
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200187 ] + kwargs.get("inputs", [])
Serge Bazanski7353e172021-03-31 22:09:22 +0200188
189 tools = [
190 executable,
191 go.sdk.go,
Tim Windelschmidtddc5e6a2024-04-23 23:44:34 +0200192 ] + go.sdk.srcs + go.sdk.tools + kwargs.get("tools", [])
193
194 copyout_env = []
195 for path in copyout:
196 to = cg.output_root + "/" + path
197 copyout_env.append("{}:{}".format(path, to))
Serge Bazanski7353e172021-03-31 22:09:22 +0200198
199 env = {
200 "GOTOOLWRAP_GOPATH": gopath.gopath_file.path,
201 "GOTOOLWRAP_GOROOT": go.sdk.root_file.dirname,
Tim Windelschmidtddc5e6a2024-04-23 23:44:34 +0200202 "GOTOOLWRAP_COPYOUT": ';'.join(copyout_env),
Serge Bazanski7353e172021-03-31 22:09:22 +0200203 }
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200204 env.update(kwargs.get("env", {}))
Serge Bazanski7353e172021-03-31 22:09:22 +0200205
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200206 kwargs_ = dict([(k, v) for (k, v) in kwargs.items() if k not in [
207 "executable",
208 "arguments",
209 "inputs",
210 "env",
211 "tools",
Serge Bazanski7353e172021-03-31 22:09:22 +0200212 ]])
213
214 ctx.actions.run(
215 executable = ctx.executable._gotoolwrap,
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200216 arguments = [executable.path] + arguments,
Serge Bazanski7353e172021-03-31 22:09:22 +0200217 env = env,
218 inputs = inputs,
219 tools = tools,
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200220 **kwargs_
Serge Bazanski7353e172021-03-31 22:09:22 +0200221 )
222
Serge Bazanski7353e172021-03-31 22:09:22 +0200223# _output_directory returns the relative path into which
224# ctx.action.declare_file writes are rooted. This is used as code-generators
225# require a root path for all outputted files, instead of a list of files to
226# emit.
227def _output_directory(ctx):
228 # We combine bin_dir, the BUILDfile path and the target name. This seems
229 # wrong. Is there no simpler way to do this?
230 buildfile_path = ctx.build_file_path
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200231 parts = buildfile_path.split("/")
232 if not parts[-1].startswith("BUILD"):
Serge Bazanski7353e172021-03-31 22:09:22 +0200233 fail("internal error: unexpected BUILD file path: {}", parts[-1])
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200234 package_path = "/".join(parts[:-1])
235 return "/".join([ctx.bin_dir.path, package_path, ctx.attr.name])
Serge Bazanski7353e172021-03-31 22:09:22 +0200236
237# _cg returns a 'codegen context', a struct that's used to accumulate the
238# results of code generation. It assumes all output will be rooted in a
239# generated importpath (with more 'shortened' importpaths underneath the root),
240# and collects outputs to pass to the codegen execution action. It also
241# collects a map of importpaths to outputs that make it up.
242def _cg(ctx, importpath):
243 output_root = _output_directory(ctx)
244
245 return struct(
246 # The 'root' importpath, under which 'shortened' importpaths reside.
247 importpath = importpath,
248 # The prefix into which all files will be emitted. We use the target
249 # name for convenience.
250 output_prefix = ctx.attr.name,
251 # The full relative path visible to the codegen, pointing to the same
252 # directory as output_prefix (just from the point of view of the
253 # runtime filesystem, not the ctx.actions filepath declaration API).
254 output_root = output_root,
255 # The list of outputs that have to be generated by the codegen.
256 outputs = [],
Tim Windelschmidtddc5e6a2024-04-23 23:44:34 +0200257 # List of files compatible with the `copyout` argument of _gotool_run.
258 # Populated by calls to _declare_library. Should be used when the tool
259 # generates files within the GOPATH instead of directly at declared
260 # output file locations.
261 copyout = [],
Serge Bazanski7353e172021-03-31 22:09:22 +0200262 # A map of importpath to list of outputs (from the above list) that
263 # make up a generated Go package/library.
264 libraries = {},
Serge Bazanski7353e172021-03-31 22:09:22 +0200265 ctx = ctx,
266 )
267
Serge Bazanski7353e172021-03-31 22:09:22 +0200268# _declare_library adds a single Go package/library at importpath to the
269# codegen context with the given file paths (rooted in the importpath).
270def _declare_library(cg, importpath, files):
271 importpath = cg.importpath + "/" + importpath
272 cg.libraries[importpath] = []
273 for f in files:
274 output = cg.ctx.actions.declare_file("{}/{}/{}".format(
275 cg.output_prefix,
276 importpath,
277 f,
278 ))
279 cg.outputs.append(output)
280 cg.libraries[importpath].append(output)
Tim Windelschmidtddc5e6a2024-04-23 23:44:34 +0200281 cg.copyout.append("{}/{}".format(importpath, f))
Serge Bazanski7353e172021-03-31 22:09:22 +0200282
Serge Bazanski7353e172021-03-31 22:09:22 +0200283# _declare_libraries declares multiple Go package/libraries to the codegen
284# context. The key of the dictionary is the importpath of the library, and the
285# value are the file names of generated outputs.
286def _declare_libraries(cg, libraries):
287 for k, v in libraries.items():
288 _declare_library(cg, k, v)
289
Serge Bazanski7353e172021-03-31 22:09:22 +0200290# _codegen_clientset runs the clientset codegenerator.
291def _codegen_clientset(ctx):
292 cg = _cg(ctx, ctx.attr.importpath)
293
294 _declare_libraries(cg, {
Lorenz Brun6211e4d2023-11-14 19:09:40 +0100295 "clientset/versioned": ["clientset.go"],
Serge Bazanski7353e172021-03-31 22:09:22 +0200296 "clientset/versioned/fake": ["register.go", "clientset_generated.go"],
297 "clientset/versioned/scheme": ["register.go", "doc.go"],
298 })
299
300 for api, types in ctx.attr.apis.items():
301 client_name = api.split("/")[-2]
302 _declare_libraries(cg, {
303 "clientset/versioned/typed/{}".format(api): [
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200304 "doc.go",
305 "generated_expansion.go",
Serge Bazanski7353e172021-03-31 22:09:22 +0200306 "{}_client.go".format(client_name),
307 ] + [
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200308 "{}.go".format(t)
309 for t in types
Serge Bazanski7353e172021-03-31 22:09:22 +0200310 ],
311 "clientset/versioned/typed/{}/fake".format(api): [
312 "doc.go",
313 "fake_{}_client.go".format(client_name),
314 ],
315 })
316
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200317 _gotool_run(
Tim Windelschmidtddc5e6a2024-04-23 23:44:34 +0200318 cg,
Serge Bazanski7353e172021-03-31 22:09:22 +0200319 mnemonic = "ClientsetGen",
320 executable = ctx.executable._client_gen,
321 arguments = [
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200322 "--clientset-name",
323 "versioned",
324 "--input-base",
325 ctx.attr.apipath,
326 "--input",
327 ",".join(ctx.attr.apis),
Tim Windelschmidtddc5e6a2024-04-23 23:44:34 +0200328 "--output-pkg",
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200329 cg.importpath + "/clientset",
Tim Windelschmidtddc5e6a2024-04-23 23:44:34 +0200330 "--output-dir",
331 cg.output_root + "/" + cg.importpath + "/clientset",
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200332 "--go-header-file",
333 ctx.file.boilerplate.path,
Serge Bazanski7353e172021-03-31 22:09:22 +0200334 ],
335 inputs = [
336 ctx.file.boilerplate,
337 ],
338 outputs = cg.outputs,
339 )
340
341 return cg.libraries
342
Serge Bazanski7353e172021-03-31 22:09:22 +0200343# _codegen_deepcopy runs the deepcopy codegenerator (outputting to the apipath,
344# not the importpath).
345def _codegen_deepcopy(ctx):
346 cg = _cg(ctx, ctx.attr.apipath)
347
348 for api, types in ctx.attr.apis.items():
349 _declare_libraries(cg, {
350 api: ["zz_generated.deepcopy.go"],
351 })
352
353 _gotool_run(
Tim Windelschmidtddc5e6a2024-04-23 23:44:34 +0200354 cg,
355 copyout = cg.copyout,
Serge Bazanski7353e172021-03-31 22:09:22 +0200356 mnemonic = "DeepcopyGen",
357 executable = ctx.executable._deepcopy_gen,
358 arguments = [
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200359 "--go-header-file",
360 ctx.file.boilerplate.path,
361 "--stderrthreshold",
362 "0",
Tim Windelschmidtddc5e6a2024-04-23 23:44:34 +0200363 "--output-file",
364 "zz_generated.deepcopy.go",
365 ] + ["{}/{}".format(ctx.attr.apipath, api) for api in ctx.attr.apis],
Serge Bazanski7353e172021-03-31 22:09:22 +0200366 inputs = [
367 ctx.file.boilerplate,
368 ],
369 outputs = cg.outputs,
370 )
371 return cg.libraries
372
Serge Bazanski7353e172021-03-31 22:09:22 +0200373# _codegen_informer runs the informer codegenerator.
374def _codegen_informer(ctx):
375 cg = _cg(ctx, ctx.attr.importpath)
376
377 _declare_libraries(cg, {
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200378 "informers/externalversions": ["factory.go", "generic.go"],
379 "informers/externalversions/internalinterfaces": ["factory_interfaces.go"],
Serge Bazanski7353e172021-03-31 22:09:22 +0200380 })
381
382 for api, types in ctx.attr.apis.items():
383 client_name = api.split("/")[-2]
384 _declare_libraries(cg, {
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200385 "informers/externalversions/{}".format(client_name): ["interface.go"],
Serge Bazanski7353e172021-03-31 22:09:22 +0200386 "informers/externalversions/{}".format(api): [
387 "interface.go",
388 ] + [
389 "{}.go".format(t)
390 for t in types
391 ],
392 })
393
394 _gotool_run(
Tim Windelschmidtddc5e6a2024-04-23 23:44:34 +0200395 cg,
Serge Bazanski7353e172021-03-31 22:09:22 +0200396 mnemonic = "InformerGen",
397 executable = ctx.executable._informer_gen,
398 arguments = [
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200399 "--versioned-clientset-package",
400 "{}/clientset/versioned".format(ctx.attr.importpath),
401 "--listers-package",
402 "{}/listers".format(ctx.attr.importpath),
Tim Windelschmidtddc5e6a2024-04-23 23:44:34 +0200403 "--output-pkg",
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200404 "{}/informers".format(ctx.attr.importpath),
Tim Windelschmidtddc5e6a2024-04-23 23:44:34 +0200405 "--output-dir",
406 cg.output_root + "/" + cg.importpath + "/informers",
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200407 "--go-header-file",
408 ctx.file.boilerplate.path,
Tim Windelschmidtddc5e6a2024-04-23 23:44:34 +0200409 ] + ["{}/{}".format(ctx.attr.apipath, api) for api in ctx.attr.apis],
Serge Bazanski7353e172021-03-31 22:09:22 +0200410 inputs = [
411 ctx.file.boilerplate,
412 ],
413 outputs = cg.outputs,
414 )
415
416 return cg.libraries
417
Serge Bazanski7353e172021-03-31 22:09:22 +0200418# _codegen_lister runs the lister codegenerator.
419def _codegen_lister(ctx):
420 cg = _cg(ctx, ctx.attr.importpath)
421
422 for api, types in ctx.attr.apis.items():
423 client_name = api.split("/")[-2]
424 _declare_libraries(cg, {
425 "listers/{}".format(api): [
426 "expansion_generated.go",
427 ] + [
428 "{}.go".format(t)
429 for t in types
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200430 ],
Serge Bazanski7353e172021-03-31 22:09:22 +0200431 })
432
433 _gotool_run(
Tim Windelschmidtddc5e6a2024-04-23 23:44:34 +0200434 cg,
Serge Bazanski7353e172021-03-31 22:09:22 +0200435 mnemonic = "ListerGen",
436 executable = ctx.executable._lister_gen,
437 arguments = [
Tim Windelschmidtddc5e6a2024-04-23 23:44:34 +0200438 "--output-pkg",
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200439 "{}/listers".format(ctx.attr.importpath),
Tim Windelschmidtddc5e6a2024-04-23 23:44:34 +0200440 "--output-dir",
441 cg.output_root + "/" + cg.importpath + "/listers",
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200442 "--go-header-file",
443 ctx.file.boilerplate.path,
444 "-v",
445 "10",
Tim Windelschmidtddc5e6a2024-04-23 23:44:34 +0200446 ] + ["{}/{}".format(ctx.attr.apipath, api) for api in ctx.attr.apis],
Serge Bazanski7353e172021-03-31 22:09:22 +0200447 inputs = [
448 ctx.file.boilerplate,
449 ],
450 outputs = cg.outputs,
451 )
452
453 return cg.libraries
454
Serge Bazanski7353e172021-03-31 22:09:22 +0200455# _update_dict_check is a helper function that updates dict a with dict b,
456# ensuring there's no overwritten keys.
457def _update_dict_check(a, b):
458 for k in b.keys():
459 if k in a:
460 fail("internal error: repeat importpath {}", k)
461 a.update(b)
462
Serge Bazanski7353e172021-03-31 22:09:22 +0200463def _go_kubernetes_resource_bundle_impl(ctx):
464 go = go_context(ctx)
465
466 all_gens = {}
467 _update_dict_check(all_gens, _codegen_clientset(ctx))
468 _update_dict_check(all_gens, _codegen_deepcopy(ctx))
469 _update_dict_check(all_gens, _codegen_informer(ctx))
470 _update_dict_check(all_gens, _codegen_lister(ctx))
471
472 libraries = []
473 for importpath, srcs in all_gens.items():
474 library = go.new_library(
475 go,
476 srcs = srcs,
477 importpath = importpath,
478 )
479 libraries.append(library)
480
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200481 return [KubeResourceBundle(libraries = libraries)]
Serge Bazanski7353e172021-03-31 22:09:22 +0200482
483# go_kubernetes_resource_bundle runs kubernetes code-generators on a codepath
484# for some requested APIs, and whose output can be made into Go library targets
485# via go_kubernetes_library. This bundle corresponds to a single Kubernetes API
486# resource group.
487go_kubernetes_resource_bundle = rule(
488 implementation = _go_kubernetes_resource_bundle_impl,
489 attrs = {
490 "gopath": attr.label(
491 mandatory = True,
492 providers = [GoPath],
493 cfg = preprocessing_transition,
494 doc = "A rules_go go_path that contains all the API libraries for which codegen should be run.",
495 ),
Serge Bazanski7353e172021-03-31 22:09:22 +0200496 "importpath": attr.string(
497 mandatory = True,
498 doc = """
499 The root importpath of the generated code (apart from deepcopy
500 codegen). The Bazel target path corresponding to this
501 importpath needs to contain the go_kubernetes_library and
502 go_library targets that allow to actually build against the
503 generated code.
504 """,
505 ),
Serge Bazanski7353e172021-03-31 22:09:22 +0200506 "apipath": attr.string(
507 mandatory = True,
508 doc = "The root importpath of the APIs for which to generate code.",
509 ),
510 "apis": attr.string_list_dict(
511 mandatory = True,
512 doc = """
513 The APIs underneath importpath for which to generated code,
514 eg. foo/v1, mapping into a list of lowercased types generated
515 from each (eg. widget for `type Widget struct`).
516 """,
517 ),
Serge Bazanski7353e172021-03-31 22:09:22 +0200518 "boilerplate": attr.label(
519 default = "//metropolis/build/kube-code-generator:boilerplate.go.txt",
520 allow_single_file = True,
521 doc = "Header that will be used in the generated code.",
522 ),
Serge Bazanski7353e172021-03-31 22:09:22 +0200523 "_go_context_data": attr.label(
524 default = "@io_bazel_rules_go//:go_context_data",
525 ),
Serge Bazanski7353e172021-03-31 22:09:22 +0200526 "_gotoolwrap": attr.label(
527 default = Label("//metropolis/build/gotoolwrap"),
528 allow_single_file = True,
529 executable = True,
530 cfg = "exec",
531 ),
Serge Bazanski7353e172021-03-31 22:09:22 +0200532 "_deepcopy_gen": attr.label(
533 default = Label("@io_k8s_code_generator//cmd/deepcopy-gen"),
534 allow_single_file = True,
535 executable = True,
536 cfg = "exec",
537 ),
538 "_client_gen": attr.label(
539 default = Label("@io_k8s_code_generator//cmd/client-gen"),
540 allow_single_file = True,
541 executable = True,
542 cfg = "exec",
543 ),
544 "_informer_gen": attr.label(
545 default = Label("@io_k8s_code_generator//cmd/informer-gen"),
546 allow_single_file = True,
547 executable = True,
548 cfg = "exec",
549 ),
550 "_lister_gen": attr.label(
551 default = Label("@io_k8s_code_generator//cmd/lister-gen"),
552 allow_single_file = True,
553 executable = True,
554 cfg = "exec",
555 ),
Serge Bazanski7353e172021-03-31 22:09:22 +0200556 "_allowlist_function_transition": attr.label(
Lorenz Brun4e0dba62021-05-17 15:25:15 +0200557 default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
558 ),
Serge Bazanski7353e172021-03-31 22:09:22 +0200559 },
560 toolchains = ["@io_bazel_rules_go//go:toolchain"],
561)