meroku 0.0.0 → 0.1.28

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,159 @@
1
+ module Meroku
2
+ module CLI
3
+ require 'action_view'
4
+ include ActionView::Helpers::TextHelper
5
+
6
+ class Server < Thor
7
+ include Meroku::Sanitychecks
8
+ include Meroku::Util
9
+
10
+ desc "_downall", "Wip"
11
+ def _downall()
12
+ admin_secrets_required
13
+ ec2_client.terminate_instances({ instance_ids: [ production_servers.first ] }) if !production_servers.empty?
14
+ end
15
+
16
+ desc "revert", "Puts server in state it was in when it was started and installed"
17
+ def revert()
18
+ puts `ssh -o 'StrictHostKeyChecking=no' -i ~/crypto/meroku/meroku.id_rsa ubuntu@34.239.241.218 'cd ~/meroku/ && git pull'`
19
+ puts `ssh -o 'StrictHostKeyChecking=no' -i ~/crypto/meroku/meroku.id_rsa ubuntu@34.239.241.218 'sudo ~/meroku/rails_app/script/revert'`
20
+ end
21
+
22
+ desc "backup", "Backup databases in production server"
23
+ def backup()
24
+ admin_secrets_required
25
+ timestamp=Time.now.to_i
26
+ aws_exports="AWS_DEFAULT_REGION=us-east-1 AWS_ACCESS_KEY_ID=#{ENV['AWS_ACCESS_KEY_ID']} AWS_SECRET_ACCESS_KEY=#{ENV['AWS_SECRET_ACCESS_KEY']}"
27
+
28
+ if production_servers.empty?
29
+ puts "Not doing backup - No production servers"
30
+ return
31
+ end
32
+
33
+ # DBs
34
+ ssh3("34.239.241.218","PGPASSWORD=bitnami pg_dumpall -U postgres -f /tmp/#{timestamp}.postgres")
35
+ ssh3("34.239.241.218","mysqldump -uroot -pbitnami --all-databases > /tmp/#{timestamp}.mysql")
36
+ ssh3("34.239.241.218","gzip -fv -9 /tmp/#{timestamp}.postgres /tmp/#{timestamp}.mysql")
37
+ ssh("34.239.241.218","#{aws_exports} aws s3 cp /tmp/#{timestamp}.postgres.gz s3://meroku-database-backups/")
38
+ ssh("34.239.241.218","#{aws_exports} aws s3 cp /tmp/#{timestamp}.postgres.gz s3://meroku-database-backups/postgres.gz")
39
+ ssh("34.239.241.218","#{aws_exports} aws s3 cp /tmp/#{timestamp}.mysql.gz s3://meroku-database-backups/")
40
+ ssh("34.239.241.218","#{aws_exports} aws s3 cp /tmp/#{timestamp}.mysql.gz s3://meroku-database-backups/mysql.gz")
41
+
42
+ # HOME DIRS
43
+ ssh3("34.239.241.218","sudo rm -f /tmp/home_dirs.tgz || true; sudo tar --exclude='/home/bitnami' -zcvf /tmp/home_dirs.gz /home/*")
44
+ ssh("34.239.241.218","#{aws_exports} aws s3 cp /tmp/home_dirs.gz s3://meroku-database-backups/")
45
+ ssh("34.239.241.218","#{aws_exports} aws s3 cp s3://meroku-database-backups/home_dirs.gz s3://meroku-database-backups/#{timestamp}.home_dirs.gz")
46
+ # CLEANUP
47
+ ssh("34.239.241.218","sudo rm -f /tmp/*.mysql.gz /tmp/*.postgres.gz /tmp/home_dirs.gz")
48
+ end
49
+
50
+ desc "activate", "Assigns production elastic ip to standby node"
51
+ def activate()
52
+ admin_secrets_required
53
+ # Terminate server with production ip
54
+ if !production_servers.empty?
55
+ ec2_client.terminate_instances({ instance_ids: [ production_servers.first ] })
56
+ end
57
+
58
+ standby_servers = unused_servers
59
+ abort "Too many unused servers (#{standby_servers.size})" if standby_servers.size > 1
60
+
61
+ ec2_client.associate_address(
62
+ {
63
+ allocation_id: 'eipalloc-139f7823', # this is eip 34.239.241.218
64
+ instance_id: standby_servers.first
65
+ }
66
+ )
67
+ puts "Associated 34.239.241.218 with #{standby_servers.first}"
68
+ puts 'ping 34.239.241.218 -c 20'
69
+ puts `ping 34.239.241.218 -c 20`
70
+ puts `ssh -i ~/crypto/meroku/meroku.id_rsa -o "StrictHostKeyChecking=no" -v ubuntu@34.239.241.218 pwd`
71
+ # remove the next 3 lines later
72
+ ssh3("34.239.241.218","cat meroku/rails_app/tmp/pids/server.pid")
73
+ ssh3("34.239.241.218","kill -9 `cat meroku/rails_app/tmp/pids/server.pid`")
74
+ ssh3("34.239.241.218","cd meroku/rails_app; RAILS_SERVE_STATIC_FILES=1 SECRET_KEY_BASE=fixme rails s -e production -d -b 0.0.0.0 && sleep 5")
75
+ ssh3("34.239.241.218","sudo ls -la /opt/bitnami/nginx/conf/vhosts/") # for debugging
76
+ end
77
+
78
+ desc "install", "installs software needed to meroku work"
79
+ def install()
80
+ admin_secrets_required
81
+ ip = server_being_built
82
+
83
+ ssh2(ip,"sudo apt-add-repository ppa:git-core/ppa -y")
84
+ ssh2(ip,"sudo apt-get update -y")
85
+ ssh2(ip,"sudo apt-get install -yqq libyaml-dev libsqlite3-dev sqlite3 libgmp-dev libgdbm-dev")
86
+ ssh2(ip,"sudo apt-get install -yqq libncurses5-dev bison pkg-config libffi-dev")
87
+ ssh2(ip,"sudo apt-get install -yqq libgmp-dev libreadline6-dev libssl-dev libpq-dev libmysqlclient-dev jq awscli")
88
+ #ssh2(ip,"sudo apt-get install -yqq nodejs")
89
+ ssh2(ip,"sudo npm install -g yarn")
90
+
91
+ ssh2(ip,"sudo apt-get install git-core -y")
92
+ ssh2(ip,"sudo rm /opt/bitnami/git/bin/git")
93
+ ssh2(ip,"sudo ln -s /usr/bin/git /opt/bitnami/git/bin/git")
94
+
95
+ ssh2(ip,"sudo addgroup meroku;")
96
+ ssh2(ip,"sudo apt-get install emacs24-nox -y")
97
+ ssh2(ip,"git clone --quiet https://github.com/meroku/meroku.git")
98
+
99
+ ssh2(ip,"sudo mkdir /opt/githooks; sudo chmod 777 /opt/githooks")
100
+ ssh2(ip,'cp ~/meroku/misc/githook_post-receive /opt/githooks/post-receive')
101
+ ssh2(ip,'cp ~/meroku/misc/app_id_by_name /opt/githooks/app_id_by_name')
102
+ ssh2(ip,'cp ~/meroku/misc/user_id_by_name /opt/githooks/user_id_by_name')
103
+
104
+ ssh2(ip,"sudo chmod 777 /opt/githooks/* ")
105
+ ssh2(ip,"sudo ln -s /usr/bin/install /bin/install")
106
+
107
+ aws_exports="AWS_DEFAULT_REGION=us-east-1 AWS_ACCESS_KEY_ID=#{ENV['AWS_ACCESS_KEY_ID']} AWS_SECRET_ACCESS_KEY=#{ENV['AWS_SECRET_ACCESS_KEY']}"
108
+
109
+ # postgres / mysql restore happens here
110
+ ssh3(ip,"#{aws_exports} aws s3 cp s3://meroku-database-backups/postgres.gz /tmp/")
111
+ ssh3(ip,"#{aws_exports} aws s3 cp s3://meroku-database-backups/mysql.gz /tmp/")
112
+ ssh3(ip,"cd /tmp/ && gunzip postgres.gz && gunzip mysql.gz")
113
+ ssh3(ip,"PGPASSWORD=bitnami psql -U postgres -f /tmp/postgres")
114
+ ssh3(ip,"mysql -uroot -pbitnami < /tmp/mysql")
115
+ ssh3(ip,"sudo rm -f /tmp/mysql /tmp/postgres")
116
+
117
+ ssh2(ip,"sudo mkdir /opt/bitnami/nginx/keys/; ")
118
+ puts `scp -i ~/crypto/meroku/meroku.id_rsa ~/crypto/meroku/meroku_site_fullchain.pem ubuntu@#{ip}:/home/bitnami/`
119
+ ssh2(ip, 'sudo mv ~/meroku_site_fullchain.pem /opt/bitnami/nginx/keys/; ')
120
+ puts `scp -i ~/crypto/meroku/meroku.id_rsa ~/crypto/meroku/meroku_site_privkey.pem ubuntu@#{ip}:/home/bitnami/`
121
+ ssh2(ip,'sudo mv ~/meroku_site_privkey.pem /opt/bitnami/nginx/keys/; ')
122
+
123
+ ssh2(ip,"sudo cp meroku/misc/gemrc /etc/gemrc")
124
+ ssh2(ip,"cd meroku/rails_app; NOKOGIRI_USE_SYSTEM_LIBRARIES=1 bundle install")
125
+
126
+ ssh3(ip,"cd meroku/rails_app; RAILS_ENV=production rake nginx:rebuild")
127
+
128
+ # create unix users
129
+ ssh3(ip,"cd meroku/rails_app; RAILS_ENV=production rake unix_users:rebuild")
130
+ # create unix users directories
131
+ ssh3(ip,"#{aws_exports} aws s3 cp s3://meroku-database-backups/home_dirs.gz /tmp/")
132
+ ssh3(ip,"#{aws_exports} cd /; sudo tar xzvf /tmp/home_dirs.gz")
133
+ ssh3(ip,"sudo rm -f /tmp/home_dirs.gz")
134
+
135
+ ssh3(ip,"cd meroku/rails_app; SECRET_KEY_BASE=fixme rake assets:precompile")
136
+ ssh3(ip,"cd meroku/rails_app; RAILS_SERVE_STATIC_FILES=1 SECRET_KEY_BASE=fixme rails s -e production -d -b 0.0.0.0 && sleep 5")
137
+
138
+ # start customer rails apps here wipwip
139
+
140
+ ssh3(ip,"sudo /opt/bitnami/ctlscript.sh stop apache")
141
+ ssh3(ip,"sudo /opt/bitnami/ctlscript.sh restart nginx")
142
+ ssh3(ip,"sudo ls -la /opt/bitnami/nginx/conf/vhosts/")
143
+ end
144
+
145
+ desc "start", "spins up an ubuntu server"
146
+ long_desc <<-LONGDESC
147
+ Spins up an ubuntu server with name tag "meroku",
148
+ with the production ip not yet assigned
149
+ LONGDESC
150
+ def start()
151
+ admin_secrets_required
152
+ terminate_unused_servers
153
+ instance_id = ec2_start_instance
154
+ ec2_tag_instance(instance_id)
155
+ ec2_await_boot(instance_id)
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,4 @@
1
+ module Meroku
2
+ module CLI
3
+ require 'action_view'
4
+ include ActionView::Helpers::TextHelper
data/lib/meroku/cli.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'thor'
2
+ module Meroku
3
+
4
+ module CLI
5
+
6
+ end
7
+
8
+ end
@@ -0,0 +1,6 @@
1
+ module Meroku
2
+ class Config < ApplicationRecord
3
+ belongs_to :app, class_name: "Meroku::App"
4
+
5
+ end
6
+ end
@@ -0,0 +1,62 @@
1
+
2
+ module Meroku
3
+
4
+ class ConfigsController < ApplicationController
5
+ skip_before_action :verify_authenticity_token, only: [:create, :destroy]
6
+ before_action :authenticate, only: [ :create, :index, :destroy ]
7
+
8
+ def index
9
+ configs = Meroku::App.last.configs.map { |x| "#{x.name}: #{x.value || 'nil'}" }.join("\n")
10
+ render json: {
11
+ "data": "#{configs}\n"
12
+ }
13
+ end
14
+
15
+ def create
16
+ @config = Meroku::Config.where(name: params["name"], app_id: @app_.id).try(:first)
17
+ if @config
18
+ # if variable exists, update its value
19
+ @config.update_attributes(value: params["value"])
20
+ else
21
+ # if it doesn't exist, create record
22
+ @config = Meroku::Config.new(
23
+ name: params["name"],
24
+ value: params["value"],
25
+ app_id: @app_.id
26
+ )
27
+ end
28
+ respond_to do |format|
29
+ if @config.save
30
+ format.json { render json: { data: @config } }
31
+ else
32
+ format.json { render json: { :errors => @config.errors }, status: :unprocessable_entity }
33
+ end
34
+ end
35
+ end
36
+
37
+ ## PATCH/PUT /keys/1
38
+ ## PATCH/PUT /keys/1.json
39
+ #def update
40
+ # respond_to do |format|
41
+ # if @key.update(key_params)
42
+ # format.html { redirect_to @key, notice: 'Key was successfully updated.' }
43
+ # format.json { render :show, status: :ok, location: @key }
44
+ # else
45
+ # format.html { render :edit }
46
+ # format.json { render json: @key.errors, status: :unprocessable_entity }
47
+ # end
48
+ # end
49
+ #end
50
+
51
+ # DELETE /keys/1
52
+ # DELETE /keys/1.json
53
+ def destroy
54
+ @config = Meroku::Config.find_by_name(params["name"])
55
+ @config.destroy
56
+ respond_to do |format|
57
+ format.json { render json: { data: @config } }
58
+ end
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,30 @@
1
+ class Array
2
+ # File activesupport/lib/active_support/core_ext/array/conversions.rb, line 59
3
+ def to_sentence(options = {})
4
+ options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
5
+
6
+ default_connectors = {
7
+ :words_connector => ', ',
8
+ :two_words_connector => ' and ',
9
+ :last_word_connector => ', and '
10
+ }
11
+ if defined?(I18n)
12
+ i18n_connectors = I18n.translate(:'support.array', locale: options[:locale], default: {})
13
+ default_connectors.merge!(i18n_connectors)
14
+ end
15
+ options = default_connectors.merge!(options)
16
+
17
+ case length
18
+ when 0
19
+ ''
20
+ when 1
21
+ self[0].to_s.dup
22
+ when 2
23
+ "#{self[0]}#{options[:two_words_connector]}#{self[1]}"
24
+ else
25
+ "#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
26
+ end
27
+ end
28
+ end
29
+
30
+
@@ -0,0 +1,6 @@
1
+ module Meroku
2
+ class Domain < ApplicationRecord
3
+ belongs_to :app, class_name: "Meroku::App"
4
+ validates_uniqueness_of :domain
5
+ end
6
+ end
@@ -0,0 +1,83 @@
1
+
2
+ module Meroku
3
+
4
+ class DomainsController < ApplicationController
5
+ #before_action :set_domain, only: [:show, :edit, :update, :destroy]
6
+ skip_before_action :verify_authenticity_token, only: [:create, :destroy]
7
+ before_action :authenticate, only: [ :create, :index, :destroy ]
8
+
9
+ ## GET /keys
10
+ ## GET /keys.json
11
+ def index
12
+ @domain_names = @app_.domains.pluck(:domain)
13
+ render json: { "data": @domain_names }
14
+ end
15
+
16
+ ## GET /keys/1
17
+ ## GET /keys/1.json
18
+ #def show
19
+ #end
20
+ #
21
+ ## GET /keys/new
22
+ #def new
23
+ # @key = Key.new
24
+ #end
25
+ #
26
+ ## GET /keys/1/edit
27
+ #def edit
28
+ #end
29
+ #
30
+ # POST /keys
31
+ # POST /keys.json
32
+ def create
33
+ @domain = Meroku::Domain.new(
34
+ domain: params["domain"],
35
+ app_id: @app_.id
36
+ )
37
+ respond_to do |format|
38
+ if @domain.save
39
+ Meroku::Util.nginx_rebuild()
40
+ format.json { render json: { data: @domain } }
41
+ else
42
+ format.json { render json: { :errors => @domain.errors }, status: :unprocessable_entity }
43
+ end
44
+ end
45
+ end
46
+ #
47
+ ## PATCH/PUT /keys/1
48
+ ## PATCH/PUT /keys/1.json
49
+ #def update
50
+ # respond_to do |format|
51
+ # if @key.update(key_params)
52
+ # format.html { redirect_to @key, notice: 'Key was successfully updated.' }
53
+ # format.json { render :show, status: :ok, location: @key }
54
+ # else
55
+ # format.html { render :edit }
56
+ # format.json { render json: @key.errors, status: :unprocessable_entity }
57
+ # end
58
+ # end
59
+ #end
60
+
61
+ # DELETE /keys/1
62
+ # DELETE /keys/1.json
63
+ def destroy
64
+ @domain = Meroku::Domain.find_by_domain(params["domain"])
65
+ @domain.destroy
66
+ Meroku::Util.nginx_rebuild()
67
+ respond_to do |format|
68
+ format.json { render json: { data: @domain } }
69
+ end
70
+ end
71
+
72
+ private
73
+ ## Use callbacks to share common setup or constraints between actions.
74
+ #def set_key
75
+ # @key = Key.find(params[:id])
76
+ #end
77
+ #
78
+ ## Never trust parameters from the scary internet, only allow the white list through.
79
+ #def key_params
80
+ # params.require(:key).permit(:key, :original_filename, :user_id)
81
+ #end
82
+ end
83
+ end
@@ -0,0 +1,6 @@
1
+ module Meroku
2
+ module Error
3
+
4
+ end
5
+
6
+ end
data/lib/meroku/key.rb ADDED
@@ -0,0 +1,11 @@
1
+ module Meroku
2
+
3
+ class Key < Meroku::ApplicationRecord
4
+ include Meroku::Util
5
+
6
+ belongs_to :user
7
+
8
+ after_create :update_authorized_keys_file
9
+ end
10
+
11
+ end
@@ -0,0 +1,82 @@
1
+
2
+ module Meroku
3
+
4
+ class KeysController < ApplicationController
5
+ before_action :set_key, only: [:show, :edit, :update, :destroy]
6
+ skip_before_action :verify_authenticity_token, only: [:create]
7
+ before_action :authenticate, only: [ :create ]
8
+
9
+ ## GET /keys
10
+ ## GET /keys.json
11
+ #def index
12
+ # @keys = Meroku::Key.allxb
13
+ # render json: { "data": @keys }
14
+ #end
15
+
16
+ ## GET /keys/1
17
+ ## GET /keys/1.json
18
+ #def show
19
+ #end
20
+ #
21
+ ## GET /keys/new
22
+ #def new
23
+ # @key = Key.new
24
+ #end
25
+ #
26
+ ## GET /keys/1/edit
27
+ #def edit
28
+ #end
29
+ #
30
+ # POST /keys
31
+ # POST /keys.json
32
+ def create
33
+ @key = Meroku::Key.new(
34
+ key: params["key"],
35
+ user_id: @user.id
36
+ )
37
+ respond_to do |format|
38
+ if @key.save
39
+ format.json { render json: { data: @key } }
40
+ else
41
+
42
+ format.json { render json: { :errors => @key.errors }, status: :unprocessable_entity }
43
+ end
44
+ end
45
+ end
46
+ #
47
+ ## PATCH/PUT /keys/1
48
+ ## PATCH/PUT /keys/1.json
49
+ #def update
50
+ # respond_to do |format|
51
+ # if @key.update(key_params)
52
+ # format.html { redirect_to @key, notice: 'Key was successfully updated.' }
53
+ # format.json { render :show, status: :ok, location: @key }
54
+ # else
55
+ # format.html { render :edit }
56
+ # format.json { render json: @key.errors, status: :unprocessable_entity }
57
+ # end
58
+ # end
59
+ #end
60
+ #
61
+ ## DELETE /keys/1
62
+ ## DELETE /keys/1.json
63
+ #def destroy
64
+ # @key.destroy
65
+ # respond_to do |format|
66
+ # format.html { redirect_to keys_url, notice: 'Key was successfully destroyed.' }
67
+ # format.json { head :no_content }
68
+ # end
69
+ #end
70
+
71
+ private
72
+ # Use callbacks to share common setup or constraints between actions.
73
+ def set_key
74
+ @key = Key.find(params[:id])
75
+ end
76
+
77
+ # Never trust parameters from the scary internet, only allow the white list through.
78
+ def key_params
79
+ params.require(:key).permit(:key, :original_filename, :user_id)
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,19 @@
1
+ module Meroku
2
+ module Sanitychecks
3
+
4
+ def admin_secrets_required
5
+ secrets_dir = "#{Dir.home}/crypto/meroku/"
6
+ IO.read("#{secrets_dir}/meroku_secrets")
7
+ require 'dotenv'
8
+ Dotenv.load("#{secrets_dir}/meroku_secrets")
9
+ IO.read("#{secrets_dir}/meroku.id_rsa")
10
+ #IO.read("#{secrets_dir}/meroku.id_rsa.pub")
11
+ #IO.read("#{secrets_dir}/meroku_site_cert.pem")
12
+ #IO.read("#{secrets_dir}/meroku_site_chain.pem")
13
+ #IO.read("#{secrets_dir}/meroku_site_fullchain.pem")
14
+ #IO.read("#{secrets_dir}/meroku_site_privkey.pem")
15
+ #IO.read("#{secrets_dir}/meroku_ssh_host_keys.tgz")
16
+ end
17
+
18
+ end
19
+ end
@@ -0,0 +1,23 @@
1
+ module Meroku
2
+
3
+ class User < Meroku::ApplicationRecord
4
+ include Meroku::Util
5
+
6
+ # Include default devise modules. Others available are:
7
+ # :confirmable, :lockable, :timeoutable and :omniauthable
8
+ devise :database_authenticatable, :registerable,
9
+ :recoverable, :rememberable, :trackable, :validatable
10
+
11
+ has_many :keys
12
+
13
+ after_create :add_unix_user
14
+ after_create :install_rvm_for_user
15
+
16
+ def database_password
17
+ encrypted_password[7..20].gsub(/[^0-9a-z ]/i, '')
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+