Skip to content

Commit

Permalink
Re-implement list
Browse files Browse the repository at this point in the history
Some options might be missing...
  • Loading branch information
tomasaschan committed Apr 30, 2024
1 parent 2b6dcd6 commit a12a6c3
Show file tree
Hide file tree
Showing 7 changed files with 193 additions and 4 deletions.
12 changes: 12 additions & 0 deletions pkg/envtest/setup/env/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@ package env
import (
"io/fs"

"github.com/go-logr/logr"
"sigs.k8s.io/controller-runtime/pkg/envtest/setup/remote"
"sigs.k8s.io/controller-runtime/pkg/envtest/setup/store"
)

const KubebuilderAssetsEnvVar = "KUBEBUILDER_ASSETS"

// Env encapsulates the environment dependencies.
type Env struct {
*store.Store
Expand Down Expand Up @@ -54,5 +57,14 @@ func New(options ...Option) (*Env, error) {
env.Store = store.NewAt(dir)
}

if env.Client == nil {
// this is the minimal configuration that won't panic
env.Client = &remote.Client{
Bucket: remote.DefaultBucket,
Server: remote.DefaultServer,
Log: logr.Discard(),
}
}

return env, nil
}
63 changes: 63 additions & 0 deletions pkg/envtest/setup/list/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package list

import (
"cmp"
"os"
"runtime"

"sigs.k8s.io/controller-runtime/pkg/envtest/setup/env"
"sigs.k8s.io/controller-runtime/pkg/envtest/setup/versions"
)

type config struct {
platform versions.Platform
assetPath string
noDownload bool
envOpts []env.Option
}

// Option is a functional option for configuring the list workflow
type Option func(*config)

// WithEnvOption provides an option for the env.Env used by the workflow
func WithEnvOption(o env.Option) Option {
return func(c *config) { c.envOpts = append(c.envOpts, o) }
}

// WithAssetsAt sets the path to the assets directory.
func WithAssetsAt(dir string) Option {
return func(c *config) { c.assetPath = dir }
}

// WithAssetsFromEnv sets the path to the assets directory from the environment.
func WithAssetsFromEnv(useEnv bool) Option {
return func(c *config) {
if useEnv {
c.assetPath = cmp.Or(os.Getenv(env.KubebuilderAssetsEnvVar), c.assetPath)
}
}
}

// WithPlatform sets the target OS and architecture for the download.
func WithPlatform(os string, arch string) Option {
return func(c *config) { c.platform = versions.Platform{OS: os, Arch: arch} }
}

// NoDownload ensures only local versions are considered
func NoDownload(noDownload bool) Option { return func(c *config) { c.noDownload = noDownload } }

func configure(options ...Option) *config {
cfg := &config{}

for _, opt := range options {
opt(cfg)
}

if cfg.platform == (versions.Platform{}) {
cfg.platform = versions.Platform{
OS: runtime.GOOS,
Arch: runtime.GOARCH,
}
}
return cfg
}
81 changes: 81 additions & 0 deletions pkg/envtest/setup/list/list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package list

import (
"cmp"
"context"
"fmt"
"slices"

"sigs.k8s.io/controller-runtime/pkg/envtest/setup/env"
"sigs.k8s.io/controller-runtime/pkg/envtest/setup/store"
"sigs.k8s.io/controller-runtime/pkg/envtest/setup/versions"
)

// Status indicates whether a version is available locally or remotely
type Status string

const (
// Installed indicates that this version is installed on the local system
Installed Status = "installed"
// Available indicates that this version is available to download
Available Status = "available"
)

// Result encapsulates a single item in the list of versions
type Result struct {
Version versions.Concrete
Platform versions.Platform
Status Status
}

// List lists available versions, local and remote
func List(ctx context.Context, version versions.Spec, options ...Option) ([]Result, error) {
cfg := configure(options...)
env, err := env.New(cfg.envOpts...)
if err != nil {
return nil, err
}

if err := env.Store.Initialize(ctx); err != nil {
return nil, err
}

vs, err := env.Store.List(ctx, store.Filter{Version: version, Platform: cfg.platform})
if err != nil {
return nil, fmt.Errorf("list installed versions: %w", err)
}

results := make([]Result, 0, len(vs))
for _, v := range vs {
results = append(results, Result{Version: v.Version, Platform: v.Platform, Status: Installed})
}

if cfg.noDownload {
return results, nil
}

remoteVersions, err := env.Client.ListVersions(ctx)
if err != nil {
return nil, fmt.Errorf("list available versions: %w", err)
}

for _, set := range remoteVersions {
if !version.Matches(set.Version) {
continue
}
slices.SortFunc(set.Platforms, func(a, b versions.PlatformItem) int {
return cmp.Or(cmp.Compare(a.OS, b.OS), cmp.Compare(a.Arch, b.Arch))
})
for _, plat := range set.Platforms {
if cfg.platform.Matches(plat.Platform) {
results = append(results, Result{
Version: set.Version,
Platform: plat.Platform,
Status: Available,
})
}
}
}

return results, nil
}
3 changes: 3 additions & 0 deletions pkg/envtest/setup/remote/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import (
"sigs.k8s.io/controller-runtime/pkg/envtest/setup/versions"
)

const DefaultBucket = "kubebuilder-tools"
const DefaultServer = "storage.googleapis.com"

// objectList is the parts we need of the GCS "list-objects-in-bucket" endpoint.
type objectList struct {
Items []bucketObject `json:"items"`
Expand Down
11 changes: 11 additions & 0 deletions pkg/envtest/setup/setup-envtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,21 @@ import (
"context"
"fmt"

"sigs.k8s.io/controller-runtime/pkg/envtest/setup/list"
"sigs.k8s.io/controller-runtime/pkg/envtest/setup/use"
"sigs.k8s.io/controller-runtime/pkg/envtest/setup/versions"
)

// List implements the list workflow for listing local and remote versions
func List(ctx context.Context, version string, options ...list.Option) ([]list.Result, error) {
spec, err := readSpec(version)
if err != nil {
return nil, err
}

return list.List(ctx, spec, options...)
}

// Use implements the use workflow for selecting and using a version of the environment.
//
// It will download a remote version if required (and options allow), and return the path to the binary asset directory.
Expand Down
4 changes: 1 addition & 3 deletions pkg/envtest/setup/use/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/envtest/setup/versions"
)

const kubebuilderAssets = "KUBEBUILDER_ASSETS"

type config struct {
platform versions.Platform
assetPath string
Expand All @@ -33,7 +31,7 @@ func WithAssetsAt(dir string) Option {
func WithAssetsFromEnv(useEnv bool) Option {
return func(c *config) {
if useEnv {
c.assetPath = cmp.Or(os.Getenv(kubebuilderAssets), c.assetPath)
c.assetPath = cmp.Or(os.Getenv(env.KubebuilderAssetsEnvVar), c.assetPath)
}
}
}
Expand Down
23 changes: 22 additions & 1 deletion tools/setup-envtest/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"fmt"
"os"
"runtime"
"text/tabwriter"

"github.com/go-logr/logr"
"github.com/go-logr/zapr"
Expand All @@ -18,6 +19,7 @@ import (

"sigs.k8s.io/controller-runtime/pkg/envtest/setup"
senv "sigs.k8s.io/controller-runtime/pkg/envtest/setup/env"
"sigs.k8s.io/controller-runtime/pkg/envtest/setup/list"
sremote "sigs.k8s.io/controller-runtime/pkg/envtest/setup/remote"
"sigs.k8s.io/controller-runtime/pkg/envtest/setup/use"
envp "sigs.k8s.io/controller-runtime/tools/setup-envtest/env"
Expand Down Expand Up @@ -289,7 +291,26 @@ Environment Variables:
result.Path,
)
case "list":
workflows.List{}.Do(env)
results, err := setup.List(
logr.NewContext(context.Background(), globalLog.WithName("list")),
version,
list.WithAssetsFromEnv(*useEnv),
list.NoDownload(*installedOnly),
list.WithEnvOption(senv.WithClient(&sremote.Client{
Bucket: *remoteBucket,
Server: *remoteServer,
Log: globalLog.WithName("remote-client"),
})),
)
if err != nil {
envp.Exit(2, err.Error())
}

w := tabwriter.NewWriter(os.Stdout, 4, 4, 2, ' ', 0)
defer w.Flush()
for _, result := range results {
fmt.Fprintf(w, "(%s)\tv%s\t%s\n", result.Status, result.Version, result.Platform)
}
case "cleanup":
workflows.Cleanup{}.Do(env)
case "sideload":
Expand Down

0 comments on commit a12a6c3

Please sign in to comment.