meroku 2.0.8 → 2.0.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +9 -5
  3. data/bin/meroku +1 -1
  4. data/circle.yml +23 -0
  5. data/frontend/Gemfile +5 -2
  6. data/frontend/Gemfile.lock +5 -2
  7. data/frontend/app/controllers/application_controller.rb +1 -0
  8. data/frontend/app/controllers/apps_controller.rb +46 -48
  9. data/frontend/app/controllers/publickeys_controller.rb +45 -46
  10. data/frontend/app/controllers/users/registrations_controller.rb +0 -15
  11. data/frontend/app/controllers/users/sessions_controller.rb +12 -3
  12. data/frontend/app/lib/cmd.rb +11 -0
  13. data/frontend/app/models/app.rb +18 -11
  14. data/frontend/app/models/publickey.rb +1 -1
  15. data/frontend/app/models/user.rb +5 -4
  16. data/frontend/app/policies/application_policy.rb +53 -0
  17. data/frontend/app/policies/publickey_policy.rb +7 -0
  18. data/frontend/app/serializable/serializable_user.rb +2 -1
  19. data/frontend/app/views/layouts/application.html.erb +1 -1
  20. data/frontend/config/database.yml +72 -10
  21. data/frontend/config/routes.rb +6 -14
  22. data/frontend/db/migrate/20171028150506_add_apisecret_to_users.rb +6 -0
  23. data/frontend/etc_nginx_sites-enabled_default +1 -1
  24. data/frontend/public/Meroku.html +140 -0
  25. data/frontend/public/Meroku/Api.html +129 -0
  26. data/frontend/public/Meroku/Api/Request.html +221 -0
  27. data/frontend/public/Meroku/Aws.html +212 -0
  28. data/frontend/public/Meroku/Aws/Ec2.html +477 -0
  29. data/frontend/public/Meroku/CLI.html +784 -0
  30. data/frontend/public/Meroku/CLI/AdminUser.html +192 -0
  31. data/frontend/public/Meroku/CLI/Help.html +224 -0
  32. data/frontend/public/Meroku/CLI/Secrets.html +191 -0
  33. data/frontend/public/Meroku/CLI/Session.html +460 -0
  34. data/frontend/public/Meroku/CLI/User.html +182 -0
  35. data/frontend/public/Meroku/Extensions.html +405 -0
  36. data/frontend/public/Meroku/Infrastructure.html +279 -0
  37. data/frontend/public/Meroku/Infrastructure/Node.html +785 -0
  38. data/frontend/public/Meroku/Infrastructure/Server.html +373 -0
  39. data/frontend/public/Meroku/Node.html +845 -0
  40. data/frontend/public/Meroku/Tunnel.html +701 -0
  41. data/frontend/public/Meroku/Tunnelable.html +243 -0
  42. data/frontend/public/_index.html +273 -0
  43. data/frontend/public/class_list.html +51 -0
  44. data/frontend/public/css/common.css +1 -0
  45. data/frontend/public/css/full_list.css +58 -0
  46. data/frontend/public/css/style.css +492 -0
  47. data/frontend/public/file.README.html +181 -0
  48. data/frontend/public/file_list.html +56 -0
  49. data/frontend/public/frames.html +17 -0
  50. data/frontend/public/index.html +181 -0
  51. data/frontend/public/js/app.js +248 -0
  52. data/frontend/public/js/full_list.js +216 -0
  53. data/frontend/public/js/jquery.js +4 -0
  54. data/frontend/public/method_list.html +395 -0
  55. data/frontend/public/robots.txt +2 -1
  56. data/frontend/public/top-level-namespace.html +110 -0
  57. data/frontend/test/policies/publickey_policy_test.rb +19 -0
  58. data/lib/meroku.rb +9 -7
  59. data/lib/meroku/api.rb +8 -0
  60. data/lib/meroku/api/request.rb +17 -0
  61. data/lib/meroku/aws.rb +14 -0
  62. data/lib/meroku/aws/ec2.rb +59 -0
  63. data/lib/meroku/cli.rb +80 -81
  64. data/lib/meroku/cli/help.rb +27 -0
  65. data/lib/meroku/cli/secrets.rb +13 -0
  66. data/lib/meroku/cli/session.rb +32 -51
  67. data/lib/meroku/extensions.rb +32 -0
  68. data/lib/meroku/infrastructure.rb +14 -17
  69. data/lib/meroku/infrastructure/server.rb +20 -0
  70. data/lib/meroku/node.rb +113 -0
  71. data/lib/meroku/tunnelable.rb +31 -0
  72. data/lib/meroku/version.rb +1 -1
  73. data/modified-cedar-14.sh +0 -4
  74. metadata +50 -9
  75. data/frontend/app/controllers/pages_controller.rb +0 -4
  76. data/frontend/app/views/pages/landing.html.erb +0 -2
  77. data/frontend/db/migrate/20171025193627_add_token_to_users.rb +0 -5
  78. data/lib/meroku/cli/admin_user.rb +0 -20
  79. data/lib/meroku/cli/user.rb +0 -14
  80. data/lib/meroku/infrastructure/node.rb +0 -102
  81. data/lib/meroku/tunnel.rb +0 -56
@@ -1 +1,2 @@
1
- # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file
1
+ User-agent: *
2
+ Disallow: /
@@ -0,0 +1,110 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>
7
+ Top Level Namespace
8
+
9
+ &mdash; Documentation by YARD 0.9.9
10
+
11
+ </title>
12
+
13
+ <link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
14
+
15
+ <link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
16
+
17
+ <script type="text/javascript" charset="utf-8">
18
+ pathId = "";
19
+ relpath = '';
20
+ </script>
21
+
22
+
23
+ <script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
24
+
25
+ <script type="text/javascript" charset="utf-8" src="js/app.js"></script>
26
+
27
+
28
+ </head>
29
+ <body>
30
+ <div class="nav_wrap">
31
+ <iframe id="nav" src="class_list.html?1"></iframe>
32
+ <div id="resizer"></div>
33
+ </div>
34
+
35
+ <div id="main" tabindex="-1">
36
+ <div id="header">
37
+ <div id="menu">
38
+
39
+ <a href="_index.html">Index</a> &raquo;
40
+
41
+
42
+ <span class="title">Top Level Namespace</span>
43
+
44
+ </div>
45
+
46
+ <div id="search">
47
+
48
+ <a class="full_list_link" id="class_list_link"
49
+ href="class_list.html">
50
+
51
+ <svg width="24" height="24">
52
+ <rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
53
+ <rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
54
+ <rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
55
+ </svg>
56
+ </a>
57
+
58
+ </div>
59
+ <div class="clear"></div>
60
+ </div>
61
+
62
+ <div id="content"><h1>Top Level Namespace
63
+
64
+
65
+
66
+ </h1>
67
+ <div class="box_info">
68
+
69
+
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+ </div>
80
+
81
+ <h2>Defined Under Namespace</h2>
82
+ <p class="children">
83
+
84
+
85
+ <strong class="modules">Modules:</strong> <span class='object_link'><a href="Meroku.html" title="Meroku (module)">Meroku</a></span>
86
+
87
+
88
+
89
+
90
+ </p>
91
+
92
+
93
+
94
+
95
+
96
+
97
+
98
+
99
+
100
+ </div>
101
+
102
+ <div id="footer">
103
+ Generated on Tue Oct 31 19:39:54 2017 by
104
+ <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
105
+ 0.9.9 (ruby-2.4.2).
106
+ </div>
107
+
108
+ </div>
109
+ </body>
110
+ </html>
@@ -0,0 +1,19 @@
1
+ require 'test_helper'
2
+
3
+ class PublickeyPolicyTest < ActiveSupport::TestCase
4
+
5
+ def test_scope
6
+ end
7
+
8
+ def test_show
9
+ end
10
+
11
+ def test_create
12
+ end
13
+
14
+ def test_update
15
+ end
16
+
17
+ def test_destroy
18
+ end
19
+ end
data/lib/meroku.rb CHANGED
@@ -1,19 +1,21 @@
1
+ require "fileutils"
1
2
  require "active_support/core_ext/object/try"
2
3
  require "net/ssh"
3
- require 'net/http'
4
+ require "net/http"
4
5
  require "escape"
5
6
  require "aws-sdk-ec2"
6
7
  require "dotenv"
7
8
  require "byebug"
8
- require 'rest-client'
9
+ require "rest-client"
10
+ require "meroku/extensions"
11
+ require "meroku/aws"
9
12
  require "meroku/version"
10
- require "meroku/tunnel"
11
- require "meroku/cli/user"
12
- require "meroku/cli/admin_user"
13
+ require "meroku/tunnelable"
14
+ require "meroku/node"
13
15
  require "meroku/infrastructure"
16
+ require "meroku/api"
14
17
  require "meroku/cli"
15
18
 
16
-
19
+ # My Heroku (Meroku)
17
20
  module Meroku
18
-
19
21
  end
data/lib/meroku/api.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'meroku/api/request'
2
+
3
+ module Meroku
4
+ # The api is the rails app/service running on the ec2 server
5
+ # handling login, logout, keys:add etc
6
+ module Api
7
+ end
8
+ end
@@ -0,0 +1,17 @@
1
+ module Meroku
2
+ module Api
3
+ # Wrapper around RestClient.post
4
+ module Request
5
+ def self.post(url, data)
6
+ response = RestClient.post(url, data.to_json,
7
+ timeout: 1,
8
+ content_type: :json,
9
+ accept: :json)
10
+ r = JSON.parse(response)
11
+ yield(r["data"]) if r.key?("data")
12
+ return unless r.key?("errors") && r["errors"].size.positive?
13
+ puts "error: #{r['errors'].map { |x| x['detail'] }.join('. ')}"
14
+ end
15
+ end
16
+ end
17
+ end
data/lib/meroku/aws.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'meroku/aws/ec2'
2
+
3
+ module Meroku
4
+ # Stuff related to Amazon Web Services
5
+ module Aws
6
+ IP = '34.239.241.218'
7
+
8
+ KEY_NAME = '~/crypto/meroku/meroku.id_rsa'
9
+
10
+ def self.bucket_url
11
+ "http://www.sam-we.com/dropbox/meroku-#{ENV['SECRET']}"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,59 @@
1
+
2
+ module Meroku
3
+ module Aws
4
+ # Logic related to the ec2 instances we use as servers
5
+ module Ec2
6
+ def tag
7
+ {
8
+ resource_type: 'instance',
9
+ tags: [
10
+ {
11
+ key: 'Name',
12
+ value: 'node'
13
+ }
14
+ ]
15
+ }
16
+ end
17
+
18
+ def make_instance
19
+ ec2_client.run_instances(
20
+ image_id: 'ami-841f46ff',
21
+ min_count: 1,
22
+ max_count: 1,
23
+ key_name: 'meroku.id_rsa',
24
+ instance_type: 't2.micro',
25
+ tag_specifications: [tag]
26
+ ).instances.first
27
+ end
28
+
29
+ def ec2_client
30
+ ::Aws::EC2::Client.new(
31
+ region: 'us-east-1',
32
+ credentials: ::Aws::Credentials.new(
33
+ ENV['AWS_ACCESS_KEY'],
34
+ ENV['AWS_SECRET']
35
+ )
36
+ )
37
+ end
38
+
39
+ def self.ec2_client
40
+ ::Aws::EC2::Client.new(
41
+ region: 'us-east-1',
42
+ credentials: ::Aws::Credentials.new(
43
+ ENV['AWS_ACCESS_KEY'],
44
+ ENV['AWS_SECRET']
45
+ )
46
+ )
47
+ end
48
+
49
+ def self.associate_address(eipalloc, id)
50
+ retries ||= 0
51
+ ec2_client.associate_address(allocation_id: eipalloc, instance_id: id)
52
+ rescue ::Aws::EC2::Errors::InvalidInstanceID
53
+ sleep 1
54
+ puts 'retrying associate_address()'
55
+ retry if (retries += 1) < 15
56
+ end
57
+ end
58
+ end
59
+ end
data/lib/meroku/cli.rb CHANGED
@@ -1,105 +1,104 @@
1
- require "meroku/cli/session"
1
+ require 'meroku/cli/help'
2
+ require 'meroku/cli/secrets'
3
+ require 'meroku/cli/session'
2
4
 
3
5
  module Meroku
6
+ # The CLI is used by end users and also maintainers
4
7
  module CLI
5
-
6
- def help
7
- <<~HEREDOC
8
- Usage: meroku command subcommand
9
-
10
- Examples
11
-
12
- meroku signup # if you havent done already
13
-
14
- meroku create
15
-
16
- meroku keys:add
17
-
18
- meroku infrastrucuture spawn # Spawns server
19
-
20
- HEREDOC
21
- end
8
+ include Meroku::Aws::Ec2
22
9
 
23
10
  def signup
24
- print "Email: "
25
- email = STDIN.gets
26
- print "Password: "
27
- password = STDIN.noecho(&:gets).chomp
28
- print "\n"
29
- url = "https://www.meroku.com/users.json"
30
- response_json = RestClient.post url, {:user=>{:email => email, :password => password, :password_confirmation => password}}.to_json, timeout: 1, :content_type => :json, :accept => :json
31
- if JSON.parse(response_json)["errors"] && JSON.parse(response_json)["errors"].size > 0
32
- puts "error: #{JSON.parse(response_json)["errors"].map{|x| x["detail"]}.join(".")}"
33
- else
34
- email = JSON.parse(response_json)["data"]["attributes"]["email"]
35
- token = JSON.parse(response_json)["data"]["attributes"]["token"]
36
- puts "Signed up #{email}"
37
- dirname = File.dirname("#{Dir.home}/.meroku")
38
- FileUtils.mkdir(dirname) if !File.directory?(dirname)
39
- File.open("#{Dir.home}/.meroku/.token", 'w') { |file| file.write(token) }
11
+ email, pw = Meroku::Extensions.mgets(%i[email password])
12
+ Meroku::Api::Request.post(
13
+ 'https://www.meroku.com/users.json',
14
+ user: { email: email, password: pw, password_confirmation: pw }
15
+ ) do |response|
16
+ puts "Signed up #{response['attributes']['email']}"
17
+ save_setting('apiusername', response['attributes']['apiusername'])
18
+ save_setting('apisecret', response['attributes']['apisecret'])
40
19
  end
20
+ true
41
21
  end
42
22
 
43
- def keys_add(session)
44
- if !File.exist? "#{Dir.home}/.ssh/id_rsa.pub"
45
- puts "error: File #{Dir.home}/.ssh/id_rsa.pub not found"
46
- puts "You can use this command to generate a key:"
47
- puts " ssh-keygen -t rsa"
48
- return nil
49
- end
50
- name = "id_rsa.pub"
51
- data = `cat ~/.ssh/id_rsa.pub`.chomp
52
- url = "https://www.meroku.com/publickeys.json"
53
- response_json = RestClient.post url, {:publickey=>{:name => name, :data=>data}, :token=>session.token}.to_json, timeout: 1, :content_type => :json, :accept => :json
54
-
55
- if JSON.parse(response_json)["errors"] && JSON.parse(response_json)["errors"].size > 0
56
- puts "error: #{JSON.parse(response_json)["errors"].map{|x| x["detail"]}.join(".")}"
57
- else
58
- name = JSON.parse(response_json)["data"]["attributes"]["name"]
59
- puts "Added #{name}"
23
+ def login
24
+ email, password = Meroku::Extensions.mgets(%i[email password])
25
+ Meroku::Api::Request.post(
26
+ 'https://www.meroku.com/users/sign_in.json',
27
+ user: { email: email, password: password }
28
+ ) do |response|
29
+ puts "Signed in as #{response['attributes']['email']}"
30
+ save_setting('apiusername', response['attributes']['apiusername'])
31
+ save_setting('apisecret', response['attributes']['apisecret'])
60
32
  end
33
+ true
61
34
  end
62
35
 
63
- def create
64
- url = "https://www.meroku.com/apps.json"
65
- token = `cat ~/.meroku/.token`.chomp
66
- response_json = RestClient.post url, {:app=>{:name => "unnamed"}, :token=>token}.to_json, timeout: 1, :content_type => :json, :accept => :json
67
-
68
- if JSON.parse(response_json)["errors"] && JSON.parse(response_json)["errors"].size > 0
69
- puts JSON.parse(response_json)["errors"].map{|x| x["detail"]}.join(".")
70
- else
71
- name = JSON.parse(response_json)["data"]["attributes"]["name"]
72
- puts "Created #{name}, adding git remote"
73
- puts "git remote remove meroku"
74
- `git remote remove meroku 2>/dev/null`
75
- puts "git remote add meroku #{token}@www.meroku.com:#{name}.git"
76
- `git remote add meroku #{token}@www.meroku.com:#{name}.git`
36
+ def logout
37
+ [
38
+ "#{Dir.home}/.meroku/.apiusername",
39
+ "#{Dir.home}/.meroku/.apisecret"
40
+ ].each do |f|
41
+ File.delete(f) if File.exist?(f)
77
42
  end
43
+ true
78
44
  end
79
45
 
80
- def self.token_check
81
- if !File.exist? "#{Dir.home}/.meroku/.token"
82
- puts "error: Have you logged in yet?"
83
- return nil
46
+ def create
47
+ Meroku::Api::Request.post(
48
+ 'https://www.meroku.com/apps.json',
49
+ app: { name: 'unnamed' }, apisecret: `cat ~/.meroku/.apisecret`.chomp
50
+ ) do |response|
51
+ puts "Created #{response['attributes']['name']}, adding git remote"
52
+ add_git_remote(
53
+ 'meroku',
54
+ "#{apiusername}@www.meroku.com:#{response['attributes']['name']}.git"
55
+ )
84
56
  end
85
57
  true
86
58
  end
87
59
 
88
- def self.load_secrets
89
- if !File.exist? "#{Dir.home}/.meroku/.secret"
90
- puts "error: File #{Dir.home}/.meroku/.secret not found"
91
- return nil
92
- end
93
- env_file = Dir.home+'/.meroku/meroku.env'
94
- if !File.exist? env_file
95
- secret=`cat ~/.meroku/.secret`.chomp
96
- remote_env_file = "http://www.sam-we.com/dropbox/meroku-#{secret}/meroku.env"
97
- File.write(env_file, Net::HTTP.get(URI.parse(remote_env_file)))
60
+ def apiusername
61
+ `cat ~/.meroku/.apiusername.chomp`
62
+ end
63
+
64
+ def add_git_remote(name, uri)
65
+ puts "git remote remove #{name}"
66
+ `git remote remove #{name} 2>/dev/null`
67
+ puts "git remote add #{name} #{uri}"
68
+ `git remote add #{name} #{uri}`
69
+ end
70
+
71
+ def keys_add
72
+ file = "#{Dir.home}/.ssh/id_rsa.pub"
73
+ apisecret = `cat ~/.meroku/.apisecret`.chomp
74
+ abort "error: #{file} not found" unless File.exist?(file)
75
+ Meroku::Api::Request.post(
76
+ 'https://www.meroku.com/publickeys.json',
77
+ publickey: { name: 'id_rsa.pub', data: `cat ~/.ssh/id_rsa.pub`.chomp },
78
+ apisecret: apisecret
79
+ ) do |response|
80
+ puts "Added #{response['attributes']['name']}"
98
81
  end
99
- Dotenv.load(env_file)
82
+ true
100
83
  end
101
84
 
102
- end
85
+ def spawn
86
+ Meroku::CLI::Secrets.load(admin: true)
87
+ node = Meroku::Node.new
88
+ node.associate_address.configure_keys.add_sources.ubuntu_updates
89
+ node.install_packages.database_inits.git_clone.nginx_configs.start_rails
90
+ true
91
+ end
103
92
 
93
+ def despawn
94
+ Meroku::CLI::Secrets.load(admin: true)
95
+ Meroku::Infrastructure.each_server(&:shutdown)
96
+ true
97
+ end
104
98
 
99
+ def save_setting(name, value)
100
+ FileUtils.mkdir_p "#{Dir.home}/.meroku"
101
+ IO.write("#{Dir.home}/.meroku/.#{name}", value)
102
+ end
103
+ end
105
104
  end