@@ -366,33 +366,51 @@ func (d *defaultLattice) FindServiceNetwork(ctx context.Context, nameOrId string
366366 nameOrId = config .DefaultServiceNetwork
367367 }
368368
369+ // Step 1: Try to find in local (owned) service networks
369370 input := & vpclattice.ListServiceNetworksInput {}
370371 allSn , err := d .ListServiceNetworksAsList (ctx , input )
371372 if err != nil {
372373 return nil , err
373374 }
374375
375376 snMatch , err := d .serviceNetworkMatch (allSn , nameOrId )
376- if err != nil {
377+
378+ // If found locally, return it with tags
379+ if err == nil {
380+ return d .buildServiceNetworkInfo (ctx , snMatch )
381+ }
382+
383+ // If error is not "not found", return the error
384+ if ! errors .Is (err , ErrNotFound ) {
377385 return nil , err
378386 }
379387
380- // try to fetch tags only if SN in the same aws account with controller's config
388+ // Step 2: Not found locally, try RAM-shared networks via VPC associations
389+ return d .findServiceNetworkViaVPCAssociation (ctx , nameOrId )
390+ }
391+
392+ // buildServiceNetworkInfo constructs ServiceNetworkInfo from a matched
393+ // service network, attempting to fetch tags if the network is local.
394+ func (d * defaultLattice ) buildServiceNetworkInfo (ctx context.Context , snMatch * vpclattice.ServiceNetworkSummary ) (* ServiceNetworkInfo , error ) {
381395 tags := Tags {}
396+
397+ // Try to fetch tags only if SN is in the same AWS account
382398 isLocal , err := d .isLocalResource (aws .StringValue (snMatch .Arn ))
383399 if err != nil {
384400 return nil , err
385401 }
402+
386403 if isLocal {
387404 tagsInput := vpclattice.ListTagsForResourceInput {ResourceArn : snMatch .Arn }
388405 tagsOutput , err := d .ListTagsForResourceWithContext (ctx , & tagsInput )
389406 if err != nil {
390407 aerr , ok := err .(awserr.Error )
391- // In case ownAccount is not set, we cant tell if SN is foreign.
408+ // In case ownAccount is not set, we can't tell if SN is foreign.
392409 // In this case access denied is expected.
393410 if ! ok || aerr .Code () != vpclattice .ErrCodeAccessDeniedException {
394411 return nil , err
395412 }
413+ // If access denied, proceed without tags
396414 } else {
397415 tags = tagsOutput .Tags
398416 }
@@ -404,6 +422,53 @@ func (d *defaultLattice) FindServiceNetwork(ctx context.Context, nameOrId string
404422 }, nil
405423}
406424
425+ // findServiceNetworkViaVPCAssociation attempts to find a service network
426+ // by examining VPC associations. This is used to discover RAM-shared
427+ // service networks that don't appear in ListServiceNetworks.
428+ func (d * defaultLattice ) findServiceNetworkViaVPCAssociation (ctx context.Context , nameOrId string ) (* ServiceNetworkInfo , error ) {
429+ // List all VPC-to-Service Network associations for the controller's VPC
430+ associations , err := d .ListServiceNetworkVpcAssociationsAsList (ctx ,
431+ & vpclattice.ListServiceNetworkVpcAssociationsInput {
432+ VpcIdentifier : aws .String (config .VpcID ),
433+ })
434+ if err != nil {
435+ return nil , fmt .Errorf ("failed to list VPC associations while searching for service network %s: %w" , nameOrId , err )
436+ }
437+
438+ // Find matching service network by name or ID
439+ var matches []* vpclattice.ServiceNetworkVpcAssociationSummary
440+ for _ , assoc := range associations {
441+ // Only consider active associations
442+ if aws .StringValue (assoc .Status ) != vpclattice .ServiceNetworkVpcAssociationStatusActive {
443+ continue
444+ }
445+
446+ if aws .StringValue (assoc .ServiceNetworkName ) == nameOrId ||
447+ aws .StringValue (assoc .ServiceNetworkId ) == nameOrId {
448+ matches = append (matches , assoc )
449+ }
450+ }
451+
452+ switch len (matches ) {
453+ case 0 :
454+ return nil , NewNotFoundError ("Service network" , nameOrId )
455+ case 1 :
456+ assoc := matches [0 ]
457+ return & ServiceNetworkInfo {
458+ SvcNetwork : vpclattice.ServiceNetworkSummary {
459+ Id : assoc .ServiceNetworkId ,
460+ Arn : assoc .ServiceNetworkArn ,
461+ Name : assoc .ServiceNetworkName ,
462+ },
463+ Tags : nil , // Cannot read tags for cross-account resources
464+ }, nil
465+ default :
466+ // Multiple matches - this shouldn't happen but handle defensively
467+ return nil , fmt .Errorf ("%w, multiple VPC associations found for service network %s" ,
468+ ErrNameConflict , nameOrId )
469+ }
470+ }
471+
407472// see utils.LatticeServiceName
408473func (d * defaultLattice ) FindService (ctx context.Context , latticeServiceName string ) (* vpclattice.ServiceSummary , error ) {
409474 input := vpclattice.ListServicesInput {}
0 commit comments