deployku 0.0.1
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.
- checksums.yaml +7 -0
- data/LICENSE +7 -0
- data/README.md +234 -0
- data/Rakefile +14 -0
- data/bin/deployku +45 -0
- data/deployku.gemspec +23 -0
- data/lib/deployku/config.rb +92 -0
- data/lib/deployku/configurable.rb +75 -0
- data/lib/deployku/containerable.rb +82 -0
- data/lib/deployku/engine.rb +55 -0
- data/lib/deployku/helpers.rb +7 -0
- data/lib/deployku/plugins/access.rb +161 -0
- data/lib/deployku/plugins/app.rb +211 -0
- data/lib/deployku/plugins/docker.rb +77 -0
- data/lib/deployku/plugins/git.rb +56 -0
- data/lib/deployku/plugins/lxc.rb +5 -0
- data/lib/deployku/plugins/nginx.rb +140 -0
- data/lib/deployku/plugins/postgres.rb +139 -0
- data/lib/deployku/plugins/rails.rb +100 -0
- data/lib/deployku/plugins.rb +111 -0
- data/lib/deployku.rb +19 -0
- metadata +63 -0
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'yaml'
|
3
|
+
require 'securerandom'
|
4
|
+
require 'open3'
|
5
|
+
|
6
|
+
module Deployku
|
7
|
+
class PostgresPlugin < Deployku::Plugin
|
8
|
+
include Deployku::Configurable
|
9
|
+
include Deployku::Containerable
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@config = {
|
13
|
+
'from' => 'postgres',
|
14
|
+
'env' => {}
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
describe :create, '<NAME>', 'creates new PostgreSQL instance', acl_sys: :admin
|
19
|
+
def create(name)
|
20
|
+
app_dir = dir(name)
|
21
|
+
unless Dir.exists?(app_dir)
|
22
|
+
FileUtils.mkdir_p(app_dir)
|
23
|
+
end
|
24
|
+
app_dir
|
25
|
+
end
|
26
|
+
|
27
|
+
describe :delete, '<NAME>', 'deletes an existing PostgreSQL instance', acl_sys: :admin
|
28
|
+
def delete(name)
|
29
|
+
app_dir = dir(name)
|
30
|
+
if Dir.exists?(app_dir)
|
31
|
+
FileUtils.rm_rf(app_dir)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe :list, '', 'lists available PostgreSQL instances', acl_sys: :admin
|
36
|
+
def list
|
37
|
+
Dir.glob(File.join(Deployku::Config.home, '.postgres', '*')) do |path|
|
38
|
+
puts File.basename(path) if File.directory?(path)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'db:create', '<NAME> <DB_NAME>', 'create a database in postgres instance', acl_sys: :admin
|
43
|
+
def db_create(name, db_name)
|
44
|
+
config_load(name)
|
45
|
+
cid = get_container_id(name)
|
46
|
+
unless Deployku::Engine.running?(cid)
|
47
|
+
puts "Database instance '#{name}' is not running."
|
48
|
+
exit 1
|
49
|
+
end
|
50
|
+
ip = Deployku::Engine.ip(cid)
|
51
|
+
db = Deployku.sanitize_app_name(db_name)
|
52
|
+
system "echo \"#{@config['env']['POSTGRES_PASSWORD']}\n\" 'CREATE DATABASE #{db};' | psql -h #{ip} -U postgres"
|
53
|
+
end
|
54
|
+
|
55
|
+
describe 'db:drop', '<NAME> <DB_NAME>', 'destroy a database in postgres instance', acl_sys: :admin
|
56
|
+
def db_drop(name, db_name)
|
57
|
+
config_load(name)
|
58
|
+
cid = get_container_id(name)
|
59
|
+
unless Deployku::Engine.running?(cid)
|
60
|
+
puts "Database instance '#{name}' is not running."
|
61
|
+
exit 1
|
62
|
+
end
|
63
|
+
ip = Deployku::Engine.ip(cid)
|
64
|
+
db = Deployku.sanitize_app_name(db_name)
|
65
|
+
system "echo \"#{@config['env']['POSTGRES_PASSWORD']}\n\" 'DROP DATABASE #{db};' | psql -h #{ip} -U postgres"
|
66
|
+
end
|
67
|
+
|
68
|
+
describe 'db:link', '<NAME> <DB_NAME> <APP>', 'connect appliaction with database', acl_sys: :admin
|
69
|
+
def db_link(name, db_name, app_name)
|
70
|
+
config_load(name)
|
71
|
+
db_id = get_container_id(name)
|
72
|
+
ip = Deployku::Engine.ip(db_id)
|
73
|
+
db = Deployku.sanitize_app_name(db_name)
|
74
|
+
user_name = 'user_' + SecureRandom.uuid.gsub('-','')
|
75
|
+
user_passwd = SecureRandom.uuid
|
76
|
+
database_url = "postgres://#{user_name}:#{user_passwd}@#{container_name(name)}/#{db}"
|
77
|
+
system "echo \"#{@config['env']['POSTGRES_PASSWORD']}\n\" \"CREATE USER #{user_name} WITH PASSWORD '#{user_passwd}';\" | psql -h #{ip} -U postgres"
|
78
|
+
system "echo \"#{@config['env']['POSTGRES_PASSWORD']}\n\" 'GRANT ALL ON DATABASE #{db} TO #{user_name};' | psql -h #{ip} -U postgres"
|
79
|
+
if $?.exitstatus == 0
|
80
|
+
Deployku::AppPlugin.run('config:set', [app_name, 'DATABASE_URL', database_url])
|
81
|
+
Deployku::AppPlugin.run(:link, [app_name, container_name(name)])
|
82
|
+
else
|
83
|
+
puts "Unable to create user in database."
|
84
|
+
exit 1
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe 'db:connect', '<NAME> <DB_NAME>', 'connect to database and enter prompt', acl_sys: :admin
|
89
|
+
def db_connect(name, db_name)
|
90
|
+
config_load(name)
|
91
|
+
db_id = get_container_id(name)
|
92
|
+
dbname = Deployku.sanitize_app_name(db_name)
|
93
|
+
ip = Deployku::Engine.ip(db_id)
|
94
|
+
system "PGPASSWORD=\"#{@config['env']['POSTGRES_PASSWORD']}\" psql -h #{ip} -U postgres #{dbname}"
|
95
|
+
end
|
96
|
+
|
97
|
+
# methods from containerable
|
98
|
+
describe :start, '<NAME>', 'starts container', acl_sys: :admin
|
99
|
+
def start(app_name)
|
100
|
+
config_load(app_name)
|
101
|
+
unless @config['volumes']
|
102
|
+
@config['volumes'] = {
|
103
|
+
File.join(dir(app_name), 'data') => '/postgresql/'
|
104
|
+
}
|
105
|
+
end
|
106
|
+
@config['env']['PGDATA'] = '/postgresql/' unless @config['env']['PGDATA']
|
107
|
+
@config['env']['POSTGRES_PASSWORD'] = SecureRandom.uuid unless @config['env']['POSTGRES_PASSWORD']
|
108
|
+
config_save(app_name)
|
109
|
+
|
110
|
+
Deployku::Config.merge!(@config)
|
111
|
+
app_hash = Deployku::Engine.start(@config['from'], dir(app_name), container_name(app_name))
|
112
|
+
exit 1 if $?.nil? || $?.exitstatus != 0
|
113
|
+
set_container_id(app_name, container_name(app_name))
|
114
|
+
puts "Container #{app_hash} started."
|
115
|
+
end
|
116
|
+
|
117
|
+
describe :status, '<NAME>', 'show container status', acl_sys: :admin
|
118
|
+
describe :stop, '<NAME>', 'stops running container', acl_sys: :admin
|
119
|
+
describe :restart, '<NAME>', 'restarts container', acl_sys: :admin
|
120
|
+
describe :logs, '<NAME>', 'show app logs', acl_sys: :admin
|
121
|
+
|
122
|
+
# methods from configurable
|
123
|
+
describe 'config:show', '<NAME>', 'shows instance configuration', acl_sys: :admin
|
124
|
+
describe 'config:set', '<NAME> <ENV_VARIABLE> <VALUE>', 'sets environment variable', acl_sys: :admin
|
125
|
+
describe 'config:unset', '<NAME> <ENV_VARIABLE>', 'unsets environment variable', acl_sys: :admin
|
126
|
+
describe 'config:set_from', '<NAME> <VALUE>', 'sets base image name for container', acl_sys: :admin
|
127
|
+
describe 'config:unset_from', '<NAME>', 'sets base image to default', acl_sys: :admin
|
128
|
+
describe 'config:set_engine', '<NAME> <ENGINE>', 'sets container engine (docker, lxc)', acl_sys: :admin
|
129
|
+
describe 'config:unset_engine', '<NAME>', 'sets engine to default', acl_sys: :admin
|
130
|
+
|
131
|
+
def dir(name)
|
132
|
+
File.join(Deployku::Config.home, '.postgres', Deployku.sanitize_app_name(name))
|
133
|
+
end
|
134
|
+
|
135
|
+
def container_name(app_name)
|
136
|
+
"deployku-postgres-#{app_name}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Deployku
|
4
|
+
class RailsPlugin < Deployku::Plugin
|
5
|
+
PACKAGES = ['nodejs']
|
6
|
+
|
7
|
+
def volumes
|
8
|
+
['/app/public/']
|
9
|
+
end
|
10
|
+
|
11
|
+
def port
|
12
|
+
3000
|
13
|
+
end
|
14
|
+
|
15
|
+
def build_start_script(path)
|
16
|
+
app_path = File.join(path, 'app')
|
17
|
+
start_path = File.join(path, 'start')
|
18
|
+
custom_start_path = File.join(app_path, 'start')
|
19
|
+
if File.exists?(custom_start_path)
|
20
|
+
FileUtils.cp(custom_start_path, start_path)
|
21
|
+
else
|
22
|
+
File.open(start_path, 'w') do |f|
|
23
|
+
f << <<EOF
|
24
|
+
#!/usr/bin/env bash
|
25
|
+
source /usr/local/rvm/scripts/rvm
|
26
|
+
cd app
|
27
|
+
export RAILS_ENV=production
|
28
|
+
bundle exec rake db:migrate RAILS_ENV=production
|
29
|
+
bundle exec rake assets:precompile RAILS_ENV=production
|
30
|
+
|
31
|
+
bundle exec rails s -p #{Deployku::Config.port} -b 0.0.0.0 -e production
|
32
|
+
EOF
|
33
|
+
end
|
34
|
+
end
|
35
|
+
File.chmod(0755, start_path)
|
36
|
+
end
|
37
|
+
|
38
|
+
def build_dockerfile(path)
|
39
|
+
app_path = File.join(path, 'app')
|
40
|
+
ruby_version = detect_ruby_version(app_path)
|
41
|
+
dockerfile_path = File.join(path, 'Dockerfile')
|
42
|
+
# TODO: process Dockerfile with erubis
|
43
|
+
custom_docker_file = File.join(app_path, 'Dockerfile')
|
44
|
+
if File.exists?(custom_docker_file)
|
45
|
+
FileUtils.cp(custom_docker_file, dockerfile_path)
|
46
|
+
else
|
47
|
+
File.open(dockerfile_path, 'w') do |f|
|
48
|
+
f << <<EOF
|
49
|
+
FROM #{Deployku::Config.from}
|
50
|
+
|
51
|
+
ENV DEBIAN_FRONTEND noninteractive
|
52
|
+
|
53
|
+
RUN apt-get update
|
54
|
+
|
55
|
+
RUN /bin/bash -l -c 'rvm install #{ruby_version} && rvm use #{ruby_version} --default'
|
56
|
+
RUN /bin/bash -l -c 'rvm rubygems current'
|
57
|
+
RUN /bin/bash -l -c 'gem install bundler'
|
58
|
+
|
59
|
+
RUN /bin/bash -l -c 'rvm cleanup all'
|
60
|
+
|
61
|
+
RUN apt-get install -y #{packages.join(' ')}
|
62
|
+
|
63
|
+
RUN apt-get -y autoclean
|
64
|
+
RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
65
|
+
|
66
|
+
EXPOSE #{Deployku::Config.port}
|
67
|
+
CMD []
|
68
|
+
ENTRYPOINT ["/start"]
|
69
|
+
|
70
|
+
ADD start /start
|
71
|
+
|
72
|
+
ADD app /app
|
73
|
+
RUN /bin/bash -l -c 'cd app && RAILS_ENV=production bundle install --without development test'
|
74
|
+
EOF
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def detect(path)
|
80
|
+
gem_file_path = File.join(path, 'Gemfile')
|
81
|
+
if File.exists?(gem_file_path)
|
82
|
+
if File.read(gem_file_path) =~ %r{^\s*gem\s+['"](rails)['"]}m
|
83
|
+
return true
|
84
|
+
end
|
85
|
+
end
|
86
|
+
false
|
87
|
+
end
|
88
|
+
|
89
|
+
def detect_ruby_version(path)
|
90
|
+
gem_file_path = File.join(path, 'Gemfile')
|
91
|
+
if File.exists?(gem_file_path)
|
92
|
+
ruby_version = File.read(gem_file_path).gsub(%r{.*ruby\s+['"]([^'"]+)['"].*}m, '\1')
|
93
|
+
end
|
94
|
+
if not ruby_version || ruby_version == ''
|
95
|
+
ruby_version = '2.1.7'
|
96
|
+
end
|
97
|
+
ruby_version
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module Deployku
|
2
|
+
|
3
|
+
class Plugin
|
4
|
+
@plugins = []
|
5
|
+
|
6
|
+
class NoMethod < NoMethodError
|
7
|
+
end
|
8
|
+
|
9
|
+
class << self
|
10
|
+
attr_reader :plugins
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.<<(plugin)
|
14
|
+
@plugins << plugin
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.find_plugin(name)
|
18
|
+
plugin_name = "Deployku::#{name.capitalize}Plugin"
|
19
|
+
@plugins.each do |plugin|
|
20
|
+
return plugin if plugin.name == plugin_name
|
21
|
+
end
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.filter_plugins(fn)
|
26
|
+
plugins = []
|
27
|
+
@plugins.each do |plugin|
|
28
|
+
plug = plugin.instance
|
29
|
+
plugins << plug if plug.respond_to?(fn)
|
30
|
+
end
|
31
|
+
plugins
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.inherited(plugin)
|
35
|
+
Plugin << plugin
|
36
|
+
plugin.instance_eval do
|
37
|
+
@help_register = []
|
38
|
+
class << self
|
39
|
+
attr_reader :help_register
|
40
|
+
end
|
41
|
+
def describe(fn_name, args, description, acl={})
|
42
|
+
@help_register << { name: fn_name, arg_list: args, desc: description, acl_app: acl[:acl_app], acl_sys: acl[:acl_sys] }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# collects info from 'describe' and returns it as a string
|
48
|
+
def self.help
|
49
|
+
str = ''
|
50
|
+
help_register = []
|
51
|
+
max_name_length = 0
|
52
|
+
max_arg_length = 0
|
53
|
+
max_desc_length = 0
|
54
|
+
@plugins.each do |plugin|
|
55
|
+
plugin.name =~ /Deployku::(.*?)Plugin/
|
56
|
+
next unless $1
|
57
|
+
name = $1.downcase
|
58
|
+
plugin.help_register.each do |reg|
|
59
|
+
new_reg = { name: "#{name}:#{reg[:name]}", args: reg[:arg_list], desc: reg[:desc] }
|
60
|
+
max_name_length = new_reg[:name].length if new_reg[:name].length > max_name_length
|
61
|
+
max_arg_length = new_reg[:args].length if new_reg[:args].length > max_arg_length
|
62
|
+
max_desc_length = new_reg[:desc].length if new_reg[:desc].length > max_desc_length
|
63
|
+
help_register << new_reg
|
64
|
+
end
|
65
|
+
end
|
66
|
+
help_register.each do |reg|
|
67
|
+
str << " %-#{max_name_length}s %-#{max_arg_length}s %s\n" % [reg[:name], reg[:args], reg[:desc]]
|
68
|
+
end
|
69
|
+
str
|
70
|
+
end
|
71
|
+
|
72
|
+
# run command in a plugin
|
73
|
+
def self.run(fn, args=[])
|
74
|
+
fn_name = fn.to_s.gsub(':', '_')
|
75
|
+
fn_desc = command_description(fn)
|
76
|
+
unless fn_desc
|
77
|
+
puts "Unknown command '#{fn}'."
|
78
|
+
exit 1
|
79
|
+
end
|
80
|
+
if fn_desc[:acl_app]
|
81
|
+
fn_desc[:acl_app].each do |idx, right|
|
82
|
+
Deployku::AccessPlugin.instance.check_app_rights(args[idx], right, true)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
if fn_desc[:acl_sys]
|
86
|
+
Deployku::AccessPlugin.instance.check_system_rights(fn_desc[:acl_sys], true)
|
87
|
+
end
|
88
|
+
plug = instance
|
89
|
+
raise Deployku::Plugin::NoMethod.new("no method '#{plug.class.name}.#{fn}'") unless plug.respond_to?(fn_name)
|
90
|
+
plug.send(fn_name, *args)
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.instance
|
94
|
+
@instance ||= self.new
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.command_description(fn)
|
98
|
+
self.help_register.each do |reg|
|
99
|
+
return reg if reg[:name].to_s == fn.to_s
|
100
|
+
end
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
|
104
|
+
# concatenate system wide packages and packages required by plugin
|
105
|
+
def packages
|
106
|
+
Deployku::Config.packages + self.class::PACKAGES
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
data/lib/deployku.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
dir = File.expand_path(File.dirname(__FILE__))
|
2
|
+
$:.unshift(dir) unless $:.include?(dir)
|
3
|
+
|
4
|
+
require 'deployku/config'
|
5
|
+
require 'deployku/helpers'
|
6
|
+
require 'deployku/configurable'
|
7
|
+
require 'deployku/containerable'
|
8
|
+
require 'deployku/plugins'
|
9
|
+
require 'deployku/engine'
|
10
|
+
|
11
|
+
# load core plugins
|
12
|
+
require 'deployku/plugins/access'
|
13
|
+
require 'deployku/plugins/docker'
|
14
|
+
require 'deployku/plugins/lxc'
|
15
|
+
require 'deployku/plugins/app'
|
16
|
+
require 'deployku/plugins/git'
|
17
|
+
require 'deployku/plugins/postgres'
|
18
|
+
require 'deployku/plugins/rails'
|
19
|
+
require 'deployku/plugins/nginx'
|
metadata
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: deployku
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Petr Kovář
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-11-09 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email: pejuko@gmail.com
|
15
|
+
executables:
|
16
|
+
- deployku
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- LICENSE
|
21
|
+
- README.md
|
22
|
+
- Rakefile
|
23
|
+
- bin/deployku
|
24
|
+
- deployku.gemspec
|
25
|
+
- lib/deployku.rb
|
26
|
+
- lib/deployku/config.rb
|
27
|
+
- lib/deployku/configurable.rb
|
28
|
+
- lib/deployku/containerable.rb
|
29
|
+
- lib/deployku/engine.rb
|
30
|
+
- lib/deployku/helpers.rb
|
31
|
+
- lib/deployku/plugins.rb
|
32
|
+
- lib/deployku/plugins/access.rb
|
33
|
+
- lib/deployku/plugins/app.rb
|
34
|
+
- lib/deployku/plugins/docker.rb
|
35
|
+
- lib/deployku/plugins/git.rb
|
36
|
+
- lib/deployku/plugins/lxc.rb
|
37
|
+
- lib/deployku/plugins/nginx.rb
|
38
|
+
- lib/deployku/plugins/postgres.rb
|
39
|
+
- lib/deployku/plugins/rails.rb
|
40
|
+
homepage: http://github.com/deployku/deployku
|
41
|
+
licenses: []
|
42
|
+
metadata: {}
|
43
|
+
post_install_message:
|
44
|
+
rdoc_options: []
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
requirements:
|
49
|
+
- - ">="
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
requirements: []
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 2.4.8
|
60
|
+
signing_key:
|
61
|
+
specification_version: 4
|
62
|
+
summary: Deploy applications using git with zero down time
|
63
|
+
test_files: []
|