forked from neillturner/terraform-aws-autospotting
-
-
Notifications
You must be signed in to change notification settings - Fork 35
/
Copy pathmain.tf
192 lines (162 loc) · 7.31 KB
/
main.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
module "label" {
source = "git::https://github.com/cloudposse/terraform-null-label.git?ref=0.25.0"
context = module.this
enabled = true
}
data "aws_arn" "role_arn" {
count = var.use_existing_iam_role ? 1 : 0
arn = var.existing_iam_role_arn
}
data "aws_arn" "permissions_boundary" {
count = var.permissions_boundary_arn != "" ? 1 : 0
arn = var.permissions_boundary_arn
}
data "aws_iam_role" "existing" {
count = var.use_existing_iam_role ? 1 : 0
name = split("/", data.aws_arn.role_arn[0].resource)[1]
}
data "aws_subnet" "existing" {
count = length(var.existing_subnets)
id = var.existing_subnets[count.index]
}
data "aws_regions" "current" {
lifecycle {
# The list of subnets should not be empty
/* postcondition {
condition = var.use_existing_subnets && length(var.existing_subnets) != 0
error_message = "The list of subnets should not be empty."
} */
}
}
data "aws_cloudwatch_event_bus" "default" {
name = "default"
}
locals {
all_regions = data.aws_regions.current.names
regions = var.autospotting_regions_enabled == [] ? local.all_regions : var.autospotting_regions_enabled
}
output "regions" {
value = local.regions
}
module "aws_lambda_function" {
source = "./modules/lambda"
label_context = module.label.context
lambda_cpu_architecture = var.lambda_cpu_architecture
lambda_source_ecr = var.lambda_source_ecr
lambda_source_image = var.lambda_source_image
lambda_source_image_tag = var.lambda_source_image_tag
lambda_timeout = var.lambda_timeout
lambda_memory_size = var.lambda_memory_size
lambda_tags = var.lambda_tags
lambda_use_public_ecr = var.lambda_use_public_ecr
sqs_fifo_queue_name = "${module.label.id}.fifo"
notify_email_addresses = var.notify_email_addresses
autospotting_allow_parallel_instance_replacements = var.autospotting_allow_parallel_instance_replacements
autospotting_allowed_instance_types = var.autospotting_allowed_instance_types
autospotting_automated_instance_data_update = var.autospotting_automated_instance_data_update
autospotting_bidding_policy = var.autospotting_bidding_policy
autospotting_consider_ebs_bandwidth = var.autospotting_consider_ebs_bandwidth
autospotting_cron_schedule = var.autospotting_cron_schedule
autospotting_cron_schedule_state = var.autospotting_cron_schedule_state
autospotting_cron_timezone = var.autospotting_cron_timezone
autospotting_disallowed_instance_types = var.autospotting_disallowed_instance_types
autospotting_enable_instance_rebalance_recommendation = var.autospotting_enable_instance_rebalance_recommendation
autospotting_instance_types_per_az = var.autospotting_instance_types_per_az
autospotting_min_on_demand_number = var.autospotting_min_on_demand_number
autospotting_min_on_demand_percentage = var.autospotting_min_on_demand_percentage
autospotting_on_demand_price_multiplier = var.autospotting_on_demand_price_multiplier
autospotting_prioritized_instance_types_bias = var.autospotting_prioritized_instance_types_bias
autospotting_regions_enabled = var.autospotting_regions_enabled
autospotting_savings_reports_frequency = var.autospotting_savings_reports_frequency
autospotting_spot_allocation_strategy = var.autospotting_spot_allocation_strategy
autospotting_spot_price_buffer_percentage = var.autospotting_spot_price_buffer_percentage
autospotting_tag_filtering_mode = var.autospotting_tag_filtering_mode
autospotting_tag_filters = var.autospotting_tag_filters
autospotting_termination_notification_action = var.autospotting_termination_notification_action
use_existing_iam_role = var.use_existing_iam_role
existing_iam_role_arn = var.use_existing_iam_role ? data.aws_arn.role_arn[0].arn : ""
use_existing_subnets = var.use_existing_subnets
existing_subnets = var.existing_subnets
permissions_boundary_arn = var.permissions_boundary_arn
}
# Regional resources that trigger the main Lambda function
module "regional" {
source = "./modules/regional"
autospotting_sqs_queue_url = module.aws_lambda_function.sqs_queue_url
autospotting_sqs_queue_arn = module.aws_lambda_function.sqs_queue_arn
label_context = module.label.context
regions = local.regions
put_event_role_arn = var.use_existing_iam_role ? var.existing_iam_role_arn : aws_iam_role.put_events_role[0].arn
}
resource "aws_lambda_permission" "cloudwatch_events_permission" {
statement_id = "AllowExecutionFromCloudWatch"
action = "lambda:InvokeFunction"
function_name = module.aws_lambda_function.function_name
principal = "events.amazonaws.com"
source_arn = aws_cloudwatch_event_rule.cloudwatch_frequency.arn
}
resource "aws_cloudwatch_event_target" "cloudwatch_target" {
rule = aws_cloudwatch_event_rule.cloudwatch_frequency.name
target_id = "run_autospotting"
arn = module.aws_lambda_function.arn
}
resource "aws_cloudwatch_event_rule" "cloudwatch_frequency" {
name = "${module.label.id}_frequency"
schedule_expression = var.lambda_run_frequency
}
resource "aws_cloudwatch_log_group" "log_group_autospotting" {
name = "/aws/lambda/${module.label.id}"
retention_in_days = 7
}
# Elastic Beanstalk policy
data "aws_iam_policy_document" "beanstalk" {
count = var.use_existing_iam_role ? 0 : 1
statement {
actions = [
"cloudformation:DescribeStackResource",
"cloudformation:DescribeStackResources",
"cloudformation:SignalResource",
"cloudformation:RegisterListener",
"cloudformation:GetListenerCredentials"
]
resources = ["*"]
}
}
resource "aws_iam_policy" "beanstalk_policy" {
count = var.use_existing_iam_role ? 0 : 1
name = "elastic_beanstalk_iam_policy_for_${module.label.id}"
policy = data.aws_iam_policy_document.beanstalk[0].json
}
resource "aws_iam_role" "put_events_role" {
count = var.use_existing_iam_role ? 0 : 1
name = "autospotting-event-bridge-role-${module.label.id}"
path = "/events/"
assume_role_policy = data.aws_iam_policy_document.put_events_assume_policy[0].json
force_detach_policies = true
permissions_boundary = var.permissions_boundary_arn != "" ? data.aws_arn.permissions_boundary[0].arn : null
}
data "aws_iam_policy_document" "put_events_policy" {
count = var.use_existing_iam_role ? 0 : 1
statement {
actions = [
"events:PutEvents",
]
resources = [data.aws_cloudwatch_event_bus.default.arn]
}
}
data "aws_iam_policy_document" "put_events_assume_policy" {
count = var.use_existing_iam_role ? 0 : 1
statement {
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["events.amazonaws.com"]
}
}
}
resource "aws_iam_role_policy" "put_event_policy_attachment" {
count = var.use_existing_iam_role ? 0 : 1
name = "policy_for_put_events_${module.label.id}"
role = aws_iam_role.put_events_role[count.index].id
policy = data.aws_iam_policy_document.put_events_policy[count.index].json
}