From e462416555bf202933948b542e35594871603be5 Mon Sep 17 00:00:00 2001 From: Andrew Lavery Date: Mon, 23 Oct 2023 20:12:45 +0300 Subject: [PATCH] address review comments --- pkg/embeddedcluster/helmvm_node.go | 1 + pkg/embeddedcluster/node_join.go | 12 ++- .../embedded_cluster_node_join_command.go | 4 +- pkg/store/mock/mock.go | 83 +++++++++++++++++++ pkg/store/store_interface.go | 6 ++ pkg/util/image.go | 26 ++++++ .../apps/EmbeddedClusterManagement.tsx | 28 ------- .../apps/EmbeddedClusterViewNode.jsx | 30 ------- 8 files changed, 126 insertions(+), 64 deletions(-) create mode 100644 pkg/util/image.go diff --git a/pkg/embeddedcluster/helmvm_node.go b/pkg/embeddedcluster/helmvm_node.go index 2b7fff9dd7..4443e3cdf8 100644 --- a/pkg/embeddedcluster/helmvm_node.go +++ b/pkg/embeddedcluster/helmvm_node.go @@ -160,6 +160,7 @@ func nodeRolesFromLabels(labels map[string]string) []string { roleLabel, ok := labels[fmt.Sprintf("%s-%d", types.EMBEDDED_CLUSTER_ROLE_LABEL, i)] if !ok { fmt.Printf("failed to find role label %d", i) + continue } toReturn = append(toReturn, roleLabel) } diff --git a/pkg/embeddedcluster/node_join.go b/pkg/embeddedcluster/node_join.go index b0835b3761..b7e85e9b35 100644 --- a/pkg/embeddedcluster/node_join.go +++ b/pkg/embeddedcluster/node_join.go @@ -3,12 +3,12 @@ package embeddedcluster import ( "context" "fmt" - "os" "strings" "sync" "time" "github.com/replicatedhq/kots/pkg/embeddedcluster/types" + "github.com/replicatedhq/kots/pkg/util" corev1 "k8s.io/api/core/v1" kuberneteserrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -70,6 +70,12 @@ func runAddNodeCommandPod(ctx context.Context, client kubernetes.Interface, node } } + // get the kotsadm image, as we know that will always exist + kotsadmImage, err := util.ThisImage(ctx, client) + if err != nil { + return "", fmt.Errorf("failed to get kotsadm image: %w", err) + } + hostPathFile := corev1.HostPathFile hostPathDir := corev1.HostPathDirectory _, err = client.CoreV1().Pods("kube-system").Create(ctx, &corev1.Pod{ @@ -143,7 +149,7 @@ func runAddNodeCommandPod(ctx context.Context, client kubernetes.Interface, node Containers: []corev1.Container{ { Name: "k0s-token-generator", - Image: "ubuntu:latest", // TODO use the kotsadm image here as we'll know it exists + Image: kotsadmImage, Command: []string{"/mnt/k0s"}, Args: []string{ "token", @@ -264,7 +270,7 @@ func GenerateK0sJoinCommand(ctx context.Context, client kubernetes.Interface, ro // gets the port of the 'admin-console' service func getAdminConsolePort(ctx context.Context, client kubernetes.Interface) (int32, error) { - svc, err := client.CoreV1().Services(os.Getenv("POD_NAMESPACE")).Get(ctx, "admin-console", metav1.GetOptions{}) + svc, err := client.CoreV1().Services(util.PodNamespace).Get(ctx, "admin-console", metav1.GetOptions{}) if err != nil { return -1, fmt.Errorf("failed to get admin-console service: %w", err) } diff --git a/pkg/handlers/embedded_cluster_node_join_command.go b/pkg/handlers/embedded_cluster_node_join_command.go index edeb07a171..8b61429999 100644 --- a/pkg/handlers/embedded_cluster_node_join_command.go +++ b/pkg/handlers/embedded_cluster_node_join_command.go @@ -33,7 +33,6 @@ func (h *Handler) GenerateEmbeddedClusterNodeJoinCommand(w http.ResponseWriter, return } - store := kotsstore.StoreFromEnv() token, err := store.GetStore().SetEmbeddedClusterInstallCommandRoles(generateEmbeddedClusterNodeJoinCommandRequest.Roles) if err != nil { logger.Error(fmt.Errorf("failed to set k0s install command roles: %w", err)) @@ -63,8 +62,7 @@ func (h *Handler) GenerateEmbeddedClusterNodeJoinCommand(w http.ResponseWriter, func (h *Handler) GetEmbeddedClusterNodeJoinCommand(w http.ResponseWriter, r *http.Request) { // read query string, ensure that the token is valid token := r.URL.Query().Get("token") - store := kotsstore.StoreFromEnv() - roles, err := store.GetEmbeddedClusterInstallCommandRoles(token) + roles, err := store.GetStore().GetEmbeddedClusterInstallCommandRoles(token) if err != nil { logger.Error(fmt.Errorf("failed to get k0s install command roles: %w", err)) w.WriteHeader(http.StatusInternalServerError) diff --git a/pkg/store/mock/mock.go b/pkg/store/mock/mock.go index 6ae23ab37b..a71c1b9f57 100644 --- a/pkg/store/mock/mock.go +++ b/pkg/store/mock/mock.go @@ -758,6 +758,21 @@ func (mr *MockStoreMockRecorder) GetEmbeddedClusterAuthToken() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEmbeddedClusterAuthToken", reflect.TypeOf((*MockStore)(nil).GetEmbeddedClusterAuthToken)) } +// GetEmbeddedClusterInstallCommandRoles mocks base method. +func (m *MockStore) GetEmbeddedClusterInstallCommandRoles(token string) ([]string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEmbeddedClusterInstallCommandRoles", token) + ret0, _ := ret[0].([]string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetEmbeddedClusterInstallCommandRoles indicates an expected call of GetEmbeddedClusterInstallCommandRoles. +func (mr *MockStoreMockRecorder) GetEmbeddedClusterInstallCommandRoles(token interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEmbeddedClusterInstallCommandRoles", reflect.TypeOf((*MockStore)(nil).GetEmbeddedClusterInstallCommandRoles), token) +} + // GetIgnoreRBACErrors mocks base method. func (m *MockStore) GetIgnoreRBACErrors(appID string, sequence int64) (bool, error) { m.ctrl.T.Helper() @@ -1644,6 +1659,21 @@ func (mr *MockStoreMockRecorder) SetEmbeddedClusterAuthToken(token interface{}) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetEmbeddedClusterAuthToken", reflect.TypeOf((*MockStore)(nil).SetEmbeddedClusterAuthToken), token) } +// SetEmbeddedClusterInstallCommandRoles mocks base method. +func (m *MockStore) SetEmbeddedClusterInstallCommandRoles(roles []string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetEmbeddedClusterInstallCommandRoles", roles) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SetEmbeddedClusterInstallCommandRoles indicates an expected call of SetEmbeddedClusterInstallCommandRoles. +func (mr *MockStoreMockRecorder) SetEmbeddedClusterInstallCommandRoles(roles interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetEmbeddedClusterInstallCommandRoles", reflect.TypeOf((*MockStore)(nil).SetEmbeddedClusterInstallCommandRoles), roles) +} + // SetIgnorePreflightPermissionErrors mocks base method. func (m *MockStore) SetIgnorePreflightPermissionErrors(appID string, sequence int64) error { m.ctrl.T.Helper() @@ -4432,3 +4462,56 @@ func (mr *MockReportingStoreMockRecorder) SaveReportingInfo(licenseID, reporting mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SaveReportingInfo", reflect.TypeOf((*MockReportingStore)(nil).SaveReportingInfo), licenseID, reportingInfo) } + +// MockEmbeddedClusterStore is a mock of EmbeddedClusterStore interface. +type MockEmbeddedClusterStore struct { + ctrl *gomock.Controller + recorder *MockEmbeddedClusterStoreMockRecorder +} + +// MockEmbeddedClusterStoreMockRecorder is the mock recorder for MockEmbeddedClusterStore. +type MockEmbeddedClusterStoreMockRecorder struct { + mock *MockEmbeddedClusterStore +} + +// NewMockEmbeddedClusterStore creates a new mock instance. +func NewMockEmbeddedClusterStore(ctrl *gomock.Controller) *MockEmbeddedClusterStore { + mock := &MockEmbeddedClusterStore{ctrl: ctrl} + mock.recorder = &MockEmbeddedClusterStoreMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use. +func (m *MockEmbeddedClusterStore) EXPECT() *MockEmbeddedClusterStoreMockRecorder { + return m.recorder +} + +// GetEmbeddedClusterInstallCommandRoles mocks base method. +func (m *MockEmbeddedClusterStore) GetEmbeddedClusterInstallCommandRoles(token string) ([]string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "GetEmbeddedClusterInstallCommandRoles", token) + ret0, _ := ret[0].([]string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// GetEmbeddedClusterInstallCommandRoles indicates an expected call of GetEmbeddedClusterInstallCommandRoles. +func (mr *MockEmbeddedClusterStoreMockRecorder) GetEmbeddedClusterInstallCommandRoles(token interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEmbeddedClusterInstallCommandRoles", reflect.TypeOf((*MockEmbeddedClusterStore)(nil).GetEmbeddedClusterInstallCommandRoles), token) +} + +// SetEmbeddedClusterInstallCommandRoles mocks base method. +func (m *MockEmbeddedClusterStore) SetEmbeddedClusterInstallCommandRoles(roles []string) (string, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "SetEmbeddedClusterInstallCommandRoles", roles) + ret0, _ := ret[0].(string) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// SetEmbeddedClusterInstallCommandRoles indicates an expected call of SetEmbeddedClusterInstallCommandRoles. +func (mr *MockEmbeddedClusterStoreMockRecorder) SetEmbeddedClusterInstallCommandRoles(roles interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetEmbeddedClusterInstallCommandRoles", reflect.TypeOf((*MockEmbeddedClusterStore)(nil).SetEmbeddedClusterInstallCommandRoles), roles) +} diff --git a/pkg/store/store_interface.go b/pkg/store/store_interface.go index 1a5df70a01..34b5872db2 100644 --- a/pkg/store/store_interface.go +++ b/pkg/store/store_interface.go @@ -47,6 +47,7 @@ type Store interface { EmbeddedStore BrandingStore ReportingStore + EmbeddedClusterStore Init() error // this may need options WaitForReady(ctx context.Context) error @@ -253,3 +254,8 @@ type ReportingStore interface { SavePreflightReport(licenseID string, preflightStatus *reportingtypes.PreflightStatus) error SaveReportingInfo(licenseID string, reportingInfo *reportingtypes.ReportingInfo) error } + +type EmbeddedClusterStore interface { + SetEmbeddedClusterInstallCommandRoles(roles []string) (string, error) + GetEmbeddedClusterInstallCommandRoles(token string) ([]string, error) +} diff --git a/pkg/util/image.go b/pkg/util/image.go new file mode 100644 index 0000000000..d1bd374831 --- /dev/null +++ b/pkg/util/image.go @@ -0,0 +1,26 @@ +package util + +import ( + "context" + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" +) + +// ThisImage looks for either a deployment 'kotsadm' or a statefulset 'kotsadm' in the current namespace +// it returns the image of the first container in the pod template +func ThisImage(ctx context.Context, client kubernetes.Interface) (string, error) { + deploy, err := client.AppsV1().Deployments(PodNamespace).Get(ctx, "kotsadm", metav1.GetOptions{}) + if err == nil { + return deploy.Spec.Template.Spec.Containers[0].Image, nil + } + + statefulset, err := client.AppsV1().StatefulSets(PodNamespace).Get(ctx, "kotsadm", metav1.GetOptions{}) + if err == nil { + return statefulset.Spec.Template.Spec.Containers[0].Image, nil + } + + return "", fmt.Errorf("failed to find deployment or statefulset") + +} diff --git a/web/src/components/apps/EmbeddedClusterManagement.tsx b/web/src/components/apps/EmbeddedClusterManagement.tsx index 1f946217fc..55834092c9 100644 --- a/web/src/components/apps/EmbeddedClusterManagement.tsx +++ b/web/src/components/apps/EmbeddedClusterManagement.tsx @@ -17,34 +17,6 @@ import "@src/scss/components/apps/EmbeddedClusterManagement.scss"; const testData = { nodes: undefined, }; -// const testData = { -// nodes: [ -// { -// name: "laverya-embeddedcluster", -// isConnected: true, -// isReady: true, -// isPrimaryNode: true, -// canDelete: false, -// kubeletVersion: "v1.28.2+k0s", -// kubeProxyVersion: "v1.28.2+k0s", -// operatingSystem: "linux", -// kernelVersion: "5.10.0-26-cloud-amd64", -// cpu: { capacity: 4, used: 1.9364847660000002 }, -// memory: { capacity: 15.633056640625, used: 3.088226318359375 }, -// pods: { capacity: 110, used: 27 }, -// labels: ["controller"], -// conditions: { -// memoryPressure: false, -// diskPressure: false, -// pidPressure: false, -// ready: true, -// }, -// podList: [], -// }, -// ], -// ha: true, -// isEmbeddedClusterEnabled: true, -// }; type State = { displayAddNode: boolean; diff --git a/web/src/components/apps/EmbeddedClusterViewNode.jsx b/web/src/components/apps/EmbeddedClusterViewNode.jsx index a581009c3c..c138aa79c5 100644 --- a/web/src/components/apps/EmbeddedClusterViewNode.jsx +++ b/web/src/components/apps/EmbeddedClusterViewNode.jsx @@ -5,36 +5,6 @@ import { Link, useParams } from "react-router-dom"; import Loader from "@components/shared/Loader"; const testData = undefined; -// const testData = { -// name: "laverya-embeddedcluster", -// isConnected: true, -// isReady: true, -// isPrimaryNode: true, -// canDelete: false, -// kubeletVersion: "v1.28.2+k0s", -// kubeProxyVersion: "v1.28.2+k0s", -// operatingSystem: "linux", -// kernelVersion: "5.10.0-26-cloud-amd64", -// cpu: { capacity: 4, used: 1.9364847660000002 }, -// memory: { capacity: 15.633056640625, used: 3.088226318359375 }, -// pods: { capacity: 110, used: 27 }, -// labels: ["controller"], -// conditions: { -// memoryPressure: false, -// diskPressure: false, -// pidPressure: false, -// ready: true, -// }, -// podList: [ -// { -// name: "example-es-85fc9df74-8x8l6", -// status: "Running", -// namespace: "embeddedcluster", -// cpu: "0.0345789345 GB", -// memory: 0, -// }, -// ], -// }; const EmbeddedClusterViewNode = () => { const { slug, nodeName } = useParams();