AB#2639 Add functions to fetch k8s and helm version of Constellation (#637)

Signed-off-by: Daniel Weiße <dw@edgeless.systems>
This commit is contained in:
Daniel Weiße 2022-11-24 16:39:33 +01:00 committed by GitHub
parent c2ea937fb5
commit 67d0424f0e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 376 additions and 36 deletions

View file

@ -13,6 +13,7 @@ import (
"fmt"
"io"
"github.com/edgelesssys/constellation/v2/cli/internal/helm"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/constants"
corev1 "k8s.io/api/core/v1"
@ -26,8 +27,9 @@ import (
// Upgrader handles upgrading the cluster's components using the CLI.
type Upgrader struct {
measurementsUpdater measurementsUpdater
imageUpdater imageUpdater
stableInterface stableInterface
dynamicInterface dynamicInterface
helmClient helmInterface
outWriter io.Writer
}
@ -50,10 +52,16 @@ func NewUpgrader(outWriter io.Writer) (*Upgrader, error) {
return nil, fmt.Errorf("setting up custom resource client: %w", err)
}
helmClient, err := helm.NewClient(constants.AdminConfFilename, constants.HelmNamespace)
if err != nil {
return nil, fmt.Errorf("setting up helm client: %w", err)
}
return &Upgrader{
measurementsUpdater: &kubeMeasurementsUpdater{client: kubeClient},
imageUpdater: &kubeImageUpdater{client: unstructuredClient},
outWriter: outWriter,
stableInterface: &stableClient{client: kubeClient},
dynamicInterface: &dynamicClient{client: unstructuredClient},
helmClient: helmClient,
outWriter: outWriter,
}, nil
}
@ -71,7 +79,7 @@ func (u *Upgrader) Upgrade(ctx context.Context, image string, measurements measu
// GetCurrentImage returns the currently used image of the cluster.
func (u *Upgrader) GetCurrentImage(ctx context.Context) (*unstructured.Unstructured, string, error) {
imageStruct, err := u.imageUpdater.getCurrent(ctx, "constellation-os")
imageStruct, err := u.dynamicInterface.getCurrent(ctx, "constellation-os")
if err != nil {
return nil, "", err
}
@ -97,8 +105,18 @@ func (u *Upgrader) GetCurrentImage(ctx context.Context) (*unstructured.Unstructu
return imageStruct, imageDefinition, nil
}
// CurrentHelmVersion returns the version of the currently installed helm release.
func (u *Upgrader) CurrentHelmVersion(release string) (string, error) {
return u.helmClient.CurrentVersion(release)
}
// KubernetesVersion returns the version of Kubernetes the Constellation is currently running on.
func (u *Upgrader) KubernetesVersion() (string, error) {
return u.stableInterface.kubernetesVersion()
}
func (u *Upgrader) updateMeasurements(ctx context.Context, newMeasurements measurements.M) error {
existingConf, err := u.measurementsUpdater.getCurrent(ctx, constants.JoinConfigMap)
existingConf, err := u.stableInterface.getCurrent(ctx, constants.JoinConfigMap)
if err != nil {
return fmt.Errorf("retrieving current measurements: %w", err)
}
@ -127,7 +145,7 @@ func (u *Upgrader) updateMeasurements(ctx context.Context, newMeasurements measu
return fmt.Errorf("marshaling measurements: %w", err)
}
existingConf.Data[constants.MeasurementsFilename] = string(measurementsJSON)
_, err = u.measurementsUpdater.update(ctx, existingConf)
_, err = u.stableInterface.update(ctx, existingConf)
if err != nil {
return fmt.Errorf("setting new measurements: %w", err)
}
@ -148,7 +166,7 @@ func (u *Upgrader) updateImage(ctx context.Context, image string) error {
}
currentImage.Object["spec"].(map[string]any)["image"] = image
if _, err := u.imageUpdater.update(ctx, currentImage); err != nil {
if _, err := u.dynamicInterface.update(ctx, currentImage); err != nil {
return fmt.Errorf("setting new image: %w", err)
}
@ -156,22 +174,23 @@ func (u *Upgrader) updateImage(ctx context.Context, image string) error {
return nil
}
type imageUpdater interface {
type dynamicInterface interface {
getCurrent(ctx context.Context, name string) (*unstructured.Unstructured, error)
update(ctx context.Context, obj *unstructured.Unstructured) (*unstructured.Unstructured, error)
}
type measurementsUpdater interface {
type stableInterface interface {
getCurrent(ctx context.Context, name string) (*corev1.ConfigMap, error)
update(ctx context.Context, configMap *corev1.ConfigMap) (*corev1.ConfigMap, error)
kubernetesVersion() (string, error)
}
type kubeImageUpdater struct {
type dynamicClient struct {
client dynamic.Interface
}
// getCurrent returns the current image definition.
func (u *kubeImageUpdater) getCurrent(ctx context.Context, name string) (*unstructured.Unstructured, error) {
func (u *dynamicClient) getCurrent(ctx context.Context, name string) (*unstructured.Unstructured, error) {
return u.client.Resource(schema.GroupVersionResource{
Group: "update.edgeless.systems",
Version: "v1alpha1",
@ -180,7 +199,7 @@ func (u *kubeImageUpdater) getCurrent(ctx context.Context, name string) (*unstru
}
// update updates the image definition.
func (u *kubeImageUpdater) update(ctx context.Context, obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
func (u *dynamicClient) update(ctx context.Context, obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
return u.client.Resource(schema.GroupVersionResource{
Group: "update.edgeless.systems",
Version: "v1alpha1",
@ -188,16 +207,28 @@ func (u *kubeImageUpdater) update(ctx context.Context, obj *unstructured.Unstruc
}).Update(ctx, obj, metav1.UpdateOptions{})
}
type kubeMeasurementsUpdater struct {
type stableClient struct {
client kubernetes.Interface
}
// getCurrent returns the cluster's expected measurements.
func (u *kubeMeasurementsUpdater) getCurrent(ctx context.Context, name string) (*corev1.ConfigMap, error) {
func (u *stableClient) getCurrent(ctx context.Context, name string) (*corev1.ConfigMap, error) {
return u.client.CoreV1().ConfigMaps(constants.ConstellationNamespace).Get(ctx, name, metav1.GetOptions{})
}
// update updates the cluster's expected measurements in Kubernetes.
func (u *kubeMeasurementsUpdater) update(ctx context.Context, configMap *corev1.ConfigMap) (*corev1.ConfigMap, error) {
func (u *stableClient) update(ctx context.Context, configMap *corev1.ConfigMap) (*corev1.ConfigMap, error) {
return u.client.CoreV1().ConfigMaps(constants.ConstellationNamespace).Update(ctx, configMap, metav1.UpdateOptions{})
}
func (u *stableClient) kubernetesVersion() (string, error) {
serverVersion, err := u.client.Discovery().ServerVersion()
if err != nil {
return "", err
}
return serverVersion.GitVersion, nil
}
type helmInterface interface {
CurrentVersion(release string) (string, error)
}