@@ -1708,14 +1708,25 @@ func (c *Config) TestConnectivity(ctx context.Context, vlab *VLAB, opts TestConn
17081708 ce := & CurlError {
17091709 Source : serverA ,
17101710 }
1711- reachable , err := apiutil . IsExternalSubnetReachable (ctx , kube , serverA , "0.0.0.0/0" ) // TODO test for specific IP
1711+ expectedReachable , err := IsExternalSubnetReachable (ctx , kube , serverA , "0.0.0.0/0" , c . Fab . Spec . Config . Gateway . Enable ) // TODO test for specific IP
17121712 if err != nil {
17131713 ce .Msg = fmt .Sprintf ("checking if should be reachable: %s" , err )
17141714
17151715 return ce
17161716 }
17171717
1718- slog .Debug ("Checking external connectivity" , "from" , serverA , "reachable" , reachable )
1718+ logArgs := []any {
1719+ "from" , serverA ,
1720+ "expected" , expectedReachable .Reachable ,
1721+ }
1722+ if expectedReachable .Reachable {
1723+ logArgs = append (logArgs , "reason" , expectedReachable .Reason )
1724+ if expectedReachable .Peering != "" {
1725+ logArgs = append (logArgs , "peering" , expectedReachable .Peering )
1726+ }
1727+ }
1728+
1729+ slog .Debug ("Checking external connectivity" , logArgs ... )
17191730
17201731 clientR , ok := sshs .Load (serverA )
17211732 if ! ok {
@@ -1727,7 +1738,7 @@ func (c *Config) TestConnectivity(ctx context.Context, vlab *VLAB, opts TestConn
17271738
17281739 // switching to 1.0.0.1 since the previously used target 8.8.8.8 was giving us issue
17291740 // when curling over virtual external peerings
1730- if ce := checkCurl (ctx , opts , curls , serverA , client , "1.0.0.1" , reachable ); ce != nil {
1741+ if ce := checkCurl (ctx , opts , curls , serverA , client , "1.0.0.1" , expectedReachable . Reachable ); ce != nil {
17311742 return ce
17321743 }
17331744
@@ -1778,6 +1789,58 @@ const (
17781789 ReachabilityReasonGatewayPeering ReachabilityReason = "gateway-peering"
17791790)
17801791
1792+ func IsExternalSubnetReachable (ctx context.Context , kube kclient.Reader , sourceServer , destSubnet string , checkGateway bool ) (Reachability , error ) {
1793+ switchPeeringReachable , err := apiutil .IsExternalSubnetReachable (ctx , kube , sourceServer , destSubnet )
1794+ if err != nil {
1795+ return Reachability {}, fmt .Errorf ("checking if external subnet %s is reachable from server %s: %w" , destSubnet , sourceServer , err )
1796+ }
1797+ if switchPeeringReachable {
1798+ return Reachability {
1799+ Reachable : true ,
1800+ Reason : ReachabilityReasonSwitchPeering ,
1801+ }, nil
1802+ }
1803+
1804+ if ! checkGateway {
1805+ return Reachability {}, nil
1806+ }
1807+
1808+ sourceSubnets , err := apiutil .GetAttachedSubnets (ctx , kube , sourceServer )
1809+ if err != nil {
1810+ return Reachability {}, fmt .Errorf ("getting attached subnets for source server %s: %w" , sourceServer , err )
1811+ }
1812+
1813+ externals := & vpcapi.ExternalList {}
1814+ if err := kube .List (ctx , externals ); err != nil {
1815+ return Reachability {}, fmt .Errorf ("listing externals: %w" , err )
1816+ }
1817+ if len (externals .Items ) == 0 {
1818+ // No externals defined, can't be reachable via gateway
1819+ return Reachability {}, nil
1820+ }
1821+ externalNames := make ([]string , len (externals .Items ))
1822+ for i , ext := range externals .Items {
1823+ externalNames [i ] = ext .Name
1824+ }
1825+
1826+ for sourceSubnetName := range sourceSubnets {
1827+ if ! strings .Contains (sourceSubnetName , "/" ) {
1828+ return Reachability {}, fmt .Errorf ("source must be full VPC subnet name (<vpc-name>/<subnet-name>)" )
1829+ }
1830+ sourceParts := strings .SplitN (sourceSubnetName , "/" , 2 )
1831+ sourceVPC , sourceSubnet := sourceParts [0 ], sourceParts [1 ]
1832+ for _ , ext := range externalNames {
1833+ if r , err := IsSubnetReachableWithGatewayPeering (ctx , kube , sourceVPC , sourceSubnet , ext , "internet" ); err != nil {
1834+ return Reachability {}, err
1835+ } else if r .Reachable {
1836+ return r , nil
1837+ }
1838+ }
1839+ }
1840+
1841+ return Reachability {}, nil
1842+ }
1843+
17811844func IsServerReachable (ctx context.Context , kube kclient.Reader , sourceServer , destServer string , checkGateway bool ) (Reachability , error ) {
17821845 sourceSubnets , err := apiutil .GetAttachedSubnets (ctx , kube , sourceServer )
17831846 if err != nil {
0 commit comments