conjure 0.2.10 → 0.3.0
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.
- 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
|