constellation/cli/internal/cmd/status_test.go
Otto Bittner c8c2953d7b cli: add status cmd
The new command allows checking the status of an upgrade
and which versions are installed.
Also remove the unused restclient.
And make GetConstellationVersion a function.
2023-04-03 12:03:41 +02:00

194 lines
4.9 KiB
Go

/*
Copyright (c) Edgeless Systems GmbH
SPDX-License-Identifier: AGPL-3.0-only
*/
package cmd
import (
"context"
"testing"
"github.com/edgelesssys/constellation/v2/cli/internal/helm"
updatev1alpha1 "github.com/edgelesssys/constellation/v2/operators/constellation-node-operator/v2/api/v1alpha1"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
)
const successOutput = `Target versions:
Image: v1.1.0
Kubernetes: v1.2.3
Installed service versions:
Cilium: v1.0.0
cert-manager: v1.0.0
constellation-operators: v1.1.0
constellation-services: v1.1.0
Cluster status: Node version of every node is up to date
`
const inProgressOutput = `Target versions:
Image: v1.1.0
Kubernetes: v1.2.3
Installed service versions:
Cilium: v1.0.0
cert-manager: v1.0.0
constellation-operators: v1.1.0
constellation-services: v1.1.0
Cluster status: Some node versions are out of date
Image: 1/2
Kubernetes: 1/2
`
// TestStatus checks that the status function produces the correct strings.
func TestStatus(t *testing.T) {
testCases := map[string]struct {
kubeClient stubKubeClient
helmClient stubHelmClient
nodeVersion updatev1alpha1.NodeVersion
dynamicErr error
expectedOutput string
wantErr bool
}{
"success": {
kubeClient: stubKubeClient{
nodes: []corev1.Node{
{
ObjectMeta: metav1.ObjectMeta{
Name: "node1",
Annotations: map[string]string{
"constellation.edgeless.systems/node-image": "v1.1.0",
},
},
Status: corev1.NodeStatus{
NodeInfo: corev1.NodeSystemInfo{
KubeletVersion: "v1.2.3",
},
},
},
},
},
helmClient: stubHelmClient{
serviceVersions: helm.NewServiceVersions("v1.0.0", "v1.0.0", "v1.1.0", "v1.1.0"),
},
nodeVersion: updatev1alpha1.NodeVersion{
Spec: updatev1alpha1.NodeVersionSpec{
ImageVersion: "v1.1.0",
ImageReference: "v1.1.0",
KubernetesClusterVersion: "v1.2.3",
},
Status: updatev1alpha1.NodeVersionStatus{
Conditions: []metav1.Condition{
{
Message: "Node version of every node is up to date",
},
},
},
},
expectedOutput: successOutput,
},
"one of two nodes not upgraded": {
kubeClient: stubKubeClient{
nodes: []corev1.Node{
{
ObjectMeta: metav1.ObjectMeta{
Name: "outdated",
Annotations: map[string]string{
"constellation.edgeless.systems/node-image": "v1.0.0",
},
},
Status: corev1.NodeStatus{
NodeInfo: corev1.NodeSystemInfo{
KubeletVersion: "v1.2.2",
},
},
},
{
ObjectMeta: metav1.ObjectMeta{
Name: "uptodate",
Annotations: map[string]string{
"constellation.edgeless.systems/node-image": "v1.1.0",
},
},
Status: corev1.NodeStatus{
NodeInfo: corev1.NodeSystemInfo{
KubeletVersion: "v1.2.3",
},
},
},
},
},
helmClient: stubHelmClient{
serviceVersions: helm.NewServiceVersions("v1.0.0", "v1.0.0", "v1.1.0", "v1.1.0"),
},
nodeVersion: updatev1alpha1.NodeVersion{
Spec: updatev1alpha1.NodeVersionSpec{
ImageVersion: "v1.1.0",
ImageReference: "v1.1.0",
KubernetesClusterVersion: "v1.2.3",
},
Status: updatev1alpha1.NodeVersionStatus{
Conditions: []metav1.Condition{
{
Message: "Some node versions are out of date",
},
},
},
},
expectedOutput: inProgressOutput,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
require := require.New(t)
assert := assert.New(t)
raw, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&tc.nodeVersion)
require.NoError(err)
output, err := status(context.Background(), tc.kubeClient, tc.helmClient, &stubDynamicInterface{data: unstructured.Unstructured{Object: raw}, err: tc.dynamicErr})
if tc.wantErr {
assert.Error(err)
return
}
require.NoError(err)
assert.Equal(tc.expectedOutput, output)
})
}
}
type stubKubeClient struct {
nodes []corev1.Node
err error
}
func (s stubKubeClient) GetNodes(_ context.Context) ([]corev1.Node, error) {
return s.nodes, s.err
}
type stubHelmClient struct {
serviceVersions helm.ServiceVersions
err error
}
func (s stubHelmClient) Versions() (helm.ServiceVersions, error) {
return s.serviceVersions, s.err
}
type stubDynamicInterface struct {
data unstructured.Unstructured
err error
}
func (s *stubDynamicInterface) GetCurrent(_ context.Context, _ string) (*unstructured.Unstructured, error) {
return &s.data, s.err
}
func (s *stubDynamicInterface) Update(_ context.Context, _ *unstructured.Unstructured) (*unstructured.Unstructured, error) {
return &s.data, s.err
}