@@ -9,19 +9,21 @@ import (
99 "github.com/LeanerCloud/CUDly/pkg/common"
1010)
1111
12- // applyFilters applies region, instance type, engine, and engine version filters to recommendations
13- // currentRegion is the region being processed in the current loop iteration - if non-empty, only recommendations for that region are included
12+ // applyFilters applies region, instance type, engine, and engine version filters to recommendations.
13+ // currentRegion is the region being processed in the current loop iteration; if non-empty, only
14+ // recommendations for that region are included.
1415func applyFilters (recs []common.Recommendation , cfg Config , instanceVersions map [string ][]InstanceEngineVersion , versionInfo map [string ]MajorEngineVersionInfo , currentRegion string ) []common.Recommendation {
1516 var filtered []common.Recommendation
16- var poolDrops [] string
17+ var poolDropCount int
1718 var poolDropInstances float64
1819
19- for _ , rec := range recs {
20+ for i := range recs {
21+ rec := recs [i ]
2022 if cfg .MinPoolSize > 0 && ! shouldIncludePoolSize (rec , cfg ) {
2123 poolDropInstances += rec .AverageInstancesUsedPerHour
2224 label := fmt .Sprintf ("%s/%s/%s" , rec .Service , rec .Region , rec .ResourceType )
2325 log .Printf ("INFO: --min-pool-size=%.1f dropped %s (avg=%.2f < threshold)" , cfg .MinPoolSize , label , rec .AverageInstancesUsedPerHour )
24- poolDrops = append ( poolDrops , label )
26+ poolDropCount ++
2527 continue
2628 }
2729 adjusted , include := processRecommendation (rec , cfg , instanceVersions , versionInfo , currentRegion )
@@ -30,8 +32,8 @@ func applyFilters(recs []common.Recommendation, cfg Config, instanceVersions map
3032 }
3133 }
3234
33- if len ( poolDrops ) > 0 {
34- log .Printf ("INFO: --min-pool-size dropped %d recommendation(s) (%.2f avg instances/hr total)" , len ( poolDrops ) , poolDropInstances )
35+ if poolDropCount > 0 {
36+ log .Printf ("INFO: --min-pool-size dropped %d recommendation(s) (%.2f avg instances/hr total)" , poolDropCount , poolDropInstances )
3537 }
3638
3739 return filtered
@@ -42,9 +44,9 @@ func applyFilters(recs []common.Recommendation, cfg Config, instanceVersions map
4244// boolean-filter checks are delegated to passesDimensionFilters to keep
4345// this function under gocyclo's complexity threshold.
4446func processRecommendation (rec common.Recommendation , cfg Config , instanceVersions map [string ][]InstanceEngineVersion , versionInfo map [string ]MajorEngineVersionInfo , currentRegion string ) (common.Recommendation , bool ) {
45- // Filter to only recommendations for the current region being processed
46- // This prevents duplicating recommendations across all regions
47- // Skip this filter for Savings Plans as they are account-level, not regional
47+ // Filter to only recommendations for the current region being processed.
48+ // This prevents duplicating recommendations across all regions.
49+ // Skip this filter for Savings Plans as they are account-level, not regional.
4850 if currentRegion != "" && rec .Region != currentRegion && ! common .IsSavingsPlan (rec .Service ) {
4951 return rec , false
5052 }
@@ -53,10 +55,10 @@ func processRecommendation(rec common.Recommendation, cfg Config, instanceVersio
5355 return rec , false
5456 }
5557
56- // Apply engine version filters - adjust instance count by subtracting extended support versions
58+ // Apply engine version filters - adjust instance count by subtracting extended support versions.
5759 if ! cfg .IncludeExtendedSupport {
5860 rec = adjustRecommendationForExcludedVersions (rec , instanceVersions , versionInfo )
59- // Skip if all instances were excluded (count reduced to 0)
61+ // Skip if all instances were excluded (count reduced to 0).
6062 if rec .Count <= 0 {
6163 return rec , false
6264 }
@@ -66,11 +68,11 @@ func processRecommendation(rec common.Recommendation, cfg Config, instanceVersio
6668}
6769
6870// passesDimensionFilters runs the stateless include/exclude checks on
69- // region, instance type, engine, account, and pool size . Returns false on
71+ // region, instance type, engine, and account . Returns false on
7072// the first failing filter. Split out of processRecommendation to keep
7173// each function's cyclomatic complexity under the gocyclo limit; the
7274// dimension filters here are pure functions of rec + cfg with no side
73- // effects.
75+ // effects. Pool-size filtering is handled with logging in applyFilters.
7476func passesDimensionFilters (rec common.Recommendation , cfg Config ) bool {
7577 if ! shouldIncludeRegion (rec .Region , cfg ) {
7678 return false
@@ -84,21 +86,18 @@ func passesDimensionFilters(rec common.Recommendation, cfg Config) bool {
8486 if ! shouldIncludeAccount (rec .AccountName , cfg ) {
8587 return false
8688 }
87- if ! shouldIncludePoolSize (rec , cfg ) {
88- return false
89- }
9089 return true
9190}
9291
9392// shouldIncludePoolSize filters out RI recommendations for pools whose
9493// AverageInstancesUsedPerHour is below cfg.MinPoolSize. The purpose is to
9594// drop tiny pools where integer-arithmetic sizing forces 100% coverage
96- // regardless of --target-coverage (e.g. avg=1 with target=80% → floor(0.8)=0
95+ // regardless of --target-coverage (e.g. avg=1 with target=80% -> floor(0.8)=0
9796// drops, ceil(0.8)=1 over-covers). Setting --min-pool-size=2 keeps pools
9897// where target can be meaningfully approximated.
9998//
10099// Pass-through cases: filter disabled (MinPoolSize<=0), or rec has no
101- // per-hour signal (avg<=0 — SPs and recs CE didn't return usage for).
100+ // per-hour signal (avg<=0 -- SPs and recs CE didn't return usage for).
102101// Those pools aren't sized via the per-hour formula so the filter doesn't
103102// apply to them.
104103func shouldIncludePoolSize (rec common.Recommendation , cfg Config ) bool {
@@ -111,53 +110,53 @@ func shouldIncludePoolSize(rec common.Recommendation, cfg Config) bool {
111110 return rec .AverageInstancesUsedPerHour >= cfg .MinPoolSize
112111}
113112
114- // shouldIncludeRegion checks if a region should be included based on filters
113+ // shouldIncludeRegion checks if a region should be included based on filters.
115114func shouldIncludeRegion (region string , cfg Config ) bool {
116- // If include list is specified, region must be in it
115+ // If include list is specified, region must be in it.
117116 if len (cfg .IncludeRegions ) > 0 && ! slices .Contains (cfg .IncludeRegions , region ) {
118117 return false
119118 }
120119
121- // If exclude list is specified, region must not be in it
120+ // If exclude list is specified, region must not be in it.
122121 if slices .Contains (cfg .ExcludeRegions , region ) {
123122 return false
124123 }
125124
126125 return true
127126}
128127
129- // shouldIncludeInstanceType checks if an instance type should be included based on filters
128+ // shouldIncludeInstanceType checks if an instance type should be included based on filters.
130129func shouldIncludeInstanceType (instanceType string , cfg Config ) bool {
131- // If include list is specified, instance type must be in it
130+ // If include list is specified, instance type must be in it.
132131 if len (cfg .IncludeInstanceTypes ) > 0 && ! slices .Contains (cfg .IncludeInstanceTypes , instanceType ) {
133132 return false
134133 }
135134
136- // If exclude list is specified, instance type must not be in it
135+ // If exclude list is specified, instance type must not be in it.
137136 if slices .Contains (cfg .ExcludeInstanceTypes , instanceType ) {
138137 return false
139138 }
140139
141140 return true
142141}
143142
144- // shouldIncludeEngine checks if a recommendation should be included based on engine filters
143+ // shouldIncludeEngine checks if a recommendation should be included based on engine filters.
145144func shouldIncludeEngine (rec common.Recommendation , cfg Config ) bool {
146- // Extract engine from recommendation
145+ // Extract engine from recommendation.
147146 engine := getEngineFromRecommendation (rec )
148147 if engine == "" {
149- // If no engine info, include by default unless there's an include list
148+ // If no engine info, include by default unless there's an include list.
150149 return len (cfg .IncludeEngines ) == 0
151150 }
152151
153- // Normalize engine name to lowercase for comparison
152+ // Normalize engine name to lowercase for comparison.
154153 engine = strings .ToLower (engine )
155154
156- // If include list is specified, engine must be in it
155+ // If include list is specified, engine must be in it.
157156 if len (cfg .IncludeEngines ) > 0 {
158157 found := false
159158 for _ , e := range cfg .IncludeEngines {
160- if strings .ToLower ( e ) == engine {
159+ if strings .EqualFold ( e , engine ) {
161160 found = true
162161 break
163162 }
@@ -167,10 +166,10 @@ func shouldIncludeEngine(rec common.Recommendation, cfg Config) bool {
167166 }
168167 }
169168
170- // If exclude list is specified, engine must not be in it
169+ // If exclude list is specified, engine must not be in it.
171170 if len (cfg .ExcludeEngines ) > 0 {
172171 for _ , e := range cfg .ExcludeEngines {
173- if strings .ToLower ( e ) == engine {
172+ if strings .EqualFold ( e , engine ) {
174173 return false
175174 }
176175 }
@@ -179,29 +178,29 @@ func shouldIncludeEngine(rec common.Recommendation, cfg Config) bool {
179178 return true
180179}
181180
182- // shouldIncludeAccount checks if an account should be included based on filters
181+ // shouldIncludeAccount checks if an account should be included based on filters.
183182func shouldIncludeAccount (accountName string , cfg Config ) bool {
184- // If account name is empty and there are filters, skip it (unless include list is empty)
183+ // If account name is empty and there are filters, skip it (unless include list is empty).
185184 if accountName == "" {
186185 return len (cfg .IncludeAccounts ) == 0 && len (cfg .ExcludeAccounts ) == 0
187186 }
188187
189188 accountLower := strings .ToLower (accountName )
190189
191- // Check include list
190+ // Check include list.
192191 if ! checkIncludeList (accountLower , cfg .IncludeAccounts ) {
193192 return false
194193 }
195194
196- // Check exclude list
195+ // Check exclude list.
197196 if checkExcludeList (accountLower , cfg .ExcludeAccounts ) {
198197 return false
199198 }
200199
201200 return true
202201}
203202
204- // checkIncludeList checks if an account matches the include filters
203+ // checkIncludeList checks if an account matches the include filters.
205204func checkIncludeList (accountLower string , includeAccounts []string ) bool {
206205 if len (includeAccounts ) == 0 {
207206 return true
@@ -216,7 +215,7 @@ func checkIncludeList(accountLower string, includeAccounts []string) bool {
216215 return false
217216}
218217
219- // checkExcludeList checks if an account matches any exclude filters
218+ // checkExcludeList checks if an account matches any exclude filters.
220219func checkExcludeList (accountLower string , excludeAccounts []string ) bool {
221220 for _ , filter := range excludeAccounts {
222221 if accountMatchesFilter (accountLower , filter ) {
@@ -226,7 +225,7 @@ func checkExcludeList(accountLower string, excludeAccounts []string) bool {
226225 return false
227226}
228227
229- // accountMatchesFilter checks if an account matches a filter pattern (exact or substring match)
228+ // accountMatchesFilter checks if an account matches a filter pattern (exact or substring match).
230229func accountMatchesFilter (accountLower , filter string ) bool {
231230 filterLower := strings .ToLower (filter )
232231 return filterLower == accountLower || strings .Contains (accountLower , filterLower )
0 commit comments