mirror of
https://github.com/siderolabs/talos.git
synced 2026-02-17 22:01:50 +01:00
feat: add k8s-version parameter to k8s-bundle
Allow overriding K8s version in the command. Signed-off-by: Mateusz Urbanek <mateusz.urbanek@siderolabs.com>
This commit is contained in:
parent
b764f5f724
commit
080efcbda2
@ -138,36 +138,56 @@ var imagePullCmd = &cobra.Command{
|
||||
},
|
||||
}
|
||||
|
||||
// imageDefaultCmd represents the image k8s-bundle command.
|
||||
var imageDefaultCmd = &cobra.Command{
|
||||
var imageK8sBundleCmdFlags = struct {
|
||||
k8sVersion pflag.Value
|
||||
flannelVersion pflag.Value
|
||||
corednsVersion pflag.Value
|
||||
etcdVersion pflag.Value
|
||||
}{
|
||||
k8sVersion: helpers.Semver(constants.DefaultKubernetesVersion),
|
||||
flannelVersion: helpers.Semver(constants.FlannelVersion),
|
||||
corednsVersion: helpers.Semver(constants.DefaultCoreDNSVersion),
|
||||
etcdVersion: helpers.Semver(constants.DefaultEtcdVersion),
|
||||
}
|
||||
|
||||
// imageK8sBundleCmd represents the image k8s-bundle command.
|
||||
var imageK8sBundleCmd = &cobra.Command{
|
||||
Use: "k8s-bundle",
|
||||
Aliases: []string{"default"},
|
||||
Short: "List the default Kubernetes images used by Talos",
|
||||
Long: ``,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
images := images.List(container.NewV1Alpha1(&v1alpha1.Config{
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineKubelet: &v1alpha1.KubeletConfig{},
|
||||
images := images.ListWithOptions(container.NewV1Alpha1(
|
||||
&v1alpha1.Config{
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineKubelet: &v1alpha1.KubeletConfig{},
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
EtcdConfig: &v1alpha1.EtcdConfig{},
|
||||
APIServerConfig: &v1alpha1.APIServerConfig{},
|
||||
ControllerManagerConfig: &v1alpha1.ControllerManagerConfig{},
|
||||
SchedulerConfig: &v1alpha1.SchedulerConfig{},
|
||||
CoreDNSConfig: &v1alpha1.CoreDNS{},
|
||||
ProxyConfig: &v1alpha1.ProxyConfig{},
|
||||
},
|
||||
}),
|
||||
images.VersionsListOptions{
|
||||
KubernetesVersion: imageK8sBundleCmdFlags.k8sVersion.String(),
|
||||
EtcdVersion: imageK8sBundleCmdFlags.etcdVersion.String(),
|
||||
FlannelVersion: imageK8sBundleCmdFlags.flannelVersion.String(),
|
||||
CoreDNSVersion: imageK8sBundleCmdFlags.corednsVersion.String(),
|
||||
},
|
||||
ClusterConfig: &v1alpha1.ClusterConfig{
|
||||
EtcdConfig: &v1alpha1.EtcdConfig{},
|
||||
APIServerConfig: &v1alpha1.APIServerConfig{},
|
||||
ControllerManagerConfig: &v1alpha1.ControllerManagerConfig{},
|
||||
SchedulerConfig: &v1alpha1.SchedulerConfig{},
|
||||
CoreDNSConfig: &v1alpha1.CoreDNS{},
|
||||
ProxyConfig: &v1alpha1.ProxyConfig{},
|
||||
},
|
||||
}))
|
||||
)
|
||||
|
||||
fmt.Printf("%s\n", images.Flannel)
|
||||
fmt.Printf("%s\n", images.CoreDNS)
|
||||
fmt.Printf("%s\n", images.Etcd)
|
||||
fmt.Printf("%s\n", images.Pause)
|
||||
fmt.Printf("%s\n", images.KubeAPIServer)
|
||||
fmt.Printf("%s\n", images.KubeControllerManager)
|
||||
fmt.Printf("%s\n", images.KubeScheduler)
|
||||
fmt.Printf("%s\n", images.KubeProxy)
|
||||
fmt.Printf("%s\n", images.Kubelet)
|
||||
fmt.Printf("%s\n", images.Pause)
|
||||
|
||||
return nil
|
||||
},
|
||||
@ -317,15 +337,15 @@ var imageIntegrationCmd = &cobra.Command{
|
||||
}))
|
||||
|
||||
imageNames := []string{
|
||||
imgs.Flannel,
|
||||
imgs.CoreDNS,
|
||||
imgs.Etcd,
|
||||
imgs.KubeAPIServer,
|
||||
imgs.KubeControllerManager,
|
||||
imgs.KubeScheduler,
|
||||
imgs.KubeProxy,
|
||||
imgs.Kubelet,
|
||||
imgs.Pause,
|
||||
imgs.Flannel.String(),
|
||||
imgs.CoreDNS.String(),
|
||||
imgs.Etcd.String(),
|
||||
imgs.KubeAPIServer.String(),
|
||||
imgs.KubeControllerManager.String(),
|
||||
imgs.KubeScheduler.String(),
|
||||
imgs.KubeProxy.String(),
|
||||
imgs.Kubelet.String(),
|
||||
imgs.Pause.String(),
|
||||
"registry.k8s.io/conformance:v" + constants.DefaultKubernetesVersion,
|
||||
"docker.io/library/alpine:latest",
|
||||
"ghcr.io/siderolabs/talosctl:latest",
|
||||
@ -651,7 +671,11 @@ func init() {
|
||||
imageTalosBundleCmd.PersistentFlags().BoolVar(&imageTalosBundleCmdFlags.overlays, "overlays", true, "Include images that belong to Talos overlays")
|
||||
imageTalosBundleCmd.PersistentFlags().BoolVar(&imageTalosBundleCmdFlags.extensions, "extensions", true, "Include images that belong to Talos extensions")
|
||||
|
||||
imageCmd.AddCommand(imageDefaultCmd)
|
||||
imageCmd.AddCommand(imageK8sBundleCmd)
|
||||
imageK8sBundleCmd.PersistentFlags().Var(imageK8sBundleCmdFlags.k8sVersion, "k8s-version", "Kubernetes semantic version")
|
||||
imageK8sBundleCmd.PersistentFlags().Var(imageK8sBundleCmdFlags.etcdVersion, "etcd-version", "ETCD semantic version")
|
||||
imageK8sBundleCmd.PersistentFlags().Var(imageK8sBundleCmdFlags.flannelVersion, "flannel-version", "Flannel CNI semantic version")
|
||||
imageK8sBundleCmd.PersistentFlags().Var(imageK8sBundleCmdFlags.corednsVersion, "coredns-version", "CoreDNS semantic version")
|
||||
|
||||
imageCmd.AddCommand(imageCacheCreateCmd)
|
||||
imageCacheCreateCmd.PersistentFlags().StringVar(&imageCacheCreateCmdFlags.imageCachePath, "image-cache-path", "", "directory to save the image cache in OCI format")
|
||||
|
||||
@ -8,32 +8,32 @@ import (
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"github.com/blang/semver/v4"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
// choiceValue implements the [pflag.Value] interface.
|
||||
type choiceValue struct {
|
||||
value string
|
||||
validate func(string) error
|
||||
}
|
||||
|
||||
// Set sets the value of the choice.
|
||||
func (f *choiceValue) Set(s string) error {
|
||||
err := f.validate(s)
|
||||
// Set implements pflag.Value interface.
|
||||
func (v *choiceValue) Set(s string) error {
|
||||
err := v.validate(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
f.value = s
|
||||
v.value = s
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Type returns the type of the choice, which must be "string" for [pflag.FlagSet.GetString].
|
||||
func (f *choiceValue) Type() string { return "string" }
|
||||
// Type implements pflag.Value interface.
|
||||
func (v *choiceValue) Type() string { return "string" }
|
||||
|
||||
// String returns the current value of the choice.
|
||||
func (f *choiceValue) String() string { return f.value }
|
||||
// String implements pflag.Value interface.
|
||||
func (v *choiceValue) String() string { return v.value }
|
||||
|
||||
// StringChoice returns a [choiceValue] that validates the value against a set
|
||||
// of choices. Only the last value will be used if multiple values are set.
|
||||
@ -51,3 +51,54 @@ func StringChoice(defaultValue string, otherChoices ...string) pflag.Value {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type semverValue struct {
|
||||
value semver.Version
|
||||
validators []SemverValidateFunc
|
||||
}
|
||||
|
||||
// SemverValidateFunc allows setting restrictions on the version.
|
||||
type SemverValidateFunc func(v semver.Version) error
|
||||
|
||||
// Set implements pflag.Value interface.
|
||||
func (v *semverValue) Set(s string) error {
|
||||
vers, err := semver.ParseTolerant(s)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, validator := range v.validators {
|
||||
if err := validator(vers); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
v.value = vers
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Type implements pflag.Value interface.
|
||||
func (v *semverValue) Type() string { return "semver" }
|
||||
|
||||
// String implements pflag.Value interface.
|
||||
func (v *semverValue) String() string { return "v" + v.value.String() }
|
||||
|
||||
// Semver returns a pflag.Value that parses and stores a semantic version.
|
||||
//
|
||||
// Parsing is performed using semver.ParseTolerant. After parsing, any provided
|
||||
// SemverValidateFunc validators are applied in order and may reject the version.
|
||||
//
|
||||
// The returned value is initialized with defaultValue, which is used until Set
|
||||
// is called successfully.
|
||||
func Semver(defaultValue string, validators ...SemverValidateFunc) pflag.Value {
|
||||
v, err := semver.ParseTolerant(defaultValue)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return &semverValue{
|
||||
value: v,
|
||||
validators: validators,
|
||||
}
|
||||
}
|
||||
|
||||
@ -101,6 +101,12 @@ The switch and inventory backfill is automatic and no action is needed from the
|
||||
description = """\
|
||||
The `talosctl images talos-bundle` command now accepts optional `--ovelays` and `--extensions` flags.
|
||||
If those are set to `false`, the command will not attempt to reach out to the container registry to fetch the latest versions and digests of the overlays and extensions.
|
||||
"""
|
||||
|
||||
[notes.images_k8s_bundle]
|
||||
title = "Talosctl images k8s-bundle subcommand accepts version parameter"
|
||||
description = """\
|
||||
The `talosctl images k8s-bundle` command now accepts an optional version overrides arguments.
|
||||
"""
|
||||
|
||||
[make_deps]
|
||||
|
||||
@ -339,7 +339,7 @@ func NewControlPlaneBootstrapManifestsController() *ControlPlaneBootstrapManifes
|
||||
DNSServiceIPv6: dnsServiceIPv6,
|
||||
|
||||
FlannelEnabled: cfgProvider.Cluster().Network().CNI().Name() == constants.FlannelCNI,
|
||||
FlannelImage: images.Flannel,
|
||||
FlannelImage: images.Flannel.String(),
|
||||
FlannelExtraArgs: cfgProvider.Cluster().Network().CNI().Flannel().ExtraArgs(),
|
||||
FlannelKubeServiceHost: flannelKubeServiceHost,
|
||||
FlannelKubeServicePort: flannelKubeServicePort,
|
||||
|
||||
@ -7,26 +7,25 @@ package images
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/config"
|
||||
"github.com/siderolabs/talos/pkg/machinery/constants"
|
||||
)
|
||||
|
||||
// Versions holds all the images (and their versions) that are used in Talos.
|
||||
type Versions struct {
|
||||
Etcd string
|
||||
Flannel string
|
||||
CoreDNS string
|
||||
Etcd name.Tag
|
||||
Flannel name.Tag
|
||||
CoreDNS name.Tag
|
||||
|
||||
Kubelet string
|
||||
KubeAPIServer string
|
||||
KubeControllerManager string
|
||||
KubeProxy string
|
||||
KubeScheduler string
|
||||
Kubelet name.Tag
|
||||
KubeAPIServer name.Tag
|
||||
KubeControllerManager name.Tag
|
||||
KubeProxy name.Tag
|
||||
KubeScheduler name.Tag
|
||||
|
||||
Installer string
|
||||
Talos string
|
||||
|
||||
Pause string
|
||||
Pause name.Tag
|
||||
}
|
||||
|
||||
// DefaultSandboxImage is defined as a constant in cri package of containerd, and it's not exported.
|
||||
@ -38,47 +37,121 @@ const DefaultSandboxImage = "registry.k8s.io/pause:3.10.1"
|
||||
func List(config config.Config) Versions {
|
||||
var images Versions
|
||||
|
||||
images.Etcd = config.Cluster().Etcd().Image()
|
||||
images.CoreDNS = config.Cluster().CoreDNS().Image()
|
||||
images.Flannel = fmt.Sprintf("ghcr.io/siderolabs/flannel:%s", constants.FlannelVersion) // mirrored from docker.io/flannelcni/flannel
|
||||
images.Kubelet = config.Machine().Kubelet().Image()
|
||||
images.KubeAPIServer = config.Cluster().APIServer().Image()
|
||||
images.KubeControllerManager = config.Cluster().ControllerManager().Image()
|
||||
images.KubeProxy = config.Cluster().Proxy().Image()
|
||||
images.KubeScheduler = config.Cluster().Scheduler().Image()
|
||||
images.Etcd = mustParseTag(config.Cluster().Etcd().Image())
|
||||
images.CoreDNS = mustParseTag(config.Cluster().CoreDNS().Image())
|
||||
images.Flannel = mustParseTag(fmt.Sprintf("ghcr.io/siderolabs/flannel:%s", constants.FlannelVersion)) // mirrored from docker.io/flannelcni/flannel
|
||||
images.Kubelet = mustParseTag(config.Machine().Kubelet().Image())
|
||||
images.KubeAPIServer = mustParseTag(config.Cluster().APIServer().Image())
|
||||
images.KubeControllerManager = mustParseTag(config.Cluster().ControllerManager().Image())
|
||||
images.KubeProxy = mustParseTag(config.Cluster().Proxy().Image())
|
||||
images.KubeScheduler = mustParseTag(config.Cluster().Scheduler().Image())
|
||||
|
||||
images.Installer = DefaultInstallerImage
|
||||
images.Talos = DefaultTalosImage
|
||||
|
||||
images.Pause = DefaultSandboxImage
|
||||
images.Pause = mustParseTag(DefaultSandboxImage)
|
||||
|
||||
return images
|
||||
}
|
||||
|
||||
// SourceBundle holds the core images (and their versions) that are used to build Talos.
|
||||
type SourceBundle struct {
|
||||
Installer string
|
||||
InstallerBase string
|
||||
Imager string
|
||||
Talos string
|
||||
TalosctlAll string
|
||||
// VersionsListOptions allows overriding the default component versions
|
||||
// displayed to the user.
|
||||
//
|
||||
// Any non-empty field value replaces the corresponding default version
|
||||
// when presenting available or selected versions. Fields left empty
|
||||
// will fall back to their built-in defaults.
|
||||
type VersionsListOptions struct {
|
||||
// KubernetesVersion overrides the default Kubernetes version.
|
||||
KubernetesVersion string
|
||||
|
||||
Overlays string
|
||||
Extensions string
|
||||
// CoreDNSVersion overrides the default CoreDNS version.
|
||||
CoreDNSVersion string
|
||||
|
||||
// EtcdVersion overrides the default etcd version.
|
||||
EtcdVersion string
|
||||
|
||||
// FlannelVersion overrides the default Flannel version.
|
||||
FlannelVersion string
|
||||
|
||||
// PauseVersion overrides the default pause container image version.
|
||||
PauseVersion string
|
||||
}
|
||||
|
||||
// ListWithOptions returns image versions with overrides.
|
||||
func ListWithOptions(config config.Config, opts VersionsListOptions) Versions {
|
||||
images := List(config)
|
||||
|
||||
if opts.CoreDNSVersion != "" {
|
||||
images.CoreDNS = images.CoreDNS.Tag(opts.CoreDNSVersion)
|
||||
}
|
||||
|
||||
if opts.EtcdVersion != "" {
|
||||
images.Etcd = images.Etcd.Tag(opts.EtcdVersion)
|
||||
}
|
||||
|
||||
if opts.FlannelVersion != "" {
|
||||
images.Flannel = images.Flannel.Tag(opts.FlannelVersion)
|
||||
}
|
||||
|
||||
if opts.PauseVersion != "" {
|
||||
images.Pause = images.Pause.Tag(opts.PauseVersion)
|
||||
}
|
||||
|
||||
if opts.KubernetesVersion != "" {
|
||||
images.Kubelet = images.Kubelet.Tag(opts.KubernetesVersion)
|
||||
images.KubeAPIServer = images.KubeAPIServer.Tag(opts.KubernetesVersion)
|
||||
images.KubeControllerManager = images.KubeControllerManager.Tag(opts.KubernetesVersion)
|
||||
images.KubeProxy = images.KubeProxy.Tag(opts.KubernetesVersion)
|
||||
images.KubeScheduler = images.KubeScheduler.Tag(opts.KubernetesVersion)
|
||||
}
|
||||
|
||||
return images
|
||||
}
|
||||
|
||||
func mustParseTag(s string) name.Tag {
|
||||
r, err := name.ParseReference(s)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
t, ok := r.(name.Tag)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("%T is not name.Tag: %#+v", r, r))
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
func mustParseReferenceWithTag(ref, tag string) name.Tag {
|
||||
r, err := name.ParseReference(ref)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
return r.Context().Tag(tag)
|
||||
}
|
||||
|
||||
// TalosBundle holds the core images (and their versions) that are used to build Talos.
|
||||
type TalosBundle struct {
|
||||
Installer name.Tag
|
||||
InstallerBase name.Tag
|
||||
Imager name.Tag
|
||||
Talos name.Tag
|
||||
TalosctlAll name.Tag
|
||||
|
||||
Overlays name.Tag
|
||||
Extensions name.Tag
|
||||
}
|
||||
|
||||
// ListSourcesFor returns source bundle for specific version.
|
||||
func ListSourcesFor(tag string) SourceBundle {
|
||||
var bundle SourceBundle
|
||||
func ListSourcesFor(tag string) TalosBundle {
|
||||
var bundle TalosBundle
|
||||
|
||||
bundle.Installer = DefaultInstallerImageRepository + ":" + tag
|
||||
bundle.InstallerBase = DefaultInstallerBaseImageRepository + ":" + tag
|
||||
bundle.Imager = DefaultImagerImageRepository + ":" + tag
|
||||
bundle.Talos = DefaultTalosImageRepository + ":" + tag
|
||||
bundle.TalosctlAll = DefaultTalosctlAllImageRepository + ":" + tag
|
||||
bundle.Installer = mustParseReferenceWithTag(DefaultInstallerImageRepository, tag)
|
||||
bundle.InstallerBase = mustParseReferenceWithTag(DefaultInstallerBaseImageRepository, tag)
|
||||
bundle.Imager = mustParseReferenceWithTag(DefaultImagerImageRepository, tag)
|
||||
bundle.Talos = mustParseReferenceWithTag(DefaultTalosImageRepository, tag)
|
||||
bundle.TalosctlAll = mustParseReferenceWithTag(DefaultTalosctlAllImageRepository, tag)
|
||||
|
||||
bundle.Overlays = DefaultOverlaysManifestRepository + ":" + tag
|
||||
bundle.Extensions = DefaultExtensionsManifestRepository + ":" + tag
|
||||
bundle.Overlays = mustParseReferenceWithTag(DefaultOverlaysManifestRepository, tag)
|
||||
bundle.Extensions = mustParseReferenceWithTag(DefaultExtensionsManifestRepository, tag)
|
||||
|
||||
return bundle
|
||||
}
|
||||
|
||||
@ -2215,7 +2215,11 @@ talosctl image k8s-bundle [flags]
|
||||
### Options
|
||||
|
||||
```
|
||||
-h, --help help for k8s-bundle
|
||||
--coredns-version semver CoreDNS semantic version (default v1.13.2)
|
||||
--etcd-version semver ETCD semantic version (default v3.6.7)
|
||||
--flannel-version semver Flannel CNI semantic version (default v0.27.4)
|
||||
-h, --help help for k8s-bundle
|
||||
--k8s-version semver Kubernetes semantic version (default v1.35.0)
|
||||
```
|
||||
|
||||
### Options inherited from parent commands
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user