@@ -23,6 +23,7 @@ import (
2323 "testing"
2424
2525 scwinstance "github.com/scaleway/scaleway-sdk-go/api/instance/v1"
26+ scwipam "github.com/scaleway/scaleway-sdk-go/api/ipam/v1"
2627 "github.com/scaleway/scaleway-sdk-go/scw"
2728 v1 "k8s.io/api/core/v1"
2829 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -134,6 +135,59 @@ func newFakeInstanceAPI() *fakeInstanceAPI {
134135 CommercialType : "GP1-XS" ,
135136 State : scwinstance .ServerStateStarting ,
136137 },
138+ // a server with private network only (no public IP)
139+ "private-only-server-id" : {
140+ Zone : "fr-par-2" ,
141+ Name : "scw-private-only" ,
142+ CommercialType : "PLAY2-NANO" ,
143+ State : scwinstance .ServerStateRunning ,
144+ Project : "test-project" ,
145+ PrivateNics : []* scwinstance.PrivateNIC {
146+ {
147+ ID : "nic-private-only" ,
148+ PrivateNetworkID : "pn-12345" ,
149+ },
150+ },
151+ },
152+ // a server with both public and private network
153+ "both-networks-server-id" : {
154+ Zone : "fr-par-2" ,
155+ Name : "scw-both-networks" ,
156+ CommercialType : "PLAY2-NANO" ,
157+ State : scwinstance .ServerStateRunning ,
158+ Project : "test-project" ,
159+ PublicIPs : []* scwinstance.ServerIP {
160+ {
161+ Address : net .ParseIP ("51.159.100.1" ),
162+ ProvisioningMode : scwinstance .ServerIPProvisioningModeDHCP ,
163+ Family : scwinstance .ServerIPIPFamilyInet ,
164+ },
165+ },
166+ PrivateNics : []* scwinstance.PrivateNIC {
167+ {
168+ ID : "nic-both-networks" ,
169+ PrivateNetworkID : "pn-12345" ,
170+ },
171+ },
172+ },
173+ // a server with multiple private networks
174+ "multi-pn-server-id" : {
175+ Zone : "fr-par-2" ,
176+ Name : "scw-multi-pn" ,
177+ CommercialType : "PLAY2-NANO" ,
178+ State : scwinstance .ServerStateRunning ,
179+ Project : "test-project" ,
180+ PrivateNics : []* scwinstance.PrivateNIC {
181+ {
182+ ID : "nic-private-only" ,
183+ PrivateNetworkID : "pn-12345" ,
184+ },
185+ {
186+ ID : "nic-other-pn" ,
187+ PrivateNetworkID : "pn-67890" ,
188+ },
189+ },
190+ },
137191 },
138192 }
139193}
@@ -171,9 +225,65 @@ func (f *fakeInstanceAPI) GetServer(req *scwinstance.GetServerRequest, opts ...s
171225 }, nil
172226}
173227
228+ // fakeIPAMAPI implements IPAMAPI for testing
229+ type fakeIPAMAPI struct {
230+ // IPs maps NIC ID to list of IPs
231+ IPs map [string ][]* scwipam.IP
232+ }
233+
234+ func newFakeIPAMAPI () * fakeIPAMAPI {
235+ return & fakeIPAMAPI {
236+ IPs : map [string ][]* scwipam.IP {
237+ // IPs for private NIC on server with private network only
238+ "nic-private-only" : {
239+ {
240+ Address : scw.IPNet {IPNet : net.IPNet {IP : net .ParseIP ("10.200.0.5" ), Mask : net .CIDRMask (20 , 32 )}},
241+ },
242+ },
243+ // IPs for private NIC on server with both public and private
244+ "nic-both-networks" : {
245+ {
246+ Address : scw.IPNet {IPNet : net.IPNet {IP : net .ParseIP ("10.200.0.10" ), Mask : net .CIDRMask (20 , 32 )}},
247+ },
248+ },
249+ // IPs for another private network
250+ "nic-other-pn" : {
251+ {
252+ Address : scw.IPNet {IPNet : net.IPNet {IP : net .ParseIP ("192.168.1.5" ), Mask : net .CIDRMask (24 , 32 )}},
253+ },
254+ },
255+ },
256+ }
257+ }
258+
259+ func (f * fakeIPAMAPI ) ListIPs (req * scwipam.ListIPsRequest , opts ... scw.RequestOption ) (* scwipam.ListIPsResponse , error ) {
260+ if req .ResourceID == nil {
261+ return & scwipam.ListIPsResponse {IPs : []* scwipam.IP {}}, nil
262+ }
263+
264+ ips , ok := f .IPs [* req .ResourceID ]
265+ if ! ok {
266+ return & scwipam.ListIPsResponse {IPs : []* scwipam.IP {}}, nil
267+ }
268+
269+ return & scwipam.ListIPsResponse {
270+ IPs : ips ,
271+ TotalCount : uint64 (len (ips )),
272+ }, nil
273+ }
274+
174275func newFakeInstances () * instances {
175276 return & instances {
176- api : newFakeInstanceAPI (),
277+ api : newFakeInstanceAPI (),
278+ ipam : newFakeIPAMAPI (),
279+ }
280+ }
281+
282+ func newFakeInstancesWithPNID (pnID string ) * instances {
283+ return & instances {
284+ api : newFakeInstanceAPI (),
285+ ipam : newFakeIPAMAPI (),
286+ pnID : pnID ,
177287 }
178288}
179289
@@ -577,3 +687,80 @@ func TestInstances_InstanceMetadata(t *testing.T) {
577687
578688 })
579689}
690+
691+ func TestInstances_PrivateNetworkAddresses (t * testing.T ) {
692+ t .Run ("PrivateNetworkOnly_NoPNID" , func (t * testing.T ) {
693+ // When no pnID is configured, the CCM should discover private IPs from all NICs
694+ instance := newFakeInstances ()
695+
696+ expectedAddresses := []v1.NodeAddress {
697+ {Type : v1 .NodeHostName , Address : "scw-private-only" },
698+ {Type : v1 .NodeInternalIP , Address : "10.200.0.5" },
699+ }
700+
701+ returnedAddresses , err := instance .NodeAddressesByProviderID (context .TODO (), "scaleway://instance/fr-par-2/private-only-server-id" )
702+ AssertNoError (t , err )
703+ Equals (t , expectedAddresses , returnedAddresses )
704+ })
705+
706+ t .Run ("PrivateNetworkOnly_WithPNID" , func (t * testing.T ) {
707+ // When pnID is configured, only look for that specific private network
708+ instance := newFakeInstancesWithPNID ("pn-12345" )
709+
710+ expectedAddresses := []v1.NodeAddress {
711+ {Type : v1 .NodeHostName , Address : "scw-private-only" },
712+ {Type : v1 .NodeInternalIP , Address : "10.200.0.5" },
713+ }
714+
715+ returnedAddresses , err := instance .NodeAddressesByProviderID (context .TODO (), "scaleway://instance/fr-par-2/private-only-server-id" )
716+ AssertNoError (t , err )
717+ Equals (t , expectedAddresses , returnedAddresses )
718+ })
719+
720+ t .Run ("BothNetworks_NoPNID" , func (t * testing.T ) {
721+ // Server with both public and private network, no specific pnID configured
722+ instance := newFakeInstances ()
723+
724+ expectedAddresses := []v1.NodeAddress {
725+ {Type : v1 .NodeHostName , Address : "scw-both-networks" },
726+ {Type : v1 .NodeExternalIP , Address : "51.159.100.1" },
727+ {Type : v1 .NodeExternalDNS , Address : "both-networks-server-id.pub.instances.scw.cloud" },
728+ {Type : v1 .NodeInternalIP , Address : "10.200.0.10" },
729+ }
730+
731+ returnedAddresses , err := instance .NodeAddressesByProviderID (context .TODO (), "scaleway://instance/fr-par-2/both-networks-server-id" )
732+ AssertNoError (t , err )
733+ Equals (t , expectedAddresses , returnedAddresses )
734+ })
735+
736+ t .Run ("MultiplePrivateNetworks_NoPNID" , func (t * testing.T ) {
737+ // Server with multiple private networks, no specific pnID configured
738+ // Should return IPs from all private networks
739+ instance := newFakeInstances ()
740+
741+ expectedAddresses := []v1.NodeAddress {
742+ {Type : v1 .NodeHostName , Address : "scw-multi-pn" },
743+ {Type : v1 .NodeInternalIP , Address : "10.200.0.5" },
744+ {Type : v1 .NodeInternalIP , Address : "192.168.1.5" },
745+ }
746+
747+ returnedAddresses , err := instance .NodeAddressesByProviderID (context .TODO (), "scaleway://instance/fr-par-2/multi-pn-server-id" )
748+ AssertNoError (t , err )
749+ Equals (t , expectedAddresses , returnedAddresses )
750+ })
751+
752+ t .Run ("MultiplePrivateNetworks_WithPNID" , func (t * testing.T ) {
753+ // Server with multiple private networks, specific pnID configured
754+ // Should only return IPs from the configured private network
755+ instance := newFakeInstancesWithPNID ("pn-67890" )
756+
757+ expectedAddresses := []v1.NodeAddress {
758+ {Type : v1 .NodeHostName , Address : "scw-multi-pn" },
759+ {Type : v1 .NodeInternalIP , Address : "192.168.1.5" },
760+ }
761+
762+ returnedAddresses , err := instance .NodeAddressesByProviderID (context .TODO (), "scaleway://instance/fr-par-2/multi-pn-server-id" )
763+ AssertNoError (t , err )
764+ Equals (t , expectedAddresses , returnedAddresses )
765+ })
766+ }
0 commit comments