1# Rules, macros, and build constants for building containers using Bazel
2
3## Third party container dependencies
4
5### `third_party_container_dep` rules
6
7The `third_party_container_dep` rule serializes third party oci containers into
8the Bazel build graph. It performs two functions:
9
101. The rule itself adds a `oci_pull` repository rule which can be used in the
11`WORKSPACE` file to create a reference to an `oci_image` usable in other rules
12that depend on images.
13
14 - Ex.: a `third_party_container_dep` that adds an image name of `alpine_new`
15 would be referenceable by other `oci_image`s via its repository name `@alpine_new`
16
171. The `third_party_container_dep` serves as an anchor for the container deps Gazelle
18extension found at `hack/build/rules/container/gazelle/language/` to create
19`container_push` targets. These targets serve two purposes:
20
21 1. Make the `oci_image` values available to Bazel so they can be
22 incorporated into the build graph and usable by other rules, specifically
23 the `kustomization` rule
24
25 1. Serve as the mechanism for how the third party images make their way
26 into the `thirdparty` GCP artifact registry.
27
28Examples for how to create third party dependencies exist in several locations
29across `edge-infra`. Some good examples include:
30
31- `third_party/k8s/calico/images.bzl`
32- `hack/deps/images.bzl`
33
34### Adding new third party container dependencies
35
36Adding a new dependency involves a few steps:
37
381. Create a new `.bzl` file in the directory where you want to keep track of the
39dependencies.
401. In this new file, add the `load()` statement for the `third_party_container_dep`
41rule:
42`my_images.bzl`
43
44 ```python
45 load("//hack/build/rules/container:third_party_images.bzl", "third_party_container_dep")
46 ```
47
48 1. Next, add a function that will wrap your `third_party_container_dep`
49 targets into a single call:
50 `my_images.bzl`
51
52 ```python
53 load("//hack/build/rules/container:third_party_images.bzl", "third_party_container_dep")
54
55 def my_images():
56 """This function wraps together the third party dependencies
57 for a specific set of needs.
58 """
59 # deps will go here
60 ```
61
62 1. For each dependency, add a `third_party_container_dep` rule filling in
63 the required fields:
64 `my_images.bzl`
65
66 ```python
67 load("//hack/build/rules/container:third_party_images.bzl", "third_party_container_dep")
68
69 def my_images():
70 """This function wraps together the third party dependencies
71 for a specific set of needs.
72 """
73
74 third_party_container_dep(
75 image_name = "alpine_new",
76 tag = "1.20",
77 digest = "sha256:abcdef1234thisisavalidsha256",
78 repository = "path/to/repository",
79 registry = "index.docker.io",
80 )
81 ```
82
83 The uses and requirements of each field can be found in the function
84 documentation for the `third_party_container_dep` rule.
85 1. It may be useful to set Starlark constants (`ALL_CAPS_SNAKE_CASE`)
86 variables to avoid repetition of certain values like the registry value:
87 `my_images.bzl`
88
89 ```python
90 load("//hack/build/rules/container:third_party_images.bzl", "third_party_container_dep")
91
92 SHARED_REGISTRY= "index.docker.io"
93
94 def my_images():
95 """This function wraps together the third party dependencies
96 for a specific set of needs.
97 """
98
99 third_party_container_dep(
100 image_name = "alpine_new",
101 tag = "v1.20",
102 digest = "sha256:abcdef1234thisisavalidsha256",
103 repository = "path/to/alpine",
104 registry = SHARED_REGISTRY,
105 )
106 third_party_container_dep(
107 image_name = "ubuntu_new",
108 tag = "v2.0",
109 digest = "sha256:abcdef1234thisisavalidsha256",
110 repository = "path/to/ubuntu",
111 registry = SHARED_REGISTRY,
112 )
113 ```
114
115 It is also possible to import constant values from another `.bzl` file:
116 `my_constants.bzl`
117
118 ```python
119 ANOTHER_REGISTRY = "gcr.io"
120 ```
121
122 `my_images.bzl`
123
124 ```python
125 load("//hack/build/rules/container:third_party_images.bzl", "third_party_container_dep")
126 load("//:my_constants.bzl", "ANOTHER_REGISTRY")
127
128 SHARED_REGISTRY= "index.docker.io"
129
130 def my_images():
131 """This function wraps together the third party dependencies
132 for a specific set of needs.
133 """
134
135 third_party_container_dep(
136 image_name = "alpine_new",
137 tag = "v1.20",
138 digest = "sha256:abcdef1234thisisavalidsha256",
139 repository = "path/to/alpine",
140 registry = SHARED_REGISTRY,
141 )
142 third_party_container_dep(
143 image_name = "ubuntu_new",
144 tag = "v2.0",
145 digest = "sha256:abcdef1234thisisavalidsha256",
146 repository = "path/to/ubuntu",
147 registry = SHARED_REGISTRY,
148 )
149 third_party_container_dep(
150 image_name = "debian_new",
151 tag = "v3.0",
152 digest = "sha256:abcdef1234thisisavalidsha256",
153 repository = "path/to/debian",
154 registry = ANOTHER_REGISTRY,
155 )
156 ```
157
1581. Once your new function is created, run `just g` and a corresponding
159`BUILD.bazel` file will be created next to your `my_images.bzl` file. This
160`BUILD.bazel` file will include a `container_push` rule for each
161`third_party_container_dep` rule that you added:
162`BUILD.bazel`
163
164 ```python
165 load("//hack/build/rules/container:index.bzl", "container_push")
166
167 container_push(
168 name = "alpine_new_container_push",
169 digest = "@alpine_new//:digest",
170 image = "@alpine_new//:alpine_new",
171 image_name = "alpine_new",
172 repository_file = "//hack/build/rules/container:thirdparty-repo",
173 tag = "v1.20",
174 visibility = ["//visibility:public"],
175 )
176 # ... other container_push rules omitted for brevity
177 ```
178
1791. Finally, `load()` your new function into `hack/deps/images.bzl` and add it
180to the `third_party_images()` function:
181
182 ```python
183 load("//path/to:my_images.bzl", "my_images")
184
185 def third_party_images():
186 base_images()
187 calico_images()
188 # your new function here
189 my_images()
190 ```
191
1921. At this point you can query bazel for the existence of your new dependency
193by running `bazel query @alpine_new//...` which should return
194`@alpine_new//:alpine_new` signifying the repository rule was created
195successfully and the `oci_image` is available for use.
1961. You can also build the `container_push` target by running
197`bazel build //path/to:alpine_new_container_push` or `bazel build //path/to/...`
198to build all `container_push` targets in that package.
199
200### Migrating existing third party containers
201
202Instructions for migrating existing third party containers are found [here](./MIGRATING_EXISTING.md)
View as plain text