hibernate 0.1.0 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e1e5b683d653f45c6747b92d58f5bc5258111837bec3eec25945c0e8b58de37f
4
- data.tar.gz: acb1ea6c6401883e116ee44da22f5179ff3009424fc90ff3d5f5db5e650470c3
3
+ metadata.gz: 21e7dde6cd66464fa7aff8bc01d5f1338e65ba5f180d27c6d7fc176fcf9dbff5
4
+ data.tar.gz: 84a9f6eb6fd06373cbe68b686048107636cb2821eee5284b9a408062378e05f8
5
5
  SHA512:
6
- metadata.gz: 0b96aa6e000fbe289ea668497918d6352103e398560e112e20898ff9a2b65583340e132e369b308990eaeede6a954c951ea9bf52a1f8947a8307336abe29a18e
7
- data.tar.gz: 92c1af50b90c66fe7ee91101e37ae76ca6abb63e2e5fb1671adc1fbfcf2d9f904b0dced62b999b1bbd3a09c48b43ee02d8cbd625c29ddcd2e8ca25e2935dac54
6
+ metadata.gz: 250624e8f6984ca9cee0685c8d99a990e6fb45c66a88a16a9fd1bc68f430d252c1377d55ca31f1b95806250748e1b8be683fef73f374e1dc708bbba77b65f8e0
7
+ data.tar.gz: 5495ddec8a33acf9c2b4a8eeb8026f762d8f37716912bb238d6c797587403e62f0bb8023202d1755b522f6e09292146bc298e97e1bd335febed73124d54a7658
data/bin/hibernate CHANGED
@@ -4,42 +4,68 @@ require 'optparse'
4
4
  require_relative '../lib/hibernate/lambda_setup'
5
5
  require_relative '../lib/hibernate/ec2_manager'
6
6
 
7
- # Define the command-line interface
8
7
  class HibernateCLI
9
8
  def self.run
10
9
  command = nil
11
10
  options = {}
12
11
 
12
+ if ARGV.include?('setup')
13
+ command = :setup
14
+ ARGV.delete('setup')
15
+ elsif ARGV.include?('rule')
16
+ command = :manage_ec2
17
+ ARGV.delete('rule')
18
+ end
19
+
13
20
  parser = OptionParser.new do |parser|
14
21
  parser.banner = "Usage: hibernate [command] [options]"
15
22
 
16
- # Command for setting up the Lambda function
17
- parser.on('setup', 'Create the Lambda function') do
18
- command = :setup
23
+ parser.on('--instance-name=<INSTANCE_NAME>', 'Specify the EC2 instance name') do |instance_name|
24
+ options[:instance_name] = instance_name
19
25
  end
20
26
 
21
- # Command for managing EC2 instances
22
- parser.on('node', 'Manage EC2 instances') do
23
- command = :manage_ec2
27
+ parser.on('--start-expression=<START_CRON>', 'Specify the cron expression to start the instance') do |start_cron|
28
+ options[:start_cron] = start_cron
24
29
  end
25
30
 
26
- # Options for the EC2 management command
27
- parser.on('--in=<INSTANCE_NAME>', 'Specify the EC2 instance name') do |instance_name|
28
- options[:instance_name] = instance_name
31
+ parser.on('--stop-expression=<STOP_CRON>', 'Specify the cron expression to stop the instance') do |stop_cron|
32
+ options[:stop_cron] = stop_cron
29
33
  end
30
34
 
31
- parser.on('--start_instance=<START_CRON>', 'Specify the cron expression to start the instance') do |start_cron|
32
- options[:start_cron] = start_cron
35
+ parser.on('--start-instance=<true/false>', 'Filter start rules') do |start_instance|
36
+ options[:start_instance] = start_instance == 'true'
33
37
  end
34
38
 
35
- parser.on('--stop_instance=<STOP_CRON>', 'Specify the cron expression to stop the instance') do |stop_cron|
36
- options[:stop_cron] = stop_cron
39
+ parser.on('--stop-instance=<true/false>', 'Filter stop rules') do |stop_instance|
40
+ options[:stop_instance] = stop_instance == 'true'
41
+ end
42
+
43
+ parser.on('--rule-name=<RULE Name>', 'Specify the rule name to remove or update') do |rule_name|
44
+ options[:rule_name] = rule_name
45
+ end
46
+
47
+ parser.on('--update', 'Update an existing rule') do
48
+ options[:update] = true
49
+ end
50
+
51
+ parser.on('--remove', 'Remove an existing rule') do
52
+ options[:remove] = true
53
+ end
54
+
55
+ parser.on('--create', 'Create a new rule') do
56
+ options[:create] = true
57
+ end
58
+
59
+ parser.on('--list', 'List rules') do
60
+ options[:list] = true
61
+ end
62
+
63
+ parser.on('--state=<enable/disable>', 'Set rule state to either enable or disable') do |state|
64
+ options[:state] = state
37
65
  end
38
66
  end
39
67
 
40
- # Parse the command-line arguments
41
68
  begin
42
- p ARGV # Debug: Print the command-line arguments
43
69
  parser.parse!(ARGV)
44
70
  rescue OptionParser::ParseError => e
45
71
  puts e.message
@@ -47,7 +73,6 @@ class HibernateCLI
47
73
  exit 1
48
74
  end
49
75
 
50
- # Ensure only one command is processed
51
76
  if command.nil?
52
77
  puts "Please provide a command."
53
78
  puts parser
@@ -58,27 +83,68 @@ class HibernateCLI
58
83
  when :setup
59
84
  create_lambda_function
60
85
  when :manage_ec2
61
- # Validate EC2 management command options
62
- if options[:instance_name].nil? || options[:start_cron].nil? || options[:stop_cron].nil?
63
- puts "Please provide the instance name, start cron expression, and stop cron expression."
64
- puts parser
65
- exit
66
- else
67
- manage_ec2(options[:instance_name], options[:start_cron], options[:stop_cron])
86
+ if options[:update]
87
+ update_ec2_rule_command(options)
88
+ elsif options[:remove]
89
+ remove_ec2_rule_command(options)
90
+ elsif options[:create]
91
+ create_ec2_rule_command(options)
92
+ elsif options[:list]
93
+ list_ec2_rule_command(options)
68
94
  end
69
95
  end
70
96
  end
71
97
 
72
98
  def self.create_lambda_function
73
- p "I am printed here in setup"
74
99
  LambdaSetup.new.run
75
100
  end
76
101
 
77
- def self.manage_ec2(instance_name, start_cron, stop_cron)
78
- p "I am printed here inside node"
79
- ec2_manager = EC2Manager.new(instance_name, start_cron, stop_cron)
80
- ec2_manager.create_event_rule
102
+ def self.create_ec2_rule_command(options)
103
+ if options[:instance_name].nil? || (options[:start_cron].nil? && options[:stop_cron].nil?)
104
+ puts "Please provide the instance name, and at least one cron expression (start or stop)."
105
+ puts "Usage: hibernate rule --create --instance-name=<INSTANCE_NAME> --start-expression=<START_CRON> --stop-expression=<STOP_CRON>"
106
+ exit
107
+ else
108
+ ec2_manager = EC2Manager.new(options[:instance_name])
109
+ ec2_manager.create_event_rule(options[:start_cron], options[:stop_cron])
110
+ end
111
+ end
112
+
113
+ def self.remove_ec2_rule_command(options)
114
+ if options[:rule_name].nil?
115
+ puts "Please provide the rule name to remove."
116
+ puts "Usage: hibernate rule --remove --rule-name=<RULE NAME>"
117
+ exit
118
+ else
119
+ ec2_manager = EC2Manager.new(options[:instance_name])
120
+ ec2_manager.remove_event_rule(options[:rule_name])
121
+ end
122
+ end
123
+
124
+ def self.list_ec2_rule_command(options)
125
+ ec2_manager = EC2Manager.new(options[:instance_name])
126
+ ec2_manager.list_event_rules(options)
127
+ end
128
+
129
+ def self.update_ec2_rule_command(options)
130
+ if options[:rule_name].nil?
131
+ puts "Please provide the rule name to update."
132
+ puts "Usage: hibernate rule --update --rule-name=<RULE_NAME> [--start-expression=<START_CRON>] [--stop-expression=<STOP_CRON>] [--state=<enable/disable>]"
133
+ exit
134
+ elsif options[:start_cron].nil? && options[:stop_cron].nil? && options[:state].nil?
135
+ puts "Please provide atleast one attribute to update."
136
+ puts "Usage: hibernate rule --update --rule-name=<RULE_NAME> [--start-expression=<START_CRON>] [--stop-expression=<STOP_CRON>] [--state=<enable/disable>]"
137
+ exit
138
+ else
139
+ ec2_manager = EC2Manager.new(options[:instance_name])
140
+ ec2_manager.update_event_rule(
141
+ rule_name: options[:rule_name],
142
+ start_cron: options[:start_cron],
143
+ stop_cron: options[:stop_cron],
144
+ state: options[:state]
145
+ )
146
+ end
81
147
  end
82
148
  end
83
149
 
84
- HibernateCLI.run
150
+ HibernateCLI.run
@@ -0,0 +1,232 @@
1
+ require 'aws-sdk-cloudwatchevents'
2
+ require 'json'
3
+ require 'dotenv/load'
4
+ require 'digest'
5
+
6
+ class CloudWatchEventManager
7
+ def initialize(events_client, instance_id = nil, instance_name = nil, lambda_function_arn)
8
+ @events_client = events_client
9
+ @instance_id = instance_id
10
+ @instance_name = instance_name
11
+ @lambda_function_arn = lambda_function_arn
12
+ @aws_region = ENV['AWS_REGION']
13
+ @account_id = ENV['ACCOUNT_ID']
14
+ @lambda_client = Aws::Lambda::Client.new(region: @aws_region)
15
+ end
16
+
17
+ attr_writer :instance_id, :instance_name
18
+
19
+ def create_start_rule(cron_expression)
20
+ rule_name = "StartInstanceRule-#{@instance_id}-#{cron_expression_hash(cron_expression)}"
21
+ create_rule(
22
+ rule_name,
23
+ cron_expression,
24
+ { instance_id: @instance_id, action: 'start' },
25
+ 'start'
26
+ )
27
+ end
28
+
29
+ def create_stop_rule(cron_expression)
30
+ rule_name = "StopInstanceRule-#{@instance_id}-#{cron_expression_hash(cron_expression)}"
31
+ create_rule(
32
+ rule_name,
33
+ cron_expression,
34
+ { instance_id: @instance_id, action: 'stop' },
35
+ 'stop'
36
+ )
37
+ end
38
+
39
+ def remove_rule(rule_name)
40
+ remove_rule_by_name(rule_name)
41
+ remove_lambda_permission(rule_name)
42
+ end
43
+
44
+ def list_event_rules(options)
45
+ next_token = nil
46
+
47
+ column_widths = {
48
+ rule_name: 40,
49
+ instance_id: 22,
50
+ schedule: 30,
51
+ state: 10,
52
+ action: 10
53
+ }
54
+
55
+ print_header(column_widths)
56
+
57
+ loop do
58
+ response = @events_client.list_rules(next_token: next_token)
59
+
60
+ response.rules.each do |rule|
61
+ process_rule(rule, options, column_widths)
62
+ end
63
+
64
+ next_token = response.next_token
65
+ break if next_token.nil?
66
+ end
67
+
68
+ print_footer(column_widths)
69
+ end
70
+
71
+ def update_rule_state(rule_name, state)
72
+ state = state == 'enable' ? 'ENABLED' : 'DISABLED'
73
+
74
+ rule_details = @events_client.describe_rule({ name: rule_name })
75
+
76
+ params = {
77
+ name: rule_name,
78
+ state: state,
79
+ description: rule_details.description
80
+ }
81
+
82
+ if rule_details.schedule_expression
83
+ params[:schedule_expression] = rule_details.schedule_expression
84
+ elsif rule_details.event_pattern
85
+ params[:event_pattern] = rule_details.event_pattern
86
+ else
87
+ puts "No ScheduleExpression or EventPattern found for rule '#{rule_name}'."
88
+ exit 1
89
+ end
90
+
91
+ @events_client.put_rule(params)
92
+ end
93
+
94
+ def get_instance_id_from_rule(rule_name)
95
+ response = @events_client.list_targets_by_rule({ rule: rule_name })
96
+ return nil if response.targets.empty?
97
+
98
+ target_input = response.targets[0].input
99
+ parsed_input = JSON.parse(target_input)
100
+ parsed_input['instance_id'] if parsed_input.key?('instance_id')
101
+ rescue Aws::CloudWatchEvents::Errors::ResourceNotFoundException => e
102
+ puts "Error fetching targets for rule: #{rule_name} - #{e.message}"
103
+ nil
104
+ end
105
+
106
+ def rule_exists?(rule_name)
107
+ begin
108
+ response = @events_client.describe_rule({ name: rule_name })
109
+ return true unless response.nil?
110
+ rescue Aws::CloudWatchEvents::Errors::ResourceNotFoundException
111
+ return false
112
+ end
113
+ end
114
+
115
+ private
116
+
117
+ def cron_expression_hash(cron_expression)
118
+ Digest::SHA256.hexdigest(cron_expression)[0..7]
119
+ end
120
+
121
+ def create_rule(rule_name, cron_expression, input_data, action)
122
+ @events_client.put_rule({
123
+ name: rule_name,
124
+ schedule_expression: "cron(#{cron_expression})",
125
+ state: 'ENABLED',
126
+ description: "Rule to #{action} EC2 instance #{@instance_id} (Name: #{@instance_name}) at specified time: cron(#{cron_expression})",
127
+ })
128
+
129
+ add_lambda_permission(rule_name)
130
+
131
+ @events_client.put_targets({
132
+ rule: rule_name,
133
+ targets: [
134
+ {
135
+ id: '1',
136
+ arn: @lambda_function_arn,
137
+ input: input_data.to_json,
138
+ },
139
+ ],
140
+ })
141
+
142
+ puts "#{action.capitalize} rule created for instance '#{@instance_name}' (ID: #{@instance_id})."
143
+ end
144
+
145
+ def add_lambda_permission(rule_name)
146
+ begin
147
+ @lambda_client.add_permission({
148
+ function_name: @lambda_function_arn,
149
+ statement_id: "#{rule_name}-Permission",
150
+ action: "lambda:InvokeFunction",
151
+ principal: "events.amazonaws.com",
152
+ source_arn: "arn:aws:events:#{@aws_region}:#{@account_id}:rule/#{rule_name}"
153
+ })
154
+
155
+ puts "Permission added for rule #{rule_name} to invoke Lambda #{@lambda_function_arn}."
156
+ rescue Aws::Lambda::Errors::ResourceConflictException => e
157
+ puts "Permission already exists: #{e.message}"
158
+ end
159
+ end
160
+
161
+ def remove_rule_by_name(rule_name)
162
+ @events_client.remove_targets({
163
+ rule: rule_name,
164
+ ids: ['1']
165
+ })
166
+ @events_client.delete_rule({
167
+ name: rule_name
168
+ })
169
+
170
+ puts "Removed rule '#{rule_name}'"
171
+ end
172
+
173
+ def remove_lambda_permission(rule_name)
174
+ begin
175
+ @lambda_client.remove_permission({
176
+ function_name: @lambda_function_arn,
177
+ statement_id: "#{rule_name}-Permission"
178
+ })
179
+ puts "Removed Lambda permission for rule '#{rule_name}' to invoke Lambda #{@lambda_function_arn}."
180
+ rescue Aws::Lambda::Errors::ResourceNotFoundException => e
181
+ puts "Permission not found: #{e.message}"
182
+ end
183
+ end
184
+
185
+ def print_header(column_widths)
186
+ total_width = column_widths.values.sum + 8
187
+ puts "-" * total_width
188
+ puts "| #{'Rule Name'.ljust(column_widths[:rule_name])} | " \
189
+ "#{ 'Instance ID'.ljust(column_widths[:instance_id])} | " \
190
+ "#{ 'Schedule (UTC)'.ljust(column_widths[:schedule])} | " \
191
+ "#{ 'State'.ljust(column_widths[:state])} | " \
192
+ "#{ 'Action'.ljust(column_widths[:action])} |"
193
+ puts "-" * total_width
194
+ end
195
+
196
+ def print_footer(column_widths)
197
+ total_width = column_widths.values.sum + 8
198
+ puts '-' * total_width
199
+ end
200
+
201
+ def process_rule(rule, options, column_widths)
202
+ targets = @events_client.list_targets_by_rule(rule: rule.name).targets
203
+ target = targets.find { |t| t.arn == @lambda_function_arn }
204
+
205
+ return unless target
206
+
207
+ input = JSON.parse(target.input)
208
+ action = input['action']
209
+ rule_instance_id = input['instance_id']
210
+
211
+ if matches_criteria?(rule_instance_id, action, options)
212
+ print_rule(rule, rule_instance_id, action, column_widths)
213
+ end
214
+ end
215
+
216
+ def matches_criteria?(rule_instance_id, action, options)
217
+ instance_id_match = options[:instance_id].nil? || options[:instance_id] == rule_instance_id
218
+ action_match = (options[:start_instance] && action == 'start') ||
219
+ (options[:stop_instance] && action == 'stop') ||
220
+ (options[:start_instance].nil? && options[:stop_instance].nil?)
221
+
222
+ instance_id_match && action_match
223
+ end
224
+
225
+ def print_rule(rule, rule_instance_id, action, column_widths)
226
+ puts "| #{rule.name.ljust(column_widths[:rule_name])} | " \
227
+ "#{rule_instance_id.ljust(column_widths[:instance_id])} | " \
228
+ "#{rule.schedule_expression.ljust(column_widths[:schedule])} | " \
229
+ "#{rule.state.ljust(column_widths[:state])} | " \
230
+ "#{action.capitalize.ljust(column_widths[:action])} |"
231
+ end
232
+ end
@@ -1,23 +1,26 @@
1
1
  require 'aws-sdk-ec2'
2
- require 'aws-sdk-cloudwatchevents'
3
2
  require 'dotenv/load'
4
3
  require 'json'
4
+ require_relative 'cloud_watch_event_manager' # Adjust the path to where the new class is located
5
5
 
6
6
  class EC2Manager
7
- def initialize(instance_name, start_cron, stop_cron)
7
+ def initialize(instance_name = nil)
8
8
  @instance_name = instance_name
9
- @start_cron = start_cron
10
- @stop_cron = stop_cron
11
9
  @aws_region = ENV['AWS_REGION']
12
10
  @account_id = ENV['ACCOUNT_ID']
13
-
11
+
14
12
  @ec2_client = Aws::EC2::Client.new(region: @aws_region)
15
13
  @events_client = Aws::CloudWatchEvents::Client.new(region: @aws_region)
16
-
14
+
17
15
  @lambda_function_name = "ec2_auto_shutdown_start_function"
18
- @instance_id = get_instance_id_by_name
16
+ @lambda_function_arn = construct_lambda_function_arn
17
+ @instance_id = get_instance_id_by_name unless @instance_name.nil?
18
+
19
+ @cloudwatch_event_manager = CloudWatchEventManager.new(@events_client, @instance_id, @instance_name, @lambda_function_arn)
19
20
  end
20
21
 
22
+ attr_writer :instance_name, :instance_id
23
+
21
24
  def get_instance_id_by_name
22
25
  response = @ec2_client.describe_instances({
23
26
  filters: [
@@ -36,59 +39,80 @@ class EC2Manager
36
39
  instance_id
37
40
  end
38
41
 
39
- def create_event_rule
40
- create_start_rule
41
- create_stop_rule
42
+ def create_event_rule(start_cron, stop_cron)
43
+ @cloudwatch_event_manager.create_start_rule(start_cron) unless start_cron.nil?
44
+ @cloudwatch_event_manager.create_stop_rule(stop_cron) unless stop_cron.nil?
42
45
  puts "CloudWatch Events created for instance '#{@instance_name}' (ID: #{@instance_id})."
43
46
  end
44
47
 
45
- private
48
+ def remove_event_rule(rule_name)
49
+ @cloudwatch_event_manager.remove_rule(rule_name)
50
+ puts "CloudWatch Events removed for rule: #{rule_name}."
51
+ end
46
52
 
47
- def create_start_rule
48
- lambda_function_arn = construct_lambda_function_arn
53
+ def list_event_rules(options)
54
+ options[:instance_id] = @instance_id unless @instance_id.nil?
55
+ @cloudwatch_event_manager.list_event_rules(options)
56
+ end
49
57
 
50
- @events_client.put_rule({
51
- name: "StartInstanceRule-#{@instance_id}",
52
- schedule_expression: "cron(#{@start_cron})",
53
- state: 'ENABLED',
54
- description: "Rule to start EC2 instance #{@instance_id} (Name: #{@instance_name}) at specified time",
55
- })
58
+ def update_event_rule(rule_name:, start_cron:, stop_cron:, state:)
59
+ rule_exists = @cloudwatch_event_manager.rule_exists?(rule_name)
56
60
 
57
- @events_client.put_targets({
58
- rule: "StartInstanceRule-#{@instance_id}",
59
- targets: [
60
- {
61
- id: '1',
62
- arn: lambda_function_arn,
63
- input: { instance_id: @instance_id, action: 'start' }.to_json,
64
- },
65
- ],
66
- })
67
- end
61
+ unless rule_exists
62
+ puts "Rule '#{rule_name}' does not exist."
63
+ exit 1
64
+ end
65
+
66
+ target_instance_id = @cloudwatch_event_manager.get_instance_id_from_rule(rule_name)
67
+ if target_instance_id.nil?
68
+ puts "No targets found for the rule '#{rule_name}'."
69
+ exit 1
70
+ end
68
71
 
69
- def create_stop_rule
70
- lambda_function_arn = construct_lambda_function_arn
72
+ instance_name = get_instance_name_by_id(target_instance_id)
71
73
 
72
- @events_client.put_rule({
73
- name: "StopInstanceRule-#{@instance_id}",
74
- schedule_expression: "cron(#{@stop_cron})",
75
- state: 'ENABLED',
76
- description: "Rule to stop EC2 instance #{@instance_id} (Name: #{@instance_name}) at specified time",
77
- })
74
+ @cloudwatch_event_manager.instance_id = target_instance_id
75
+ @cloudwatch_event_manager.instance_name = instance_name
78
76
 
79
- @events_client.put_targets({
80
- rule: "StopInstanceRule-#{@instance_id}",
81
- targets: [
82
- {
83
- id: '1',
84
- arn: lambda_function_arn,
85
- input: { instance_id: @instance_id, action: 'stop' }.to_json,
86
- },
87
- ],
88
- })
77
+ self.instance_id = target_instance_id
78
+ self.instance_name = instance_name
79
+
80
+ puts "Found instance ID: #{@instance_id} from the rule: #{rule_name}"
81
+
82
+ if start_cron || stop_cron
83
+ puts "Removing old rule: #{rule_name} as cron expression is being updated."
84
+ remove_event_rule(rule_name)
85
+
86
+ create_event_rule(start_cron, stop_cron)
87
+ puts "Created new rule with updated cron expression for instance '#{@instance_name}' (ID: #{@instance_id})."
88
+ end
89
+
90
+ return if state.nil?
91
+
92
+ @cloudwatch_event_manager.update_rule_state(rule_name, state)
93
+ puts "Rule '#{rule_name}' has been #{state == 'enable' ? 'enabled' : 'disabled'}."
89
94
  end
90
95
 
96
+ private
97
+
91
98
  def construct_lambda_function_arn
92
99
  "arn:aws:lambda:#{@aws_region}:#{@account_id}:function:#{@lambda_function_name}"
93
100
  end
94
- end
101
+
102
+ def get_instance_name_by_id(instance_id)
103
+ response = @ec2_client.describe_instances({
104
+ instance_ids: [instance_id]
105
+ })
106
+
107
+ if response.reservations.empty?
108
+ puts "No instance found with ID '#{instance_id}'."
109
+ return nil
110
+ end
111
+
112
+ instance = response.reservations[0].instances[0]
113
+ tags = instance.tags || []
114
+
115
+ name_tag = tags.find { |tag| tag.key == 'Name' }
116
+ name_tag&.value
117
+ end
118
+ end
@@ -1,12 +1,13 @@
1
1
  require 'aws-sdk-lambda'
2
- require 'aws-sdk-iam' # For creating the IAM role and policy
2
+ require 'aws-sdk-iam'
3
3
  require 'zip'
4
- require 'dotenv/load' # Automatically loads environment variables from .env
4
+ require 'dotenv/load'
5
5
  require 'fileutils'
6
+ require 'pry'
6
7
 
7
8
  class LambdaSetup
8
9
  def initialize
9
- @lambda_role_name = "ec2-auto-shutdown-start" # Define a unique role name
10
+ @lambda_role_name = "ec2-auto-shutdown-start"
10
11
  @lambda_handler = "ec2_auto_shutdown_start_function"
11
12
  @lambda_zip = "lambda_function.zip"
12
13
  @aws_region = ENV['AWS_REGION']
@@ -18,33 +19,34 @@ class LambdaSetup
18
19
  )
19
20
  end
20
21
 
21
- # Function to zip the Lambda function code
22
22
  def create_zip_file(dir)
23
- FileUtils.rm_f(@lambda_zip) # Remove any existing zip file
23
+ FileUtils.rm_f(@lambda_zip)
24
24
 
25
25
  Zip::File.open(@lambda_zip, Zip::File::CREATE) do |zip|
26
- Dir[File.join(dir, '**', '**')].each do |file|
27
- zip.add(file.sub(dir + '/', ''), file)
26
+ Dir.glob(File.join('lib', 'hibernate',dir, '**', '*')).each do |file|
27
+ next if File.directory?(file)
28
+ zip_path = File.basename(file)
29
+ puts "Adding #{file} as #{zip_path}"
30
+ File.open(file, 'rb') do |io|
31
+ zip.add(zip_path, io)
32
+ end
28
33
  end
29
34
  end
30
35
 
31
36
  puts "ZIP file created: #{@lambda_zip}"
32
37
  end
33
38
 
34
- # Function to check if an IAM role exists
35
39
  def iam_role_exists?(role_name)
36
40
  begin
37
41
  @iam_client.get_role(role_name: role_name)
38
- true # Role exists
42
+ true
39
43
  rescue Aws::IAM::Errors::NoSuchEntity
40
- false # Role does not exist
44
+ false
41
45
  end
42
46
  end
43
47
 
44
- # Function to create the IAM role and policy
45
48
  def create_lambda_role
46
49
  unless iam_role_exists?(@lambda_role_name)
47
- # Trust policy for Lambda service to assume this role
48
50
  trust_policy = {
49
51
  Version: "2012-10-17",
50
52
  Statement: [
@@ -58,14 +60,12 @@ class LambdaSetup
58
60
  ]
59
61
  }.to_json
60
62
 
61
- # Create the IAM role
62
63
  puts "Creating IAM role..."
63
64
  @iam_client.create_role({
64
65
  role_name: @lambda_role_name,
65
66
  assume_role_policy_document: trust_policy
66
67
  })
67
68
 
68
- # Define the custom policy for EC2 actions
69
69
  policy_document = {
70
70
  Version: "2012-10-17",
71
71
  Statement: [
@@ -81,7 +81,6 @@ class LambdaSetup
81
81
  ]
82
82
  }.to_json
83
83
 
84
- # Attach custom policy to the IAM role
85
84
  puts "Attaching custom EC2 policy to IAM role..."
86
85
  @iam_client.put_role_policy({
87
86
  role_name: @lambda_role_name,
@@ -89,7 +88,6 @@ class LambdaSetup
89
88
  policy_document: policy_document
90
89
  })
91
90
 
92
- # Attach basic execution role to allow CloudWatch logging
93
91
  @iam_client.attach_role_policy({
94
92
  role_name: @lambda_role_name,
95
93
  policy_arn: 'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole'
@@ -101,39 +99,35 @@ class LambdaSetup
101
99
  end
102
100
  end
103
101
 
104
- # Function to check if the Lambda function exists
105
102
  def lambda_function_exists?(function_name)
106
103
  begin
107
104
  @lambda_client.get_function(function_name: function_name)
108
- true # Lambda function exists
105
+ true
109
106
  rescue Aws::Lambda::Errors::ResourceNotFoundException
110
- false # Lambda function does not exist
107
+ false
111
108
  end
112
109
  end
113
110
 
114
- # Function to create the Lambda function
115
111
  def create_lambda_function
116
112
  role_arn = @iam_client.get_role(role_name: @lambda_role_name).role.arn
117
113
 
118
114
  if lambda_function_exists?(@lambda_handler)
119
115
  puts "Lambda function '#{@lambda_handler}' already exists. Skipping creation."
120
116
  else
121
- # Read the ZIP file as binary content
122
117
  zip_content = File.read(@lambda_zip)
123
118
 
124
- # Create Lambda function
125
119
  begin
126
120
  puts "Creating Lambda function..."
127
121
  @lambda_client.create_function({
128
122
  function_name: @lambda_handler,
129
- runtime: 'ruby3.2', # Specify your desired runtime
130
- role: role_arn, # Use the ARN of the newly created role
123
+ runtime: 'ruby3.2',
124
+ role: role_arn,
131
125
  handler: "#{@lambda_handler}.lambda_handler",
132
126
  code: {
133
127
  zip_file: zip_content,
134
128
  },
135
129
  description: 'Lambda function to start and stop EC2 instances',
136
- timeout: 30,
130
+ timeout: 30
137
131
  })
138
132
  puts "Lambda function created."
139
133
  rescue Aws::Lambda::Errors::ServiceError => e
@@ -142,10 +136,9 @@ class LambdaSetup
142
136
  end
143
137
  end
144
138
 
145
- # Main method to execute the setup
146
139
  def run
147
- create_zip_file('lambda_function') # Pass the directory containing your Lambda function code
140
+ create_zip_file('lambda_function')
148
141
  create_lambda_role
149
142
  create_lambda_function
150
143
  end
151
- end
144
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Hibernate
2
- VERSION = "0.1.0"
3
- end
4
+ VERSION = '0.1.3'
5
+ end
data/lib/hibernate.rb CHANGED
@@ -3,4 +3,8 @@ require 'aws-sdk-cloudwatch'
3
3
  require 'dotenv'
4
4
  require 'json'
5
5
 
6
- Dotenv.load
6
+ Dotenv.load
7
+
8
+ module Hibernate
9
+ require_relative 'hibernate/version'
10
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hibernate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
- - Your Name
7
+ - Manish Sharma
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-09-29 00:00:00.000000000 Z
11
+ date: 2024-10-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk-ec2
@@ -108,25 +108,28 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
- description: A Ruby gem to automate the management of EC2 instances using AWS Lambda.
111
+ description: A Ruby gem to automate the shutdown and start of our EC2 instances
112
112
  email:
113
- - youremail@example.com
113
+ - sharma.manish7575@gmail.com
114
114
  executables:
115
115
  - hibernate
116
116
  extensions: []
117
117
  extra_rdoc_files: []
118
118
  files:
119
- - Readme.md
120
119
  - bin/hibernate
121
120
  - lib/hibernate.rb
121
+ - lib/hibernate/cloud_watch_event_manager.rb
122
122
  - lib/hibernate/ec2_manager.rb
123
- - lib/hibernate/lambda_function/function.rb
123
+ - lib/hibernate/lambda_function/ec2_auto_shutdown_start_function.rb
124
124
  - lib/hibernate/lambda_setup.rb
125
125
  - lib/hibernate/version.rb
126
- homepage: https://github.com/yourusername/ec2_manager
126
+ homepage: https://github.com/maniSHarma7575/hibernate
127
127
  licenses:
128
128
  - MIT
129
- metadata: {}
129
+ metadata:
130
+ source_code_uri: https://github.com/maniSHarma7575/hibernate
131
+ homepage_uri: https://github.com/maniSHarma7575/hibernate
132
+ bug_tracker_uri: https://github.com/maniSHarma7575/hibernate/issues
130
133
  post_install_message:
131
134
  rdoc_options: []
132
135
  require_paths:
@@ -145,5 +148,5 @@ requirements: []
145
148
  rubygems_version: 3.5.1
146
149
  signing_key:
147
150
  specification_version: 4
148
- summary: Manage EC2 instances with Lambda functions
151
+ summary: Automating the shutdown and start of our EC2 instances
149
152
  test_files: []
data/Readme.md DELETED
File without changes