meroku 2.0.8 → 2.0.9

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 (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