@@ -3,24 +3,14 @@ package main
33import  (
44	"bytes" 
55	"context" 
6- 	"encoding/json" 
7- 	"fmt" 
86	"io" 
97	"net/http" 
10- 	"net/http/httptest" 
11- 	"strings" 
128	"testing" 
13- 	"time" 
149
1510	"github.com/Azure/azure-container-networking/cns" 
1611	"github.com/Azure/azure-container-networking/cns/fakes" 
1712	"github.com/Azure/azure-container-networking/cns/logger" 
18- 	"github.com/Azure/azure-container-networking/crd/multitenancy/api/v1alpha1" 
1913	"github.com/stretchr/testify/assert" 
20- 	"github.com/stretchr/testify/require" 
21- 	corev1 "k8s.io/api/core/v1" 
22- 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 
23- 	"k8s.io/client-go/rest" 
2414)
2515
2616// MockHTTPClient is a mock implementation of HTTPClient 
@@ -79,184 +69,3 @@ func TestSendRegisterNodeRequest_StatusAccepted(t *testing.T) {
7969
8070	assert .Error (t , sendRegisterNodeRequest (ctx , mockClient , httpServiceFake , nodeRegisterReq , url ))
8171}
82- 
83- func  TestCreateOrUpdateNodeInfoCRD_PopulatesHomeAZ (t  * testing.T ) {
84- 	vmID  :=  "test-vm-unique-id-12345" 
85- 	homeAZ  :=  uint (2 )
86- 	HomeAZStr  :=  fmt .Sprintf ("AZ0%d" , homeAZ )
87- 
88- 	// Create mock IMDS server 
89- 	mockIMDSServer  :=  httptest .NewServer (http .HandlerFunc (func (w  http.ResponseWriter , r  * http.Request ) {
90- 		if  strings .Contains (r .URL .Path , "/metadata/instance/compute" ) {
91- 			w .Header ().Set ("Content-Type" , "application/json" )
92- 			w .WriteHeader (http .StatusOK )
93- 			response  :=  map [string ]interface {}{
94- 				"vmId" :              vmID ,
95- 				"name" :              "test-vm" ,
96- 				"resourceGroupName" : "test-rg" ,
97- 			}
98- 			_  =  json .NewEncoder (w ).Encode (response )
99- 			return 
100- 		}
101- 		w .WriteHeader (http .StatusNotFound )
102- 	}))
103- 	defer  mockIMDSServer .Close ()
104- 
105- 	// Create mock CNS server 
106- 	mockCNSServer  :=  httptest .NewServer (http .HandlerFunc (func (w  http.ResponseWriter , r  * http.Request ) {
107- 		if  strings .Contains (r .URL .Path , "/homeaz" ) ||  strings .Contains (r .URL .Path , "homeaz" ) {
108- 			w .Header ().Set ("Content-Type" , "application/json" )
109- 			w .WriteHeader (http .StatusOK )
110- 			response  :=  map [string ]interface {}{
111- 				"ReturnCode" : 0 ,
112- 				"Message" :    "" ,
113- 				"HomeAzResponse" : map [string ]interface {}{
114- 					"IsSupported" : true ,
115- 					"HomeAz" :      homeAZ ,
116- 				},
117- 			}
118- 			_  =  json .NewEncoder (w ).Encode (response )
119- 			return 
120- 		}
121- 		w .WriteHeader (http .StatusNotFound )
122- 	}))
123- 	defer  mockCNSServer .Close ()
124- 
125- 	// Set up HTTP transport to mock IMDS and CNS 
126- 	originalTransport  :=  http .DefaultTransport 
127- 	defer  func () { http .DefaultTransport  =  originalTransport  }()
128- 
129- 	http .DefaultTransport  =  & mockTransport {
130- 		imdsServer : mockIMDSServer ,
131- 		cnsServer :  mockCNSServer ,
132- 		original :   originalTransport ,
133- 	}
134- 
135- 	// Create a mock Kubernetes server that captures the NodeInfo being created 
136- 	var  capturedNodeInfo  * v1alpha1.NodeInfo 
137- 
138- 	mockK8sServer  :=  httptest .NewServer (http .HandlerFunc (func (w  http.ResponseWriter , r  * http.Request ) {
139- 		// Handle specific API group discovery - multitenancy.acn.azure.com 
140- 		if  r .URL .Path  ==  "/apis/multitenancy.acn.azure.com/v1alpha1"  &&  r .Method  ==  "GET"  {
141- 			w .Header ().Set ("Content-Type" , "application/json" )
142- 			w .WriteHeader (http .StatusOK )
143- 			_  =  json .NewEncoder (w ).Encode (map [string ]interface {}{
144- 				"kind" :         "APIResourceList" ,
145- 				"groupVersion" : "multitenancy.acn.azure.com/v1alpha1" ,
146- 				"resources" : []map [string ]interface {}{
147- 					{
148- 						"name" :         "nodeinfos" ,
149- 						"singularName" : "nodeinfo" ,
150- 						"namespaced" :   false ,
151- 						"kind" :         "NodeInfo" ,
152- 						"verbs" :        []string {"create" , "delete" , "get" , "list" , "patch" , "update" , "watch" },
153- 					},
154- 				},
155- 			})
156- 			return 
157- 		}
158- 
159- 		// Handle NodeInfo resource requests 
160- 		if  strings .Contains (r .URL .Path , "nodeinfos" ) ||  strings .Contains (r .URL .Path , "multitenancy" ) {
161- 			if  r .Method  ==  "POST"  ||  r .Method  ==  "PATCH"  ||  r .Method  ==  "PUT"  {
162- 				body , _  :=  io .ReadAll (r .Body )
163- 
164- 				// Try to parse the NodeInfo from the request 
165- 				var  nodeInfo  v1alpha1.NodeInfo 
166- 				if  err  :=  json .Unmarshal (body , & nodeInfo ); err  ==  nil  {
167- 					capturedNodeInfo  =  & nodeInfo 
168- 				}
169- 
170- 				w .Header ().Set ("Content-Type" , "application/json" )
171- 				w .WriteHeader (http .StatusOK )
172- 				// Return the created NodeInfo 
173- 				_  =  json .NewEncoder (w ).Encode (map [string ]interface {}{
174- 					"apiVersion" : "multitenancy.acn.azure.com/v1alpha1" ,
175- 					"kind" :       "NodeInfo" ,
176- 					"metadata" : map [string ]interface {}{
177- 						"name" : "test-node" ,
178- 					},
179- 					"spec" : map [string ]interface {}{
180- 						"vmUniqueID" : vmID ,
181- 						"homeAZ" :     HomeAZStr ,
182- 					},
183- 				})
184- 				return 
185- 			}
186- 		}
187- 
188- 		// Default success response for any other API calls 
189- 		w .Header ().Set ("Content-Type" , "application/json" )
190- 		w .WriteHeader (http .StatusOK )
191- 		_  =  json .NewEncoder (w ).Encode (map [string ]interface {}{
192- 			"kind" :   "Status" ,
193- 			"status" : "Success" ,
194- 		})
195- 	}))
196- 	defer  mockK8sServer .Close ()
197- 
198- 	// Test the function with mocked dependencies 
199- 	ctx , cancel  :=  context .WithTimeout (context .Background (), 10 * time .Second )
200- 	defer  cancel ()
201- 
202- 	// Point to our mock Kubernetes server 
203- 	restConfig  :=  & rest.Config {
204- 		Host : mockK8sServer .URL ,
205- 	}
206- 
207- 	node  :=  & corev1.Node {
208- 		ObjectMeta : metav1.ObjectMeta {Name : "test-node" },
209- 	}
210- 
211- 	// Call the createOrUpdateNodeInfoCRD function 
212- 	err  :=  createOrUpdateNodeInfoCRD (ctx , restConfig , node )
213- 
214- 	// Verify the function succeeded 
215- 	require .NoError (t , err , "Function should succeed with mocked dependencies" )
216- 
217- 	// Verify the captured values 
218- 	assert .NotNil (t , capturedNodeInfo , "NodeInfo should have been captured from K8s API call" )
219- 	if  capturedNodeInfo  !=  nil  {
220- 		assert .Equal (t , vmID , capturedNodeInfo .Spec .VMUniqueID , "VMUniqueID should be from IMDS" )
221- 		assert .Equal (t , HomeAZStr , capturedNodeInfo .Spec .HomeAZ , "HomeAZ should be formatted from CNS response" )
222- 	}
223- }
224- 
225- // mockTransport redirects HTTP requests to mock servers for testing. 
226- // It intercepts requests to IMDS and CNS endpoints and routes them to local test servers. 
227- type  mockTransport  struct  {
228- 	imdsServer  * httptest.Server 
229- 	cnsServer   * httptest.Server 
230- 	original    http.RoundTripper 
231- }
232- 
233- func  (m  * mockTransport ) RoundTrip (req  * http.Request ) (* http.Response , error ) {
234- 	// Redirect IMDS calls to mock IMDS server 
235- 	if  req .URL .Host  ==  "169.254.169.254"  {
236- 		req .URL .Scheme  =  "http" 
237- 		req .URL .Host  =  strings .TrimPrefix (m .imdsServer .URL , "http://" )
238- 		resp , err  :=  m .original .RoundTrip (req )
239- 		if  err  !=  nil  {
240- 			return  nil , fmt .Errorf ("IMDS mock transport failed: %w" , err )
241- 		}
242- 		return  resp , nil 
243- 	}
244- 
245- 	// Redirect CNS calls to mock CNS server 
246- 	if  req .URL .Host  ==  "localhost:10090"  ||  strings .Contains (req .URL .Host , "10090" ) {
247- 		req .URL .Scheme  =  "http" 
248- 		req .URL .Host  =  strings .TrimPrefix (m .cnsServer .URL , "http://" )
249- 		resp , err  :=  m .original .RoundTrip (req )
250- 		if  err  !=  nil  {
251- 			return  nil , fmt .Errorf ("CNS mock transport failed: %w" , err )
252- 		}
253- 		return  resp , nil 
254- 	}
255- 
256- 	// All other calls go through original transport 
257- 	resp , err  :=  m .original .RoundTrip (req )
258- 	if  err  !=  nil  {
259- 		return  nil , fmt .Errorf ("mock transport failed: %w" , err )
260- 	}
261- 	return  resp , nil 
262- }
0 commit comments