Skip to content

Commit

Permalink
Merge pull request #7 from jimzucker/cloud_formation
Browse files Browse the repository at this point in the history
#1 Cloud formation
  • Loading branch information
jimzucker authored Dec 20, 2020
2 parents 8d3b625 + 4e54f18 commit fd4a1c8
Show file tree
Hide file tree
Showing 3 changed files with 148 additions and 10 deletions.
5 changes: 5 additions & 0 deletions build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
rm -fr target
mkdir target
cd target
zip get_forecast.zip ../get_forecast.py
aws s3 --profile jim-zucker cp get_forecast.zip s3://jimzucker-github-getforecast
19 changes: 9 additions & 10 deletions get_forecast.py
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,6 @@ def calc_forecast(boto3_session):
}
}

#get accountname for organization
org_account_id = sts.get_caller_identity().get('Account')
org_name=org.describe_account(AccountId=org_account_id)['Account']['Name']


utcnow = datetime.datetime.utcnow()
today = utcnow.strftime('%Y-%m-%d')
first_day_of_month = utcnow.strftime('%Y-%m') + "-01"
Expand Down Expand Up @@ -217,7 +212,7 @@ def calc_forecast(boto3_session):
"account_name": 'Total',
"amount_usage": amount_usage,
"amount_forecast": amount_forecast,
"forecast_variance": (amount_forecast-amount_usage_prior_month) / amount_usage_prior_month *100
"forecast_variance": forecast_variance
}
output=[]
output.append(result)
Expand Down Expand Up @@ -286,14 +281,19 @@ def calc_forecast(boto3_session):
if amount_usage_prior_month > 0 :
variance = (amount_forecast-amount_usage_prior_month) / amount_usage_prior_month *100

account_name=org.describe_account(AccountId=linked_account)['Account']['Name']
try:
account_name=org.describe_account(AccountId=linked_account)['Account']['Name']
except AWSOrganizationsNotInUseException as e:
account_name=linked_account

result = {
"account_name": account_name,
"amount_usage": amount_usage,
"amount_forecast": amount_forecast,
"forecast_variance": variance
}
output.append(result)

return output


Expand All @@ -317,7 +317,7 @@ def format_rows(output,account_width):
lines = sorted(output, key=lambda k: k.get('amount_forecast'), reverse=True)
for line in lines :
if len(lines) == 2 and line.get('account_name') == 'Total':
break
continue
change = "{0:,.1f}%".format(line.get('forecast_variance'))
row = {
"Account": line.get('account_name')[:account_width].ljust(account_width),
Expand All @@ -326,11 +326,10 @@ def format_rows(output,account_width):
"Change": change.rjust(change_width)
}
output_rows.append(row)

return output_rows

def publish_forecast(boto3_session) :

#read params
columns_displayed = ["Account", "MTD", "Forecast", "Change"]
if 'GET_FORECAST_COLUMNS_DISPLAYED' in os.environ:
Expand Down
134 changes: 134 additions & 0 deletions get_forecast_cf.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@


Parameters:
slackUrlParameter:
NoEcho: true
Type: String
Default: ""
Description: Enter slack url if you want slack sent.

cronParameter:
Type: String
Default: "cron(0 14 * * ? *)"
Description: Schedule expression.

snsArnParameter:
Type: String
Default: ""
Description: Enter sns ARN if you want slack sent.

columnsToDisplayParameter:
Type: String
Default: "Account,MTD,Forecast,Change"
Description: Specify column order and columns to display.

getForecastAccountNameColumnWidth:
Type: Number
Default: 17
Description: Specify max width for account names.

Conditions:
useSnsCondition: !Not [ !Equals [ !Ref snsArnParameter , "" ] ]

Resources:
#create a role for lambda
getForecastFunctionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: "/"
Policies:
- PolicyName: root
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:*
Resource: arn:aws:logs:*:*:*
- Effect: Allow
Action:
- organizations:DescribeAccount
Resource: "*"
- Effect: Allow
Action:
- ce:GetCostAndUsage
Resource: "*"
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'

getForecastLambda:
Type: AWS::Lambda::Function
Properties:
FunctionName: getForecastLambda
Role: !GetAtt getForecastFunctionRole.Arn
Timeout: 30
Handler: get_forecast.lambda_handler
Runtime: python3.6
Code:
S3Bucket: jimzucker-github-getforecast
S3Key: get_forecast.zip
Description: Post current forecast to slack.

getForecastLambdaPermission:
Condition: useSnsCondition
Type: 'AWS::Lambda::Permission'
Properties:
Action: 'lambda:InvokeFunction'
FunctionName: !Ref getForecastLambda
Principal: sns.amazonaws.com
SourceArn: !Ref snsArnParameter

# if you dont define this it will get created but will have a indefinite retention
# so we define it to ensure lgos roll
getForecastLambdaLogGroup:
Type: 'AWS::Logs::LogGroup'
DependsOn: getForecastLambda
Properties:
LogGroupName: !Sub "/aws/lambda/${getForecastLambda}"
RetentionInDays: '7'


getForecastScheduledRule:
Type: AWS::Events::Rule
Properties:
Description: "Crontab schedule for daily forecast"
ScheduleExpression: !Ref cronParameter
# ScheduleExpression: "cron(0 14 * * ? *)"
State: "ENABLED"
Targets:
-
Arn:
Fn::GetAtt:
- "getForecastLambda"
- "Arn"
Id: "TargetFunctionV1"

getForecastScheduledRulePermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !Ref "getForecastLambda"
Action: "lambda:InvokeFunction"
Principal: "events.amazonaws.com"
SourceArn:
Fn::GetAtt:
- "getForecastScheduledRule"
- "Arn"

awsGenieSecretManager:
Type: 'AWS::SecretsManager::Secret'
Properties:
Name: awsgenie_secret_manager
SecretString: !Join [ '', [ '{"slack_url":', !Ref slackUrlParameter, '"sns_arn":', !Ref snsArnParameter, '}' ]]



################################################################################################

0 comments on commit fd4a1c8

Please sign in to comment.