cli: add kubernetes pkg to interface with cluster

Previously the content of files status and upgrade within the
cloudcmd pkg did not fit cloudcmd's pkg description.
This patch introduces a separate pkg to fix that.
This commit is contained in:
Otto Bittner 2023-03-30 16:13:14 +02:00
parent c8c2953d7b
commit 7c8215e507
13 changed files with 628 additions and 70 deletions

View file

@ -9,16 +9,13 @@ go_library(
"create.go",
"iam.go",
"rollback.go",
"status.go",
"terminate.go",
"upgrade.go",
"validators.go",
],
importpath = "github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd",
visibility = ["//cli:__subpackages__"],
deps = [
"//cli/internal/clusterid",
"//cli/internal/helm",
"//cli/internal/iamid",
"//cli/internal/image",
"//cli/internal/libvirt",
@ -29,30 +26,14 @@ go_library(
"//internal/attestation/measurements",
"//internal/cloud/cloudprovider",
"//internal/cloud/gcpshared",
"//internal/compatibility",
"//internal/config",
"//internal/constants",
"//internal/kubernetes",
"//internal/kubernetes/kubectl",
"//internal/variant",
"//internal/versions",
"//internal/versions/components",
"//internal/versionsapi",
"//operators/constellation-node-operator/api/v1alpha1",
"@com_github_azure_azure_sdk_for_go//profiles/latest/attestation/attestation",
"@com_github_azure_azure_sdk_for_go_sdk_azcore//policy",
"@com_github_azure_azure_sdk_for_go_sdk_azidentity//:azidentity",
"@com_github_hashicorp_terraform_json//:terraform-json",
"@com_github_spf13_cobra//:cobra",
"@io_k8s_api//core/v1:core",
"@io_k8s_apimachinery//pkg/api/errors",
"@io_k8s_apimachinery//pkg/apis/meta/v1:meta",
"@io_k8s_apimachinery//pkg/apis/meta/v1/unstructured",
"@io_k8s_apimachinery//pkg/runtime",
"@io_k8s_apimachinery//pkg/runtime/schema",
"@io_k8s_client_go//dynamic",
"@io_k8s_client_go//kubernetes",
"@io_k8s_client_go//tools/clientcmd",
],
)
@ -64,7 +45,6 @@ go_test(
"iam_test.go",
"rollback_test.go",
"terminate_test.go",
"upgrade_test.go",
"validators_test.go",
],
embed = [":cloudcmd"],
@ -80,22 +60,13 @@ go_test(
"//internal/attestation/qemu",
"//internal/cloud/cloudprovider",
"//internal/cloud/gcpshared",
"//internal/compatibility",
"//internal/config",
"//internal/constants",
"//internal/logger",
"//internal/variant",
"//internal/versions",
"//internal/versions/components",
"//operators/constellation-node-operator/api/v1alpha1",
"@com_github_hashicorp_terraform_json//:terraform-json",
"@com_github_spf13_cobra//:cobra",
"@com_github_stretchr_testify//assert",
"@com_github_stretchr_testify//require",
"@io_k8s_api//core/v1:core",
"@io_k8s_apimachinery//pkg/apis/meta/v1:meta",
"@io_k8s_apimachinery//pkg/apis/meta/v1/unstructured",
"@io_k8s_apimachinery//pkg/runtime",
"@org_uber_go_goleak//:goleak",
],
)

View file

@ -138,3 +138,8 @@ func (wl warnLogger) Infof(fmtStr string, args ...any) {
func (wl warnLogger) Warnf(fmtStr string, args ...any) {
wl.cmd.PrintErrf("Warning: %s\n", fmt.Sprintf(fmtStr, args...))
}
type debugLog interface {
Debugf(format string, args ...any)
Sync()
}

View file

@ -40,6 +40,7 @@ go_library(
"//cli/internal/clusterid",
"//cli/internal/helm",
"//cli/internal/iamid",
"//cli/internal/kubernetes",
"//cli/internal/libvirt",
"//cli/internal/terraform",
"//disk-mapper/recoverproto",
@ -117,6 +118,7 @@ go_test(
"//cli/internal/clusterid",
"//cli/internal/helm",
"//cli/internal/iamid",
"//cli/internal/kubernetes",
"//disk-mapper/recoverproto",
"//internal/atls",
"//internal/attestation/measurements",

View file

@ -11,8 +11,8 @@ import (
"fmt"
"strings"
"github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd"
"github.com/edgelesssys/constellation/v2/cli/internal/helm"
"github.com/edgelesssys/constellation/v2/cli/internal/kubernetes"
"github.com/edgelesssys/constellation/v2/internal/constants"
"github.com/edgelesssys/constellation/v2/internal/file"
"github.com/edgelesssys/constellation/v2/internal/kubernetes/kubectl"
@ -74,7 +74,7 @@ func runStatus(cmd *cobra.Command, args []string) error {
return fmt.Errorf("setting up helm client: %w", err)
}
output, err := status(cmd.Context(), kubeClient, helmClient, cloudcmd.NewNodeVersionClient(unstructuredClient))
output, err := status(cmd.Context(), kubeClient, helmClient, kubernetes.NewNodeVersionClient(unstructuredClient))
if err != nil {
return fmt.Errorf("getting status: %w", err)
}
@ -84,8 +84,8 @@ func runStatus(cmd *cobra.Command, args []string) error {
}
// status queries the cluster for the relevant status information and returns the output string.
func status(ctx context.Context, kubeClient kubeClient, helmClient helmClient, dynamicInterface cloudcmd.DynamicInterface) (string, error) {
nodeVersion, err := cloudcmd.GetConstellationVersion(ctx, dynamicInterface)
func status(ctx context.Context, kubeClient kubeClient, helmClient helmClient, dynamicInterface kubernetes.DynamicInterface) (string, error) {
nodeVersion, err := kubernetes.GetConstellationVersion(ctx, dynamicInterface)
if err != nil {
return "", fmt.Errorf("getting constellation version: %w", err)
}
@ -93,7 +93,7 @@ func status(ctx context.Context, kubeClient kubeClient, helmClient helmClient, d
return "", fmt.Errorf("expected exactly one condition, got %d", len(nodeVersion.Status.Conditions))
}
targetVersions, err := cloudcmd.NewTargetVersions(nodeVersion)
targetVersions, err := kubernetes.NewTargetVersions(nodeVersion)
if err != nil {
return "", fmt.Errorf("getting configured versions: %w", err)
}
@ -103,7 +103,7 @@ func status(ctx context.Context, kubeClient kubeClient, helmClient helmClient, d
return "", fmt.Errorf("getting service versions: %w", err)
}
status, err := cloudcmd.ClusterStatus(ctx, kubeClient)
status, err := kubernetes.ClusterStatus(ctx, kubeClient)
if err != nil {
return "", fmt.Errorf("getting cluster status: %w", err)
}
@ -112,7 +112,7 @@ func status(ctx context.Context, kubeClient kubeClient, helmClient helmClient, d
}
// statusOutput creates the status cmd output string by formatting the received information.
func statusOutput(targetVersions cloudcmd.TargetVersions, serviceVersions helm.ServiceVersions, status map[string]cloudcmd.NodeStatus, nodeVersion v1alpha1.NodeVersion) string {
func statusOutput(targetVersions kubernetes.TargetVersions, serviceVersions helm.ServiceVersions, status map[string]kubernetes.NodeStatus, nodeVersion v1alpha1.NodeVersion) string {
builder := strings.Builder{}
builder.WriteString(targetVersionsString(targetVersions))
@ -124,7 +124,7 @@ func statusOutput(targetVersions cloudcmd.TargetVersions, serviceVersions helm.S
}
// nodeStatusString creates the node status part of the output string.
func nodeStatusString(status map[string]cloudcmd.NodeStatus, targetVersions cloudcmd.TargetVersions) string {
func nodeStatusString(status map[string]kubernetes.NodeStatus, targetVersions kubernetes.TargetVersions) string {
var upToDateImages int
var upToDateK8s int
for _, node := range status {
@ -157,7 +157,7 @@ func serviceVersionsString(versions helm.ServiceVersions) string {
}
// targetVersionsString creates the target versions part of the output string.
func targetVersionsString(target cloudcmd.TargetVersions) string {
func targetVersionsString(target kubernetes.TargetVersions) string {
builder := strings.Builder{}
builder.WriteString("Target versions:\n")
builder.WriteString(fmt.Sprintf("\tImage: %s\n", target.Image()))

View file

@ -12,8 +12,8 @@ import (
"fmt"
"time"
"github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd"
"github.com/edgelesssys/constellation/v2/cli/internal/helm"
"github.com/edgelesssys/constellation/v2/cli/internal/kubernetes"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/compatibility"
@ -53,7 +53,7 @@ func runUpgradeApply(cmd *cobra.Command, _ []string) error {
defer log.Sync()
fileHandler := file.NewHandler(afero.NewOsFs())
upgrader, err := cloudcmd.NewUpgrader(cmd.OutOrStdout(), log)
upgrader, err := kubernetes.NewUpgrader(cmd.OutOrStdout(), log)
if err != nil {
return err
}
@ -93,7 +93,7 @@ func (u *upgradeApplyCmd) upgradeApply(cmd *cobra.Command, fileHandler file.Hand
err = u.upgrader.UpgradeNodeVersion(cmd.Context(), conf)
switch {
case errors.Is(err, cloudcmd.ErrInProgress):
case errors.Is(err, kubernetes.ErrInProgress):
cmd.PrintErrln("Skipping image and Kubernetes upgrades. Another upgrade is in progress.")
case errors.As(err, &upgradeErr):
cmd.PrintErrln(err)

View file

@ -12,7 +12,7 @@ import (
"testing"
"time"
"github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd"
"github.com/edgelesssys/constellation/v2/cli/internal/kubernetes"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/config"
@ -39,7 +39,7 @@ func TestUpgradeApply(t *testing.T) {
wantErr: true,
},
"nodeVersion in progress error": {
upgrader: stubUpgrader{nodeVersionErr: cloudcmd.ErrInProgress},
upgrader: stubUpgrader{nodeVersionErr: kubernetes.ErrInProgress},
},
"helm other error": {
upgrader: stubUpgrader{helmErr: someErr},

View file

@ -15,8 +15,8 @@ import (
"sort"
"strings"
"github.com/edgelesssys/constellation/v2/cli/internal/cloudcmd"
"github.com/edgelesssys/constellation/v2/cli/internal/helm"
"github.com/edgelesssys/constellation/v2/cli/internal/kubernetes"
"github.com/edgelesssys/constellation/v2/internal/attestation/measurements"
"github.com/edgelesssys/constellation/v2/internal/cloud/cloudprovider"
"github.com/edgelesssys/constellation/v2/internal/compatibility"
@ -61,7 +61,7 @@ func runUpgradeCheck(cmd *cobra.Command, _ []string) error {
if err != nil {
return err
}
checker, err := cloudcmd.NewUpgrader(cmd.OutOrStdout(), log)
checker, err := kubernetes.NewUpgrader(cmd.OutOrStdout(), log)
if err != nil {
return err
}

View file

@ -0,0 +1,58 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
load("//bazel/go:go_test.bzl", "go_test")
go_library(
name = "kubernetes",
srcs = [
"kubernetes.go",
"status.go",
"upgrade.go",
],
importpath = "github.com/edgelesssys/constellation/v2/cli/internal/kubernetes",
visibility = ["//cli:__subpackages__"],
deps = [
"//cli/internal/helm",
"//cli/internal/image",
"//internal/attestation/measurements",
"//internal/compatibility",
"//internal/config",
"//internal/constants",
"//internal/kubernetes",
"//internal/kubernetes/kubectl",
"//internal/versions",
"//internal/versions/components",
"//internal/versionsapi",
"//operators/constellation-node-operator/api/v1alpha1",
"@io_k8s_api//core/v1:core",
"@io_k8s_apimachinery//pkg/api/errors",
"@io_k8s_apimachinery//pkg/apis/meta/v1:meta",
"@io_k8s_apimachinery//pkg/apis/meta/v1/unstructured",
"@io_k8s_apimachinery//pkg/runtime",
"@io_k8s_apimachinery//pkg/runtime/schema",
"@io_k8s_client_go//dynamic",
"@io_k8s_client_go//kubernetes",
"@io_k8s_client_go//tools/clientcmd",
],
)
go_test(
name = "kubernetes_test",
srcs = ["upgrade_test.go"],
embed = [":kubernetes"],
deps = [
"//internal/attestation/measurements",
"//internal/compatibility",
"//internal/config",
"//internal/constants",
"//internal/logger",
"//internal/versions",
"//internal/versions/components",
"//operators/constellation-node-operator/api/v1alpha1",
"@com_github_stretchr_testify//assert",
"@com_github_stretchr_testify//require",
"@io_k8s_api//core/v1:core",
"@io_k8s_apimachinery//pkg/apis/meta/v1:meta",
"@io_k8s_apimachinery//pkg/apis/meta/v1/unstructured",
"@io_k8s_apimachinery//pkg/runtime",
],
)

View file

@ -0,0 +1,12 @@
/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
/*
Package kubernetes provides functions to interact with a live cluster to the CLI.
Currently it is used to implement the status and upgrade commands.
*/
package kubernetes

View file

@ -4,7 +4,7 @@ Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package cloudcmd
package kubernetes
import (
"context"

View file

@ -4,7 +4,7 @@ Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package cloudcmd
package kubernetes
import (
"context"
@ -413,3 +413,8 @@ type debugLog interface {
Debugf(format string, args ...any)
Sync()
}
// imageFetcher gets an image reference from the versionsapi.
type imageFetcher interface {
FetchReference(ctx context.Context, config *config.Config) (string, error)
}

View file

@ -4,7 +4,7 @@ Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package cloudcmd
package kubernetes
import (
"context"
@ -468,3 +468,12 @@ func (s *stubStableClient) createConfigMap(_ context.Context, configMap *corev1.
func (s *stubStableClient) kubernetesVersion() (string, error) {
return s.k8sVersion, s.k8sErr
}
type stubImageFetcher struct {
reference string
fetchReferenceErr error
}
func (f *stubImageFetcher) FetchReference(_ context.Context, _ *config.Config) (string, error) {
return f.reference, f.fetchReferenceErr
}