Skip to content

Commit

Permalink
fix: tests based on packngo to metal conversion
Browse files Browse the repository at this point in the history
  • Loading branch information
aayushrangwala committed Jan 5, 2024
1 parent c84a27e commit 25968c5
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 53 deletions.
101 changes: 89 additions & 12 deletions metal/cloud_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
package metal

import (
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"testing"

metal "github.com/equinix/equinix-sdk-go/services/metalv1"
"github.com/google/uuid"
"github.com/gorilla/mux"
clientset "k8s.io/client-go/kubernetes"
k8sfake "k8s.io/client-go/kubernetes/fake"
restclient "k8s.io/client-go/rest"
Expand All @@ -23,6 +26,16 @@ const (
validZoneCode = "ewr1"
)

type MockMetalServer struct {
DeviceStore map[string]*metal.Device
ProjectStore map[string]struct {
Devices []*metal.Device
BgpEnabled bool
}

T *testing.T
}

// mockControllerClientBuilder mock implementation of https://pkg.go.dev/k8s.io/cloud-provider#ControllerClientBuilder
// so we can pass it to cloud.Initialize()
type mockControllerClientBuilder struct{}
Expand All @@ -44,9 +57,16 @@ func (m mockControllerClientBuilder) ClientOrDie(name string) clientset.Interfac
}

// create a valid cloud with a client
func testGetValidCloud(t *testing.T, LoadBalancerSetting string) *cloud {
func testGetValidCloud(t *testing.T, LoadBalancerSetting string) (*cloud, *MockMetalServer) {
mockServer := &MockMetalServer{
DeviceStore: map[string]*metal.Device{},
ProjectStore: map[string]struct {
Devices []*metal.Device
BgpEnabled bool
}{},
}
// mock endpoint so our client can handle it
ts := httptest.NewServer(nil)
ts := httptest.NewServer(mockServer.CreateHandler())

url, _ := url.Parse(ts.URL)
urlString := url.String()
Expand All @@ -62,11 +82,11 @@ func testGetValidCloud(t *testing.T, LoadBalancerSetting string) *cloud {
ccb := &mockControllerClientBuilder{}
c.Initialize(ccb, nil)

return c.(*cloud)
return c.(*cloud), mockServer
}

func TestLoadBalancerDefaultDisabled(t *testing.T) {
vc := testGetValidCloud(t, "")
vc, _ := testGetValidCloud(t, "")
response, supported := vc.LoadBalancer()
var (
expectedSupported = false
Expand All @@ -82,7 +102,7 @@ func TestLoadBalancerDefaultDisabled(t *testing.T) {

func TestLoadBalancerMetalLB(t *testing.T) {
t.Skip("Test needs a k8s client to work")
vc := testGetValidCloud(t, "metallb:///metallb-system/config")
vc, _ := testGetValidCloud(t, "metallb:///metallb-system/config")
response, supported := vc.LoadBalancer()
var (
expectedSupported = true
Expand All @@ -98,7 +118,7 @@ func TestLoadBalancerMetalLB(t *testing.T) {

func TestLoadBalancerEmpty(t *testing.T) {
t.Skip("Test needs a k8s client to work")
vc := testGetValidCloud(t, "empty://")
vc, _ := testGetValidCloud(t, "empty://")
response, supported := vc.LoadBalancer()
var (
expectedSupported = true
Expand All @@ -114,7 +134,7 @@ func TestLoadBalancerEmpty(t *testing.T) {

func TestLoadBalancerKubeVIP(t *testing.T) {
t.Skip("Test needs a k8s client to work")
vc := testGetValidCloud(t, "kube-vip://")
vc, _ := testGetValidCloud(t, "kube-vip://")
response, supported := vc.LoadBalancer()
var (
expectedSupported = true
Expand All @@ -129,7 +149,7 @@ func TestLoadBalancerKubeVIP(t *testing.T) {
}

func TestInstances(t *testing.T) {
vc := testGetValidCloud(t, "")
vc, _ := testGetValidCloud(t, "")
response, supported := vc.Instances()
expectedSupported := false
expectedResponse := cloudprovider.Instances(nil)
Expand All @@ -142,7 +162,7 @@ func TestInstances(t *testing.T) {
}

func TestClusters(t *testing.T) {
vc := testGetValidCloud(t, "")
vc, _ := testGetValidCloud(t, "")
response, supported := vc.Clusters()
var (
expectedSupported = false
Expand All @@ -157,7 +177,7 @@ func TestClusters(t *testing.T) {
}

func TestRoutes(t *testing.T) {
vc := testGetValidCloud(t, "")
vc, _ := testGetValidCloud(t, "")
response, supported := vc.Routes()
var (
expectedSupported = false
Expand All @@ -172,15 +192,15 @@ func TestRoutes(t *testing.T) {
}

func TestProviderName(t *testing.T) {
vc := testGetValidCloud(t, "")
vc, _ := testGetValidCloud(t, "")
name := vc.ProviderName()
if name != ProviderName {
t.Errorf("returned %s instead of expected %s", name, ProviderName)
}
}

func TestHasClusterID(t *testing.T) {
vc := testGetValidCloud(t, "")
vc, _ := testGetValidCloud(t, "")
cid := vc.HasClusterID()
expectedCid := true
if cid != expectedCid {
Expand Down Expand Up @@ -218,3 +238,60 @@ func constructClient(authToken string, baseUrl *string) *metal.APIClient {
configuration.UserAgent = fmt.Sprintf("cloud-provider-equinix-metal/%s %s", version.Get(), configuration.UserAgent)
return metal.NewAPIClient(configuration)
}

func (s *MockMetalServer) CreateHandler() http.Handler {
r := mux.NewRouter()
// create a BGP config for a project
r.HandleFunc("/projects/{projectID}/bgp-configs", s.createBGPHandler).Methods("POST")
// get all devices for a project
r.HandleFunc("/projects/{projectID}/devices", s.listDevicesHandler).Methods("GET")
// get a single device
r.HandleFunc("/devices/{deviceID}", s.getDeviceHandler).Methods("GET")
// handle metadata requests
return r
}

func (s *MockMetalServer) listDevicesHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
projectID := vars["projectID"]

data := s.ProjectStore[projectID]
devices := data.Devices
var resp = struct {
Devices []*metal.Device `json:"devices"`
}{
Devices: devices,
}

w.Header().Set("Content-Type", "application/json")
if err := json.NewEncoder(w).Encode(&resp); err != nil {
s.T.Fatal(err.Error())
}
}

// get information about a specific device
func (s *MockMetalServer) getDeviceHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
volID := vars["deviceID"]
dev := s.DeviceStore[volID]
w.Header().Set("Content-Type", "application/json")
if dev != nil {
err := json.NewEncoder(w).Encode(dev)
if err != nil {
s.T.Fatal(err)
}
return
}
w.WriteHeader(http.StatusNotFound)
}

// createBGPHandler enable BGP for a project
func (s *MockMetalServer) createBGPHandler(w http.ResponseWriter, r *http.Request) {
vars := mux.Vars(r)
projectID := vars["projectID"]
projectData := s.ProjectStore[projectID]
projectData.BgpEnabled = true
s.ProjectStore[projectID] = projectData
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusCreated)
}
7 changes: 2 additions & 5 deletions metal/devices.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,6 @@ func (i *instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloud
//
// https://kubernetes.io/docs/reference/labels-annotations-taints/#topologykubernetesiozone

if device.Facility != nil {
z = device.Facility.GetCode()
}
if device.Metro != nil {
r = device.Metro.GetCode()
}
Expand Down Expand Up @@ -158,8 +155,8 @@ func (i *instances) deviceByNode(node *v1.Node) (*metal.Device, error) {

func deviceByID(client *metal.DevicesApiService, id string) (*metal.Device, error) {
klog.V(2).Infof("called deviceByID with ID %s", id)
device, _, err := client.FindDeviceById(context.Background(), id).Execute()
if isNotFound(err) {
device, resp, err := client.FindDeviceById(context.Background(), id).Execute()
if isNotFound(resp, err) {
return nil, cloudprovider.InstanceNotFound
}
return device, err
Expand Down
Loading

0 comments on commit 25968c5

Please sign in to comment.