@@ -3,6 +3,7 @@ package kubernetes
33import (
44 _ "embed"
55 "fmt"
6+ "log"
67 "regexp"
78 "strings"
89
@@ -30,6 +31,20 @@ func NewKindCluster(env config.Env, vm *remote.Host, name string, kubeVersion st
3031 return NewKindClusterWithConfig (env , vm , name , kubeVersion , kindClusterConfig , opts ... )
3132}
3233
34+ func validateKubeVersionFormat (kubeVersion string ) error {
35+ // Pattern: v{semver}@sha256:{hash}
36+ // Example: v1.32.0@sha256:c48c62eac5da28cdadcf560d1d8616cfa6783b58f0d94cf63ad1bf49600cb027
37+ pattern := `^v\d+\.\d+\.\d+@sha256:[a-f0-9]{64}$`
38+ matched , err := regexp .MatchString (pattern , kubeVersion )
39+ if err != nil {
40+ return fmt .Errorf ("error validating kubeVersion format: %w" , err )
41+ }
42+ if ! matched {
43+ return fmt .Errorf ("kubeVersion must be in format 'v{semver}@sha256:{hash}' (e.g., v1.32.0@sha256:c48c62eac5da28cdadcf560d1d8616cfa6783b58f0d94cf63ad1bf49600cb027), got: %s" , kubeVersion )
44+ }
45+ return nil
46+ }
47+
3348func NewKindClusterWithConfig (env config.Env , vm * remote.Host , name string , kubeVersion , kindConfig string , opts ... pulumi.ResourceOption ) (* Cluster , error ) {
3449 return components .NewComponent (env , name , func (clusterComp * Cluster ) error {
3550 kindClusterName := env .CommonNamer ().DisplayName (49 ) // We can have some issues if the name is longer than 50 characters
@@ -48,9 +63,25 @@ func NewKindClusterWithConfig(env config.Env, vm *remote.Host, name string, kube
4863 }
4964 opts = utils .MergeOptions (opts , utils .PulumiDependsOn (dockerManager , curlCommand ))
5065
66+ /*
67+ We'll first try to resolve the kind version and node image from our static map, if we can't find
68+ it (ex. 1.34 not in our map yet), we'll continue because we have the ability to pull down arbitrary
69+ versions from the mirror - although it should be noted the sha is required. So sometimes the version is
70+ just the tag, and sometimes it's the tag with the sha.
71+ */
5172 kindVersionConfig , err := GetKindVersionConfig (kubeVersion )
5273 if err != nil {
53- return err
74+ log .Printf ("[WARN] Could not find version %s in our static map, using default kind version and the provided k8s version as node image" , kubeVersion )
75+
76+ // Validate the kubeVersion format when not in static map
77+ if err := validateKubeVersionFormat (kubeVersion ); err != nil {
78+ return err
79+ }
80+
81+ kindVersionConfig = & KindConfig {
82+ KindVersion : env .KindVersion (),
83+ NodeImageVersion : kubeVersion ,
84+ }
5485 }
5586
5687 kindInstall , err := InstallKindBinary (env , vm , kindVersionConfig .KindVersion , opts ... )
@@ -66,7 +97,18 @@ func NewKindClusterWithConfig(env config.Env, vm *remote.Host, name string, kube
6697 return err
6798 }
6899
69- nodeImage := fmt .Sprintf ("%s/%s:%s" , env .InternalDockerhubMirror (), kindNodeImageName , kindVersionConfig .NodeImageVersion )
100+ /*
101+ The internal mirror should be able to pull arbitrary kubernetes images but the sha is required
102+ with the tag. We also support the user supplying the url (in case we want to host
103+ kubernetes rc candidates in some registry, etc)
104+ */
105+ var nodeImage string
106+ if env .KubeNodeURL () != "" {
107+ nodeImage = env .KubeNodeURL ()
108+ } else {
109+ nodeImage = fmt .Sprintf ("%s/%s:%s" , env .InternalDockerhubMirror (), kindNodeImageName , kindVersionConfig .NodeImageVersion )
110+ }
111+ log .Printf ("[INFO] Resolved node image url: %s" , nodeImage )
70112 createCluster , err := runner .Command (
71113 commonEnvironment .CommonNamer ().ResourceName ("kind-create-cluster" ),
72114 & command.Args {
0 commit comments