Skip to content

[tmpnet] Define reusable flags for configuring kubernetes client access #3945

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
May 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ tasks:
desc: Generates protobuf
cmd: ./scripts/protobuf_codegen.sh

ginkgo-build:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For some reason ginkgo build . is no longer working, this task enables invoking ginkgo from anywhere in the tree against the cwd rather than having to use a root-based path.

desc: Runs ginkgo against the current working directory
cmd: ./bin/ginkgo build {{.USER_WORKING_DIR}}

install-nix:
desc: Installs nix with the determinate systems installer
cmd: curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
Expand Down
10 changes: 5 additions & 5 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@

# Kube tools
kubectl # Kubernetes CLI
k9s # Kubernetes TUI
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Handy for diagnosing kube issues

kind # Kubernetes-in-Docker
kubernetes-helm # Helm CLI (Kubernetes package manager)
self.packages.${system}.kind-with-registry # Script installing kind configured with a local registry
Expand Down
15 changes: 15 additions & 0 deletions scripts/start_kind_cluster.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script is reused in subsequent PRs


set -euo pipefail

# --kubeconfig and --kubeconfig-context should be provided in the form --arg=value
# to work with the simplistic mechanism enabling flag reuse.

# Enable reuse of the arguments to ginkgo relevant to starting a cluster
START_CLUSTER_ARGS=()
for arg in "$@"; do
if [[ "${arg}" =~ "--kubeconfig=" || "${arg}" =~ "--kubeconfig-context=" ]]; then
START_CLUSTER_ARGS+=("${arg}")
fi
done
./bin/tmpnetctl start-kind-cluster "${START_CLUSTER_ARGS[@]}"
8 changes: 5 additions & 3 deletions scripts/tests.e2e.bootstrap_monitor.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
set -euo pipefail

# Run e2e tests for bootstrap monitor.
#
# --kubeconfig and --kubeconfig-context should be provided in the form --arg=value
# to work with the simplistic mechanism enabling flag reuse.

if ! [[ "$0" =~ scripts/tests.e2e.bootstrap_monitor.sh ]]; then
echo "must be run from repository root"
exit 255
fi

./bin/tmpnetctl start-kind-cluster

KUBECONFIG="$HOME/.kube/config" ./bin/ginkgo -v ./tests/fixture/bootstrapmonitor/e2e
./scripts/start_kind_cluster.sh "$@"
./bin/ginkgo -v ./tests/fixture/bootstrapmonitor/e2e "$@"
5 changes: 3 additions & 2 deletions tests/fixture/bootstrapmonitor/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"k8s.io/client-go/kubernetes"

"github.com/ava-labs/avalanchego/tests/fixture/tmpnet"
"github.com/ava-labs/avalanchego/tests/fixture/tmpnet/flags"
"github.com/ava-labs/avalanchego/utils/logging"
"github.com/ava-labs/avalanchego/version"

Expand Down Expand Up @@ -221,6 +222,6 @@ func getLatestImageDetails(

func getClientset(log logging.Logger) (*kubernetes.Clientset, error) {
log.Info("Initializing clientset")
kubeConfigPath := os.Getenv("KUBECONFIG")
return tmpnet.GetClientset(log, kubeConfigPath, "")
kubeconfigPath := os.Getenv(flags.KubeconfigPathEnvVar)
return tmpnet.GetClientset(log, kubeconfigPath, "")
}
6 changes: 4 additions & 2 deletions tests/fixture/bootstrapmonitor/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"github.com/ava-labs/avalanchego/tests/fixture/bootstrapmonitor"
"github.com/ava-labs/avalanchego/tests/fixture/e2e"
"github.com/ava-labs/avalanchego/tests/fixture/tmpnet"
"github.com/ava-labs/avalanchego/tests/fixture/tmpnet/flags"
"github.com/ava-labs/avalanchego/utils/constants"

appsv1 "k8s.io/api/apps/v1"
Expand Down Expand Up @@ -60,13 +61,15 @@ const (
)

var (
kubeconfigVars *flags.KubeconfigVars
skipAvalanchegoImageBuild bool
skipMonitorImageBuild bool

nodeDataDir = bootstrapmonitor.NodeDataDir(dataDir) // Use a subdirectory of the data path so that os.RemoveAll can be used when starting a new test
)

func init() {
kubeconfigVars = flags.NewKubeconfigFlagVars()
flag.BoolVar(
&skipAvalanchegoImageBuild,
"skip-avalanchego-image-build",
Expand Down Expand Up @@ -103,8 +106,7 @@ var _ = ginkgo.Describe("[Bootstrap Tester]", func() {
}

ginkgo.By("Configuring a kubernetes client")
kubeconfigPath := os.Getenv("KUBECONFIG")
kubeconfig, err := tmpnet.GetClientConfig(tc.Log(), kubeconfigPath, "")
kubeconfig, err := tmpnet.GetClientConfig(tc.Log(), kubeconfigVars.Path, kubeconfigVars.Context)
require.NoError(err)
clientset, err := kubernetes.NewForConfig(kubeconfig)
require.NoError(err)
Expand Down
63 changes: 63 additions & 0 deletions tests/fixture/tmpnet/flags/kubeconfig.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved.
// See the file LICENSE for licensing terms.

package flags

import (
"flag"
"fmt"
"os"

"github.com/spf13/pflag"

"github.com/ava-labs/avalanchego/tests/fixture/tmpnet"
)

const KubeconfigPathEnvVar = "KUBECONFIG"

type KubeconfigVars struct {
Path string
Context string
}

// NewKubeconfigFlagVars registers kubeconfig flag variables for stdlib flag
func NewKubeconfigFlagVars() *KubeconfigVars {
return newKubeconfigFlagVars("")
}

// internal method enabling configuration of the doc prefix
func newKubeconfigFlagVars(docPrefix string) *KubeconfigVars {
v := &KubeconfigVars{}
v.register(flag.StringVar, docPrefix)
return v
}

// NewKubeconfigFlagSetVars registers kubeconfig flag variables for pflag
func NewKubeconfigFlagSetVars(flagSet *pflag.FlagSet) *KubeconfigVars {
return newKubeconfigFlagSetVars(flagSet, "")
}

// internal method enabling configuration of the doc prefix
func newKubeconfigFlagSetVars(flagSet *pflag.FlagSet, docPrefix string) *KubeconfigVars {
v := &KubeconfigVars{}
v.register(flagSet.StringVar, docPrefix)
return v
}

func (v *KubeconfigVars) register(stringVar varFunc[string], docPrefix string) {
stringVar(
&v.Path,
"kubeconfig",
tmpnet.GetEnvWithDefault(KubeconfigPathEnvVar, os.ExpandEnv("$HOME/.kube/config")),
docPrefix+fmt.Sprintf(
"The path to a kubernetes configuration file for the target cluster. Also possible to configure via the %s env variable.",
KubeconfigPathEnvVar,
),
)
stringVar(
&v.Context,
"kubeconfig-context",
"",
docPrefix+"The optional kubeconfig context to use",
)
}
35 changes: 12 additions & 23 deletions tests/fixture/tmpnet/tmpnetctl/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"path/filepath"

"github.com/spf13/cobra"
"github.com/spf13/pflag"
"go.uber.org/zap"

"github.com/ava-labs/avalanchego/tests"
Expand All @@ -24,7 +23,10 @@ import (

const cliVersion = "0.0.1"

var errNetworkDirRequired = fmt.Errorf("--network-dir or %s are required", tmpnet.NetworkDirEnvName)
var (
errNetworkDirRequired = fmt.Errorf("--network-dir or %s is required", tmpnet.NetworkDirEnvName)
errKubeconfigRequired = errors.New("--kubeconfig is required")
)

func main() {
var (
Expand Down Expand Up @@ -226,10 +228,7 @@ func main() {
)
rootCmd.AddCommand(checkLogsCmd)

var (
kubeConfigPath string
kubeConfigContext string
)
var kubeconfigVars *flags.KubeconfigVars
startKindClusterCmd := &cobra.Command{
Use: "start-kind-cluster",
Short: "Starts a local kind cluster with an integrated registry",
Expand All @@ -240,10 +239,15 @@ func main() {
if err != nil {
return err
}
return tmpnet.StartKindCluster(ctx, log, kubeConfigPath, kubeConfigContext)
// A valid kubeconfig is required for local kind usage but this is not validated by KubeconfigVars
// since unlike kind, tmpnet usage may involve an implicit in-cluster config.
if len(kubeconfigVars.Path) == 0 {
return errKubeconfigRequired
}
return tmpnet.StartKindCluster(ctx, log, kubeconfigVars.Path, kubeconfigVars.Context)
},
}
SetKubeConfigFlags(startKindClusterCmd.PersistentFlags(), &kubeConfigPath, &kubeConfigContext)
kubeconfigVars = flags.NewKubeconfigFlagSetVars(startKindClusterCmd.PersistentFlags())
rootCmd.AddCommand(startKindClusterCmd)

if err := rootCmd.Execute(); err != nil {
Expand All @@ -252,18 +256,3 @@ func main() {
}
os.Exit(0)
}

func SetKubeConfigFlags(flagSet *pflag.FlagSet, kubeConfigPath *string, kubeConfigContext *string) {
flagSet.StringVar(
kubeConfigPath,
"kubeconfig",
os.Getenv("KUBECONFIG"),
"The path to a kubernetes configuration file for the target cluster",
)
flagSet.StringVar(
kubeConfigContext,
"kubeconfig-context",
"",
"The path to a kubernetes configuration file for the target cluster",
)
}