refactor: create abstraction over cluster/instancegroup for building assets

This abstraction should let us change the version on an instance group level.
This commit is contained in:
justinsb 2024-11-25 08:10:39 -05:00
parent 59e06d8a96
commit 3f38846ca5
17 changed files with 254 additions and 76 deletions

View File

@ -177,7 +177,7 @@ func (b *ContainerdBuilder) installContainerd(c *fi.NodeupModelBuilderContext) e
return nil
}
func (b *ContainerdBuilder) buildSystemdService(sv semver.Version) *nodetasks.Service {
func (b *ContainerdBuilder) buildSystemdService(containerdVersion semver.Version) *nodetasks.Service {
// Based on https://github.com/containerd/containerd/blob/master/containerd.service
manifest := &systemd.Manifest{}

View File

@ -27,12 +27,10 @@ import (
awsconfig "github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
"github.com/blang/semver/v4"
hcloudmetadata "github.com/hetznercloud/hcloud-go/hcloud/metadata"
"k8s.io/klog/v2"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/model"
"k8s.io/kops/pkg/apis/kops/util"
kopsmodel "k8s.io/kops/pkg/apis/kops/model"
"k8s.io/kops/pkg/apis/nodeup"
"k8s.io/kops/pkg/systemd"
"k8s.io/kops/upup/pkg/fi"
@ -74,7 +72,7 @@ type NodeupModelContext struct {
// usesNoneDNS is true if the cluster runs with dns=none (which uses fixed IPs, for example a load balancer, instead of DNS)
usesNoneDNS bool
kubernetesVersion semver.Version
kubernetesVersion *kopsmodel.KubernetesVersion
bootstrapCerts map[string]*nodetasks.BootstrapCert
bootstrapKeypairIDs map[string]string
@ -86,11 +84,11 @@ type NodeupModelContext struct {
// Init completes initialization of the object, for example pre-parsing the kubernetes version
func (c *NodeupModelContext) Init() error {
k8sVersion, err := util.ParseKubernetesVersion(c.NodeupConfig.KubernetesVersion)
if err != nil || k8sVersion == nil {
return fmt.Errorf("unable to parse KubernetesVersion %q", c.NodeupConfig.KubernetesVersion)
k8sVersion, err := kopsmodel.ParseKubernetesVersion(c.NodeupConfig.KubernetesVersion)
if err != nil {
return fmt.Errorf("unable to parse KubernetesVersion %q: %w", c.NodeupConfig.KubernetesVersion, err)
}
c.kubernetesVersion = *k8sVersion
c.kubernetesVersion = k8sVersion
c.bootstrapCerts = map[string]*nodetasks.BootstrapCert{}
c.bootstrapKeypairIDs = map[string]string{}
@ -303,20 +301,20 @@ func (c *NodeupModelContext) RemapImage(image string) string {
return image
}
// IsKubernetesGTE checks if the version is greater-than-or-equal
// IsKubernetesGTE checks if the kubernetes version is greater-than-or-equal-to version
func (c *NodeupModelContext) IsKubernetesGTE(version string) bool {
if c.kubernetesVersion.Major == 0 {
if c.kubernetesVersion == nil {
klog.Fatalf("kubernetesVersion not set (%s); Init not called", c.kubernetesVersion)
}
return util.IsKubernetesGTE(version, c.kubernetesVersion)
return c.kubernetesVersion.IsGTE(version)
}
// IsKubernetesLT checks if the version is less-than
// IsKubernetesLT checks if the kubernetes version is less-than version
func (c *NodeupModelContext) IsKubernetesLT(version string) bool {
if c.kubernetesVersion.Major == 0 {
if c.kubernetesVersion == nil {
klog.Fatalf("kubernetesVersion not set (%s); Init not called", c.kubernetesVersion)
}
return !c.IsKubernetesGTE(version)
return c.kubernetesVersion.IsLT(version)
}
// UseVolumeMounts is used to check if we have volume mounts enabled as we need to
@ -327,11 +325,11 @@ func (c *NodeupModelContext) UseVolumeMounts() bool {
// UseChallengeCallback is true if we should use a callback challenge during node provisioning with kops-controller.
func (c *NodeupModelContext) UseChallengeCallback(cloudProvider kops.CloudProviderID) bool {
return model.UseChallengeCallback(cloudProvider)
return kopsmodel.UseChallengeCallback(cloudProvider)
}
func (c *NodeupModelContext) UseExternalKubeletCredentialProvider() bool {
return model.UseExternalKubeletCredentialProvider(c.kubernetesVersion, c.CloudProvider())
return kopsmodel.UseExternalKubeletCredentialProvider(c.kubernetesVersion, c.CloudProvider())
}
// UsesSecondaryIP checks if the CNI in use attaches secondary interfaces to the host.

View File

@ -21,13 +21,13 @@ import (
"testing"
"k8s.io/kops/pkg/apis/kops"
kopsmodel "k8s.io/kops/pkg/apis/kops/model"
"k8s.io/kops/pkg/apis/nodeup"
"k8s.io/kops/pkg/flagbuilder"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/util/pkg/architectures"
"k8s.io/kops/util/pkg/exec"
"github.com/blang/semver/v4"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -70,7 +70,7 @@ func TestKubeProxyBuilder_buildPod(t *testing.T) {
fields{
&NodeupModelContext{
NodeupConfig: nodeupConfig,
kubernetesVersion: semver.Version{Major: 1, Minor: 20},
kubernetesVersion: kopsmodel.MustParseKubernetesVersion("1.20"),
},
},
&v1.Pod{

View File

@ -17,9 +17,7 @@ limitations under the License.
package model
import (
"github.com/blang/semver/v4"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/util"
)
// UseChallengeCallback is true if we should use a callback challenge during node provisioning with kops-controller.
@ -70,12 +68,12 @@ func UseCiliumEtcd(cluster *kops.Cluster) bool {
}
// Configures a Kubelet Credential Provider if Kubernetes is newer than a specific version
func UseExternalKubeletCredentialProvider(k8sVersion semver.Version, cloudProvider kops.CloudProviderID) bool {
func UseExternalKubeletCredentialProvider(k8sVersion *KubernetesVersion, cloudProvider kops.CloudProviderID) bool {
switch cloudProvider {
case kops.CloudProviderGCE:
return util.IsKubernetesGTE("1.29", k8sVersion)
return k8sVersion.IsGTE("1.29")
case kops.CloudProviderAWS:
return util.IsKubernetesGTE("1.27", k8sVersion)
return k8sVersion.IsGTE("1.27")
default:
return false
}

View File

@ -0,0 +1,69 @@
/*
Copyright 2024 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package model
import (
"fmt"
"k8s.io/kops/pkg/apis/kops"
)
// InstanceGroup is a subset of the full Cluster and InstanceGroup functionality,
// that gives us some abstraction over the raw types.
type InstanceGroup interface {
// KubernetesVersion returns the Kubernetes version for the instance group
KubernetesVersion() *KubernetesVersion
// GetCloudProvider returns the cloud provider for the instance group
GetCloudProvider() kops.CloudProviderID
// RawClusterSpec returns the cluster spec for the instance group.
// If possible, prefer abstracted methods over accessing this data directly.
RawClusterSpec() *kops.ClusterSpec
}
// ForInstanceGroup creates an InstanceGroup model for the given cluster and instance group.
func ForInstanceGroup(cluster *kops.Cluster, ig *kops.InstanceGroup) (InstanceGroup, error) {
kubernetesVersionString := cluster.Spec.KubernetesVersion
kubernetesVersion, err := ParseKubernetesVersion(kubernetesVersionString)
if err != nil {
return nil, fmt.Errorf("error parsing Kubernetes version %q: %v", kubernetesVersionString, err)
}
return &instanceGroupModel{cluster: cluster, ig: ig, kubernetesVersion: kubernetesVersion}, nil
}
// instanceGroupModel is a concrete implementation of InstanceGroup.
type instanceGroupModel struct {
cluster *kops.Cluster
ig *kops.InstanceGroup
kubernetesVersion *KubernetesVersion
}
var _ InstanceGroup = &instanceGroupModel{}
func (m *instanceGroupModel) KubernetesVersion() *KubernetesVersion {
return m.kubernetesVersion
}
func (m *instanceGroupModel) GetCloudProvider() kops.CloudProviderID {
return m.cluster.GetCloudProvider()
}
func (m *instanceGroupModel) RawClusterSpec() *kops.ClusterSpec {
return &m.cluster.Spec
}

View File

@ -0,0 +1,89 @@
/*
Copyright 2024 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package model
import (
"fmt"
"strings"
"github.com/blang/semver/v4"
"k8s.io/kops/pkg/apis/kops/util"
)
// KubernetesVersion is a wrapper over semver functionality,
// that offers some functionality particularly useful for kubernetes version semantics.
type KubernetesVersion struct {
versionString string
version semver.Version
}
// ParseKubernetesVersion parses a Kubernetes version string and returns a KubernetesVersion object.
func ParseKubernetesVersion(versionString string) (*KubernetesVersion, error) {
parsedVersion, err := util.ParseKubernetesVersion(versionString)
if err != nil {
return nil, fmt.Errorf("error parsing version %q: %v", versionString, err)
}
return &KubernetesVersion{versionString: versionString, version: *parsedVersion}, nil
}
// MustParseKubernetesVersion parses a Kubernetes version string and panics if it fails.
func MustParseKubernetesVersion(versionString string) *KubernetesVersion {
kubernetesVersion, err := ParseKubernetesVersion(versionString)
if err != nil || kubernetesVersion == nil {
panic(err)
}
return kubernetesVersion
}
func (v *KubernetesVersion) String() string {
return v.versionString
}
// IsBaseURL checks if the version string is a URL, rather than a version identifier.
// URLs are typically used for CI builds and during development.
func IsBaseURL(kubernetesVersion string) bool {
return strings.HasPrefix(kubernetesVersion, "http:") || strings.HasPrefix(kubernetesVersion, "https:") || strings.HasPrefix(kubernetesVersion, "memfs:")
}
// IsBaseURL checks if the version string is a URL, rather than a version identifier.
// URLs are typically used for CI builds and during development.
func (v *KubernetesVersion) IsBaseURL() bool {
return IsBaseURL(v.versionString)
}
// IsGTE checks if the version is greater than or equal (>=) to the specified version.
// It panics if the kubernetes version in the cluster is invalid, or if the version is invalid.
func (v *KubernetesVersion) IsGTE(version string) bool {
parsedVersion, err := util.ParseKubernetesVersion(version)
if err != nil || parsedVersion == nil {
panic(fmt.Sprintf("error parsing version %q: %v", version, err))
}
// Ignore Pre & Build fields
clusterVersion := v.version
clusterVersion.Pre = nil
clusterVersion.Build = nil
return clusterVersion.GTE(*parsedVersion)
}
// IsLT checks if the version is strictly less (<) than the specified version.
// It panics if the kubernetes version in the cluster is invalid, or if the version is invalid.
func (v *KubernetesVersion) IsLT(version string) bool {
return !v.IsGTE(version)
}

View File

@ -46,8 +46,7 @@ func ParseKubernetesVersion(version string) (*semver.Version, error) {
return &sv, nil
}
// TODO: Convert to our own KubernetesVersion type?
// Deprecated: prefer using KubernetesVersion.IsGTE()
func IsKubernetesGTE(version string, k8sVersion semver.Version) bool {
parsedVersion, err := ParseKubernetesVersion(version)
if err != nil {

View File

@ -24,6 +24,7 @@ import (
"strings"
"k8s.io/kops/pkg/apis/kops"
kopsmodel "k8s.io/kops/pkg/apis/kops/model"
"k8s.io/kops/pkg/apis/kops/util"
"k8s.io/kops/pkg/assets"
"k8s.io/kops/pkg/k8sversion"
@ -89,10 +90,6 @@ func WellKnownServiceIP(networkingSpec *kops.NetworkingSpec, id int) (net.IP, er
return nil, fmt.Errorf("unexpected IP address type for ServiceClusterIPRange: %s", networkingSpec.ServiceClusterIPRange)
}
func IsBaseURL(kubernetesVersion string) bool {
return strings.HasPrefix(kubernetesVersion, "http:") || strings.HasPrefix(kubernetesVersion, "https:") || strings.HasPrefix(kubernetesVersion, "memfs:")
}
// Image returns the docker image name for the specified component
func Image(component string, clusterSpec *kops.ClusterSpec, assetsBuilder *assets.AssetBuilder) (string, error) {
if assetsBuilder == nil {
@ -106,7 +103,7 @@ func Image(component string, clusterSpec *kops.ClusterSpec, assetsBuilder *asset
imageName := component
if !IsBaseURL(clusterSpec.KubernetesVersion) {
if !kopsmodel.IsBaseURL(clusterSpec.KubernetesVersion) {
image := "registry.k8s.io/" + imageName + ":" + "v" + kubernetesVersion.String()
image, err := assetsBuilder.RemapImage(image)

View File

@ -24,9 +24,7 @@ import (
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/model"
"k8s.io/kops/pkg/apis/kops/util"
"k8s.io/kops/pkg/assets"
"k8s.io/kops/pkg/model/components"
"k8s.io/kops/pkg/nodemodel/wellknownassets"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/util/pkg/architectures"
@ -40,12 +38,14 @@ type KubernetesFileAssets struct {
}
// BuildKubernetesFileAssets returns the Kubernetes file assets for the given cluster
func BuildKubernetesFileAssets(cluster *kops.Cluster, assetBuilder *assets.AssetBuilder) (*KubernetesFileAssets, error) {
func BuildKubernetesFileAssets(ig model.InstanceGroup, assetBuilder *assets.AssetBuilder) (*KubernetesFileAssets, error) {
kubernetesVersion := ig.KubernetesVersion()
var baseURL string
if components.IsBaseURL(cluster.Spec.KubernetesVersion) {
baseURL = cluster.Spec.KubernetesVersion
if kubernetesVersion.IsBaseURL() {
baseURL = kubernetesVersion.String()
} else {
baseURL = "https://dl.k8s.io/release/v" + cluster.Spec.KubernetesVersion
baseURL = "https://dl.k8s.io/release/v" + kubernetesVersion.String()
}
kubernetesAssets := make(map[architectures.Architecture][]*assets.MirroredAsset)
@ -57,7 +57,7 @@ func BuildKubernetesFileAssets(cluster *kops.Cluster, assetBuilder *assets.Asset
fmt.Sprintf("/bin/linux/%s/kubectl", arch),
}
if needsMounterAsset(cluster) {
if needsMounterAsset(ig) {
k8sAssetsNames = append(k8sAssetsNames, fmt.Sprintf("/bin/linux/%s/mounter", arch))
}
@ -75,13 +75,11 @@ func BuildKubernetesFileAssets(cluster *kops.Cluster, assetBuilder *assets.Asset
kubernetesAssets[arch] = append(kubernetesAssets[arch], assets.BuildMirroredAsset(asset))
}
kubernetesVersion, _ := util.ParseKubernetesVersion(cluster.Spec.KubernetesVersion)
cloudProvider := cluster.GetCloudProvider()
if ok := model.UseExternalKubeletCredentialProvider(*kubernetesVersion, cloudProvider); ok {
cloudProvider := ig.GetCloudProvider()
if ok := model.UseExternalKubeletCredentialProvider(kubernetesVersion, cloudProvider); ok {
switch cloudProvider {
case kops.CloudProviderGCE:
binaryLocation := cluster.Spec.CloudProvider.GCE.BinariesLocation
binaryLocation := ig.RawClusterSpec().CloudProvider.GCE.BinariesLocation
if binaryLocation == nil {
binaryLocation = fi.PtrTo("https://storage.googleapis.com/k8s-staging-cloud-provider-gcp/auth-provider-gcp")
}
@ -107,7 +105,7 @@ func BuildKubernetesFileAssets(cluster *kops.Cluster, assetBuilder *assets.Asset
kubernetesAssets[arch] = append(kubernetesAssets[arch], assets.BuildMirroredAsset(asset))
case kops.CloudProviderAWS:
binaryLocation := cluster.Spec.CloudProvider.AWS.BinariesLocation
binaryLocation := ig.RawClusterSpec().CloudProvider.AWS.BinariesLocation
if binaryLocation == nil {
binaryLocation = fi.PtrTo("https://artifacts.k8s.io/binaries/cloud-provider-aws/v1.27.1")
}
@ -125,15 +123,15 @@ func BuildKubernetesFileAssets(cluster *kops.Cluster, assetBuilder *assets.Asset
}
{
cniAsset, err := wellknownassets.FindCNIAssets(cluster, assetBuilder, arch)
cniAsset, err := wellknownassets.FindCNIAssets(ig, assetBuilder, arch)
if err != nil {
return nil, err
}
kubernetesAssets[arch] = append(kubernetesAssets[arch], assets.BuildMirroredAsset(cniAsset))
}
if cluster.Spec.Containerd == nil || !cluster.Spec.Containerd.SkipInstall {
containerdAsset, err := wellknownassets.FindContainerdAsset(cluster, assetBuilder, arch)
if ig.RawClusterSpec().Containerd == nil || !ig.RawClusterSpec().Containerd.SkipInstall {
containerdAsset, err := wellknownassets.FindContainerdAsset(ig, assetBuilder, arch)
if err != nil {
return nil, err
}
@ -141,14 +139,14 @@ func BuildKubernetesFileAssets(cluster *kops.Cluster, assetBuilder *assets.Asset
kubernetesAssets[arch] = append(kubernetesAssets[arch], assets.BuildMirroredAsset(containerdAsset))
}
runcAsset, err := wellknownassets.FindRuncAsset(cluster, assetBuilder, arch)
runcAsset, err := wellknownassets.FindRuncAsset(ig, assetBuilder, arch)
if err != nil {
return nil, err
}
if runcAsset != nil {
kubernetesAssets[arch] = append(kubernetesAssets[arch], assets.BuildMirroredAsset(runcAsset))
}
nerdctlAsset, err := wellknownassets.FindNerdctlAsset(cluster, assetBuilder, arch)
nerdctlAsset, err := wellknownassets.FindNerdctlAsset(ig, assetBuilder, arch)
if err != nil {
return nil, err
}
@ -157,7 +155,7 @@ func BuildKubernetesFileAssets(cluster *kops.Cluster, assetBuilder *assets.Asset
}
}
crictlAsset, err := wellknownassets.FindCrictlAsset(cluster, assetBuilder, arch)
crictlAsset, err := wellknownassets.FindCrictlAsset(ig, assetBuilder, arch)
if err != nil {
return nil, err
}
@ -194,9 +192,9 @@ func BuildNodeUpAssets(ctx context.Context, assetBuilder *assets.AssetBuilder) (
// needsMounterAsset checks if we need the mounter program
// This is only needed currently on ContainerOS i.e. GCE, but we don't have a nice way to detect it yet
func needsMounterAsset(c *kops.Cluster) bool {
func needsMounterAsset(ig model.InstanceGroup) bool {
// TODO: Do real detection of ContainerOS (but this has to work with image names, and maybe even forked images)
switch c.GetCloudProvider() {
switch ig.GetCloudProvider() {
case kops.CloudProviderGCE:
return true
default:

View File

@ -28,11 +28,10 @@ import (
"strings"
"k8s.io/kops/pkg/apis/kops"
apiModel "k8s.io/kops/pkg/apis/kops/model"
kopsmodel "k8s.io/kops/pkg/apis/kops/model"
"k8s.io/kops/pkg/apis/nodeup"
"k8s.io/kops/pkg/assets"
"k8s.io/kops/pkg/model"
"k8s.io/kops/pkg/model/components"
"k8s.io/kops/pkg/nodemodel/wellknownassets"
"k8s.io/kops/pkg/wellknownports"
"k8s.io/kops/pkg/wellknownservices"
@ -93,7 +92,7 @@ func NewNodeUpConfigBuilder(cluster *kops.Cluster, assetBuilder *assets.AssetBui
isAPIServer := role == kops.InstanceGroupRoleAPIServer
images[role] = make(map[architectures.Architecture][]*nodeup.Image)
if components.IsBaseURL(cluster.Spec.KubernetesVersion) {
if kopsmodel.IsBaseURL(cluster.Spec.KubernetesVersion) {
// When using a custom version, we want to preload the images over http
components := []string{"kube-proxy"}
if isMaster {
@ -220,7 +219,12 @@ func (n *nodeUpConfigBuilder) BuildConfig(ig *kops.InstanceGroup, wellKnownAddre
config, bootConfig := nodeup.NewConfig(cluster, ig)
kubernetesAssets, err := BuildKubernetesFileAssets(cluster, n.assetBuilder)
igModel, err := kopsmodel.ForInstanceGroup(cluster, ig)
if err != nil {
return nil, nil, fmt.Errorf("building instance group model: %w", err)
}
kubernetesAssets, err := BuildKubernetesFileAssets(igModel, n.assetBuilder)
if err != nil {
return nil, nil, err
}
@ -371,7 +375,7 @@ func (n *nodeUpConfigBuilder) BuildConfig(ig *kops.InstanceGroup, wellKnownAddre
}
}
useConfigServer := apiModel.UseKopsControllerForNodeConfig(cluster) && !ig.HasAPIServer()
useConfigServer := kopsmodel.UseKopsControllerForNodeConfig(cluster) && !ig.HasAPIServer()
if useConfigServer {
hosts := []string{"kops-controller.internal." + cluster.ObjectMeta.Name}
if len(bootConfig.APIServerIPs) > 0 {

View File

@ -22,7 +22,7 @@ import (
"os"
"k8s.io/klog/v2"
kopsapi "k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/model"
"k8s.io/kops/pkg/assets"
"k8s.io/kops/util/pkg/architectures"
"k8s.io/kops/util/pkg/hashing"
@ -47,7 +47,7 @@ const (
ENV_VAR_CNI_ASSET_HASH = "CNI_ASSET_HASH_STRING"
)
func FindCNIAssets(c *kopsapi.Cluster, assetBuilder *assets.AssetBuilder, arch architectures.Architecture) (*assets.FileAsset, error) {
func FindCNIAssets(ig model.InstanceGroup, assetBuilder *assets.AssetBuilder, arch architectures.Architecture) (*assets.FileAsset, error) {
// Override CNI packages from env vars
cniAssetURL := os.Getenv(ENV_VAR_CNI_ASSET_URL)
cniAssetHash := os.Getenv(ENV_VAR_CNI_ASSET_HASH)
@ -76,14 +76,14 @@ func FindCNIAssets(c *kopsapi.Cluster, assetBuilder *assets.AssetBuilder, arch a
switch arch {
case architectures.ArchitectureAmd64:
if c.IsKubernetesLT("1.27") {
if ig.KubernetesVersion().IsLT("1.27") {
cniAssetURL = defaultCNIAssetAmd64K8s_22
} else {
cniAssetURL = defaultCNIAssetAmd64K8s_27
}
klog.V(2).Infof("Adding default ARM64 CNI plugin binaries asset: %s", cniAssetURL)
case architectures.ArchitectureArm64:
if c.IsKubernetesLT("1.27") {
if ig.KubernetesVersion().IsLT("1.27") {
cniAssetURL = defaultCNIAssetArm64K8s_22
} else {
cniAssetURL = defaultCNIAssetArm64K8s_27

View File

@ -20,6 +20,7 @@ import (
"testing"
api "k8s.io/kops/pkg/apis/kops"
kopsmodel "k8s.io/kops/pkg/apis/kops/model"
"k8s.io/kops/pkg/assets"
"k8s.io/kops/util/pkg/architectures"
"k8s.io/kops/util/pkg/vfs"
@ -35,8 +36,16 @@ func Test_FindCNIAssetFromEnvironmentVariable(t *testing.T) {
cluster := &api.Cluster{}
cluster.Spec.KubernetesVersion = "v1.18.0"
ig := &api.InstanceGroup{}
assetBuilder := assets.NewAssetBuilder(vfs.Context, cluster.Spec.Assets, cluster.Spec.KubernetesVersion, false)
asset, err := FindCNIAssets(cluster, assetBuilder, architectures.ArchitectureAmd64)
igModel, err := kopsmodel.ForInstanceGroup(cluster, ig)
if err != nil {
t.Fatalf("building instance group model: %v", err)
}
asset, err := FindCNIAssets(igModel, assetBuilder, architectures.ArchitectureAmd64)
if err != nil {
t.Fatalf("Unable to parse CNI version: %v", err)
}
@ -57,8 +66,16 @@ func Test_FindCNIAssetFromDefaults122(t *testing.T) {
cluster := &api.Cluster{}
cluster.Spec.KubernetesVersion = "v1.22.0"
ig := &api.InstanceGroup{}
igModel, err := kopsmodel.ForInstanceGroup(cluster, ig)
if err != nil {
t.Fatalf("building instance group model: %v", err)
}
assetBuilder := assets.NewAssetBuilder(vfs.Context, cluster.Spec.Assets, cluster.Spec.KubernetesVersion, false)
asset, err := FindCNIAssets(cluster, assetBuilder, architectures.ArchitectureAmd64)
asset, err := FindCNIAssets(igModel, assetBuilder, architectures.ArchitectureAmd64)
if err != nil {
t.Fatalf("Unable to parse CNI version: %s", err)
}

View File

@ -22,7 +22,7 @@ import (
"github.com/blang/semver/v4"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/model"
"k8s.io/kops/pkg/assets"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/util/pkg/architectures"
@ -37,11 +37,11 @@ const (
containerdBundleUrlAmd64 = "https://github.com/containerd/containerd/releases/download/v%s/cri-containerd-cni-%s-linux-amd64.tar.gz"
)
func FindContainerdAsset(c *kops.Cluster, assetBuilder *assets.AssetBuilder, arch architectures.Architecture) (*assets.FileAsset, error) {
if c.Spec.Containerd == nil {
func FindContainerdAsset(ig model.InstanceGroup, assetBuilder *assets.AssetBuilder, arch architectures.Architecture) (*assets.FileAsset, error) {
containerd := ig.RawClusterSpec().Containerd
if containerd == nil {
return nil, fmt.Errorf("unable to find containerd config")
}
containerd := c.Spec.Containerd
canonicalURL := ""
knownHash := ""

View File

@ -20,7 +20,7 @@ import (
"fmt"
"net/url"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/model"
"k8s.io/kops/pkg/assets"
"k8s.io/kops/util/pkg/architectures"
)
@ -30,7 +30,7 @@ const (
crictlAssetUrlArm64 = "https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.29.0/crictl-v1.29.0-linux-arm64.tar.gz"
)
func FindCrictlAsset(c *kops.Cluster, assetBuilder *assets.AssetBuilder, arch architectures.Architecture) (*assets.FileAsset, error) {
func FindCrictlAsset(ig model.InstanceGroup, assetBuilder *assets.AssetBuilder, arch architectures.Architecture) (*assets.FileAsset, error) {
var assetURL string
switch arch {
case architectures.ArchitectureAmd64:

View File

@ -20,6 +20,7 @@ import (
"testing"
"k8s.io/kops/pkg/apis/kops"
kopsmodel "k8s.io/kops/pkg/apis/kops/model"
"k8s.io/kops/pkg/assets"
"k8s.io/kops/util/pkg/architectures"
"k8s.io/kops/util/pkg/vfs"
@ -32,8 +33,16 @@ func Test_FindCrictlVersionHash(t *testing.T) {
cluster := &kops.Cluster{}
cluster.Spec.KubernetesVersion = "v1.29.0"
ig := &kops.InstanceGroup{}
igModel, err := kopsmodel.ForInstanceGroup(cluster, ig)
if err != nil {
t.Fatalf("building instance group model: %v", err)
}
assetBuilder := assets.NewAssetBuilder(vfs.Context, cluster.Spec.Assets, cluster.Spec.KubernetesVersion, false)
crictlAsset, err := FindCrictlAsset(cluster, assetBuilder, architectures.ArchitectureAmd64)
crictlAsset, err := FindCrictlAsset(igModel, assetBuilder, architectures.ArchitectureAmd64)
if err != nil {
t.Errorf("Unable to parse crictl version %s", err)
}

View File

@ -19,7 +19,7 @@ package wellknownassets
import (
"fmt"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/model"
"k8s.io/kops/pkg/assets"
"k8s.io/kops/util/pkg/architectures"
)
@ -31,7 +31,7 @@ const (
nerdctlAssetHashArm64 = "d8df47708ca57b9cd7f498055126ba7dcfc811d9ba43aae1830c93a09e70e22d"
)
func FindNerdctlAsset(c *kops.Cluster, assetBuilder *assets.AssetBuilder, arch architectures.Architecture) (*assets.FileAsset, error) {
func FindNerdctlAsset(ig model.InstanceGroup, assetBuilder *assets.AssetBuilder, arch architectures.Architecture) (*assets.FileAsset, error) {
var assetURL, assetHash string
switch arch {
case architectures.ArchitectureAmd64:

View File

@ -21,7 +21,7 @@ import (
"github.com/blang/semver/v4"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/pkg/apis/kops/model"
"k8s.io/kops/pkg/assets"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/util/pkg/architectures"
@ -32,11 +32,11 @@ const (
runcVersionUrlArm64 = "https://github.com/opencontainers/runc/releases/download/v%s/runc.arm64"
)
func FindRuncAsset(c *kops.Cluster, assetBuilder *assets.AssetBuilder, arch architectures.Architecture) (*assets.FileAsset, error) {
if c.Spec.Containerd == nil {
func FindRuncAsset(ig model.InstanceGroup, assetBuilder *assets.AssetBuilder, arch architectures.Architecture) (*assets.FileAsset, error) {
containerd := ig.RawClusterSpec().Containerd
if containerd == nil {
return nil, fmt.Errorf("unable to find containerd config")
}
containerd := c.Spec.Containerd
containerdVersion, err := semver.ParseTolerant(fi.ValueOf(containerd.Version))
if err != nil {