@@ -22,19 +22,28 @@ import (
2222 "sync/atomic"
2323
2424 ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types"
25+ "github.com/awslabs/operatorpkg/option"
2526 "sigs.k8s.io/controller-runtime/pkg/log"
2627
2728 "github.com/patrickmn/go-cache"
2829)
2930
30- // PlacementGroupScope optionally scopes ICE cache entries to a specific placement group and partition.
31- // When set, ICE entries are isolated so that placement-group-specific failures don't block non-PG launches.
32- type PlacementGroupScope struct {
33- // ID is the placement group ID (e.g., "pg-0123456789abcdef0")
34- ID string
35- // Partition is the partition number as a string (e.g., "3"). Empty when no specific partition is targeted
36- // or for non-partition placement groups.
37- Partition string
31+ // UnavailableOfferingsOption is a functional option for scoping ICE cache entries.
32+ type UnavailableOfferingsOption = option.Function [unavailableOfferingsOptions ]
33+
34+ type unavailableOfferingsOptions struct {
35+ placementGroupID string
36+ placementGroupPartition string
37+ }
38+
39+ // WithPlacementGroup scopes an ICE cache entry to a specific placement group ID.
40+ func WithPlacementGroup (id string ) UnavailableOfferingsOption {
41+ return func (o * unavailableOfferingsOptions ) { o .placementGroupID = id }
42+ }
43+
44+ // WithPlacementGroupPartition further scopes an ICE cache entry to a specific partition.
45+ func WithPlacementGroupPartition (partition string ) UnavailableOfferingsOption {
46+ return func (o * unavailableOfferingsOptions ) { o .placementGroupPartition = partition }
3847}
3948
4049// UnavailableOfferings stores any offerings that return ICE (insufficient capacity errors) when
@@ -93,8 +102,8 @@ func (u *UnavailableOfferings) SeqNum(instanceType ec2types.InstanceType) uint64
93102// The pgScope parameter scopes the lookup so that an ICE from a placement group launch
94103// does not incorrectly prevent launches of the same instance type + zone without that placement group.
95104// When a partition is specified in the scope, the lookup is further scoped to that partition.
96- func (u * UnavailableOfferings ) IsUnavailable (instanceType ec2types.InstanceType , zone , capacityType string , pgScope ... PlacementGroupScope ) bool {
97- _ , offeringFound := u .offeringCache .Get (u .key (instanceType , zone , capacityType , pgScope ... ))
105+ func (u * UnavailableOfferings ) IsUnavailable (instanceType ec2types.InstanceType , zone , capacityType string , opts ... UnavailableOfferingsOption ) bool {
106+ _ , offeringFound := u .offeringCache .Get (u .key (instanceType , zone , capacityType , opts ... ))
98107 _ , capacityTypeFound := u .capacityTypeCache .Get (capacityType )
99108 _ , azFound := u .azCache .Get (zone )
100109 return offeringFound || capacityTypeFound || azFound
@@ -104,7 +113,8 @@ func (u *UnavailableOfferings) IsUnavailable(instanceType ec2types.InstanceType,
104113// The pgScope parameter scopes the cache entry so that placement-group-specific ICEs don't
105114// block non-PG launches of the same instance type + zone. When a partition is specified, the cache
106115// entry is further scoped so only that partition is marked unavailable.
107- func (u * UnavailableOfferings ) MarkUnavailable (ctx context.Context , instanceType ec2types.InstanceType , zone , capacityType string , unavailableReason map [string ]string , pgScope ... PlacementGroupScope ) {
116+ func (u * UnavailableOfferings ) MarkUnavailable (ctx context.Context , instanceType ec2types.InstanceType , zone , capacityType string , unavailableReason map [string ]string , opts ... UnavailableOfferingsOption ) {
117+ resolved := option .Resolve (opts ... )
108118 // even if the key is already in the cache, we still need to call Set to extend the cached entry's TTL
109119 logValues := []any {
110120 "reason" , unavailableReason ["reason" ],
@@ -113,10 +123,10 @@ func (u *UnavailableOfferings) MarkUnavailable(ctx context.Context, instanceType
113123 "capacity-type" , capacityType ,
114124 "ttl" , UnavailableOfferingsTTL ,
115125 }
116- if len ( pgScope ) > 0 && pgScope [ 0 ]. ID != "" {
117- logValues = append (logValues , "placement-group-id" , pgScope [ 0 ]. ID )
118- if pgScope [ 0 ]. Partition != "" {
119- logValues = append (logValues , "placement-group-partition" , pgScope [ 0 ]. Partition )
126+ if resolved . placementGroupID != "" {
127+ logValues = append (logValues , "placement-group-id" , resolved . placementGroupID )
128+ if resolved . placementGroupPartition != "" {
129+ logValues = append (logValues , "placement-group-partition" , resolved . placementGroupPartition )
120130 }
121131 }
122132 // Add fleetID if provided
@@ -126,7 +136,7 @@ func (u *UnavailableOfferings) MarkUnavailable(ctx context.Context, instanceType
126136 logValues = append (logValues , key , unavailableReason [key ])
127137 }
128138 log .FromContext (ctx ).WithValues (logValues ... ).V (1 ).Info ("removing offering from offerings" )
129- u .offeringCache .SetDefault (u .key (instanceType , zone , capacityType , pgScope ... ), struct {}{})
139+ u .offeringCache .SetDefault (u .key (instanceType , zone , capacityType , opts ... ), struct {}{})
130140 u .offeringCacheSeqNumMu .Lock ()
131141 u .offeringCacheSeqNum [instanceType ]++
132142 u .offeringCacheSeqNumMu .Unlock ()
@@ -156,12 +166,13 @@ func (u *UnavailableOfferings) Flush() {
156166// When a placement group scope is provided, the PG ID (and optionally partition) is included in the key
157167// to scope ICE entries per placement group and partition.
158168// Format: <capacityType>:<instanceType>:<zone>[:<pgID>[:<partition>]]
159- func (u * UnavailableOfferings ) key (instanceType ec2types.InstanceType , zone string , capacityType string , pgScope ... PlacementGroupScope ) string {
160- if len (pgScope ) > 0 && pgScope [0 ].ID != "" {
161- if pgScope [0 ].Partition != "" {
162- return fmt .Sprintf ("%s:%s:%s:%s:%s" , capacityType , instanceType , zone , pgScope [0 ].ID , pgScope [0 ].Partition )
169+ func (u * UnavailableOfferings ) key (instanceType ec2types.InstanceType , zone string , capacityType string , opts ... UnavailableOfferingsOption ) string {
170+ resolved := option .Resolve (opts ... )
171+ if resolved .placementGroupID != "" {
172+ if resolved .placementGroupPartition != "" {
173+ return fmt .Sprintf ("%s:%s:%s:%s:%s" , capacityType , instanceType , zone , resolved .placementGroupID , resolved .placementGroupPartition )
163174 }
164- return fmt .Sprintf ("%s:%s:%s:%s" , capacityType , instanceType , zone , pgScope [ 0 ]. ID )
175+ return fmt .Sprintf ("%s:%s:%s:%s" , capacityType , instanceType , zone , resolved . placementGroupID )
165176 }
166177 return fmt .Sprintf ("%s:%s:%s" , capacityType , instanceType , zone )
167178}
0 commit comments