diff --git a/pkg/nodepassword/nodepassword_test.go b/pkg/nodepassword/nodepassword_test.go index 4e7de581ec10..8dfcda28602c 100644 --- a/pkg/nodepassword/nodepassword_test.go +++ b/pkg/nodepassword/nodepassword_test.go @@ -9,7 +9,7 @@ import ( "testing" "github.com/golang/mock/gomock" - "github.com/rancher/wrangler/v3/pkg/generic/fake" + "github.com/k3s-io/k3s/tests/mock" v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -28,10 +28,11 @@ func Test_UnitAsserts(t *testing.T) { func Test_UnitEnsureDelete(t *testing.T) { logMemUsage(t) - ctrl := gomock.NewController(t) - secretClient := fake.NewMockControllerInterface[*v1.Secret, *v1.SecretList](ctrl) - secretCache := fake.NewMockCacheInterface[*v1.Secret](ctrl) - secretStore := &mockSecretStore{} + v1Mock := mock.NewV1(gomock.NewController(t)) + + secretClient := v1Mock.SecretMock + secretCache := v1Mock.SecretCache + secretStore := &mock.SecretStore{} // Set up expected call counts for tests // Expect to see 2 creates, any number of cache gets, and 2 deletes. @@ -59,15 +60,15 @@ func Test_UnitMigrateFile(t *testing.T) { nodePasswordFile := generateNodePasswordFile(migrateNumNodes) defer os.Remove(nodePasswordFile) - ctrl := gomock.NewController(t) + v1Mock := mock.NewV1(gomock.NewController(t)) - secretClient := fake.NewMockControllerInterface[*v1.Secret, *v1.SecretList](ctrl) - secretCache := fake.NewMockCacheInterface[*v1.Secret](ctrl) - secretStore := &mockSecretStore{} + secretClient := v1Mock.SecretMock + secretCache := v1Mock.SecretCache + secretStore := &mock.SecretStore{} - nodeClient := fake.NewMockNonNamespacedControllerInterface[*v1.Node, *v1.NodeList](ctrl) - nodeCache := fake.NewMockNonNamespacedCacheInterface[*v1.Node](ctrl) - nodeStore := &mockNodeStore{} + nodeClient := v1Mock.NodeMock + nodeCache := v1Mock.NodeCache + nodeStore := &mock.NodeStore{} // Set up expected call counts for tests // Expect to see 1 node list, any number of cache gets, and however many @@ -93,19 +94,20 @@ func Test_UnitMigrateFileNodes(t *testing.T) { nodePasswordFile := generateNodePasswordFile(migrateNumNodes) defer os.Remove(nodePasswordFile) - ctrl := gomock.NewController(t) + v1Mock := mock.NewV1(gomock.NewController(t)) - secretClient := fake.NewMockControllerInterface[*v1.Secret, *v1.SecretList](ctrl) - secretCache := fake.NewMockCacheInterface[*v1.Secret](ctrl) - secretStore := &mockSecretStore{} + secretClient := v1Mock.SecretMock + secretCache := v1Mock.SecretCache + secretStore := &mock.SecretStore{} - nodeClient := fake.NewMockNonNamespacedControllerInterface[*v1.Node, *v1.NodeList](ctrl) - nodeCache := fake.NewMockNonNamespacedCacheInterface[*v1.Node](ctrl) - nodeStore := &mockNodeStore{} + nodeClient := v1Mock.NodeMock + nodeCache := v1Mock.NodeCache + nodeStore := &mock.NodeStore{} - nodeStore.nodes = make([]v1.Node, createNumNodes, createNumNodes) - for i := range nodeStore.nodes { - nodeStore.nodes[i].Name = fmt.Sprintf("node%d", i+1) + for i := 0; i < createNumNodes; i++ { + if _, err := nodeStore.Create(&v1.Node{ObjectMeta: metav1.ObjectMeta{Name: fmt.Sprintf("node%d", i+1)}}); err != nil { + t.Fatal(err) + } } // Set up expected call counts for tests @@ -124,9 +126,13 @@ func Test_UnitMigrateFileNodes(t *testing.T) { } logMemUsage(t) - for _, node := range nodeStore.nodes { - assertNotEqual(t, Ensure(secretClient, node.Name, "wrong-password"), nil) - assertEqual(t, Ensure(secretClient, node.Name, node.Name), nil) + if nodes, err := nodeStore.List(labels.Everything()); err != nil { + t.Fatal(err) + } else { + for _, node := range nodes { + assertNotEqual(t, Ensure(secretClient, node.Name, "wrong-password"), nil) + assertEqual(t, Ensure(secretClient, node.Name, node.Name), nil) + } } newNode := fmt.Sprintf("node%d", migrateNumNodes+1) @@ -141,65 +147,6 @@ func Test_PasswordError(t *testing.T) { assertNotEqual(t, errors.Unwrap(err), nil) } -// -------------------------- -// mock secret store interface - -type mockSecretStore struct { - entries map[string]map[string]v1.Secret -} - -func (m *mockSecretStore) Create(secret *v1.Secret) (*v1.Secret, error) { - if m.entries == nil { - m.entries = map[string]map[string]v1.Secret{} - } - if _, ok := m.entries[secret.Namespace]; !ok { - m.entries[secret.Namespace] = map[string]v1.Secret{} - } - if _, ok := m.entries[secret.Namespace][secret.Name]; ok { - return nil, errorAlreadyExists() - } - m.entries[secret.Namespace][secret.Name] = *secret - return secret, nil -} - -func (m *mockSecretStore) Delete(namespace, name string, options *metav1.DeleteOptions) error { - if m.entries == nil { - return errorNotFound() - } - if _, ok := m.entries[namespace]; !ok { - return errorNotFound() - } - if _, ok := m.entries[namespace][name]; !ok { - return errorNotFound() - } - delete(m.entries[namespace], name) - return nil -} - -func (m *mockSecretStore) Get(namespace, name string) (*v1.Secret, error) { - if m.entries == nil { - return nil, errorNotFound() - } - if _, ok := m.entries[namespace]; !ok { - return nil, errorNotFound() - } - if secret, ok := m.entries[namespace][name]; ok { - return &secret, nil - } - return nil, errorNotFound() -} - -// -------------------------- -// mock node store interface - -type mockNodeStore struct { - nodes []v1.Node -} - -func (m *mockNodeStore) List(ls labels.Selector) ([]v1.Node, error) { - return m.nodes, nil -} - // -------------------------- // utility functions diff --git a/tests/mock/core.go b/tests/mock/core.go index b4ab80080927..7664b657f6a0 100644 --- a/tests/mock/core.go +++ b/tests/mock/core.go @@ -7,6 +7,8 @@ import ( "github.com/rancher/wrangler/v3/pkg/generic/fake" v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/runtime/schema" ) @@ -35,32 +37,54 @@ func (m *CoreMock) V1() corev1.Interface { var _ corev1.Interface = &V1Mock{} type V1Mock struct { - ConfigMapMock *fake.MockControllerInterface[*v1.ConfigMap, *v1.ConfigMapList] - EndpointsMock *fake.MockControllerInterface[*v1.Endpoints, *v1.EndpointsList] - EventMock *fake.MockControllerInterface[*v1.Event, *v1.EventList] - NamespaceMock *fake.MockNonNamespacedControllerInterface[*v1.Namespace, *v1.NamespaceList] - NodeMock *fake.MockNonNamespacedControllerInterface[*v1.Node, *v1.NodeList] - PersistentVolumeMock *fake.MockNonNamespacedControllerInterface[*v1.PersistentVolume, *v1.PersistentVolumeList] - PersistentVolumeClaimMock *fake.MockControllerInterface[*v1.PersistentVolumeClaim, *v1.PersistentVolumeClaimList] - PodMock *fake.MockControllerInterface[*v1.Pod, *v1.PodList] - SecretMock *fake.MockControllerInterface[*v1.Secret, *v1.SecretList] - ServiceMock *fake.MockControllerInterface[*v1.Service, *v1.ServiceList] - ServiceAccountMock *fake.MockControllerInterface[*v1.ServiceAccount, *v1.ServiceAccountList] + ConfigMapMock *fake.MockControllerInterface[*v1.ConfigMap, *v1.ConfigMapList] + ConfigMapCache *fake.MockCacheInterface[*v1.ConfigMap] + EndpointsMock *fake.MockControllerInterface[*v1.Endpoints, *v1.EndpointsList] + EndpointsCache *fake.MockCacheInterface[*v1.Endpoints] + EventMock *fake.MockControllerInterface[*v1.Event, *v1.EventList] + EventCache *fake.MockCacheInterface[*v1.Event] + NamespaceMock *fake.MockNonNamespacedControllerInterface[*v1.Namespace, *v1.NamespaceList] + NamespaceCache *fake.MockNonNamespacedCacheInterface[*v1.Namespace] + NodeMock *fake.MockNonNamespacedControllerInterface[*v1.Node, *v1.NodeList] + NodeCache *fake.MockNonNamespacedCacheInterface[*v1.Node] + PersistentVolumeMock *fake.MockNonNamespacedControllerInterface[*v1.PersistentVolume, *v1.PersistentVolumeList] + PersistentVolumeCache *fake.MockNonNamespacedCacheInterface[*v1.PersistentVolume] + PersistentVolumeClaimMock *fake.MockControllerInterface[*v1.PersistentVolumeClaim, *v1.PersistentVolumeClaimList] + PersistentVolumeClaimCache *fake.MockCacheInterface[*v1.PersistentVolumeClaim] + PodMock *fake.MockControllerInterface[*v1.Pod, *v1.PodList] + PodCache *fake.MockCacheInterface[*v1.Pod] + SecretMock *fake.MockControllerInterface[*v1.Secret, *v1.SecretList] + SecretCache *fake.MockCacheInterface[*v1.Secret] + ServiceMock *fake.MockControllerInterface[*v1.Service, *v1.ServiceList] + ServiceCache *fake.MockCacheInterface[*v1.Service] + ServiceAccountMock *fake.MockControllerInterface[*v1.ServiceAccount, *v1.ServiceAccountList] + ServiceAccountCache *fake.MockCacheInterface[*v1.ServiceAccount] } func NewV1(c *gomock.Controller) *V1Mock { return &V1Mock{ - ConfigMapMock: fake.NewMockControllerInterface[*v1.ConfigMap, *v1.ConfigMapList](c), - EndpointsMock: fake.NewMockControllerInterface[*v1.Endpoints, *v1.EndpointsList](c), - EventMock: fake.NewMockControllerInterface[*v1.Event, *v1.EventList](c), - NamespaceMock: fake.NewMockNonNamespacedControllerInterface[*v1.Namespace, *v1.NamespaceList](c), - NodeMock: fake.NewMockNonNamespacedControllerInterface[*v1.Node, *v1.NodeList](c), - PersistentVolumeMock: fake.NewMockNonNamespacedControllerInterface[*v1.PersistentVolume, *v1.PersistentVolumeList](c), - PersistentVolumeClaimMock: fake.NewMockControllerInterface[*v1.PersistentVolumeClaim, *v1.PersistentVolumeClaimList](c), - PodMock: fake.NewMockControllerInterface[*v1.Pod, *v1.PodList](c), - SecretMock: fake.NewMockControllerInterface[*v1.Secret, *v1.SecretList](c), - ServiceMock: fake.NewMockControllerInterface[*v1.Service, *v1.ServiceList](c), - ServiceAccountMock: fake.NewMockControllerInterface[*v1.ServiceAccount, *v1.ServiceAccountList](c), + ConfigMapMock: fake.NewMockControllerInterface[*v1.ConfigMap, *v1.ConfigMapList](c), + ConfigMapCache: fake.NewMockCacheInterface[*v1.ConfigMap](c), + EndpointsMock: fake.NewMockControllerInterface[*v1.Endpoints, *v1.EndpointsList](c), + EndpointsCache: fake.NewMockCacheInterface[*v1.Endpoints](c), + EventMock: fake.NewMockControllerInterface[*v1.Event, *v1.EventList](c), + EventCache: fake.NewMockCacheInterface[*v1.Event](c), + NamespaceMock: fake.NewMockNonNamespacedControllerInterface[*v1.Namespace, *v1.NamespaceList](c), + NamespaceCache: fake.NewMockNonNamespacedCacheInterface[*v1.Namespace](c), + NodeMock: fake.NewMockNonNamespacedControllerInterface[*v1.Node, *v1.NodeList](c), + NodeCache: fake.NewMockNonNamespacedCacheInterface[*v1.Node](c), + PersistentVolumeMock: fake.NewMockNonNamespacedControllerInterface[*v1.PersistentVolume, *v1.PersistentVolumeList](c), + PersistentVolumeCache: fake.NewMockNonNamespacedCacheInterface[*v1.PersistentVolume](c), + PersistentVolumeClaimMock: fake.NewMockControllerInterface[*v1.PersistentVolumeClaim, *v1.PersistentVolumeClaimList](c), + PersistentVolumeClaimCache: fake.NewMockCacheInterface[*v1.PersistentVolumeClaim](c), + PodMock: fake.NewMockControllerInterface[*v1.Pod, *v1.PodList](c), + PodCache: fake.NewMockCacheInterface[*v1.Pod](c), + SecretMock: fake.NewMockControllerInterface[*v1.Secret, *v1.SecretList](c), + SecretCache: fake.NewMockCacheInterface[*v1.Secret](c), + ServiceMock: fake.NewMockControllerInterface[*v1.Service, *v1.ServiceList](c), + ServiceCache: fake.NewMockCacheInterface[*v1.Service](c), + ServiceAccountMock: fake.NewMockControllerInterface[*v1.ServiceAccount, *v1.ServiceAccountList](c), + ServiceAccountCache: fake.NewMockCacheInterface[*v1.ServiceAccount](c), } } @@ -108,6 +132,89 @@ func (m *V1Mock) ServiceAccount() corev1.ServiceAccountController { return m.ServiceAccountMock } +// mock secret store interface + +type SecretStore struct { + secrets map[string]map[string]v1.Secret +} + +func (m *SecretStore) Create(secret *v1.Secret) (*v1.Secret, error) { + if m.secrets == nil { + m.secrets = map[string]map[string]v1.Secret{} + } + if _, ok := m.secrets[secret.Namespace]; !ok { + m.secrets[secret.Namespace] = map[string]v1.Secret{} + } + if _, ok := m.secrets[secret.Namespace][secret.Name]; ok { + return nil, ErrorAlreadyExists("secret", secret.Name) + } + m.secrets[secret.Namespace][secret.Name] = *secret + return secret, nil +} + +func (m *SecretStore) Delete(namespace, name string, options *metav1.DeleteOptions) error { + if m.secrets == nil { + return ErrorNotFound("secret", name) + } + if _, ok := m.secrets[namespace]; !ok { + return ErrorNotFound("secret", name) + } + if _, ok := m.secrets[namespace][name]; !ok { + return ErrorNotFound("secret", name) + } + delete(m.secrets[namespace], name) + return nil +} + +func (m *SecretStore) Get(namespace, name string) (*v1.Secret, error) { + if m.secrets == nil { + return nil, ErrorNotFound("secret", name) + } + if _, ok := m.secrets[namespace]; !ok { + return nil, ErrorNotFound("secret", name) + } + if secret, ok := m.secrets[namespace][name]; ok { + return &secret, nil + } + return nil, ErrorNotFound("secret", name) +} + +// mock node store interface + +type NodeStore struct { + nodes map[string]v1.Node +} + +func (m *NodeStore) Create(node *v1.Node) (*v1.Node, error) { + if m.nodes == nil { + m.nodes = map[string]v1.Node{} + } + if _, ok := m.nodes[node.Name]; ok { + return nil, ErrorAlreadyExists("node", node.Name) + } + m.nodes[node.Name] = *node + return node, nil +} + +func (m *NodeStore) List(ls labels.Selector) ([]v1.Node, error) { + nodes := []v1.Node{} + if ls == nil { + ls = labels.Everything() + } + for _, node := range m.nodes { + if ls.Matches(labels.Set(node.Labels)) { + nodes = append(nodes, node) + } + } + return nodes, nil +} + +// utility functions + func ErrorNotFound(gv, name string) error { return apierrors.NewNotFound(schema.ParseGroupResource(gv), name) } + +func ErrorAlreadyExists(gv, name string) error { + return apierrors.NewAlreadyExists(schema.ParseGroupResource(gv), name) +}