Skip to content

Commit 6e3e164

Browse files
Merge pull request #139 from shiftstack/merge-bot-master
Merge https://github.com/kubernetes/cloud-provider-openstack:master into master
2 parents d067cf2 + f2f058c commit 6e3e164

File tree

9 files changed

+91
-44
lines changed

9 files changed

+91
-44
lines changed

docs/developers-guide.md

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,48 @@ If you are ready for code contribution, you need to have development environment
5858
1. IDE. You can choose any IDE that supports Golang, e.g. Visual Studio Code, GoLand, etc.
5959
1. Install [Docker Engine](https://docs.docker.com/engine/install/) or other tools that could build container images such as [podman](https://podman.io/). After writing the code, the best way to test openstack-cloud-controller-manager is to replace the container image specified in its Deployment/StatefulSet/DaemonSet manifest in the kubernetes cluster. We are using docker in this guide.
6060

61+
### Testing
62+
63+
*cloud-provider-openstack* includes a number of different types of test. As is usual for Kubernetes projects, jobs definitions live in the [test-infra](https://github.com/kubernetes/test-infra/tree/master/config/jobs/kubernetes/cloud-provider-openstack) project. A variety of tests run on each PR, however, you can also run your tests locally.
64+
65+
### Unit tests
66+
67+
Unit tests require a go environment with a suitable go version, as noted previously. Assuming you have this, you can run unit tests using the `unit` Makefile target.
68+
69+
```
70+
make unit
71+
```
72+
73+
### E2E tests
74+
75+
End-to-end or _e2e_ tests are more complex to run as they require a functioning OpenStack cloud and Kubernetes (well, k3s) deployment. Fortunately, you can rely on the infrastructure used for CI to run this on your own machines.
76+
77+
For example, to run the Cinder CSI e2e tests, the CI calls the `tests/ci-csi-cinder-e2e.sh` script. Inspecting this, you'll note that a lot of the commands in here are simply provisioning an instance on GCE, using [Boskos](https://github.com/kubernetes-sigs/boskos) to manage static resources (projects, in this case) if needed. If you have a set of GCE credentials, then in theory you could run this script as-is. However, all you need is a VM with sufficient resources and network connectivity running the correct image (Ubuntu 20.04 cloud image as of writing - check `tests/scripts/create-gce-vm.sh` for the latest info). For example, using OpenStack:
78+
79+
```
80+
openstack server create \
81+
--image ubuntu2004 \
82+
--flavor m1.large \
83+
--key-name <key-name> \
84+
--network <network> \
85+
--wait \
86+
${USER}-csi-cinder-e2e-tests
87+
openstack server add floating ip <server> <ip-address>
88+
```
89+
90+
Once done, you can run the same Ansible commands seen in `tests/ci-csi-cinder-e2e.sh`:
91+
92+
```
93+
ansible-playbook \
94+
-v \
95+
--user ubuntu \
96+
--inventory 10.0.110.127, \
97+
--ssh-common-args "-o StrictHostKeyChecking=no" \
98+
tests/playbooks/test-csi-cinder-e2e.yaml
99+
```
100+
101+
As you can see, this whole area needs improvement to make this a little more approachable for non-CI use cases. This should be enough direction to get started though.
102+
61103
### Build openstack-cloud-controller-manager image
62104
In cloud-provider-openstack repo directory, run:
63105

@@ -96,7 +138,7 @@ IMAGE_NAMES=openstack-cloud-controller-manager \
96138
make upload-image-amd64
97139
```
98140

99-
Now, you can change openstack-cloud-controller-manager image in the kubernetes cluster, assuming the openstack-cloud-controller-manager is running as a DaemonSet:
141+
Now you can change openstack-cloud-controller-manager image in the kubernetes cluster, assuming the openstack-cloud-controller-manager is running as a DaemonSet:
100142

101143
```
102144
kubectl -n kube-system set image \

pkg/ingress/controller/controller.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ import (
5757
"k8s.io/cloud-provider-openstack/pkg/ingress/config"
5858
"k8s.io/cloud-provider-openstack/pkg/ingress/controller/openstack"
5959
"k8s.io/cloud-provider-openstack/pkg/ingress/utils"
60+
cpoerrors "k8s.io/cloud-provider-openstack/pkg/util/errors"
6061
openstackutil "k8s.io/cloud-provider-openstack/pkg/util/openstack"
6162
)
6263

@@ -456,7 +457,7 @@ func (c *Controller) nodeSyncLoop() {
456457
lbName := utils.GetResourceName(ing.Namespace, ing.Name, c.config.ClusterName)
457458
loadbalancer, err := openstackutil.GetLoadbalancerByName(c.osClient.Octavia, lbName)
458459
if err != nil {
459-
if err != openstackutil.ErrNotFound {
460+
if err != cpoerrors.ErrNotFound {
460461
log.WithFields(log.Fields{"name": lbName}).Errorf("Failed to retrieve loadbalancer from OpenStack: %v", err)
461462
}
462463

@@ -564,7 +565,7 @@ func (c *Controller) deleteIngress(ing *nwv1.Ingress) error {
564565
// If load balancer doesn't exist, assume it's already deleted.
565566
loadbalancer, err := openstackutil.GetLoadbalancerByName(c.osClient.Octavia, lbName)
566567
if err != nil {
567-
if err != openstackutil.ErrNotFound {
568+
if err != cpoerrors.ErrNotFound {
568569
return fmt.Errorf("error getting loadbalancer %s: %v", ing.Name, err)
569570
}
570571

pkg/ingress/controller/openstack/octavia.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ func (os *OpenStack) EnsureLoadBalancer(name string, subnetID string, ingNamespa
287287

288288
loadbalancer, err := openstackutil.GetLoadbalancerByName(os.Octavia, name)
289289
if err != nil {
290-
if err != openstackutil.ErrNotFound {
290+
if err != cpoerrors.ErrNotFound {
291291
return nil, fmt.Errorf("error getting loadbalancer %s: %v", name, err)
292292
}
293293

@@ -339,7 +339,7 @@ func (os *OpenStack) UpdateLoadBalancerDescription(lbID string, newDescription s
339339
func (os *OpenStack) EnsureListener(name string, lbID string, secretRefs []string, listenerAllowedCIDRs []string) (*listeners.Listener, error) {
340340
listener, err := openstackutil.GetListenerByName(os.Octavia, name, lbID)
341341
if err != nil {
342-
if err != openstackutil.ErrNotFound {
342+
if err != cpoerrors.ErrNotFound {
343343
return nil, fmt.Errorf("error getting listener %s: %v", name, err)
344344
}
345345

@@ -394,7 +394,7 @@ func (os *OpenStack) EnsurePoolMembers(deleted bool, poolName string, lbID strin
394394
if deleted {
395395
pool, err := openstackutil.GetPoolByName(os.Octavia, poolName, lbID)
396396
if err != nil {
397-
if err != openstackutil.ErrNotFound {
397+
if err != cpoerrors.ErrNotFound {
398398
return nil, fmt.Errorf("error getting pool %s: %v", poolName, err)
399399
}
400400
return nil, nil
@@ -416,7 +416,7 @@ func (os *OpenStack) EnsurePoolMembers(deleted bool, poolName string, lbID strin
416416

417417
pool, err := openstackutil.GetPoolByName(os.Octavia, poolName, lbID)
418418
if err != nil {
419-
if err != openstackutil.ErrNotFound {
419+
if err != cpoerrors.ErrNotFound {
420420
return nil, fmt.Errorf("error getting pool %s: %v", poolName, err)
421421
}
422422

pkg/openstack/loadbalancer.go

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -984,7 +984,7 @@ func (lbaas *LbaasV2) deleteListeners(lbID string, listenerList []listeners.List
984984
klog.InfoS("Deleting listener", "listenerID", listener.ID, "lbID", lbID)
985985

986986
pool, err := openstackutil.GetPoolByListener(lbaas.lb, lbID, listener.ID)
987-
if err != nil && err != openstackutil.ErrNotFound {
987+
if err != nil && err != cpoerrors.ErrNotFound {
988988
return fmt.Errorf("error getting pool for obsolete listener %s: %v", listener.ID, err)
989989
}
990990
if pool != nil {
@@ -1013,7 +1013,7 @@ func (lbaas *LbaasV2) deleteOctaviaListeners(lbID string, listenerList []listene
10131013
klog.InfoS("Deleting listener", "listenerID", listener.ID, "lbID", lbID)
10141014

10151015
pool, err := openstackutil.GetPoolByListener(lbaas.lb, lbID, listener.ID)
1016-
if err != nil && err != openstackutil.ErrNotFound {
1016+
if err != nil && err != cpoerrors.ErrNotFound {
10171017
return fmt.Errorf("error getting pool for listener %s: %v", listener.ID, err)
10181018
}
10191019
if pool != nil {
@@ -1243,7 +1243,7 @@ func (lbaas *LbaasV2) buildMonitorCreateOpts(svcConf *serviceConfig, port corev1
12431243
// Make sure the pool is created for the Service, nodes are added as pool members.
12441244
func (lbaas *LbaasV2) ensureOctaviaPool(lbID string, name string, listener *listeners.Listener, service *corev1.Service, port corev1.ServicePort, nodes []*corev1.Node, svcConf *serviceConfig) (*v2pools.Pool, error) {
12451245
pool, err := openstackutil.GetPoolByListener(lbaas.lb, lbID, listener.ID)
1246-
if err != nil && err != openstackutil.ErrNotFound {
1246+
if err != nil && err != cpoerrors.ErrNotFound {
12471247
return nil, fmt.Errorf("error getting pool for listener %s: %v", listener.ID, err)
12481248
}
12491249

@@ -1285,7 +1285,7 @@ func (lbaas *LbaasV2) ensureOctaviaPool(lbID string, name string, listener *list
12851285
klog.Errorf("failed to get members in the pool %s: %v", pool.ID, err)
12861286
}
12871287
for _, m := range poolMembers {
1288-
curMembers.Insert(fmt.Sprintf("%s-%d-%d", m.Address, m.ProtocolPort, m.MonitorPort))
1288+
curMembers.Insert(fmt.Sprintf("%s-%s-%d-%d", m.Name, m.Address, m.ProtocolPort, m.MonitorPort))
12891289
}
12901290

12911291
members, newMembers, err := lbaas.buildBatchUpdateMemberOpts(port, nodes, svcConf)
@@ -1364,7 +1364,7 @@ func (lbaas *LbaasV2) buildBatchUpdateMemberOpts(port corev1.ServicePort, nodes
13641364
member.MonitorPort = &svcConf.healthCheckNodePort
13651365
}
13661366
members = append(members, member)
1367-
newMembers.Insert(fmt.Sprintf("%s-%d-%d", addr, member.ProtocolPort, svcConf.healthCheckNodePort))
1367+
newMembers.Insert(fmt.Sprintf("%s-%s-%d-%d", node.Name, addr, member.ProtocolPort, svcConf.healthCheckNodePort))
13681368
}
13691369
return members, newMembers, nil
13701370
}
@@ -2344,7 +2344,7 @@ func (lbaas *LbaasV2) ensureLoadBalancer(ctx context.Context, clusterName string
23442344
oldListeners = popListener(oldListeners, listener.ID)
23452345

23462346
pool, err := openstackutil.GetPoolByListener(lbaas.lb, loadbalancer.ID, listener.ID)
2347-
if err != nil && err != openstackutil.ErrNotFound {
2347+
if err != nil && err != cpoerrors.ErrNotFound {
23482348
return nil, fmt.Errorf("error getting pool for listener %s: %v", listener.ID, err)
23492349
}
23502350
if pool == nil {
@@ -2460,7 +2460,7 @@ func (lbaas *LbaasV2) ensureLoadBalancer(ctx context.Context, clusterName string
24602460
klog.V(4).Infof("Deleting obsolete listener %s:", listener.ID)
24612461
// get pool for listener
24622462
pool, err := openstackutil.GetPoolByListener(lbaas.lb, loadbalancer.ID, listener.ID)
2463-
if err != nil && err != openstackutil.ErrNotFound {
2463+
if err != nil && err != cpoerrors.ErrNotFound {
24642464
return nil, fmt.Errorf("error getting pool for obsolete listener %s: %v", listener.ID, err)
24652465
}
24662466
if pool != nil {
@@ -3366,7 +3366,7 @@ func (lbaas *LbaasV2) ensureLoadBalancerDeletedLegacy(loadbalancer *loadbalancer
33663366
var monitorIDs []string
33673367
for _, listener := range listenerList {
33683368
pool, err := openstackutil.GetPoolByListener(lbaas.lb, loadbalancer.ID, listener.ID)
3369-
if err != nil && err != openstackutil.ErrNotFound {
3369+
if err != nil && err != cpoerrors.ErrNotFound {
33703370
return fmt.Errorf("error getting pool for listener %s: %v", listener.ID, err)
33713371
}
33723372
if pool != nil {
@@ -3416,7 +3416,7 @@ func (lbaas *LbaasV2) ensureLoadBalancerDeleted(ctx context.Context, clusterName
34163416
// This may happen when this Service creation was failed previously.
34173417
loadbalancer, err = getLoadbalancerByName(lbaas.lb, lbName, legacyName)
34183418
}
3419-
if err != nil && err != cpoerrors.ErrNotFound {
3419+
if err != nil && !cpoerrors.IsNotFound(err) {
34203420
return err
34213421
}
34223422
if loadbalancer == nil {
@@ -3522,7 +3522,7 @@ func (lbaas *LbaasV2) ensureLoadBalancerDeleted(ctx context.Context, clusterName
35223522
var monitorIDs []string
35233523
for _, listener := range listenerList {
35243524
pool, err := openstackutil.GetPoolByListener(lbaas.lb, loadbalancer.ID, listener.ID)
3525-
if err != nil && err != openstackutil.ErrNotFound {
3525+
if err != nil && err != cpoerrors.ErrNotFound {
35263526
return fmt.Errorf("error getting pool for listener %s: %v", listener.ID, err)
35273527
}
35283528
if pool != nil {

pkg/util/errors/errors.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ var ErrIPv6SupportDisabled = errors.New("IPv6 support is disabled")
4040
var ErrNoRouterID = errors.New("router-id not set in cloud provider config")
4141

4242
func IsNotFound(err error) bool {
43+
if err == ErrNotFound {
44+
return true
45+
}
46+
4347
if _, ok := err.(gophercloud.ErrDefault404); ok {
4448
return true
4549
}
@@ -54,10 +58,6 @@ func IsNotFound(err error) bool {
5458
}
5559
}
5660

57-
if err == ErrNotFound {
58-
return true
59-
}
60-
6161
return false
6262
}
6363

pkg/util/openstack/keymanager.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@ import (
2323
"github.com/gophercloud/gophercloud"
2424
"github.com/gophercloud/gophercloud/openstack/keymanager/v1/secrets"
2525
"k8s.io/cloud-provider-openstack/pkg/metrics"
26+
cpoerrors "k8s.io/cloud-provider-openstack/pkg/util/errors"
2627
)
2728

2829
// EnsureSecret creates a secret if it doesn't exist.
2930
func EnsureSecret(client *gophercloud.ServiceClient, name string, secretType string, payload string) (string, error) {
3031
secret, err := GetSecret(client, name)
3132
if err != nil {
32-
if err == ErrNotFound {
33+
if err == cpoerrors.ErrNotFound {
3334
// Create a new one
3435
return CreateSecret(client, name, secretType, payload)
3536
}
@@ -56,10 +57,10 @@ func GetSecret(client *gophercloud.ServiceClient, name string) (*secrets.Secret,
5657
}
5758

5859
if len(allSecrets) == 0 {
59-
return nil, ErrNotFound
60+
return nil, cpoerrors.ErrNotFound
6061
}
6162
if len(allSecrets) > 1 {
62-
return nil, ErrMultipleResults
63+
return nil, cpoerrors.ErrMultipleResults
6364
}
6465

6566
return &allSecrets[0], nil

pkg/util/openstack/loadbalancer.go

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
package openstack
1818

1919
import (
20-
"errors"
2120
"fmt"
2221
"time"
2322

@@ -56,11 +55,15 @@ const (
5655
var (
5756
octaviaVersion string
5857

59-
// ErrNotFound is used to inform that the object is missing
60-
ErrNotFound = errors.New("failed to find object")
58+
// ErrNotFound is used to inform that the object is missing.
59+
// Deprecated: use cpoerrors.ErrNotFound instead.
60+
// TODO: remove in v1.27.0.
61+
ErrNotFound = cpoerrors.ErrNotFound
6162

62-
// ErrMultipleResults is used when we unexpectedly get back multiple results
63-
ErrMultipleResults = errors.New("multiple results where only one expected")
63+
// ErrMultipleResults is used when we unexpectedly get back multiple results.
64+
// Deprecated: use cpoerrors.ErrMultipleResults instead.
65+
// TODO: remove in v1.27.0.
66+
ErrMultipleResults = cpoerrors.ErrMultipleResults
6467
)
6568

6669
// getOctaviaVersion returns the current Octavia API version.
@@ -221,10 +224,10 @@ func GetLoadbalancerByName(client *gophercloud.ServiceClient, name string) (*loa
221224
}
222225

223226
if len(loadbalancerList) > 1 {
224-
return nil, ErrMultipleResults
227+
return nil, cpoerrors.ErrMultipleResults
225228
}
226229
if len(loadbalancerList) == 0 {
227-
return nil, ErrNotFound
230+
return nil, cpoerrors.ErrNotFound
228231
}
229232

230233
return &loadbalancerList[0], nil
@@ -364,19 +367,19 @@ func GetListenerByName(client *gophercloud.ServiceClient, name string, lbID stri
364367
}
365368
listenerList = append(listenerList, v...)
366369
if len(listenerList) > 1 {
367-
return false, ErrMultipleResults
370+
return false, cpoerrors.ErrMultipleResults
368371
}
369372
return true, nil
370373
})
371374
if mc.ObserveRequest(err) != nil {
372375
if cpoerrors.IsNotFound(err) {
373-
return nil, ErrNotFound
376+
return nil, cpoerrors.ErrNotFound
374377
}
375378
return nil, err
376379
}
377380

378381
if len(listenerList) == 0 {
379-
return nil, ErrNotFound
382+
return nil, cpoerrors.ErrNotFound
380383
}
381384

382385
return &listenerList[0], nil
@@ -430,21 +433,21 @@ func GetPoolByName(client *gophercloud.ServiceClient, name string, lbID string)
430433
}
431434
listenerPools = append(listenerPools, v...)
432435
if len(listenerPools) > 1 {
433-
return false, ErrMultipleResults
436+
return false, cpoerrors.ErrMultipleResults
434437
}
435438
return true, nil
436439
})
437440
if mc.ObserveRequest(err) != nil {
438441
if cpoerrors.IsNotFound(err) {
439-
return nil, ErrNotFound
442+
return nil, cpoerrors.ErrNotFound
440443
}
441444
return nil, err
442445
}
443446

444447
if len(listenerPools) == 0 {
445-
return nil, ErrNotFound
448+
return nil, cpoerrors.ErrNotFound
446449
} else if len(listenerPools) > 1 {
447-
return nil, ErrMultipleResults
450+
return nil, cpoerrors.ErrMultipleResults
448451
}
449452

450453
return &listenerPools[0], nil
@@ -468,19 +471,19 @@ func GetPoolByListener(client *gophercloud.ServiceClient, lbID, listenerID strin
468471
}
469472
}
470473
if len(listenerPools) > 1 {
471-
return false, ErrMultipleResults
474+
return false, cpoerrors.ErrMultipleResults
472475
}
473476
return true, nil
474477
})
475478
if mc.ObserveRequest(err) != nil {
476479
if cpoerrors.IsNotFound(err) {
477-
return nil, ErrNotFound
480+
return nil, cpoerrors.ErrNotFound
478481
}
479482
return nil, err
480483
}
481484

482485
if len(listenerPools) == 0 {
483-
return nil, ErrNotFound
486+
return nil, cpoerrors.ErrNotFound
484487
}
485488

486489
return &listenerPools[0], nil

tests/playbooks/roles/install-csi-cinder/tasks/main.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@
158158
-storage.testdriver=tests/e2e/csi/cinder/test-driver.yaml \
159159
-ginkgo.focus='External.Storage' \
160160
-ginkgo.skip='\[Disruptive\]|\[Testpattern:\s+Dynamic\s+PV\s+\(default\s+fs\)\]\s+provisioning\s+should\s+mount\s+multiple\s+PV\s+pointing\s+to\s+the\s+same\s+storage\s+on\s+the\s+same\s+node|\[Testpattern:\s+Dynamic\s+PV\s+\(default\s+fs\)\]\s+provisioning\s+should\s+provision\s+storage\s+with\s+any\s+volume\s+data\s+source\s+\[Serial\]' \
161-
-ginkgo.noColor \
161+
-ginkgo.no-color \
162162
-ginkgo.progress \
163163
-ginkgo.v \
164164
-test.timeout=0 \
@@ -172,7 +172,7 @@
172172
cmd: |
173173
set -x
174174
set -e
175-
175+
176176
kubectl logs deployment/csi-cinder-controllerplugin -n kube-system -c cinder-csi-plugin > /var/log/csi-pod/csi-cinder-controllerplugin.log
177177
kubectl logs daemonset/csi-cinder-nodeplugin -n kube-system -c cinder-csi-plugin > /var/log/csi-pod/csi-cinder-nodeplugin.log
178178
ignore_errors: true

0 commit comments

Comments
 (0)