conjure 0.2.10 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/History.md +8 -0
- data/README.md +35 -76
- data/lib/conjure.rb +1 -12
- data/lib/conjure/delayed_job.rb +39 -0
- data/lib/conjure/digital_ocean/droplet.rb +5 -2
- data/lib/conjure/docker/host.rb +75 -0
- data/lib/conjure/docker/template.rb +71 -0
- data/lib/conjure/instance.rb +31 -76
- data/lib/conjure/passenger.rb +123 -0
- data/lib/conjure/postgres.rb +67 -0
- data/lib/conjure/rails_application.rb +32 -0
- data/lib/conjure/server.rb +41 -0
- data/lib/conjure/swap.rb +28 -0
- data/lib/conjure/{provision/templates → templates}/application-no-ssl.conf.erb +2 -1
- data/lib/conjure/{provision/templates → templates}/application-ssl.conf.erb +2 -1
- data/lib/conjure/version.rb +1 -1
- metadata +12 -41
- data/lib/conjure/application.rb +0 -35
- data/lib/conjure/command.rb +0 -74
- data/lib/conjure/command_target.rb +0 -25
- data/lib/conjure/config.rb +0 -44
- data/lib/conjure/data_set.rb +0 -7
- data/lib/conjure/identity.rb +0 -25
- data/lib/conjure/log.rb +0 -26
- data/lib/conjure/provider.rb +0 -26
- data/lib/conjure/provision.rb +0 -1
- data/lib/conjure/provision/docker/host.rb +0 -32
- data/lib/conjure/provision/docker/image.rb +0 -55
- data/lib/conjure/provision/docker/template.rb +0 -55
- data/lib/conjure/provision/instance.rb +0 -52
- data/lib/conjure/provision/local_docker.rb +0 -16
- data/lib/conjure/provision/passenger.rb +0 -111
- data/lib/conjure/provision/postgres.rb +0 -70
- data/lib/conjure/provision/server.rb +0 -78
- data/lib/conjure/service/cloud_server.rb +0 -112
- data/lib/conjure/service/database.rb +0 -25
- data/lib/conjure/service/database/mysql.rb +0 -69
- data/lib/conjure/service/database/postgres.rb +0 -77
- data/lib/conjure/service/digital_ocean_account.rb +0 -31
- data/lib/conjure/service/docker_host.rb +0 -259
- data/lib/conjure/service/docker_shell.rb +0 -46
- data/lib/conjure/service/forwarded_shell.rb +0 -25
- data/lib/conjure/service/rails_codebase.rb +0 -67
- data/lib/conjure/service/rails_console.rb +0 -10
- data/lib/conjure/service/rails_log_view.rb +0 -14
- data/lib/conjure/service/rails_server.rb +0 -91
- data/lib/conjure/service/rake_task.rb +0 -11
- data/lib/conjure/service/remote_file_set.rb +0 -24
- data/lib/conjure/service/remote_shell.rb +0 -73
- data/lib/conjure/service/repository_link.rb +0 -52
- data/lib/conjure/service/volume.rb +0 -28
- data/lib/conjure/target.rb +0 -19
- data/lib/conjure/view/application_view.rb +0 -42
- data/lib/conjure/view/table_view.rb +0 -38
@@ -1,70 +0,0 @@
|
|
1
|
-
require "conjure/provision/docker/template"
|
2
|
-
require "securerandom"
|
3
|
-
|
4
|
-
module Conjure
|
5
|
-
module Provision
|
6
|
-
class Postgres
|
7
|
-
def initialize(platform)
|
8
|
-
@platform = platform
|
9
|
-
@name = "conjure_db_#{SecureRandom.hex 8}"
|
10
|
-
@password = new_password
|
11
|
-
end
|
12
|
-
|
13
|
-
def start
|
14
|
-
@ip_address = server_template.build(@platform).start_daemon("/sbin/my_init", start_options)
|
15
|
-
end
|
16
|
-
|
17
|
-
def rails_config
|
18
|
-
{
|
19
|
-
"adapter" => "postgresql",
|
20
|
-
"database" => @name,
|
21
|
-
"host" => container_name,
|
22
|
-
"username" => "db",
|
23
|
-
"password" => @password,
|
24
|
-
"template" => "template0",
|
25
|
-
}
|
26
|
-
end
|
27
|
-
|
28
|
-
def container_link
|
29
|
-
{container_name => container_name}
|
30
|
-
end
|
31
|
-
|
32
|
-
private
|
33
|
-
|
34
|
-
def start_options
|
35
|
-
{
|
36
|
-
:name => container_name,
|
37
|
-
:volume_containers => [data_container_name],
|
38
|
-
}
|
39
|
-
end
|
40
|
-
|
41
|
-
def container_name
|
42
|
-
"postgres"
|
43
|
-
end
|
44
|
-
|
45
|
-
def data_container_name
|
46
|
-
data_template.build(@platform).start_volume(:name => "postgres_data")
|
47
|
-
"postgres_data"
|
48
|
-
end
|
49
|
-
|
50
|
-
def data_template
|
51
|
-
file = Docker::Template.new("conjure/postgres93:1.0.0")
|
52
|
-
file.volume "/var/lib/postgresql/9.3/main"
|
53
|
-
file
|
54
|
-
end
|
55
|
-
|
56
|
-
def server_template
|
57
|
-
file = Docker::Template.new("conjure/postgres93:1.0.0")
|
58
|
-
file.run "echo \"ALTER USER db PASSWORD '#{@password}'\" >/tmp/setpass"
|
59
|
-
file.run "/sbin/my_init -- /sbin/setuser postgres sh -c \"sleep 1; psql -f /tmp/setpass\""
|
60
|
-
file.run "rm /tmp/setpass"
|
61
|
-
file.run "/sbin/my_init -- /sbin/setuser db sh -c \"sleep 1; /usr/bin/createdb #{@name}\""
|
62
|
-
file
|
63
|
-
end
|
64
|
-
|
65
|
-
def new_password
|
66
|
-
SecureRandom.urlsafe_base64 20
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
@@ -1,78 +0,0 @@
|
|
1
|
-
require "conjure/digital_ocean/droplet"
|
2
|
-
require "securerandom"
|
3
|
-
|
4
|
-
module Conjure
|
5
|
-
module Provision
|
6
|
-
class Server
|
7
|
-
def initialize(server)
|
8
|
-
@server = server
|
9
|
-
puts "Configuring droplet..."
|
10
|
-
install_swap
|
11
|
-
end
|
12
|
-
|
13
|
-
def ip_address
|
14
|
-
@server.ip_address
|
15
|
-
end
|
16
|
-
|
17
|
-
def run(command)
|
18
|
-
`ssh #{ssh_options} root@#{ip_address} '#{shell_escape_single_quotes command}'`
|
19
|
-
end
|
20
|
-
|
21
|
-
def send_file(local_name, remote_name)
|
22
|
-
`scp #{ssh_options} #{local_name} root@#{ip_address}:#{remote_name}`
|
23
|
-
end
|
24
|
-
|
25
|
-
def ssh_options
|
26
|
-
"-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
|
27
|
-
end
|
28
|
-
|
29
|
-
def shell_escape_single_quotes(command)
|
30
|
-
command.gsub("'", "'\"'\"'")
|
31
|
-
end
|
32
|
-
|
33
|
-
def install_swap
|
34
|
-
run "dd if=/dev/zero of=/root/swapfile bs=4096 count=524288"
|
35
|
-
run "mkswap /root/swapfile; swapon /root/swapfile"
|
36
|
-
end
|
37
|
-
|
38
|
-
def self.create(name, options = {})
|
39
|
-
puts "Creating DigitalOcean droplet..."
|
40
|
-
new DigitalOcean::Droplet.new(droplet_options(uniquify(name), options))
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.droplet_options(name, options = {})
|
44
|
-
raise "Error: DIGITALOCEAN_API_TOKEN must be set." unless ENV["DIGITALOCEAN_API_TOKEN"]
|
45
|
-
{
|
46
|
-
image: "docker",
|
47
|
-
key_data: key_data,
|
48
|
-
name: name,
|
49
|
-
region: "nyc3",
|
50
|
-
size: (options[:instance_size] || "512mb"),
|
51
|
-
token: ENV["DIGITALOCEAN_API_TOKEN"],
|
52
|
-
}
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.key_data
|
56
|
-
ssh_dir = File.expand_path "~/.ssh"
|
57
|
-
raise "Error: ~/.ssh/id_rsa.pub must exist." unless File.exist?(ssh_dir) && File.exist?("#{ssh_dir}/id_rsa.pub")
|
58
|
-
File.read "#{ssh_dir}/id_rsa.pub"
|
59
|
-
end
|
60
|
-
|
61
|
-
def self.uniquify(server_name)
|
62
|
-
"#{server_name}-#{SecureRandom.hex 4}"
|
63
|
-
end
|
64
|
-
|
65
|
-
def with_directory(local_path, &block)
|
66
|
-
local_archive = remote_archive = "/tmp/archive.tar.gz"
|
67
|
-
remote_path = "/tmp/unpacked_archive"
|
68
|
-
`cd #{local_path}; tar czf #{local_archive} *`
|
69
|
-
send_file local_archive, remote_archive
|
70
|
-
run "mkdir #{remote_path}; cd #{remote_path}; tar mxzf #{remote_archive}"
|
71
|
-
yield remote_path
|
72
|
-
ensure
|
73
|
-
`rm #{local_archive}`
|
74
|
-
run "rm -Rf #{remote_path} #{remote_archive}"
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
@@ -1,112 +0,0 @@
|
|
1
|
-
module Conjure
|
2
|
-
module Service
|
3
|
-
class CloudServer
|
4
|
-
require "pathname"
|
5
|
-
attr_reader :name
|
6
|
-
|
7
|
-
def initialize(name)
|
8
|
-
@name = name
|
9
|
-
end
|
10
|
-
|
11
|
-
def run(command, options = {}, &block)
|
12
|
-
set_fog_credentials
|
13
|
-
file_set = RemoteFileSet.new(:shell => remote_shell, :files => options[:files])
|
14
|
-
file_set.upload
|
15
|
-
result = remote_shell.run(command, :stream_stdin => options[:stream_stdin], &block)
|
16
|
-
file_set.remove
|
17
|
-
result
|
18
|
-
end
|
19
|
-
|
20
|
-
def server
|
21
|
-
@server ||= existing_server
|
22
|
-
@server ||= new_server
|
23
|
-
@server.wait_for { ready? }
|
24
|
-
@server
|
25
|
-
end
|
26
|
-
|
27
|
-
def ip_address
|
28
|
-
server.public_ip_address
|
29
|
-
end
|
30
|
-
|
31
|
-
def existing_server
|
32
|
-
@existing_server ||= connection.servers.find{|s| s.name == @name } if connection
|
33
|
-
end
|
34
|
-
|
35
|
-
def self.connection
|
36
|
-
new("").connection
|
37
|
-
end
|
38
|
-
|
39
|
-
def self.each_with_name_prefix(prefix, &block)
|
40
|
-
return unless connection
|
41
|
-
connection.servers.all.select{|s| s.name.match(/^#{prefix}/)}.each do |server|
|
42
|
-
block.call new(server.name)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.ensure_unique_name(name)
|
47
|
-
return name unless connection
|
48
|
-
existing_names = connection.servers.all.map{ |s| s.name }
|
49
|
-
name = increment_numeric_suffix(name) while existing_names.include? name
|
50
|
-
name
|
51
|
-
end
|
52
|
-
|
53
|
-
def self.increment_numeric_suffix(name)
|
54
|
-
parts = name.split("-")
|
55
|
-
parts[2] = parts[2] ? ((parts[2].to_i)+1).to_s : "2"
|
56
|
-
parts.join("-")
|
57
|
-
end
|
58
|
-
|
59
|
-
def new_server
|
60
|
-
Log.info " [cloud] Launching new server #{@name}"
|
61
|
-
bootstrap_options = account.bootstrap_options.merge(:name => @name)
|
62
|
-
options = prepare_bootstrap_options(bootstrap_options).merge(fog_credentials)
|
63
|
-
connection.servers.bootstrap options
|
64
|
-
end
|
65
|
-
|
66
|
-
def account
|
67
|
-
@account ||= Provider.all(:cloud_account).first
|
68
|
-
end
|
69
|
-
|
70
|
-
def connection
|
71
|
-
@connection ||= Fog::Compute.new account.compute_options if account
|
72
|
-
end
|
73
|
-
|
74
|
-
def add_resource_id(options, type)
|
75
|
-
id = "#{type}_id".to_sym
|
76
|
-
name = "#{type}_name".to_sym
|
77
|
-
collection = "#{type}s".to_sym
|
78
|
-
options[id] = resource_id(collection, options[name]) if options[name]
|
79
|
-
end
|
80
|
-
|
81
|
-
def prepare_bootstrap_options(options)
|
82
|
-
add_resource_id(options, :flavor)
|
83
|
-
add_resource_id(options, :region)
|
84
|
-
add_resource_id(options, :image)
|
85
|
-
options
|
86
|
-
end
|
87
|
-
|
88
|
-
def resource_id(collection, name)
|
89
|
-
connection.send(collection).find{|i| i.name == name}.id
|
90
|
-
end
|
91
|
-
|
92
|
-
def set_fog_credentials
|
93
|
-
Fog.credential = Conjure.identity.unique_identifier
|
94
|
-
Fog.credentials.merge! fog_credentials
|
95
|
-
end
|
96
|
-
|
97
|
-
def fog_credentials
|
98
|
-
{
|
99
|
-
private_key_path: Conjure.identity.private_key_path,
|
100
|
-
public_key_path: Conjure.identity.public_key_path,
|
101
|
-
}
|
102
|
-
end
|
103
|
-
|
104
|
-
def remote_shell
|
105
|
-
@remote_shell ||= RemoteShell.new(
|
106
|
-
:ip_address => server.public_ip_address,
|
107
|
-
:username => "root",
|
108
|
-
)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
module Conjure
|
2
|
-
module Service
|
3
|
-
class Database
|
4
|
-
def self.new(options)
|
5
|
-
services_by_gem.each do |gem_name, service_class|
|
6
|
-
if options[:codebase].gem_names.include? gem_name
|
7
|
-
return service_class.new(
|
8
|
-
:target => options[:target],
|
9
|
-
:database_name => "rails_app_db",
|
10
|
-
:adapter_name => adapters_by_gem[gem_name],
|
11
|
-
)
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.services_by_gem
|
17
|
-
{"pg" => Postgres, "mysql2" => Mysql, "mysql" => Mysql}
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.adapters_by_gem
|
21
|
-
{"pg" => "postgresql", "mysql2" => "mysql2", "mysql" => "mysql"}
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
@@ -1,69 +0,0 @@
|
|
1
|
-
module Conjure
|
2
|
-
module Service
|
3
|
-
class Database
|
4
|
-
class Mysql
|
5
|
-
def initialize(options)
|
6
|
-
@target = options[:target]
|
7
|
-
@db_name = options[:database_name]
|
8
|
-
@adapter_name = options[:adapter_name]
|
9
|
-
end
|
10
|
-
|
11
|
-
def base_image
|
12
|
-
@base_image ||= @target.shell.prepare(
|
13
|
-
label: "mysql",
|
14
|
-
setup_commands: [
|
15
|
-
"apt-get install -y mysql-server mysql-client"
|
16
|
-
],
|
17
|
-
)
|
18
|
-
end
|
19
|
-
|
20
|
-
def server_image
|
21
|
-
@server_image ||= base_image.prepare(
|
22
|
-
label: "mysqlserver",
|
23
|
-
setup_commands: [
|
24
|
-
"/usr/sbin/mysqld & sleep 5; echo \"GRANT ALL ON *.* TO root@'%' IDENTIFIED BY '' WITH GRANT OPTION\" | /usr/bin/mysql",
|
25
|
-
],
|
26
|
-
daemon_command: "/usr/sbin/mysqld --bind-address=0.0.0.0",
|
27
|
-
volumes: ["/var/lib/mysql"],
|
28
|
-
)
|
29
|
-
end
|
30
|
-
|
31
|
-
def run
|
32
|
-
container
|
33
|
-
end
|
34
|
-
|
35
|
-
def container
|
36
|
-
@container ||= server_image.run
|
37
|
-
end
|
38
|
-
|
39
|
-
def name
|
40
|
-
@db_name
|
41
|
-
end
|
42
|
-
|
43
|
-
def ip_address
|
44
|
-
container.ip_address
|
45
|
-
end
|
46
|
-
|
47
|
-
def export(file)
|
48
|
-
File.open file, "w" do |f|
|
49
|
-
f.write base_image.command("/usr/bin/mysqldump #{client_options}")
|
50
|
-
end
|
51
|
-
Log.info "[export] #{File.size file} bytes exported to #{file}"
|
52
|
-
end
|
53
|
-
|
54
|
-
def import(file)
|
55
|
-
base_image.command "echo 'source /files/#{File.basename file}' | /usr/bin/mysql #{client_options}", files: [file]
|
56
|
-
Log.info "[import] #{File.size file} bytes imported from #{file}"
|
57
|
-
end
|
58
|
-
|
59
|
-
def client_options
|
60
|
-
"-u root -h #{ip_address} #{@db_name}"
|
61
|
-
end
|
62
|
-
|
63
|
-
def adapter_name
|
64
|
-
@adapter_name || "mysql2"
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|
@@ -1,77 +0,0 @@
|
|
1
|
-
module Conjure
|
2
|
-
module Service
|
3
|
-
class Database
|
4
|
-
class Postgres
|
5
|
-
def initialize(options)
|
6
|
-
@target = options[:target]
|
7
|
-
@db_name = options[:database_name]
|
8
|
-
end
|
9
|
-
|
10
|
-
def base_image
|
11
|
-
@base_image ||= @target.shell.prepare(
|
12
|
-
label: "postgres",
|
13
|
-
setup_commands: [
|
14
|
-
"apt-get install -y python-software-properties software-properties-common",
|
15
|
-
"add-apt-repository -y ppa:pitti/postgresql",
|
16
|
-
"apt-get update",
|
17
|
-
"apt-get install -y postgresql-9.2 postgresql-client-9.2 postgresql-contrib-9.2",
|
18
|
-
],
|
19
|
-
)
|
20
|
-
end
|
21
|
-
|
22
|
-
def server_image
|
23
|
-
@server_image ||= base_image.prepare(
|
24
|
-
label: "pgserver",
|
25
|
-
setup_commands: [
|
26
|
-
"service postgresql start; su postgres -c 'createuser -d -r -s root; createdb -O root root'; service postgresql stop",
|
27
|
-
"echo 'host all all 0.0.0.0/0 trust' >>/etc/postgresql/9.2/main/pg_hba.conf",
|
28
|
-
"echo \"listen_addresses='*'\" >>/etc/postgresql/9.2/main/postgresql.conf",
|
29
|
-
],
|
30
|
-
daemon_command: "su postgres -c '#{bin_path}/postgres -c config_file=/etc/postgresql/9.2/main/postgresql.conf'",
|
31
|
-
volumes: ["/var/lib/postgresql/9.2/main"],
|
32
|
-
)
|
33
|
-
end
|
34
|
-
|
35
|
-
def run
|
36
|
-
container
|
37
|
-
end
|
38
|
-
|
39
|
-
def container
|
40
|
-
@container ||= server_image.run
|
41
|
-
end
|
42
|
-
|
43
|
-
def name
|
44
|
-
@db_name
|
45
|
-
end
|
46
|
-
|
47
|
-
def ip_address
|
48
|
-
container.ip_address
|
49
|
-
end
|
50
|
-
|
51
|
-
def export(file)
|
52
|
-
File.open file, "w" do |f|
|
53
|
-
f.write base_image.command("#{bin_path}/pg_dump #{client_options} #{@db_name}")
|
54
|
-
end
|
55
|
-
Log.info "[export] #{File.size file} bytes exported to #{file}"
|
56
|
-
end
|
57
|
-
|
58
|
-
def import(file)
|
59
|
-
base_image.command "#{bin_path}/psql #{client_options} -d #{@db_name} -f /files/#{File.basename file}", files: [file]
|
60
|
-
Log.info "[import] #{File.size file} bytes imported from #{file}"
|
61
|
-
end
|
62
|
-
|
63
|
-
def client_options
|
64
|
-
"-U root -h #{ip_address}"
|
65
|
-
end
|
66
|
-
|
67
|
-
def bin_path
|
68
|
-
"/usr/lib/postgresql/9.2/bin"
|
69
|
-
end
|
70
|
-
|
71
|
-
def adapter_name
|
72
|
-
"postgresql"
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module Conjure
|
2
|
-
module Service
|
3
|
-
class DigitalOceanAccount
|
4
|
-
include Conjure::Provider
|
5
|
-
|
6
|
-
provides :cloud_account do
|
7
|
-
new if configured?
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.configured?
|
11
|
-
Conjure.config.digitalocean_api_key and Conjure.config.digitalocean_client_id
|
12
|
-
end
|
13
|
-
|
14
|
-
def compute_options
|
15
|
-
{
|
16
|
-
:provider => :digitalocean,
|
17
|
-
:digitalocean_api_key => Conjure.config.digitalocean_api_key,
|
18
|
-
:digitalocean_client_id => Conjure.config.digitalocean_client_id,
|
19
|
-
}
|
20
|
-
end
|
21
|
-
|
22
|
-
def bootstrap_options
|
23
|
-
{
|
24
|
-
:flavor_name => "512MB",
|
25
|
-
:region_name => (Conjure.config.digitalocean_region || "New York 1"),
|
26
|
-
:image_name => "Ubuntu 13.04 x64",
|
27
|
-
}
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|