eleventh 0.0.0

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.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/bin/eleventh +87 -0
  3. data/lib/eleventh.rb +151 -0
  4. metadata +103 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 0372a28de281ad13d900d9655e3e1da0f21ae7a5
4
+ data.tar.gz: e105edd9947b1f4cd60df988fe98a23bb40adaf7
5
+ SHA512:
6
+ metadata.gz: acfd47ad4b59403f6aeacf62bb10852c5a9aad340c5c177e62a89ab628b9ccc6e94b2f36c53a97525865a8fa1f90abe5994eee3f3ca2b9d0dd924cfa3fb2db01
7
+ data.tar.gz: 2365d17939d494d10f8d25b2d333831e0270a73d392cd59e275f53c77a35a710a413db46a8e1a6e9d26477b30d4c6faa35581dcb1297a988f0fbe7eb54e5f567
data/bin/eleventh ADDED
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'commander/import'
5
+ require 'aws-sdk'
6
+
7
+ $:.push File.expand_path("../lib", __FILE__)
8
+ require 'eleventh'
9
+
10
+ program :version, Eleventh::VERSION
11
+ program :description, 'Synchronize locally developed Lambda functions to AWS Lambda'
12
+
13
+ program :help, 'Author', 'Michael Wood <mike@attendease.com>'
14
+ program :help, 'Website', 'https://attendease.com'
15
+ program :help_formatter, :compact
16
+
17
+ command :init do |c|
18
+ c.syntax = 'eleventh init <project> [options]'
19
+ c.description = 'Initializes a project of Lambda functions for syncing'
20
+ c.option '--project NAME', String, 'Project name'
21
+ c.option '--region REGION', String, 'AWS Region'
22
+ c.option '--profile_name YOUR_AWS_CLI_PROFILE', String, 'AWS CLI Profile'
23
+ c.option '--dest DIR', String, 'Destination directory'
24
+ c.action do |args, options|
25
+ profile_name = options.profile_name || 'default'
26
+
27
+ credentials = Aws::SharedCredentials.new(:profile_name => profile_name)
28
+
29
+ if credentials.loadable?
30
+ options.default \
31
+ :region => 'us-west-2'
32
+
33
+ project = args.first || options.project
34
+
35
+ unless project || options.region
36
+ say_error "Must specify --project NAME --region REGION --profile_name YOUR_AWS_CLI_PROFILE"
37
+ abort
38
+ end
39
+
40
+ if options.dest
41
+ initPath = File.expand_path(File.join(options.dest, project))
42
+ else
43
+ initPath = File.expand_path(File.join(Dir.pwd, project))
44
+ end
45
+
46
+ say "Amazing Web Services Config:"
47
+ say " AWS Region: #{options.region}"
48
+ say " AWS CLI Profile: #{profile_name}"
49
+ say " AWS Access Key ID: #{credentials.credentials.access_key_id}"
50
+ say " AWS Secret Access Key: #{credentials.credentials.secret_access_key}"
51
+
52
+ print "Initialize project to #{initPath}? [Y/n]: "
53
+ confirm = $stdin.gets.chomp
54
+
55
+ abort("Whoa, that was close!") if confirm.downcase == 'n'
56
+
57
+ say "Cool. Initializing project to #{initPath}..."
58
+
59
+ result = Eleventh.init_project(initPath, options.region, profile_name)
60
+
61
+ if result[:success]
62
+ say "Done."
63
+ else
64
+ say_error result[:message]
65
+ abort
66
+ end
67
+ else
68
+ say_error "You must set up your AWS CLI profile before proceeding."
69
+ abort
70
+ end
71
+ end
72
+ end
73
+
74
+ command :sync do |c|
75
+ c.syntax = 'eleventh sync [options]'
76
+ c.description = 'Synchronizes the local Lambda functions with AWS'
77
+ c.action do |args, options|
78
+ result = Eleventh.sync
79
+
80
+ if result[:success]
81
+ say "Done."
82
+ else
83
+ say_error result[:message]
84
+ abort
85
+ end
86
+ end
87
+ end
data/lib/eleventh.rb ADDED
@@ -0,0 +1,151 @@
1
+ require 'aws-sdk'
2
+ require 'json'
3
+ require 'zip'
4
+ require 'fileutils'
5
+ require 'base64'
6
+ require 'open-uri'
7
+
8
+ module Eleventh
9
+ VERSION = '0.0.0'
10
+
11
+ def self.init_project(initPath, region, profile_name)
12
+
13
+ unless File.exists?(initPath)
14
+ FileUtils.mkdir_p initPath
15
+ FileUtils.mkdir_p "#{initPath}/builds"
16
+
17
+ config = {
18
+ 'AWS' => {
19
+ 'Region' => region,
20
+ 'CredentialsProfile' => profile_name
21
+ }
22
+ }
23
+
24
+ File.open("#{initPath}/eleventh.json", "w+") { |file| file.write(JSON.pretty_generate config, :indent => ' ') }
25
+
26
+ lambda = Aws::Lambda::Client.new(
27
+ region: region,
28
+ credentials: Aws::SharedCredentials.new(:profile_name => profile_name)
29
+ )
30
+
31
+ lambda.list_functions.functions.each do |function|
32
+ self.init_function(initPath, lambda, function)
33
+ end
34
+
35
+ {:success => true}
36
+ else
37
+ {:success => false, :message => "Argh! Can't initialize the project there because something already exists." }
38
+ end
39
+ end
40
+
41
+ def self.init_function(initPath, lambda, function)
42
+ function_name = function.function_name
43
+
44
+ FileUtils.mkdir_p "#{initPath}/functions/#{function_name}"
45
+
46
+ config = {
47
+ "FunctionName" => function_name,
48
+ "MemorySize" => function.memory_size,
49
+ "Handler" => function.handler,
50
+ "Role" => function.role,
51
+ "Timeout" => function.timeout,
52
+ "Runtime" => function.runtime,
53
+ "Description" => function.description
54
+ }
55
+
56
+ File.open("#{initPath}/functions/#{function_name}/lambda.json", "w+") { |file| file.write(JSON.pretty_generate config, :indent => ' ') }
57
+
58
+ File.open("#{initPath}/builds/#{function.function_name}.zip", "wb") do |saved_file|
59
+ function_code = lambda.get_function(:function_name => function.function_name).code
60
+
61
+ open(function_code.location, "rb") do |read_file|
62
+ saved_file.write(read_file.read)
63
+ end
64
+ end
65
+
66
+ Zip::File.open("#{initPath}/builds/#{function_name}.zip") do |zip_file|
67
+ zip_file.each do |entry|
68
+ entry.extract("#{initPath}/functions/#{function_name}/#{entry.name}")
69
+ end
70
+ end
71
+ end
72
+
73
+ def self.sync
74
+ if File.exists?('./eleventh.json')
75
+ config = JSON.parse(File.read('./eleventh.json'))
76
+
77
+ lambda = Aws::Lambda::Client.new(
78
+ region: config['AWS']['Region'],
79
+ credentials: Aws::SharedCredentials.new(:profile_name => config['AWS']['CredentialsProfile'])
80
+ )
81
+
82
+ begin
83
+ function_names = lambda.list_functions.functions.map{|f| f.function_name}
84
+
85
+ # Remove old builds
86
+ Dir.foreach('./builds') do |f|
87
+ if ['.', '..'].include? f then next
88
+ elsif File.directory?("./builds/#{f}") then FileUtils.rm_rf("./builds/#{f}")
89
+ else FileUtils.rm("./builds/#{f}")
90
+ end
91
+ end
92
+
93
+ local_functions = []
94
+
95
+ Dir.foreach('./functions') do |f|
96
+ if ['.', '..'].include? f then next
97
+ else local_functions << f
98
+ end
99
+ end
100
+
101
+ local_functions.each do |function_name|
102
+ if File.exists?("./functions/#{function_name}/lambda.json")
103
+ function_config = JSON.parse(File.read("./functions/#{function_name}/lambda.json"))
104
+
105
+ Zip::File.open("./builds/#{function_name}.zip", Zip::File::CREATE) do |zipfile|
106
+ zipfile.add('index.js', "./functions/#{function_name}/index.js")
107
+ end
108
+
109
+ if function_names.include? function_name
110
+ resp = lambda.update_function_configuration({
111
+ function_name: function_name,
112
+ role: function_config['Role'],
113
+ handler: function_config['Handler'],
114
+ description: function_config['Description'],
115
+ timeout: function_config['Timeout'],
116
+ memory_size: function_config['MemorySize']
117
+ })
118
+
119
+ resp = lambda.update_function_code({
120
+ function_name: function_name,
121
+ zip_file: File.read("./builds/#{function_name}.zip")
122
+ })
123
+ else
124
+ resp = lambda.create_function({
125
+ function_name: function_name,
126
+ runtime: function_config['Runtime'],
127
+ role: function_config['Role'],
128
+ handler: function_config['Handler'],
129
+ description: function_config['Description'],
130
+ timeout: function_config['Timeout'],
131
+ memory_size: function_config['MemorySize'],
132
+ code: {
133
+ zip_file: File.read("./builds/#{function_name}.zip")
134
+ },
135
+ })
136
+ end
137
+
138
+ puts "Synced #{function_name} (#{resp.function_arn})"
139
+ end
140
+ end
141
+
142
+ {:success => true}
143
+ rescue Aws::Lambda::Errors::ServiceError => e
144
+ puts e.message
145
+ {:success => false, :message => "Oh no! Something went wrong."}
146
+ end
147
+ else
148
+ {:success => false, :message => "Darn! No eleventh.json config file."}
149
+ end
150
+ end
151
+ end
metadata ADDED
@@ -0,0 +1,103 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: eleventh
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Michael Wood
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-08-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: commander
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '4.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '4.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: json
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.8'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.8'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rubyzip
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.1'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: aws-sdk
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.1'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.1'
69
+ description: This gem will synchronize locally developed Lambda functions to Amazon
70
+ Web Services Lambda.
71
+ email: support@attendease.com
72
+ executables:
73
+ - eleventh
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - bin/eleventh
78
+ - lib/eleventh.rb
79
+ homepage: https://attendease.com
80
+ licenses:
81
+ - MIT
82
+ metadata: {}
83
+ post_install_message:
84
+ rdoc_options: []
85
+ require_paths:
86
+ - lib
87
+ required_ruby_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ requirements: []
98
+ rubyforge_project:
99
+ rubygems_version: 2.2.3
100
+ signing_key:
101
+ specification_version: 4
102
+ summary: Synchronize locally developed Lambda functions to AWS Lambda.
103
+ test_files: []