Skip to content

Commit 56dcc14

Browse files
committed
setup-envtest: allow downloading envtest binaries from controller-tools
releases
1 parent 834905b commit 56dcc14

15 files changed

+1261
-652
lines changed

tools/setup-envtest/README.md

+25-10
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
This is a small tool that manages binaries for envtest. It can be used to
44
download new binaries, list currently installed and available ones, and
5-
clean up versions.
5+
clean up versions. Binaries can be downloaded either via HTTP via an index
6+
or from GCS.
67

78
To use it, just go-install it on 1.19+ (it's a separate, self-contained
89
module):
@@ -40,6 +41,16 @@ setup-envtest use -i --use-env
4041

4142
# sideload a pre-downloaded tarball as Kubernetes 1.16.2 into our store
4243
setup-envtest sideload 1.16.2 < downloaded-envtest.tar.gz
44+
45+
# Per default envtest binaries are downloaded from:
46+
# https://raw.githubusercontent.com/kubernetes-sigs/controller-tools/master/envtest-releases.yaml
47+
# To download from a custom index use the following:
48+
setup-envtest use --index https://custom.com/envtest-releases.yaml
49+
50+
# To download from the kubebuilder-tools GCS bucket: (default behavior before v0.18)
51+
# Note: This is a Google-owned bucket and it might be shutdown at any time
52+
# see: https://github.com/kubernetes/k8s.io/issues/2647#event-12439345373
53+
setup-envtest use --use-gcs
4354
```
4455

4556
## Where does it put all those binaries?
@@ -51,16 +62,16 @@ On Linux, this is `$XDG_DATA_HOME`; on Windows, `%LocalAppData`; and on
5162
OSX, `~/Library/Application Support`.
5263

5364
There's an overall folder that holds all files, and inside that is
54-
a folder for each version/platform pair. The exact directory structure is
55-
not guarnateed, except that the leaf directory will contain the names
56-
expected by envtest. You should always use `setup-envtest fetch` or
65+
a folder for each version/platform pair. The exact directory structure is
66+
not guaranteed, except that the leaf directory will contain the names
67+
expected by envtest. You should always use `setup-envtest fetch` or
5768
`setup-envtest switch` (generally with the `-p path` or `-p env` flags) to
5869
get the directory that you should use.
5970

6071
## Why do I have to do that `source <(blah blah blah)` thing
6172

6273
This is a normal binary, not a shell script, so we can't set the parent
63-
process's environment variables. If you use this by hand a lot and want
74+
process's environment variables. If you use this by hand a lot and want
6475
to save the typing, you could put something like the following in your
6576
`~/.zshrc` (or similar for bash/fish/whatever, modified to those):
6677

@@ -79,7 +90,7 @@ setup-envtest() {
7990
There are a few options.
8091

8192
First, you'll probably want to set the `-i/--installed` flag. If you want
82-
to avoid forgetting to set this flag, set the `ENVTEST_INSTALLED_ONLY`
93+
to avoid forgetting to set this flag, set the `ENVTEST_INSTALLED_ONLY`
8394
env variable, which will switch that flag on by default.
8495

8596
Then, you have a few options for managing your binaries:
@@ -98,13 +109,17 @@ Then, you have a few options for managing your binaries:
98109
`--use-env` on by default.
99110

100111
- If you want to use this tool, but download your gziped tarballs
101-
separately, you can use the `sideload` command. You'll need to use the
112+
separately, you can use the `sideload` command. You'll need to use the
102113
`-k/--version` flag to indicate which version you're sideloading.
103114

104115
After that, it'll be as if you'd installed the binaries with `use`.
105116

106-
- If you want to talk to some internal source, you can use the
107-
`--remote-bucket` and `--remote-server` options. The former sets which
117+
- If you want to talk to some internal source via HTTP, you can simply set `--index`
118+
The index must contain references to envtest binary archives in the same format as:
119+
https://raw.githubusercontent.com/kubernetes-sigs/controller-tools/master/envtest-releases.yaml
120+
121+
- If you want to talk to some internal source in a GCS "style", you can use the
122+
`--remote-bucket` and `--remote-server` options together with `--use-gcs`. The former sets which
108123
GCS bucket to download from, and the latter sets the host to talk to as
109124
if it were a GCS endpoint. Theoretically, you could use the latter
110125
version to run an internal "mirror" -- the tool expects
@@ -114,7 +129,7 @@ Then, you have a few options for managing your binaries:
114129
```json
115130
{"items": [
116131
{"name": "kubebuilder-tools-X.Y.Z-os-arch.tar.gz", "md5Hash": "<base-64-encoded-md5-hash>"},
117-
{"name": "kubebuilder-tools-X.Y.Z-os-arch.tar.gz", "md5Hash": "<base-64-encoded-md5-hash>"},
132+
{"name": "kubebuilder-tools-X.Y.Z-os-arch.tar.gz", "md5Hash": "<base-64-encoded-md5-hash>"}
118133
]}
119134
```
120135

tools/setup-envtest/env/env.go

+22-18
Original file line numberDiff line numberDiff line change
@@ -33,17 +33,21 @@ type Env struct {
3333
// Platform is our current platform
3434
Platform versions.PlatformItem
3535

36-
// VerifiySum indicates whether or not we should run checksums.
36+
// VerifySum indicates whether we should run checksums.
3737
VerifySum bool
38-
// NoDownload forces us to not contact GCS, looking only
39-
// at local files instead.
38+
// NoDownload forces us to not contact GCS or download the index via HTTP,
39+
// looking only at local files instead.
4040
NoDownload bool
4141
// ForceDownload forces us to ignore local files and always
42-
// contact GCS & re-download.
42+
// contact GCS or download the index via HTTP & re-download.
4343
ForceDownload bool
4444

45-
// Client is our remote client for contacting GCS.
46-
Client *remote.Client
45+
// UseGCS signals if the GCS client is used.
46+
UseGCS bool
47+
48+
// Client is our remote client for contacting GCS or
49+
// to download the index via HTTP.
50+
Client remote.Client
4751

4852
// Log allows us to log.
4953
Log logr.Logger
@@ -133,7 +137,7 @@ func (e *Env) ListVersions(ctx context.Context) {
133137
}
134138

135139
// LatestVersion returns the latest version matching our version selector and
136-
// platform from the remote server, with the correspoding checksum for later
140+
// platform from the remote server, with the corresponding checksum for later
137141
// use as well.
138142
func (e *Env) LatestVersion(ctx context.Context) (versions.Concrete, versions.PlatformItem) {
139143
vers, err := e.Client.ListVersions(ctx)
@@ -193,7 +197,7 @@ func (e *Env) ExistsAndValid() bool {
193197
//
194198
// If necessary, it will enumerate on-disk and remote versions to accomplish
195199
// this, finding a version that matches our version selector and platform.
196-
// It will always yield a concrete version, it *may* yield a concrete platorm
200+
// It will always yield a concrete version, it *may* yield a concrete platform
197201
// as well.
198202
func (e *Env) EnsureVersionIsSet(ctx context.Context) {
199203
if e.Version.AsConcrete() != nil {
@@ -247,13 +251,13 @@ func (e *Env) EnsureVersionIsSet(ctx context.Context) {
247251

248252
// if we're not forcing a download, and we have a newer local version, just use that
249253
if !e.ForceDownload && localVer != nil && localVer.NewerThan(serverVer) {
250-
e.Platform.Platform = localPlat // update our data with md5
254+
e.Platform.Platform = localPlat // update our data with hash
251255
e.Version.MakeConcrete(*localVer)
252256
return
253257
}
254258

255259
// otherwise, use the new version from the server
256-
e.Platform = platform // update our data with md5
260+
e.Platform = platform // update our data with hash
257261
e.Version.MakeConcrete(serverVer)
258262
}
259263

@@ -266,13 +270,13 @@ func (e *Env) Fetch(ctx context.Context) {
266270
log := e.Log.WithName("fetch")
267271

268272
// if we didn't just fetch it, grab the sum to verify
269-
if e.VerifySum && e.Platform.MD5 == "" {
273+
if e.VerifySum && e.Platform.Hash == nil {
270274
if err := e.Client.FetchSum(ctx, *e.Version.AsConcrete(), &e.Platform); err != nil {
271-
ExitCause(2, err, "unable to fetch checksum for requested version")
275+
ExitCause(2, err, "unable to fetch hash for requested version")
272276
}
273277
}
274278
if !e.VerifySum {
275-
e.Platform.MD5 = "" // skip verification
279+
e.Platform.Hash = nil // skip verification
276280
}
277281

278282
var packedPath string
@@ -287,7 +291,7 @@ func (e *Env) Fetch(ctx context.Context) {
287291
}
288292
})
289293

290-
archiveOut, err := e.FS.TempFile("", "*-"+e.Platform.ArchiveName(*e.Version.AsConcrete()))
294+
archiveOut, err := e.FS.TempFile("", "*-"+e.Platform.ArchiveName(e.UseGCS, *e.Version.AsConcrete()))
291295
if err != nil {
292296
ExitCause(2, err, "unable to open file to write downloaded archive to")
293297
}
@@ -365,8 +369,8 @@ func (e *Env) PrintInfo(printFmt PrintFormat) {
365369
case PrintOverview:
366370
fmt.Fprintf(e.Out, "Version: %s\n", e.Version)
367371
fmt.Fprintf(e.Out, "OS/Arch: %s\n", e.Platform)
368-
if e.Platform.MD5 != "" {
369-
fmt.Fprintf(e.Out, "md5: %s\n", e.Platform.MD5)
372+
if e.Platform.Hash != nil {
373+
fmt.Fprintf(e.Out, "%s: %s\n", e.Platform.Hash.Type, e.Platform.Hash.Value)
370374
}
371375
fmt.Fprintf(e.Out, "Path: %s\n", path)
372376
case PrintPath:
@@ -409,7 +413,7 @@ func (e *Env) Sideload(ctx context.Context, input io.Reader) {
409413
}
410414

411415
var (
412-
// expectedExectuables are the executables that are checked in PathMatches
416+
// expectedExecutables are the executables that are checked in PathMatches
413417
// for non-store paths.
414418
expectedExecutables = []string{
415419
"kube-apiserver",
@@ -458,7 +462,7 @@ func (e *Env) PathMatches(value string) bool {
458462
}
459463

460464
// versionFromPathName checks if the given path's last component looks like one
461-
// of our versions, and, if so, what version it represents. If succesfull,
465+
// of our versions, and, if so, what version it represents. If successful,
462466
// it'll set version and platform, and return true. Otherwise it returns
463467
// false.
464468
func (e *Env) versionFromPathName(value string) bool {

tools/setup-envtest/go.mod

+14-12
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,27 @@ module sigs.k8s.io/controller-runtime/tools/setup-envtest
33
go 1.22.0
44

55
require (
6-
github.com/go-logr/logr v1.2.4
7-
github.com/go-logr/zapr v1.2.4
8-
github.com/onsi/ginkgo/v2 v2.12.1
9-
github.com/onsi/gomega v1.27.10
6+
github.com/go-logr/logr v1.4.1
7+
github.com/go-logr/zapr v1.3.0
8+
github.com/onsi/ginkgo/v2 v2.17.1
9+
github.com/onsi/gomega v1.32.0
1010
github.com/spf13/afero v1.6.0
1111
github.com/spf13/pflag v1.0.5
1212
go.uber.org/zap v1.26.0
13+
k8s.io/apimachinery v0.0.0-20240424173219-03f2f3350dc5
14+
sigs.k8s.io/yaml v1.3.0
1315
)
1416

1517
require (
1618
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
17-
github.com/golang/protobuf v1.5.3 // indirect
18-
github.com/google/go-cmp v0.5.9 // indirect
19-
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
19+
github.com/google/go-cmp v0.6.0 // indirect
20+
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect
2021
go.uber.org/multierr v1.10.0 // indirect
21-
golang.org/x/net v0.14.0 // indirect
22-
golang.org/x/sys v0.12.0 // indirect
23-
golang.org/x/text v0.12.0 // indirect
24-
golang.org/x/tools v0.12.0 // indirect
25-
google.golang.org/protobuf v1.28.0 // indirect
22+
golang.org/x/net v0.23.0 // indirect
23+
golang.org/x/sys v0.18.0 // indirect
24+
golang.org/x/text v0.14.0 // indirect
25+
golang.org/x/tools v0.18.0 // indirect
26+
google.golang.org/protobuf v1.33.0 // indirect
27+
gopkg.in/yaml.v2 v2.4.0 // indirect
2628
gopkg.in/yaml.v3 v3.0.1 // indirect
2729
)

0 commit comments

Comments
 (0)