Add an initial structure for openstack cloudmock

More info in the docs changes. This adds stubbed http handlers for every resource type used by Kops.
This commit is contained in:
Peter Rifel 2020-08-05 22:38:22 -05:00
parent d1fe0a12a5
commit 23dc8383da
No known key found for this signature in database
GPG Key ID: BC6469E5B16DB2B6
32 changed files with 1130 additions and 6 deletions

View File

@ -1,16 +1,16 @@
cloudmock is a mock implementation of the AWS APIs.
cloudmock is a mock implementation of the CloudProvider APIs.
The goal is to let us test code that interacts with the AWS APIs, without creating actual AWS resources.
The goal is to let us test code that interacts with the CloudProvider APIs, without creating actual resources.
While no resources are created, we maintain state so that (for example) after you call `CreateVpc`, a subsequent
call to `DescribeVpcs` will return that VPC. The end-goal is that we simulate the AWS APIs accurately,
call to `DescribeVpcs` will return that VPC. The end-goal is that we simulate the CloudProvider APIs accurately,
so that we can quickly run test-cases that might otherwise require a lot of time or money to run with real
AWS resources.
resources.
In future, we can also do fault injection etc.
Note: The AWS API is very large, and most of it is not implemented. Functions that are implemented may
Note: The APIs are very large, and most of them are not implemented. Functions that are implemented may
not be implemented correctly, particularly around edge-cases (such as error handling).
Typical use: `c := &mockec2.MockEC2{}`. `MockEC2` implements the EC2 API interface `ec2iface.EC2API`,
Typical AWS use: `c := &mockec2.MockEC2{}`. `MockEC2` implements the EC2 API interface `ec2iface.EC2API`,
so can be used where otherwise you would use a real EC2 client.

View File

@ -0,0 +1,9 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = ["mock.go"],
importpath = "k8s.io/kops/cloudmock/openstack",
visibility = ["//visibility:public"],
deps = ["//vendor/github.com/gophercloud/gophercloud:go_default_library"],
)

View File

@ -0,0 +1,13 @@
# Openstack Cloudmock
## Design
Because the gophercloud library does not provide client interfaces whose client-side functions could be mocked like aws-sdk-go, this cloudmock uses a local HTTP server and updates state based on incoming requests from the gophercloud clients.
This is how the [gophercloud library tests](https://github.com/gophercloud/gophercloud/blob/51f8fa152459ae60d3b348023ad79f850db3a931/openstack/compute/v2/servers/testing/fixtures.go#L896-L914) themselves are implemented.
Each package represents one of the Openstack service clients and contains its own `net/http/httptest` server.
Each package defines the endpoints for that client's resources.
## Troubleshooting
One recommended way to troubleshoot requests and responses is with Wireshark or an equivalent, monitoring the loopback interface.

View File

@ -0,0 +1,52 @@
/*
Copyright 2020 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 openstack
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/gophercloud/gophercloud"
)
type MockOpenstackServer struct {
Mux *http.ServeMux
Server *httptest.Server
}
// SetupMux prepares the Mux and Server.
func (m *MockOpenstackServer) SetupMux() {
m.Mux = http.NewServeMux()
m.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNotImplemented)
panic(fmt.Sprintf("Unhandled mock request: %+v\n", r))
})
}
// TeardownHTTP releases HTTP-related resources.
func (m *MockOpenstackServer) TeardownHTTP() {
m.Server.Close()
}
func (m *MockOpenstackServer) ServiceClient() *gophercloud.ServiceClient {
return &gophercloud.ServiceClient{
ProviderClient: &gophercloud.ProviderClient{},
Endpoint: m.Server.URL + "/",
}
}

View File

@ -0,0 +1,17 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"api.go",
"availabilityzones.go",
"volumes.go",
],
importpath = "k8s.io/kops/cloudmock/openstack/mockblockstorage",
visibility = ["//visibility:public"],
deps = [
"//cloudmock/openstack:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/availabilityzones:go_default_library",
],
)

View File

@ -0,0 +1,52 @@
/*
Copyright 2020 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 mockblockstorage
import (
"net/http/httptest"
"sync"
cinderv3 "github.com/gophercloud/gophercloud/openstack/blockstorage/v3/volumes"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/availabilityzones"
"k8s.io/kops/cloudmock/openstack"
)
// MockClient represents a mocked blockstorage (cinderv3) client
type MockClient struct {
openstack.MockOpenstackServer
mutex sync.Mutex
volumes map[string]cinderv3.Volume
availabilityZones map[string]availabilityzones.AvailabilityZone
}
// CreateClient will create a new mock blockstorage client
func CreateClient() *MockClient {
m := &MockClient{}
m.Reset()
m.SetupMux()
m.mockVolumes()
m.mockAvailabilityZones()
m.Server = httptest.NewServer(m.Mux)
return m
}
// Reset will empty the state of the mock data
func (m *MockClient) Reset() {
m.volumes = make(map[string]cinderv3.Volume)
m.availabilityZones = make(map[string]availabilityzones.AvailabilityZone)
}

View File

@ -0,0 +1,32 @@
/*
Copyright 2020 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 mockblockstorage
import (
"net/http"
)
func (m *MockClient) mockAvailabilityZones() {
handler := func(w http.ResponseWriter, r *http.Request) {
m.mutex.Lock()
defer m.mutex.Unlock()
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
m.Mux.HandleFunc("/os-availability-zone", handler)
}

View File

@ -0,0 +1,34 @@
/*
Copyright 2020 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 mockblockstorage
import (
"net/http"
)
func (m *MockClient) mockVolumes() {
handler := func(w http.ResponseWriter, r *http.Request) {
m.mutex.Lock()
defer m.mutex.Unlock()
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
m.Mux.HandleFunc("/volumes/", handler)
m.Mux.HandleFunc("/volumes", handler)
}

View File

@ -0,0 +1,23 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"api.go",
"flavors.go",
"images.go",
"keypairs.go",
"servergroups.go",
"servers.go",
],
importpath = "k8s.io/kops/cloudmock/openstack/mockcompute",
visibility = ["//visibility:public"],
deps = [
"//cloudmock/openstack:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/flavors:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/compute/v2/servers:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/imageservice/v2/images:go_default_library",
],
)

View File

@ -0,0 +1,79 @@
/*
Copyright 2020 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 mockcompute
import (
"net/http/httptest"
"sync"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/keypairs"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/servergroups"
"github.com/gophercloud/gophercloud/openstack/compute/v2/flavors"
"github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
"github.com/gophercloud/gophercloud/openstack/imageservice/v2/images"
"k8s.io/kops/cloudmock/openstack"
)
// MockClient represents a mocked networks (nebula) client
type MockClient struct {
openstack.MockOpenstackServer
mutex sync.Mutex
serverGroups map[string]servergroups.ServerGroup
servers map[string]servers.Server
keyPairs map[string]keypairs.KeyPair
images map[string]images.Image
flavors map[string]flavors.Flavor
}
// CreateClient will create a new mock networking client
func CreateClient() *MockClient {
m := &MockClient{}
m.SetupMux()
m.Reset()
m.mockServerGroups()
m.mockServers()
m.mockKeyPairs()
m.mockImages()
m.mockFlavors()
m.Server = httptest.NewServer(m.Mux)
return m
}
// Reset will empty the state of the mock data
func (m *MockClient) Reset() {
m.serverGroups = make(map[string]servergroups.ServerGroup)
m.servers = make(map[string]servers.Server)
m.keyPairs = make(map[string]keypairs.KeyPair)
m.images = make(map[string]images.Image)
m.flavors = make(map[string]flavors.Flavor)
}
// All returns a map of all resource IDs to their resources
func (m *MockClient) All() map[string]interface{} {
all := make(map[string]interface{})
for id, sg := range m.serverGroups {
all[id] = sg
}
for id, kp := range m.keyPairs {
all[id] = kp
}
for id, s := range m.servers {
all[id] = s
}
return all
}

View File

@ -0,0 +1,34 @@
/*
Copyright 2020 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 mockcompute
import (
"net/http"
)
func (m *MockClient) mockFlavors() {
handler := func(w http.ResponseWriter, r *http.Request) {
m.mutex.Lock()
defer m.mutex.Unlock()
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
m.Mux.HandleFunc("/flavors/", handler)
m.Mux.HandleFunc("/flavors", handler)
}

View File

@ -0,0 +1,34 @@
/*
Copyright 2020 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 mockcompute
import (
"net/http"
)
func (m *MockClient) mockImages() {
handler := func(w http.ResponseWriter, r *http.Request) {
m.mutex.Lock()
defer m.mutex.Unlock()
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
m.Mux.HandleFunc("/images/", handler)
m.Mux.HandleFunc("/images", handler)
}

View File

@ -0,0 +1,34 @@
/*
Copyright 2020 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 mockcompute
import (
"net/http"
)
func (m *MockClient) mockKeyPairs() {
handler := func(w http.ResponseWriter, r *http.Request) {
m.mutex.Lock()
defer m.mutex.Unlock()
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
m.Mux.HandleFunc("/os-keypairs/", handler)
m.Mux.HandleFunc("/os-keypairs", handler)
}

View File

@ -0,0 +1,34 @@
/*
Copyright 2020 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 mockcompute
import (
"net/http"
)
func (m *MockClient) mockServerGroups() {
handler := func(w http.ResponseWriter, r *http.Request) {
m.mutex.Lock()
defer m.mutex.Unlock()
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
m.Mux.HandleFunc("/os-server-groups/", handler)
m.Mux.HandleFunc("/os-server-groups", handler)
}

View File

@ -0,0 +1,34 @@
/*
Copyright 2020 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 mockcompute
import (
"net/http"
)
func (m *MockClient) mockServers() {
handler := func(w http.ResponseWriter, r *http.Request) {
m.mutex.Lock()
defer m.mutex.Unlock()
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
m.Mux.HandleFunc("/servers/", handler)
m.Mux.HandleFunc("/servers", handler)
}

View File

@ -0,0 +1,16 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"api.go",
"zones.go",
],
importpath = "k8s.io/kops/cloudmock/openstack/mockdns",
visibility = ["//visibility:public"],
deps = [
"//cloudmock/openstack:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/dns/v2/zones:go_default_library",
],
)

View File

@ -0,0 +1,60 @@
/*
Copyright 2020 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 mockdns
import (
"net/http/httptest"
"sync"
"github.com/gophercloud/gophercloud/openstack/dns/v2/recordsets"
"github.com/gophercloud/gophercloud/openstack/dns/v2/zones"
"k8s.io/kops/cloudmock/openstack"
)
// MockClient represents a mocked dns client
type MockClient struct {
openstack.MockOpenstackServer
mutex sync.Mutex
zones map[string]zones.Zone
recordSets map[string]recordsets.RecordSet
}
// CreateClient will create a new mock dns client
func CreateClient() *MockClient {
m := &MockClient{}
m.Reset()
m.SetupMux()
m.mockZones()
m.Server = httptest.NewServer(m.Mux)
return m
}
// Reset will empty the state of the mock data
func (m *MockClient) Reset() {
m.zones = make(map[string]zones.Zone)
m.recordSets = make(map[string]recordsets.RecordSet)
}
// All returns a map of all resource IDs to their resources
func (m *MockClient) All() map[string]interface{} {
all := make(map[string]interface{})
for id, sg := range m.recordSets {
all[id] = sg
}
return all
}

View File

@ -0,0 +1,34 @@
/*
Copyright 2020 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 mockdns
import (
"net/http"
)
func (m *MockClient) mockZones() {
handler := func(w http.ResponseWriter, r *http.Request) {
m.mutex.Lock()
defer m.mutex.Unlock()
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
m.Mux.HandleFunc("/zones/", handler)
m.Mux.HandleFunc("/zones", handler)
}

View File

@ -0,0 +1,19 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"api.go",
"listeners.go",
"loadbalancers.go",
"pools.go",
],
importpath = "k8s.io/kops/cloudmock/openstack/mockloadbalancer",
visibility = ["//visibility:public"],
deps = [
"//cloudmock/openstack:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools:go_default_library",
],
)

View File

@ -0,0 +1,71 @@
/*
Copyright 2020 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 mockloadbalancer
import (
"net/http/httptest"
"sync"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/listeners"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/loadbalancers"
"github.com/gophercloud/gophercloud/openstack/loadbalancer/v2/pools"
"k8s.io/kops/cloudmock/openstack"
)
// MockClient represents a mocked networks (nebula) client
type MockClient struct {
openstack.MockOpenstackServer
mutex sync.Mutex
loadbalancers map[string]loadbalancers.LoadBalancer
listeners map[string]listeners.Listener
pools map[string]pools.Pool
}
// CreateClient will create a new mock networking client
func CreateClient() *MockClient {
m := &MockClient{}
m.Reset()
m.SetupMux()
m.mockListeners()
m.mockLoadBalancers()
m.mockPools()
m.Server = httptest.NewServer(m.Mux)
return m
}
// Reset will empty the state of the mock data
func (m *MockClient) Reset() {
m.loadbalancers = make(map[string]loadbalancers.LoadBalancer)
m.listeners = make(map[string]listeners.Listener)
m.pools = make(map[string]pools.Pool)
}
// All returns a map of all resource IDs to their resources
func (m *MockClient) All() map[string]interface{} {
all := make(map[string]interface{})
for id, sg := range m.loadbalancers {
all[id] = sg
}
for id, l := range m.listeners {
all[id] = l
}
for id, p := range m.pools {
all[id] = p
}
return all
}

View File

@ -0,0 +1,34 @@
/*
Copyright 2020 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 mockloadbalancer
import (
"net/http"
)
func (m *MockClient) mockListeners() {
handler := func(w http.ResponseWriter, r *http.Request) {
m.mutex.Lock()
defer m.mutex.Unlock()
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
m.Mux.HandleFunc("/lbaas/listeners/", handler)
m.Mux.HandleFunc("/lbaas/listeners", handler)
}

View File

@ -0,0 +1,34 @@
/*
Copyright 2020 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 mockloadbalancer
import (
"net/http"
)
func (m *MockClient) mockLoadBalancers() {
handler := func(w http.ResponseWriter, r *http.Request) {
m.mutex.Lock()
defer m.mutex.Unlock()
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
m.Mux.HandleFunc("/lbaas/loadbalancers/", handler)
m.Mux.HandleFunc("/lbaas/loadbalancers", handler)
}

View File

@ -0,0 +1,34 @@
/*
Copyright 2020 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 mockloadbalancer
import (
"net/http"
)
func (m *MockClient) mockPools() {
handler := func(w http.ResponseWriter, r *http.Request) {
m.mutex.Lock()
defer m.mutex.Unlock()
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
m.Mux.HandleFunc("/lbaas/pools/", handler)
m.Mux.HandleFunc("/lbaas/pools", handler)
}

View File

@ -0,0 +1,24 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"api.go",
"networks.go",
"ports.go",
"routers.go",
"securitygrouprules.go",
"securitygroups.go",
"subnets.go",
],
importpath = "k8s.io/kops/cloudmock/openstack/mocknetworking",
visibility = ["//visibility:public"],
deps = [
"//cloudmock/openstack:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/ports:go_default_library",
"//vendor/github.com/gophercloud/gophercloud/openstack/networking/v2/subnets:go_default_library",
],
)

View File

@ -0,0 +1,96 @@
/*
Copyright 2020 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 mocknetworking
import (
"net/http/httptest"
"sync"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/groups"
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules"
"github.com/gophercloud/gophercloud/openstack/networking/v2/ports"
"github.com/gophercloud/gophercloud/openstack/networking/v2/subnets"
"k8s.io/kops/cloudmock/openstack"
)
// MockClient represents a mocked networks (nebula) client
type MockClient struct {
openstack.MockOpenstackServer
mutex sync.Mutex
networks map[string]externalNetwork
ports map[string]ports.Port
routers map[string]routers.Router
routerInterfaces map[string][]routers.InterfaceInfo
securityGroups map[string]groups.SecGroup
securityGroupRules map[string]rules.SecGroupRule
subnets map[string]subnets.Subnet
}
// CreateClient will create a new mock networking client
func CreateClient() *MockClient {
m := &MockClient{}
m.Reset()
m.SetupMux()
m.mockNetworks()
m.mockPorts()
m.mockRouters()
m.mockSecurityGroups()
m.mockSecurityGroupRules()
m.mockSubnets()
m.Server = httptest.NewServer(m.Mux)
return m
}
// Reset will empty the state of the mock data
func (m *MockClient) Reset() {
m.networks = make(map[string]externalNetwork)
m.ports = make(map[string]ports.Port)
m.routers = make(map[string]routers.Router)
m.routerInterfaces = make(map[string][]routers.InterfaceInfo)
m.securityGroups = make(map[string]groups.SecGroup)
m.securityGroupRules = make(map[string]rules.SecGroupRule)
m.subnets = make(map[string]subnets.Subnet)
}
// All returns a map of all resource IDs to their resources
func (m *MockClient) All() map[string]interface{} {
all := make(map[string]interface{})
for id, n := range m.networks {
all[id] = n
}
for id, p := range m.ports {
all[id] = p
}
for id, r := range m.routers {
all[id] = r
}
for id, ri := range m.routerInterfaces {
all[id] = ri
}
for id, sg := range m.securityGroups {
all[id] = sg
}
for id, sgr := range m.securityGroupRules {
all[id] = sgr
}
for id, s := range m.subnets {
all[id] = s
}
return all
}

View File

@ -0,0 +1,45 @@
/*
Copyright 2020 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 mocknetworking
import (
"net/http"
)
// Theres no type that represents a network with the "external" extension
// Copied from https://github.com/gophercloud/gophercloud/blob/bd999d0da882fe8c5b0077b7af2dcc019c1ab458/openstack/networking/v2/networks/results.go#L51
type externalNetwork struct {
ID string `json:"id"`
Name string `json:"name"`
AdminStateUp bool `json:"admin_state_up"`
Status string `json:"status"`
External bool `json:"router:external"`
Tags []string `json:"tags"`
}
func (m *MockClient) mockNetworks() {
handler := func(w http.ResponseWriter, r *http.Request) {
m.mutex.Lock()
defer m.mutex.Unlock()
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
m.Mux.HandleFunc("/networks/", handler)
m.Mux.HandleFunc("/networks", handler)
}

View File

@ -0,0 +1,34 @@
/*
Copyright 2020 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 mocknetworking
import (
"net/http"
)
func (m *MockClient) mockPorts() {
handler := func(w http.ResponseWriter, r *http.Request) {
m.mutex.Lock()
defer m.mutex.Unlock()
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
m.Mux.HandleFunc("/ports/", handler)
m.Mux.HandleFunc("/ports", handler)
}

View File

@ -0,0 +1,34 @@
/*
Copyright 2020 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 mocknetworking
import (
"net/http"
)
func (m *MockClient) mockRouters() {
handler := func(w http.ResponseWriter, r *http.Request) {
m.mutex.Lock()
defer m.mutex.Unlock()
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
m.Mux.HandleFunc("/routers/", handler)
m.Mux.HandleFunc("/routers", handler)
}

View File

@ -0,0 +1,34 @@
/*
Copyright 2020 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 mocknetworking
import (
"net/http"
)
func (m *MockClient) mockSecurityGroupRules() {
handler := func(w http.ResponseWriter, r *http.Request) {
m.mutex.Lock()
defer m.mutex.Unlock()
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
m.Mux.HandleFunc("/security-group-rules/", handler)
m.Mux.HandleFunc("/security-group-rules", handler)
}

View File

@ -0,0 +1,34 @@
/*
Copyright 2020 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 mocknetworking
import (
"net/http"
)
func (m *MockClient) mockSecurityGroups() {
handler := func(w http.ResponseWriter, r *http.Request) {
m.mutex.Lock()
defer m.mutex.Unlock()
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
m.Mux.HandleFunc("/security-groups/", handler)
m.Mux.HandleFunc("/security-groups", handler)
}

View File

@ -0,0 +1,34 @@
/*
Copyright 2020 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 mocknetworking
import (
"net/http"
)
func (m *MockClient) mockSubnets() {
handler := func(w http.ResponseWriter, r *http.Request) {
m.mutex.Lock()
defer m.mutex.Unlock()
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
}
m.Mux.HandleFunc("/subnets/", handler)
m.Mux.HandleFunc("/subnets", handler)
}

View File

@ -9,6 +9,12 @@ k8s.io/kops/cloudmock/aws/mockelb
k8s.io/kops/cloudmock/aws/mockelbv2
k8s.io/kops/cloudmock/aws/mockiam
k8s.io/kops/cloudmock/aws/mockroute53
k8s.io/kops/cloudmock/openstack
k8s.io/kops/cloudmock/openstack/mockblockstorage
k8s.io/kops/cloudmock/openstack/mockcompute
k8s.io/kops/cloudmock/openstack/mockdns
k8s.io/kops/cloudmock/openstack/mockloadbalancer
k8s.io/kops/cloudmock/openstack/mocknetworking
k8s.io/kops/cmd/kops
k8s.io/kops/cmd/kops/util
k8s.io/kops/cmd/kops-controller