meroku 0.0.0 → 0.1.28

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.
@@ -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
+