@@ -1672,14 +1672,25 @@ func (c *Config) TestConnectivity(ctx context.Context, vlab *VLAB, opts TestConn
16721672 ce := & CurlError {
16731673 Source : serverA ,
16741674 }
1675- reachable , err := apiutil . IsExternalSubnetReachable (ctx , kube , serverA , "0.0.0.0/0" ) // TODO test for specific IP
1675+ expectedReachable , err := IsExternalSubnetReachable (ctx , kube , serverA , "0.0.0.0/0" , c . Fab . Spec . Config . Gateway . Enable ) // TODO test for specific IP
16761676 if err != nil {
16771677 ce .Msg = fmt .Sprintf ("checking if should be reachable: %s" , err )
16781678
16791679 return ce
16801680 }
16811681
1682- slog .Debug ("Checking external connectivity" , "from" , serverA , "reachable" , reachable )
1682+ logArgs := []any {
1683+ "from" , serverA ,
1684+ "expected" , expectedReachable .Reachable ,
1685+ }
1686+ if expectedReachable .Reachable {
1687+ logArgs = append (logArgs , "reason" , expectedReachable .Reason )
1688+ if expectedReachable .Peering != "" {
1689+ logArgs = append (logArgs , "peering" , expectedReachable .Peering )
1690+ }
1691+ }
1692+
1693+ slog .Debug ("Checking external connectivity" , logArgs ... )
16831694
16841695 clientR , ok := sshs .Load (serverA )
16851696 if ! ok {
@@ -1691,7 +1702,7 @@ func (c *Config) TestConnectivity(ctx context.Context, vlab *VLAB, opts TestConn
16911702
16921703 // switching to 1.0.0.1 since the previously used target 8.8.8.8 was giving us issue
16931704 // when curling over virtual external peerings
1694- if ce := checkCurl (ctx , opts , curls , serverA , client , "1.0.0.1" , reachable ); ce != nil {
1705+ if ce := checkCurl (ctx , opts , curls , serverA , client , "1.0.0.1" , expectedReachable . Reachable ); ce != nil {
16951706 return ce
16961707 }
16971708
@@ -1742,6 +1753,58 @@ const (
17421753 ReachabilityReasonGatewayPeering ReachabilityReason = "gateway-peering"
17431754)
17441755
1756+ func IsExternalSubnetReachable (ctx context.Context , kube kclient.Reader , sourceServer , destSubnet string , checkGateway bool ) (Reachability , error ) {
1757+ switchPeeringReachable , err := apiutil .IsExternalSubnetReachable (ctx , kube , sourceServer , destSubnet )
1758+ if err != nil {
1759+ return Reachability {}, fmt .Errorf ("checking if external subnet %s is reachable from server %s: %w" , destSubnet , sourceServer , err )
1760+ }
1761+ if switchPeeringReachable {
1762+ return Reachability {
1763+ Reachable : true ,
1764+ Reason : ReachabilityReasonSwitchPeering ,
1765+ }, nil
1766+ }
1767+
1768+ if ! checkGateway {
1769+ return Reachability {}, nil
1770+ }
1771+
1772+ sourceSubnets , err := apiutil .GetAttachedSubnets (ctx , kube , sourceServer )
1773+ if err != nil {
1774+ return Reachability {}, fmt .Errorf ("getting attached subnets for source server %s: %w" , sourceServer , err )
1775+ }
1776+
1777+ externals := & vpcapi.ExternalList {}
1778+ if err := kube .List (ctx , externals ); err != nil {
1779+ return Reachability {}, fmt .Errorf ("listing externals: %w" , err )
1780+ }
1781+ if len (externals .Items ) == 0 {
1782+ // No externals defined, can't be reachable via gateway
1783+ return Reachability {}, nil
1784+ }
1785+ externalNames := make ([]string , len (externals .Items ))
1786+ for i , ext := range externals .Items {
1787+ externalNames [i ] = ext .Name
1788+ }
1789+
1790+ for sourceSubnetName := range sourceSubnets {
1791+ if ! strings .Contains (sourceSubnetName , "/" ) {
1792+ return Reachability {}, fmt .Errorf ("source must be full VPC subnet name (<vpc-name>/<subnet-name>)" )
1793+ }
1794+ sourceParts := strings .SplitN (sourceSubnetName , "/" , 2 )
1795+ sourceVPC , sourceSubnet := sourceParts [0 ], sourceParts [1 ]
1796+ for _ , ext := range externalNames {
1797+ if r , err := IsSubnetReachableWithGatewayPeering (ctx , kube , sourceVPC , sourceSubnet , ext , "internet" ); err != nil {
1798+ return Reachability {}, err
1799+ } else if r .Reachable {
1800+ return r , nil
1801+ }
1802+ }
1803+ }
1804+
1805+ return Reachability {}, nil
1806+ }
1807+
17451808func IsServerReachable (ctx context.Context , kube kclient.Reader , sourceServer , destServer string , checkGateway bool ) (Reachability , error ) {
17461809 sourceSubnets , err := apiutil .GetAttachedSubnets (ctx , kube , sourceServer )
17471810 if err != nil {
0 commit comments