Skip to content

Commit

Permalink
Example mocked envtest
Browse files Browse the repository at this point in the history
  • Loading branch information
mdbooth authored and stephenfin committed Jul 1, 2022
1 parent b2ded6f commit 5f68052
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 45 deletions.
78 changes: 34 additions & 44 deletions controllers/openstackcluster_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ import (
"context"
"fmt"

"github.com/golang/mock/gomock"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -32,6 +35,9 @@ import (
"sigs.k8s.io/controller-runtime/pkg/reconcile"

infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients"
mock_clients "sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mocks"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/scope"
)

var (
Expand Down Expand Up @@ -165,51 +171,35 @@ var _ = Describe("OpenStackCluster controller", func() {
Expect(err).ToNot(BeNil())
Expect(result).To(Equal(reconcile.Result{}))
})
It("should be able to reconcile when basition disabled", func() {
mockCtrl := gomock.NewController(GinkgoT())
computeClient := mock_clients.NewMockComputeClient(mockCtrl)
networkClient := mock_clients.NewMockNetworkClient(mockCtrl)
loadBalancerClient := mock_clients.NewMockLoadBalancerClient(mockCtrl)

scope := scope.NewMockScopeFactory(computeClient, networkClient, loadBalancerClient)

computeClientRecorder := computeClient.EXPECT()
computeClientRecorder.ListServers(servers.ListOpts{
Name: "^capi-cluster-bastion$",
}).Return([]clients.ServerExt{}, nil)

networkClientRecorder := networkClient.EXPECT()
networkClientRecorder.ListSecGroup(gomock.Any()).Return([]groups.SecGroup{}, nil)

testCluster.SetName("no-bastion")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
Enabled: false,
},
}
err := k8sClient.Create(ctx, testCluster)
Expect(err).To(BeNil())
err = k8sClient.Create(ctx, capiCluster)
Expect(err).To(BeNil())

// TODO: This test is set to pending (PIt instead of It) since it is not working.
PIt("should be able to reconcile when basition disabled", func() {
// verify := false
// cloud := clientconfig.Cloud{
// Cloud: "test",
// RegionName: "test",
// Verify: &verify,
// AuthInfo: &clientconfig.AuthInfo{
// AuthURL: "https://example.com:5000",
// Username: "testuser",
// Password: "secret",
// ProjectName: "test",
// DomainName: "test",
// UserDomainName: "test",
// },
// }
// // TODO: Can we fake the client in some way?
// providerClient, clientOpts, _, err := provider.NewClient(cloud, nil)
// Expect(err).To(BeNil())
// scope := &scope.Scope{
// ProviderClient: providerClient,
// ProviderClientOpts: clientOpts,
// }

// TODO: This won't work without filling in proper values.
/*
scope := &scope.Scope{
ProviderClient: &gophercloud.ProviderClient{},
ProviderClientOpts: &clientconfig.ClientOpts{},
}
testCluster.SetName("no-bastion")
testCluster.Spec = infrav1.OpenStackClusterSpec{
Bastion: &infrav1.Bastion{
Enabled: false,
},
}
err := k8sClient.Create(ctx, testCluster)
Expect(err).To(BeNil())
err = k8sClient.Create(ctx, capiCluster)
Expect(err).To(BeNil())
err = deleteBastion(scope, capiCluster, testCluster)
Expect(err).To(BeNil())
*/
err = deleteBastion(scope, capiCluster, testCluster)
Expect(err).To(BeNil())
})
})

Expand Down
69 changes: 69 additions & 0 deletions pkg/scope/mock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
Copyright 2022 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package scope

import (
"context"

"github.com/go-logr/logr"
"sigs.k8s.io/controller-runtime/pkg/client"

infrav1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1alpha6"
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients"
mock_clients "sigs.k8s.io/cluster-api-provider-openstack/pkg/clients/mocks"
)

// MockScopeFactory implements both the ScopeFactory and ClientScope interfaces. It can be used in place of the default ProviderScopeFactory
// when we want to use mocked service clients which do not attempt to connect to a running OpenStack cloud.
type MockScopeFactory struct {
ComputeClient *mock_clients.MockComputeClient
NetworkClient *mock_clients.MockNetworkClient
LoadBalancerClient *mock_clients.MockLoadBalancerClient
baseScope
}

func NewMockScopeFactory(computeClient *mock_clients.MockComputeClient, networkClient *mock_clients.MockNetworkClient, loadBalancerClient *mock_clients.MockLoadBalancerClient) *MockScopeFactory {
return &MockScopeFactory{
ComputeClient: computeClient,
NetworkClient: networkClient,
LoadBalancerClient: loadBalancerClient,
baseScope: baseScope{
projectID: "",
logger: logr.Discard(),
},
}
}

func (f *MockScopeFactory) NewClientScopeFromMachine(ctx context.Context, ctrlClient client.Client, openStackMachine *infrav1.OpenStackMachine, logger logr.Logger) (ClientScope, error) {
return f, nil
}

func (f *MockScopeFactory) NewClientScopeFromCluster(ctx context.Context, ctrlClient client.Client, openStackCluster *infrav1.OpenStackCluster, logger logr.Logger) (ClientScope, error) {
return f, nil
}

func (f *MockScopeFactory) NewComputeClient() (clients.ComputeClient, error) {
return f.ComputeClient, nil
}

func (f *MockScopeFactory) NewNetworkClient() (clients.NetworkClient, error) {
return f.NetworkClient, nil
}

func (f *MockScopeFactory) NewLoadBalancerClient() (clients.LoadBalancerClient, error) {
return f.LoadBalancerClient, nil
}
1 change: 1 addition & 0 deletions pkg/scope/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ const (
caSecretKey = "cacert"
)

// ProviderScopeFactory is the default scope factory. It generates service clients which make OpenStack API calls against a running cloud.
var ProviderScopeFactory Factory = providerScopeFactory{}

type providerScopeFactory struct{}
Expand Down
4 changes: 3 additions & 1 deletion pkg/scope/scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,21 @@ import (
"sigs.k8s.io/cluster-api-provider-openstack/pkg/clients"
)

// Factory instantiates a new ClientScope using credentials from either a cluster or a machine.
type Factory interface {
NewClientScopeFromMachine(ctx context.Context, ctrlClient client.Client, openStackMachine *infrav1.OpenStackMachine, logger logr.Logger) (ClientScope, error)
NewClientScopeFromCluster(ctx context.Context, ctrlClient client.Client, openStackCluster *infrav1.OpenStackCluster, logger logr.Logger) (ClientScope, error)
}

// ClientScope is a Scope that can also be used to create service clients.
type ClientScope interface {
NewComputeClient() (clients.ComputeClient, error)
NewNetworkClient() (clients.NetworkClient, error)
NewLoadBalancerClient() (clients.LoadBalancerClient, error)
Scope
}

// Scope is used to initialize Services from Controllers.
// Scope contains arguments common to most operations.
type Scope interface {
Logger() logr.Logger
ProjectID() string
Expand Down

0 comments on commit 5f68052

Please sign in to comment.