import { cloneDeep } from 'lodash' ; import type { ISimplePolicyDescription , IStepPolicyDescription , IUpsertAlarmDescription , IUpsertScalingPolicyCommand , } from '../ScalingPolicyWriter' ; import type { IAmazonServerGroup , IScalingPolicy , IScalingPolicyAlarm , IStepAdjustment , ITargetTrackingPolicy , } from '../../../../domain' ; type PolicyType = 'Step' | 'TargetTracking' ; export const ScalingPolicyCommandBuilder = { buildAlarm : ( policy , region , asgName ) : IUpsertAlarmDescription => { const alarm = policy ?. alarms ? policy . alarms [ 0 ] : ( { } as IScalingPolicyAlarm ) ; return { name : alarm . alarmName , actionsEnabled : true , alarmActionArns : alarm . alarmActions , alarmDescription : alarm . alarmDescription , asgName : asgName , comparisonOperator : alarm . comparisonOperator , dimensions : alarm . dimensions , evaluationPeriods : alarm . evaluationPeriods , insufficientDataActionArns : alarm . insufficientDataActions , metricName : alarm . metricName , namespace : alarm . namespace , okActionArns : alarm . okactions , period : alarm . period , region , statistic : alarm . statistic , threshold : alarm . threshold , unit : alarm . unit , } ; } , buildStepPolicy : ( policy , threshold , cooldown ) : IStepPolicyDescription => { const stepAdjustments = policy . stepAdjustments . map ( ( adjustment ) => { const step = { scalingAdjustment : Math . abs ( adjustment . scalingAdjustment ) , } as IStepAdjustment ; if ( adjustment . metricIntervalUpperBound !== undefined ) { step . metricIntervalUpperBound = adjustment . metricIntervalUpperBound + threshold ; } if ( adjustment . metricIntervalLowerBound !== undefined ) { step . metricIntervalLowerBound = adjustment . metricIntervalLowerBound + threshold ; } return step ; } ) ; return { estimatedInstanceWarmup : policy . estimatedInstanceWarmup ?? cooldown ?? 600 , metricAggregationType : 'Average' , stepAdjustments , } ; } , buildSimplePolicy : ( policy ) : ISimplePolicyDescription => ( { cooldown : policy . cooldown ?? 600 , scalingAdjustment : Math . abs ( policy . scalingAdjustment ) ?? 1 , } ) , buildNewCommand : ( type , serverGroup , policy ) : IUpsertScalingPolicyCommand => { const command = { name : policy . policyName , adjustmentType : type === 'Step' ? policy . adjustmentType : null , cloudProvider : serverGroup . cloudProvider , credentials : serverGroup . account , provider : serverGroup . type , region : serverGroup . region , serverGroupName : serverGroup . name , } as IUpsertScalingPolicyCommand ; if ( type === 'Step' ) { command . alarm = ScalingPolicyCommandBuilder . buildAlarm ( policy , serverGroup . region , serverGroup . name ) ; command . minAdjustmentMagnitude = policy . minAdjustmentMagnitude ?? 1 ; if ( policy . stepAdjustments ?. length ) { command . step = ScalingPolicyCommandBuilder . buildStepPolicy ( policy , command . alarm . threshold , command . cooldown ) ; } else { command . simple = ScalingPolicyCommandBuilder . buildSimplePolicy ( policy ) ; } } if ( type === 'TargetTracking' ) { command . estimatedInstanceWarmup = policy . estimatedInstanceWarmup ?? 600 ; command . targetTrackingConfiguration = { ... policy . targetTrackingConfiguration } ; } return command ; } , prepareCommandForUpsert : ( command , isRemove ) : IUpsertScalingPolicyCommand => { const commandToSubmit = cloneDeep ( command ) ; if ( commandToSubmit . adjustmentType !== 'PercentChangeInCapacity' ) { delete commandToSubmit . minAdjustmentMagnitude ; } if ( commandToSubmit . step ) { commandToSubmit . step . stepAdjustments . forEach ( ( step ) => { if ( isRemove ) { step . scalingAdjustment = 0 - step . scalingAdjustment ; delete commandToSubmit . step . estimatedInstanceWarmup ; } if ( step . metricIntervalLowerBound !== undefined ) { step . metricIntervalLowerBound -= commandToSubmit . alarm . threshold ; } if ( step . metricIntervalUpperBound !== undefined ) { step . metricIntervalUpperBound -= commandToSubmit . alarm . threshold ; } } ) ; } else { if ( isRemove ) { command . simple . scalingAdjustment = 0 - command . simple . scalingAdjustment ; } } return commandToSubmit ; } , } ;