internal: move components into their own package

This commit is contained in:
Leonard Cohnen 2023-01-06 12:04:36 +01:00 committed by 3u13r
parent 433e9cdd8b
commit 3637909a46
18 changed files with 156 additions and 135 deletions

View File

@ -12,7 +12,7 @@ import (
"github.com/edgelesssys/constellation/v2/internal/cloud/metadata" "github.com/edgelesssys/constellation/v2/internal/cloud/metadata"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/role" "github.com/edgelesssys/constellation/v2/internal/role"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions/components"
kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3" kubeadm "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
) )
@ -22,13 +22,13 @@ type clusterFake struct{}
// InitCluster fakes bootstrapping a new cluster with the current node being the master, returning the arguments required to join the cluster. // InitCluster fakes bootstrapping a new cluster with the current node being the master, returning the arguments required to join the cluster.
func (c *clusterFake) InitCluster( func (c *clusterFake) InitCluster(
context.Context, string, string, []byte, []uint32, bool, []byte, bool, context.Context, string, string, []byte, []uint32, bool, []byte, bool,
[]byte, bool, versions.ComponentVersions, *logger.Logger, []byte, bool, components.Components, *logger.Logger,
) ([]byte, error) { ) ([]byte, error) {
return []byte{}, nil return []byte{}, nil
} }
// JoinCluster will fake joining the current node to an existing cluster. // JoinCluster will fake joining the current node to an existing cluster.
func (c *clusterFake) JoinCluster(context.Context, *kubeadm.BootstrapTokenDiscovery, role.Role, string, versions.ComponentVersions, *logger.Logger) error { func (c *clusterFake) JoinCluster(context.Context, *kubeadm.BootstrapTokenDiscovery, role.Role, string, components.Components, *logger.Logger) error {
return nil return nil
} }

View File

@ -25,7 +25,7 @@ import (
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/nodestate" "github.com/edgelesssys/constellation/v2/internal/nodestate"
"github.com/edgelesssys/constellation/v2/internal/role" "github.com/edgelesssys/constellation/v2/internal/role"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions/components"
"go.uber.org/zap" "go.uber.org/zap"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"google.golang.org/grpc" "google.golang.org/grpc"
@ -150,7 +150,7 @@ func (s *Server) Init(ctx context.Context, req *initproto.InitRequest) (*initpro
s.issuerWrapper.VMType() == vmtype.AzureCVM, s.issuerWrapper.VMType() == vmtype.AzureCVM,
req.HelmDeployments, req.HelmDeployments,
req.ConformanceMode, req.ConformanceMode,
versions.NewComponentVersionsFromInitProto(req.KubernetesComponents), components.NewComponentsFromInitProto(req.KubernetesComponents),
s.log, s.log,
) )
if err != nil { if err != nil {
@ -251,7 +251,7 @@ type ClusterInitializer interface {
azureCVM bool, azureCVM bool,
helmDeployments []byte, helmDeployments []byte,
conformanceMode bool, conformanceMode bool,
kubernetesComponents versions.ComponentVersions, kubernetesComponents components.Components,
log *logger.Logger, log *logger.Logger,
) ([]byte, error) ) ([]byte, error)
} }

View File

@ -19,7 +19,7 @@ import (
"github.com/edgelesssys/constellation/v2/internal/crypto/testvector" "github.com/edgelesssys/constellation/v2/internal/crypto/testvector"
"github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/file"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions/components"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -302,7 +302,7 @@ type stubClusterInitializer struct {
func (i *stubClusterInitializer) InitCluster( func (i *stubClusterInitializer) InitCluster(
context.Context, string, string, []byte, []uint32, bool, []byte, bool, context.Context, string, string, []byte, []uint32, bool, []byte, bool,
[]byte, bool, versions.ComponentVersions, *logger.Logger, []byte, bool, components.Components, *logger.Logger,
) ([]byte, error) { ) ([]byte, error) {
return i.initClusterKubeconfig, i.initClusterErr return i.initClusterKubeconfig, i.initClusterErr
} }

View File

@ -25,7 +25,7 @@ import (
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/nodestate" "github.com/edgelesssys/constellation/v2/internal/nodestate"
"github.com/edgelesssys/constellation/v2/internal/role" "github.com/edgelesssys/constellation/v2/internal/role"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions/components"
"github.com/edgelesssys/constellation/v2/joinservice/joinproto" "github.com/edgelesssys/constellation/v2/joinservice/joinproto"
"github.com/spf13/afero" "github.com/spf13/afero"
"go.uber.org/zap" "go.uber.org/zap"
@ -287,7 +287,7 @@ func (c *JoinClient) startNodeAndJoin(ticket *joinproto.IssueJoinTicketResponse,
Token: ticket.Token, Token: ticket.Token,
CACertHashes: []string{ticket.DiscoveryTokenCaCertHash}, CACertHashes: []string{ticket.DiscoveryTokenCaCertHash},
} }
k8sComponents := versions.NewComponentVersionsFromJoinProto(ticket.KubernetesComponents) k8sComponents := components.NewComponentsFromJoinProto(ticket.KubernetesComponents)
if err := c.joiner.JoinCluster(ctx, btd, c.role, ticket.KubernetesVersion, k8sComponents, c.log); err != nil { if err := c.joiner.JoinCluster(ctx, btd, c.role, ticket.KubernetesVersion, k8sComponents, c.log); err != nil {
return fmt.Errorf("joining Kubernetes cluster: %w", err) return fmt.Errorf("joining Kubernetes cluster: %w", err)
@ -402,7 +402,7 @@ type ClusterJoiner interface {
args *kubeadm.BootstrapTokenDiscovery, args *kubeadm.BootstrapTokenDiscovery,
peerRole role.Role, peerRole role.Role,
k8sVersion string, k8sVersion string,
k8sComponents versions.ComponentVersions, k8sComponents components.Components,
log *logger.Logger, log *logger.Logger,
) error ) error
} }

View File

@ -23,7 +23,7 @@ import (
"github.com/edgelesssys/constellation/v2/internal/grpc/testdialer" "github.com/edgelesssys/constellation/v2/internal/grpc/testdialer"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/role" "github.com/edgelesssys/constellation/v2/internal/role"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions/components"
"github.com/edgelesssys/constellation/v2/joinservice/joinproto" "github.com/edgelesssys/constellation/v2/joinservice/joinproto"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -393,7 +393,7 @@ type stubClusterJoiner struct {
joinClusterErr error joinClusterErr error
} }
func (j *stubClusterJoiner) JoinCluster(context.Context, *kubeadm.BootstrapTokenDiscovery, role.Role, string, versions.ComponentVersions, *logger.Logger) error { func (j *stubClusterJoiner) JoinCluster(context.Context, *kubeadm.BootstrapTokenDiscovery, role.Role, string, components.Components, *logger.Logger) error {
j.joinClusterCalled = true j.joinClusterCalled = true
return j.joinClusterErr return j.joinClusterErr
} }

View File

@ -26,6 +26,7 @@ import (
"github.com/edgelesssys/constellation/v2/bootstrapper/internal/kubernetes/k8sapi/resources" "github.com/edgelesssys/constellation/v2/bootstrapper/internal/kubernetes/k8sapi/resources"
"github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/role" "github.com/edgelesssys/constellation/v2/internal/role"
"github.com/edgelesssys/constellation/v2/internal/versions/components"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
kubeconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
@ -33,7 +34,6 @@ import (
"github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/file"
"github.com/edgelesssys/constellation/v2/internal/installer" "github.com/edgelesssys/constellation/v2/internal/installer"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/versions"
"github.com/spf13/afero" "github.com/spf13/afero"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -57,7 +57,7 @@ type Client interface {
type componentsInstaller interface { type componentsInstaller interface {
Install( Install(
ctx context.Context, kubernetesComponent versions.ComponentVersion, ctx context.Context, kubernetesComponent components.Component,
) error ) error
} }
@ -76,7 +76,7 @@ func NewKubernetesUtil() *KubernetesUtil {
} }
// InstallComponents installs the kubernetes components passed from the CLI. // InstallComponents installs the kubernetes components passed from the CLI.
func (k *KubernetesUtil) InstallComponents(ctx context.Context, kubernetesComponents versions.ComponentVersions) error { func (k *KubernetesUtil) InstallComponents(ctx context.Context, kubernetesComponents components.Components) error {
for _, component := range kubernetesComponents { for _, component := range kubernetesComponents {
if err := k.inst.Install(ctx, component); err != nil { if err := k.inst.Install(ctx, component); err != nil {
return fmt.Errorf("installing kubernetes component from URL %s: %w", component.URL, err) return fmt.Errorf("installing kubernetes component from URL %s: %w", component.URL, err)

View File

@ -14,11 +14,11 @@ import (
"github.com/edgelesssys/constellation/v2/internal/deploy/helm" "github.com/edgelesssys/constellation/v2/internal/deploy/helm"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/role" "github.com/edgelesssys/constellation/v2/internal/role"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions/components"
) )
type clusterUtil interface { type clusterUtil interface {
InstallComponents(ctx context.Context, kubernetesComponents versions.ComponentVersions) error InstallComponents(ctx context.Context, kubernetesComponents components.Components) error
InitCluster(ctx context.Context, initConfig []byte, nodeName string, ips []net.IP, controlPlaneEndpoint string, conformanceMode bool, log *logger.Logger) error InitCluster(ctx context.Context, initConfig []byte, nodeName string, ips []net.IP, controlPlaneEndpoint string, conformanceMode bool, log *logger.Logger) error
JoinCluster(ctx context.Context, joinConfig []byte, peerRole role.Role, controlPlaneEndpoint string, log *logger.Logger) error JoinCluster(ctx context.Context, joinConfig []byte, peerRole role.Role, controlPlaneEndpoint string, log *logger.Logger) error
FixCilium(log *logger.Logger) FixCilium(log *logger.Logger)

View File

@ -29,7 +29,7 @@ import (
"github.com/edgelesssys/constellation/v2/internal/deploy/helm" "github.com/edgelesssys/constellation/v2/internal/deploy/helm"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/role" "github.com/edgelesssys/constellation/v2/internal/role"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions/components"
"github.com/spf13/afero" "github.com/spf13/afero"
"go.uber.org/zap" "go.uber.org/zap"
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
@ -90,7 +90,7 @@ func New(cloudProvider string, clusterUtil clusterUtil, configProvider configura
func (k *KubeWrapper) InitCluster( func (k *KubeWrapper) InitCluster(
ctx context.Context, cloudServiceAccountURI, versionString string, measurementSalt []byte, enforcedPCRs []uint32, ctx context.Context, cloudServiceAccountURI, versionString string, measurementSalt []byte, enforcedPCRs []uint32,
enforceIDKeyDigest bool, idKeyDigest []byte, azureCVM bool, enforceIDKeyDigest bool, idKeyDigest []byte, azureCVM bool,
helmReleasesRaw []byte, conformanceMode bool, kubernetesComponents versions.ComponentVersions, log *logger.Logger, helmReleasesRaw []byte, conformanceMode bool, kubernetesComponents components.Components, log *logger.Logger,
) ([]byte, error) { ) ([]byte, error) {
log.With(zap.String("version", versionString)).Infof("Installing Kubernetes components") log.With(zap.String("version", versionString)).Infof("Installing Kubernetes components")
if err := k.clusterUtil.InstallComponents(ctx, kubernetesComponents); err != nil { if err := k.clusterUtil.InstallComponents(ctx, kubernetesComponents); err != nil {
@ -255,7 +255,7 @@ func (k *KubeWrapper) InitCluster(
} }
// JoinCluster joins existing Kubernetes cluster. // JoinCluster joins existing Kubernetes cluster.
func (k *KubeWrapper) JoinCluster(ctx context.Context, args *kubeadm.BootstrapTokenDiscovery, peerRole role.Role, versionString string, k8sComponents versions.ComponentVersions, log *logger.Logger) error { func (k *KubeWrapper) JoinCluster(ctx context.Context, args *kubeadm.BootstrapTokenDiscovery, peerRole role.Role, versionString string, k8sComponents components.Components, log *logger.Logger) error {
log.With("k8sComponents", k8sComponents).Infof("Installing provided kubernetes components") log.With("k8sComponents", k8sComponents).Infof("Installing provided kubernetes components")
if err := k.clusterUtil.InstallComponents(ctx, k8sComponents); err != nil { if err := k.clusterUtil.InstallComponents(ctx, k8sComponents); err != nil {
return fmt.Errorf("installing kubernetes components: %w", err) return fmt.Errorf("installing kubernetes components: %w", err)
@ -319,7 +319,7 @@ func (k *KubeWrapper) GetKubeconfig() ([]byte, error) {
// setupK8sComponentsConfigMap applies a ConfigMap (cf. server-side apply) to store the installed k8s components. // setupK8sComponentsConfigMap applies a ConfigMap (cf. server-side apply) to store the installed k8s components.
// It returns the name of the ConfigMap. // It returns the name of the ConfigMap.
func (k *KubeWrapper) setupK8sComponentsConfigMap(ctx context.Context, components versions.ComponentVersions, clusterVersion string) (string, error) { func (k *KubeWrapper) setupK8sComponentsConfigMap(ctx context.Context, components components.Components, clusterVersion string) (string, error) {
componentsMarshalled, err := json.Marshal(components) componentsMarshalled, err := json.Marshal(components)
if err != nil { if err != nil {
return "", fmt.Errorf("marshalling component versions: %w", err) return "", fmt.Errorf("marshalling component versions: %w", err)

View File

@ -22,6 +22,7 @@ import (
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/role" "github.com/edgelesssys/constellation/v2/internal/role"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions"
"github.com/edgelesssys/constellation/v2/internal/versions/components"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"go.uber.org/goleak" "go.uber.org/goleak"
@ -284,7 +285,7 @@ func TestJoinCluster(t *testing.T) {
privateIP := "192.0.2.1" privateIP := "192.0.2.1"
k8sVersion := versions.Default k8sVersion := versions.Default
k8sComponents := versions.ComponentVersions{ k8sComponents := components.Components{
{ {
URL: "URL", URL: "URL",
Hash: "Hash", Hash: "Hash",
@ -298,7 +299,7 @@ func TestJoinCluster(t *testing.T) {
providerMetadata ProviderMetadata providerMetadata ProviderMetadata
wantConfig kubeadm.JoinConfiguration wantConfig kubeadm.JoinConfiguration
role role.Role role role.Role
k8sComponents versions.ComponentVersions k8sComponents components.Components
wantErr bool wantErr bool
}{ }{
"kubeadm join worker works with metadata and remote Kubernetes Components": { "kubeadm join worker works with metadata and remote Kubernetes Components": {
@ -510,7 +511,7 @@ func (s *stubClusterUtil) SetupKonnectivity(kubectl k8sapi.Client, konnectivityA
return s.setupKonnectivityError return s.setupKonnectivityError
} }
func (s *stubClusterUtil) InstallComponents(ctx context.Context, kubernetesComponents versions.ComponentVersions) error { func (s *stubClusterUtil) InstallComponents(ctx context.Context, kubernetesComponents components.Components) error {
return s.installComponentsErr return s.installComponentsErr
} }

View File

@ -21,7 +21,7 @@ import (
"time" "time"
"github.com/edgelesssys/constellation/v2/internal/retry" "github.com/edgelesssys/constellation/v2/internal/retry"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions/components"
"github.com/spf13/afero" "github.com/spf13/afero"
"k8s.io/utils/clock" "k8s.io/utils/clock"
) )
@ -54,7 +54,7 @@ func NewOSInstaller() *OsInstaller {
// Install downloads a resource from a URL, applies any given text transformations and extracts the resulting file if required. // Install downloads a resource from a URL, applies any given text transformations and extracts the resulting file if required.
// The resulting file(s) are copied to the destination. It also verifies the sha256 hash of the downloaded file. // The resulting file(s) are copied to the destination. It also verifies the sha256 hash of the downloaded file.
func (i *OsInstaller) Install(ctx context.Context, kubernetesComponent versions.ComponentVersion) error { func (i *OsInstaller) Install(ctx context.Context, kubernetesComponent components.Component) error {
tempPath, err := i.retryDownloadToTempDir(ctx, kubernetesComponent.URL) tempPath, err := i.retryDownloadToTempDir(ctx, kubernetesComponent.URL)
if err != nil { if err != nil {
return err return err

View File

@ -22,7 +22,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions/components"
"github.com/spf13/afero" "github.com/spf13/afero"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -35,7 +35,7 @@ func TestInstall(t *testing.T) {
serverURL := "http://server/path" serverURL := "http://server/path"
testCases := map[string]struct { testCases := map[string]struct {
server httpBufconnServer server httpBufconnServer
component versions.ComponentVersion component components.Component
hash string hash string
destination string destination string
extract bool extract bool
@ -44,7 +44,7 @@ func TestInstall(t *testing.T) {
}{ }{
"download works": { "download works": {
server: newHTTPBufconnServerWithBody([]byte("file-contents")), server: newHTTPBufconnServerWithBody([]byte("file-contents")),
component: versions.ComponentVersion{ component: components.Component{
URL: serverURL, URL: serverURL,
Hash: "sha256:f03779b36bece74893fd6533a67549675e21573eb0e288d87158738f9c24594e", Hash: "sha256:f03779b36bece74893fd6533a67549675e21573eb0e288d87158738f9c24594e",
InstallPath: "/destination", InstallPath: "/destination",
@ -53,7 +53,7 @@ func TestInstall(t *testing.T) {
}, },
"download with extract works": { "download with extract works": {
server: newHTTPBufconnServerWithBody(createTarGz([]byte("file-contents"), "/destination")), server: newHTTPBufconnServerWithBody(createTarGz([]byte("file-contents"), "/destination")),
component: versions.ComponentVersion{ component: components.Component{
URL: serverURL, URL: serverURL,
Hash: "sha256:a52a1664ca0a6ec9790384e3d058852ab8b3a8f389a9113d150fdc6ab308d949", Hash: "sha256:a52a1664ca0a6ec9790384e3d058852ab8b3a8f389a9113d150fdc6ab308d949",
InstallPath: "/prefix", InstallPath: "/prefix",
@ -63,7 +63,7 @@ func TestInstall(t *testing.T) {
}, },
"hash validation fails": { "hash validation fails": {
server: newHTTPBufconnServerWithBody([]byte("file-contents")), server: newHTTPBufconnServerWithBody([]byte("file-contents")),
component: versions.ComponentVersion{ component: components.Component{
URL: serverURL, URL: serverURL,
Hash: "sha256:abc", Hash: "sha256:abc",
InstallPath: "/destination", InstallPath: "/destination",
@ -72,7 +72,7 @@ func TestInstall(t *testing.T) {
}, },
"download fails": { "download fails": {
server: newHTTPBufconnServer(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(500) }), server: newHTTPBufconnServer(func(w http.ResponseWriter, r *http.Request) { w.WriteHeader(500) }),
component: versions.ComponentVersion{ component: components.Component{
URL: serverURL, URL: serverURL,
Hash: "sha256:abc", Hash: "sha256:abc",
InstallPath: "/destination", InstallPath: "/destination",

View File

@ -0,0 +1,90 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package components
import (
"crypto/sha256"
"errors"
"fmt"
"strings"
"github.com/edgelesssys/constellation/v2/bootstrapper/initproto"
"github.com/edgelesssys/constellation/v2/joinservice/joinproto"
)
// Component is a Kubernetes component.
type Component struct {
URL string
Hash string
InstallPath string
Extract bool
}
// Components is a list of Kubernetes components.
type Components []Component
// NewComponentsFromInitProto converts a protobuf KubernetesVersion to Components.
func NewComponentsFromInitProto(protoComponents []*initproto.KubernetesComponent) Components {
components := Components{}
for _, protoComponent := range protoComponents {
if protoComponent == nil {
continue
}
components = append(components, Component{URL: protoComponent.Url, Hash: protoComponent.Hash, InstallPath: protoComponent.InstallPath, Extract: protoComponent.Extract})
}
return components
}
// NewComponentsFromJoinProto converts a protobuf KubernetesVersion to Components.
func NewComponentsFromJoinProto(protoComponents []*joinproto.KubernetesComponent) Components {
components := Components{}
for _, protoComponent := range protoComponents {
if protoComponent == nil {
continue
}
components = append(components, Component{URL: protoComponent.Url, Hash: protoComponent.Hash, InstallPath: protoComponent.InstallPath, Extract: protoComponent.Extract})
}
return components
}
// ToInitProto converts Components to a protobuf KubernetesVersion.
func (c Components) ToInitProto() []*initproto.KubernetesComponent {
protoComponents := []*initproto.KubernetesComponent{}
for _, component := range c {
protoComponents = append(protoComponents, &initproto.KubernetesComponent{Url: component.URL, Hash: component.Hash, InstallPath: component.InstallPath, Extract: component.Extract})
}
return protoComponents
}
// ToJoinProto converts Components to a protobuf KubernetesVersion.
func (c Components) ToJoinProto() []*joinproto.KubernetesComponent {
protoComponents := []*joinproto.KubernetesComponent{}
for _, component := range c {
protoComponents = append(protoComponents, &joinproto.KubernetesComponent{Url: component.URL, Hash: component.Hash, InstallPath: component.InstallPath, Extract: component.Extract})
}
return protoComponents
}
// GetHash returns the hash over all component hashes.
func (c Components) GetHash() string {
sha := sha256.New()
for _, component := range c {
sha.Write([]byte(component.Hash))
}
return fmt.Sprintf("sha256:%x", sha.Sum(nil))
}
// GetKubeadmComponent returns the kubeadm component.
func (c Components) GetKubeadmComponent() (Component, error) {
for _, component := range c {
if strings.Contains(component.URL, "kubeadm") {
return component, nil
}
}
return Component{}, errors.New("kubeadm component not found")
}

View File

@ -7,13 +7,11 @@ SPDX-License-Identifier: AGPL-3.0-only
package versions package versions
import ( import (
"crypto/sha256"
"fmt" "fmt"
"strings" "strings"
"github.com/edgelesssys/constellation/v2/bootstrapper/initproto"
"github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/joinservice/joinproto" "github.com/edgelesssys/constellation/v2/internal/versions/components"
) )
// ValidK8sVersion represents any of the three currently supported k8s versions. // ValidK8sVersion represents any of the three currently supported k8s versions.
@ -104,7 +102,7 @@ const (
var VersionConfigs = map[ValidK8sVersion]KubernetesVersion{ var VersionConfigs = map[ValidK8sVersion]KubernetesVersion{
V1_23: { V1_23: {
ClusterVersion: "v1.23.15", // renovate:kubernetes-release ClusterVersion: "v1.23.15", // renovate:kubernetes-release
KubernetesComponents: ComponentVersions{ KubernetesComponents: components.Components{
{ {
URL: "https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-amd64-v1.1.1.tgz", // renovate:cni-plugins-release URL: "https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-amd64-v1.1.1.tgz", // renovate:cni-plugins-release
Hash: "sha256:b275772da4026d2161bf8a8b41ed4786754c8a93ebfb6564006d5da7f23831e5", Hash: "sha256:b275772da4026d2161bf8a8b41ed4786754c8a93ebfb6564006d5da7f23831e5",
@ -150,7 +148,7 @@ var VersionConfigs = map[ValidK8sVersion]KubernetesVersion{
}, },
V1_24: { V1_24: {
ClusterVersion: "v1.24.9", // renovate:kubernetes-release ClusterVersion: "v1.24.9", // renovate:kubernetes-release
KubernetesComponents: ComponentVersions{ KubernetesComponents: components.Components{
{ {
URL: "https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-amd64-v1.1.1.tgz", // renovate:cni-plugins-release URL: "https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-amd64-v1.1.1.tgz", // renovate:cni-plugins-release
Hash: "sha256:b275772da4026d2161bf8a8b41ed4786754c8a93ebfb6564006d5da7f23831e5", Hash: "sha256:b275772da4026d2161bf8a8b41ed4786754c8a93ebfb6564006d5da7f23831e5",
@ -196,7 +194,7 @@ var VersionConfigs = map[ValidK8sVersion]KubernetesVersion{
}, },
V1_25: { V1_25: {
ClusterVersion: "v1.25.5", // renovate:kubernetes-release ClusterVersion: "v1.25.5", // renovate:kubernetes-release
KubernetesComponents: ComponentVersions{ KubernetesComponents: components.Components{
{ {
URL: "https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-amd64-v1.1.1.tgz", // renovate:cni-plugins-release URL: "https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-amd64-v1.1.1.tgz", // renovate:cni-plugins-release
Hash: "sha256:b275772da4026d2161bf8a8b41ed4786754c8a93ebfb6564006d5da7f23831e5", Hash: "sha256:b275772da4026d2161bf8a8b41ed4786754c8a93ebfb6564006d5da7f23831e5",
@ -245,7 +243,7 @@ var VersionConfigs = map[ValidK8sVersion]KubernetesVersion{
}, },
V1_26: { V1_26: {
ClusterVersion: "v1.26.0", // renovate:kubernetes-release ClusterVersion: "v1.26.0", // renovate:kubernetes-release
KubernetesComponents: ComponentVersions{ KubernetesComponents: components.Components{
{ {
URL: "https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-amd64-v1.1.1.tgz", // renovate:cni-plugins-release URL: "https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-amd64-v1.1.1.tgz", // renovate:cni-plugins-release
Hash: "sha256:b275772da4026d2161bf8a8b41ed4786754c8a93ebfb6564006d5da7f23831e5", Hash: "sha256:b275772da4026d2161bf8a8b41ed4786754c8a93ebfb6564006d5da7f23831e5",
@ -297,7 +295,7 @@ var VersionConfigs = map[ValidK8sVersion]KubernetesVersion{
// KubernetesVersion bundles download URLs to all version-releated binaries necessary for installing/deploying a particular Kubernetes version. // KubernetesVersion bundles download URLs to all version-releated binaries necessary for installing/deploying a particular Kubernetes version.
type KubernetesVersion struct { type KubernetesVersion struct {
ClusterVersion string ClusterVersion string
KubernetesComponents ComponentVersions KubernetesComponents components.Components
CloudControllerManagerImageAWS string // k8s version dependency. CloudControllerManagerImageAWS string // k8s version dependency.
CloudControllerManagerImageGCP string // Using self-built image until resolved: https://github.com/kubernetes/cloud-provider-gcp/issues/289 CloudControllerManagerImageGCP string // Using self-built image until resolved: https://github.com/kubernetes/cloud-provider-gcp/issues/289
CloudControllerManagerImageAzure string // k8s version dependency. CloudControllerManagerImageAzure string // k8s version dependency.
@ -305,69 +303,6 @@ type KubernetesVersion struct {
ClusterAutoscalerImage string // Matches k8s versioning scheme. ClusterAutoscalerImage string // Matches k8s versioning scheme.
} }
// ComponentVersion is a version of a particular artifact.
type ComponentVersion struct {
URL string
Hash string
InstallPath string
Extract bool
}
// ComponentVersions is a list of ComponentVersion.
type ComponentVersions []ComponentVersion
// NewComponentVersionsFromInitProto converts a protobuf KubernetesVersion to ComponentVersions.
func NewComponentVersionsFromInitProto(protoComponents []*initproto.KubernetesComponent) ComponentVersions {
components := ComponentVersions{}
for _, protoComponent := range protoComponents {
if protoComponent == nil {
continue
}
components = append(components, ComponentVersion{URL: protoComponent.Url, Hash: protoComponent.Hash, InstallPath: protoComponent.InstallPath, Extract: protoComponent.Extract})
}
return components
}
// NewComponentVersionsFromJoinProto converts a protobuf KubernetesVersion to ComponentVersions.
func NewComponentVersionsFromJoinProto(protoComponents []*joinproto.KubernetesComponent) ComponentVersions {
components := ComponentVersions{}
for _, protoComponent := range protoComponents {
if protoComponent == nil {
continue
}
components = append(components, ComponentVersion{URL: protoComponent.Url, Hash: protoComponent.Hash, InstallPath: protoComponent.InstallPath, Extract: protoComponent.Extract})
}
return components
}
// ToInitProto converts a ComponentVersions to a protobuf KubernetesVersion.
func (c ComponentVersions) ToInitProto() []*initproto.KubernetesComponent {
protoComponents := []*initproto.KubernetesComponent{}
for _, component := range c {
protoComponents = append(protoComponents, &initproto.KubernetesComponent{Url: component.URL, Hash: component.Hash, InstallPath: component.InstallPath, Extract: component.Extract})
}
return protoComponents
}
// ToJoinProto converts a ComponentVersions to a protobuf KubernetesVersion.
func (c ComponentVersions) ToJoinProto() []*joinproto.KubernetesComponent {
protoComponents := []*joinproto.KubernetesComponent{}
for _, component := range c {
protoComponents = append(protoComponents, &joinproto.KubernetesComponent{Url: component.URL, Hash: component.Hash, InstallPath: component.InstallPath, Extract: component.Extract})
}
return protoComponents
}
// GetHash returns the hash over all component hashes.
func (c ComponentVersions) GetHash() string {
sha := sha256.New()
for _, component := range c {
sha.Write([]byte(component.Hash))
}
return fmt.Sprintf("sha256:%x", sha.Sum(nil))
}
// versionFromDockerImage returns the version tag from the image name, e.g. "v1.22.2" from "foocr.io/org/repo:v1.22.2@sha256:3009fj0...". // versionFromDockerImage returns the version tag from the image name, e.g. "v1.22.2" from "foocr.io/org/repo:v1.22.2@sha256:3009fj0...".
func versionFromDockerImage(imageName string) string { func versionFromDockerImage(imageName string) string {
beforeAt, _, _ := strings.Cut(imageName, "@") beforeAt, _, _ := strings.Cut(imageName, "@")

View File

@ -15,7 +15,7 @@ import (
"time" "time"
"github.com/edgelesssys/constellation/v2/internal/constants" "github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions/components"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
@ -52,16 +52,16 @@ func New() (*Client, error) {
} }
// GetComponents returns the components of the cluster. // GetComponents returns the components of the cluster.
func (c *Client) GetComponents(ctx context.Context, configMapName string) (versions.ComponentVersions, error) { func (c *Client) GetComponents(ctx context.Context, configMapName string) (components.Components, error) {
componentsRaw, err := c.getConfigMapData(ctx, configMapName, constants.ComponentsListKey) componentsRaw, err := c.getConfigMapData(ctx, configMapName, constants.ComponentsListKey)
if err != nil { if err != nil {
return versions.ComponentVersions{}, fmt.Errorf("failed to get components: %w", err) return components.Components{}, fmt.Errorf("failed to get components: %w", err)
} }
var components versions.ComponentVersions var clusterComponents components.Components
if err := json.Unmarshal([]byte(componentsRaw), &components); err != nil { if err := json.Unmarshal([]byte(componentsRaw), &clusterComponents); err != nil {
return versions.ComponentVersions{}, fmt.Errorf("failed to unmarshal components %s: %w", componentsRaw, err) return components.Components{}, fmt.Errorf("failed to unmarshal components %s: %w", componentsRaw, err)
} }
return components, nil return clusterComponents, nil
} }
func (c *Client) getConfigMapData(ctx context.Context, name, key string) (string, error) { func (c *Client) getConfigMapData(ctx context.Context, name, key string) (string, error) {

View File

@ -17,7 +17,7 @@ import (
"github.com/edgelesssys/constellation/v2/internal/crypto" "github.com/edgelesssys/constellation/v2/internal/crypto"
"github.com/edgelesssys/constellation/v2/internal/grpc/grpclog" "github.com/edgelesssys/constellation/v2/internal/grpc/grpclog"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions/components"
"github.com/edgelesssys/constellation/v2/joinservice/internal/kubernetes" "github.com/edgelesssys/constellation/v2/joinservice/internal/kubernetes"
"github.com/edgelesssys/constellation/v2/joinservice/joinproto" "github.com/edgelesssys/constellation/v2/joinservice/joinproto"
"go.uber.org/zap" "go.uber.org/zap"
@ -224,6 +224,6 @@ type certificateAuthority interface {
type kubeClient interface { type kubeClient interface {
GetK8sComponentsRefFromNodeVersionCRD(ctx context.Context, nodeName string) (string, error) GetK8sComponentsRefFromNodeVersionCRD(ctx context.Context, nodeName string) (string, error)
GetComponents(ctx context.Context, configMapName string) (versions.ComponentVersions, error) GetComponents(ctx context.Context, configMapName string) (components.Components, error)
AddNodeToJoiningNodes(ctx context.Context, nodeName string, componentsHash string, isControlPlane bool) error AddNodeToJoiningNodes(ctx context.Context, nodeName string, componentsHash string, isControlPlane bool) error
} }

View File

@ -14,7 +14,7 @@ import (
"github.com/edgelesssys/constellation/v2/internal/attestation" "github.com/edgelesssys/constellation/v2/internal/attestation"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions/components"
"github.com/edgelesssys/constellation/v2/joinservice/joinproto" "github.com/edgelesssys/constellation/v2/joinservice/joinproto"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -39,7 +39,7 @@ func TestIssueJoinTicket(t *testing.T) {
Token: "token", Token: "token",
} }
components := versions.ComponentVersions{ clusterComponents := components.Components{
{ {
URL: "URL", URL: "URL",
Hash: "hash", Hash: "hash",
@ -64,7 +64,7 @@ func TestIssueJoinTicket(t *testing.T) {
attestation.MeasurementSecretContext: measurementSecret, attestation.MeasurementSecretContext: measurementSecret,
}}, }},
ca: stubCA{cert: testCert, nodeName: "node"}, ca: stubCA{cert: testCert, nodeName: "node"},
kubeClient: stubKubeClient{getComponentsVal: components, getK8sComponentsRefFromNodeVersionCRDVal: "k8s-components-ref"}, kubeClient: stubKubeClient{getComponentsVal: clusterComponents, getK8sComponentsRefFromNodeVersionCRDVal: "k8s-components-ref"},
}, },
"kubeclient fails": { "kubeclient fails": {
kubeadm: stubTokenGetter{token: testJoinToken}, kubeadm: stubTokenGetter{token: testJoinToken},
@ -83,7 +83,7 @@ func TestIssueJoinTicket(t *testing.T) {
attestation.MeasurementSecretContext: measurementSecret, attestation.MeasurementSecretContext: measurementSecret,
}}, }},
ca: stubCA{cert: testCert, nodeName: "node", getNameErr: someErr}, ca: stubCA{cert: testCert, nodeName: "node", getNameErr: someErr},
kubeClient: stubKubeClient{getComponentsVal: components, getK8sComponentsRefFromNodeVersionCRDVal: "k8s-components-ref"}, kubeClient: stubKubeClient{getComponentsVal: clusterComponents, getK8sComponentsRefFromNodeVersionCRDVal: "k8s-components-ref"},
wantErr: true, wantErr: true,
}, },
"Cannot add node to JoiningNode CRD": { "Cannot add node to JoiningNode CRD": {
@ -93,14 +93,14 @@ func TestIssueJoinTicket(t *testing.T) {
attestation.MeasurementSecretContext: measurementSecret, attestation.MeasurementSecretContext: measurementSecret,
}}, }},
ca: stubCA{cert: testCert, nodeName: "node"}, ca: stubCA{cert: testCert, nodeName: "node"},
kubeClient: stubKubeClient{getComponentsVal: components, addNodeToJoiningNodesErr: someErr, getK8sComponentsRefFromNodeVersionCRDVal: "k8s-components-ref"}, kubeClient: stubKubeClient{getComponentsVal: clusterComponents, addNodeToJoiningNodesErr: someErr, getK8sComponentsRefFromNodeVersionCRDVal: "k8s-components-ref"},
wantErr: true, wantErr: true,
}, },
"GetDataKey fails": { "GetDataKey fails": {
kubeadm: stubTokenGetter{token: testJoinToken}, kubeadm: stubTokenGetter{token: testJoinToken},
kms: stubKeyGetter{dataKeys: make(map[string][]byte), getDataKeyErr: someErr}, kms: stubKeyGetter{dataKeys: make(map[string][]byte), getDataKeyErr: someErr},
ca: stubCA{cert: testCert, nodeName: "node"}, ca: stubCA{cert: testCert, nodeName: "node"},
kubeClient: stubKubeClient{getComponentsVal: components, getK8sComponentsRefFromNodeVersionCRDVal: "k8s-components-ref"}, kubeClient: stubKubeClient{getComponentsVal: clusterComponents, getK8sComponentsRefFromNodeVersionCRDVal: "k8s-components-ref"},
wantErr: true, wantErr: true,
}, },
"GetJoinToken fails": { "GetJoinToken fails": {
@ -110,7 +110,7 @@ func TestIssueJoinTicket(t *testing.T) {
attestation.MeasurementSecretContext: measurementSecret, attestation.MeasurementSecretContext: measurementSecret,
}}, }},
ca: stubCA{cert: testCert, nodeName: "node"}, ca: stubCA{cert: testCert, nodeName: "node"},
kubeClient: stubKubeClient{getComponentsVal: components, getK8sComponentsRefFromNodeVersionCRDVal: "k8s-components-ref"}, kubeClient: stubKubeClient{getComponentsVal: clusterComponents, getK8sComponentsRefFromNodeVersionCRDVal: "k8s-components-ref"},
wantErr: true, wantErr: true,
}, },
"GetCertificate fails": { "GetCertificate fails": {
@ -120,7 +120,7 @@ func TestIssueJoinTicket(t *testing.T) {
attestation.MeasurementSecretContext: measurementSecret, attestation.MeasurementSecretContext: measurementSecret,
}}, }},
ca: stubCA{getCertErr: someErr, nodeName: "node"}, ca: stubCA{getCertErr: someErr, nodeName: "node"},
kubeClient: stubKubeClient{getComponentsVal: components, getK8sComponentsRefFromNodeVersionCRDVal: "k8s-components-ref"}, kubeClient: stubKubeClient{getComponentsVal: clusterComponents, getK8sComponentsRefFromNodeVersionCRDVal: "k8s-components-ref"},
wantErr: true, wantErr: true,
}, },
"control plane": { "control plane": {
@ -134,7 +134,7 @@ func TestIssueJoinTicket(t *testing.T) {
attestation.MeasurementSecretContext: measurementSecret, attestation.MeasurementSecretContext: measurementSecret,
}}, }},
ca: stubCA{cert: testCert, nodeName: "node"}, ca: stubCA{cert: testCert, nodeName: "node"},
kubeClient: stubKubeClient{getComponentsVal: components, getK8sComponentsRefFromNodeVersionCRDVal: "k8s-components-ref"}, kubeClient: stubKubeClient{getComponentsVal: clusterComponents, getK8sComponentsRefFromNodeVersionCRDVal: "k8s-components-ref"},
}, },
"GetControlPlaneCertificateKey fails": { "GetControlPlaneCertificateKey fails": {
isControlPlane: true, isControlPlane: true,
@ -144,7 +144,7 @@ func TestIssueJoinTicket(t *testing.T) {
attestation.MeasurementSecretContext: measurementSecret, attestation.MeasurementSecretContext: measurementSecret,
}}, }},
ca: stubCA{cert: testCert, nodeName: "node"}, ca: stubCA{cert: testCert, nodeName: "node"},
kubeClient: stubKubeClient{getComponentsVal: components, getK8sComponentsRefFromNodeVersionCRDVal: "k8s-components-ref"}, kubeClient: stubKubeClient{getComponentsVal: clusterComponents, getK8sComponentsRefFromNodeVersionCRDVal: "k8s-components-ref"},
wantErr: true, wantErr: true,
}, },
} }
@ -286,7 +286,7 @@ func (f stubCA) GetNodeNameFromCSR(csr []byte) (string, error) {
} }
type stubKubeClient struct { type stubKubeClient struct {
getComponentsVal versions.ComponentVersions getComponentsVal components.Components
getComponentsErr error getComponentsErr error
getK8sComponentsRefFromNodeVersionCRDErr error getK8sComponentsRefFromNodeVersionCRDErr error
@ -301,7 +301,7 @@ func (s *stubKubeClient) GetK8sComponentsRefFromNodeVersionCRD(ctx context.Conte
return s.getK8sComponentsRefFromNodeVersionCRDVal, s.getK8sComponentsRefFromNodeVersionCRDErr return s.getK8sComponentsRefFromNodeVersionCRDVal, s.getK8sComponentsRefFromNodeVersionCRDErr
} }
func (s *stubKubeClient) GetComponents(ctx context.Context, configMapName string) (versions.ComponentVersions, error) { func (s *stubKubeClient) GetComponents(ctx context.Context, configMapName string) (components.Components, error) {
return s.getComponentsVal, s.getComponentsErr return s.getComponentsVal, s.getComponentsErr
} }

View File

@ -19,7 +19,7 @@ import (
"github.com/edgelesssys/constellation/v2/internal/file" "github.com/edgelesssys/constellation/v2/internal/file"
"github.com/edgelesssys/constellation/v2/internal/installer" "github.com/edgelesssys/constellation/v2/internal/installer"
"github.com/edgelesssys/constellation/v2/internal/logger" "github.com/edgelesssys/constellation/v2/internal/logger"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions/components"
"github.com/edgelesssys/constellation/v2/upgrade-agent/upgradeproto" "github.com/edgelesssys/constellation/v2/upgrade-agent/upgradeproto"
"golang.org/x/mod/semver" "golang.org/x/mod/semver"
"google.golang.org/grpc" "google.golang.org/grpc"
@ -127,17 +127,12 @@ func prepareUpdate(ctx context.Context, installer osInstaller, updateRequest *up
} }
// download & install the kubeadm binary // download & install the kubeadm binary
err = installer.Install(ctx, versions.ComponentVersion{ return installer.Install(ctx, components.Component{
URL: updateRequest.KubeadmUrl, URL: updateRequest.KubeadmUrl,
Hash: updateRequest.KubeadmHash, Hash: updateRequest.KubeadmHash,
InstallPath: constants.KubeadmPath, InstallPath: constants.KubeadmPath,
Extract: false, Extract: false,
}) })
if err != nil {
return err
}
return nil
} }
// verifyVersion verifies the provided Kubernetes version. // verifyVersion verifies the provided Kubernetes version.
@ -150,7 +145,7 @@ func verifyVersion(version string) error {
type osInstaller interface { type osInstaller interface {
// Install downloads, installs and verifies the kubernetes component. // Install downloads, installs and verifies the kubernetes component.
Install(ctx context.Context, kubernetesComponent versions.ComponentVersion) error Install(ctx context.Context, kubernetesComponent components.Component) error
} }
type serveStopper interface { type serveStopper interface {

View File

@ -11,7 +11,7 @@ import (
"fmt" "fmt"
"testing" "testing"
"github.com/edgelesssys/constellation/v2/internal/versions" "github.com/edgelesssys/constellation/v2/internal/versions/components"
"github.com/edgelesssys/constellation/v2/upgrade-agent/upgradeproto" "github.com/edgelesssys/constellation/v2/upgrade-agent/upgradeproto"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
@ -100,6 +100,6 @@ type stubOsInstaller struct {
InstallErr error InstallErr error
} }
func (s stubOsInstaller) Install(ctx context.Context, kubernetesComponent versions.ComponentVersion) error { func (s stubOsInstaller) Install(ctx context.Context, kubernetesComponent components.Component) error {
return s.InstallErr return s.InstallErr
} }