Skip to content

all: Accept ServiceClient as an interface#3203

Closed
pierreprinetti wants to merge 2 commits intogophercloud:mainfrom
shiftstack:service_client_interface
Closed

all: Accept ServiceClient as an interface#3203
pierreprinetti wants to merge 2 commits intogophercloud:mainfrom
shiftstack:service_client_interface

Conversation

@pierreprinetti
Copy link
Copy Markdown
Member

Allow client libraries to modify the behaviour of ServiceClient or mock calls to the OpenStack API.

This change is targeted at v3.

@github-actions github-actions bot added edit:networking This PR updates networking code edit:dns This PR updates dns code edit:common This PR updates common code edit:image This PR updates image code edit:orchestration This PR updates orchestration code edit:db This PR updates db code edit:loadbalancer This PR updates loadbalancer code edit:compute This PR updates compute code edit:keymanager This PR updates keymanager code edit:utils This PR updates utils code edit:messaging This PR updates messaging code edit:containerinfra This PR updates containerinfra code edit:placement This PR updates placement code edit:objectstorage This PR updates objectstorage code edit:workflow This PR updates workflow code edit:sharedfilesystems This PR updates sharedfilesystems code edit:baremetal This PR updates baremetal code edit:gophercloud This PR updates common Gophercloud code edit:blockstorage This PR updates blockstorage code edit:identity This PR updates identity code edit:container This PR updates container code edit:baremetalintrospection This PR updates baremetalintrospection code semver:major Breaking change labels Oct 7, 2024
@pierreprinetti pierreprinetti force-pushed the service_client_interface branch from 879e4c8 to d7a0053 Compare October 9, 2024 11:25
@mdbooth
Copy link
Copy Markdown
Contributor

mdbooth commented Oct 9, 2024

How do you see client code using this?

Here's an example of how we're using mocks in CAPO: https://github.com/kubernetes-sigs/cluster-api-provider-openstack/blob/852272197ad100fecd9cc7e95a77e88897812520/pkg/cloud/services/compute/instance_test.go#L82-L96

		{
			testName: "Return image ID when name given",
			image: infrav1.ImageParam{
				Filter: &infrav1.ImageFilter{
					Name: ptr.To(imageName),
				},
			},
			want: ptr.To(imageID),
			expect: func(m *mock.MockImageClientMockRecorder) {
				m.ListImages(images.ListOpts{Name: imageName}).Return(
					[]images.Image{{ID: imageID, Name: imageName}},
					nil)
			},
			wantErr: false,
		},

ListImages is defined here: https://github.com/kubernetes-sigs/cluster-api-provider-openstack/blob/852272197ad100fecd9cc7e95a77e88897812520/pkg/clients/image.go#L59-L66. It's just a mockable wrapper round gophercloud's images.List (plus some prometheus stuff which is probably a waste of time).

With my 'gophercloud library user' hat on, what I'm trying to achieve here is:

  • I am asserting that we must call images.List with some arguments that I can match in flexible ways
  • I am providing the return value of this call

I like that I can use gophercloud structs here. I'm asserting that the call uses an images.ListOpts, and I'm defining the return in terms of gophercloud images.Image objects. As a gophercloud library user, this is the level I want to interact with OpenStack at.

I could theoretically use the ServiceClient interface to mock my OpenStack calls, but this would take the gophercloud abstractions away from me. I would have to define my expected behaviours in terms of HTTP and raw json.

I can imagine that we could fairly easily add a 'recording' mock ServiceClient interface which we create in the tests. My test might have a 'record' phase something like:

mockServiceClient := MyMockServiceClient()
images.List(mockServiceClient ,images.ListOpts{Name: imageName})
... something with pages? ...

I can imagine that MyMockServiceClient could record any resulting invocation, however complicated, which could be used later in the 'execute' phase of the test. I can't immediately think of a good way to use an interface like this to provide a return value, though. The return value I'm interested in is []images.Image. How can I make mockServiceClient return data that will be marshalled correctly into the []images.Image I need for this test case?

Have gophercloud.ServiceClient expose and EndpointURL method so that it
can be used as a gophercloud.Client.
Allow client libraries to modify the behaviour of ServiceClient or mock
calls to the OpenStack API.
@pierreprinetti pierreprinetti force-pushed the service_client_interface branch from d7a0053 to c44b16b Compare December 6, 2024 16:12
@pierreprinetti
Copy link
Copy Markdown
Member Author

Let's park this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

edit:baremetal This PR updates baremetal code edit:baremetalintrospection This PR updates baremetalintrospection code edit:blockstorage This PR updates blockstorage code edit:common This PR updates common code edit:compute This PR updates compute code edit:container This PR updates container code edit:containerinfra This PR updates containerinfra code edit:db This PR updates db code edit:dns This PR updates dns code edit:gophercloud This PR updates common Gophercloud code edit:identity This PR updates identity code edit:image This PR updates image code edit:keymanager This PR updates keymanager code edit:loadbalancer This PR updates loadbalancer code edit:messaging This PR updates messaging code edit:networking This PR updates networking code edit:objectstorage This PR updates objectstorage code edit:orchestration This PR updates orchestration code edit:placement This PR updates placement code edit:sharedfilesystems This PR updates sharedfilesystems code edit:utils This PR updates utils code edit:workflow This PR updates workflow code semver:major Breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants