conjure 0.2.3 → 0.2.4
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 +6 -0
- data/lib/conjure/provision/docker/host.rb +32 -0
- data/lib/conjure/provision/docker/image.rb +22 -0
- data/lib/conjure/provision/docker/template.rb +50 -0
- data/lib/conjure/provision/instance.rb +24 -53
- data/lib/conjure/provision/local_docker.rb +16 -0
- data/lib/conjure/provision/passenger.rb +60 -0
- data/lib/conjure/provision/postgres.rb +44 -0
- data/lib/conjure/provision/server.rb +15 -2
- data/lib/conjure/version.rb +1 -1
- metadata +9 -5
- data/lib/conjure/provision/docker_image.rb +0 -20
- data/lib/conjure/provision/dockerfile.rb +0 -62
data/History.md
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
module Conjure
|
2
|
+
module Provision
|
3
|
+
module Docker
|
4
|
+
class Host
|
5
|
+
def initialize(platform)
|
6
|
+
@platform = platform
|
7
|
+
end
|
8
|
+
|
9
|
+
def built_image_name(dockerfile_directory)
|
10
|
+
result = @platform.with_directory(dockerfile_directory) do |remote_dir|
|
11
|
+
@platform.run "docker build #{remote_dir}"
|
12
|
+
end
|
13
|
+
if match = result.match(/Successfully built ([0-9a-z]+)/)
|
14
|
+
match[1]
|
15
|
+
else
|
16
|
+
raise "Failed to build Docker image, output was #{result}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def started_container_id(image_name, daemon_command, run_options = nil)
|
21
|
+
all_options = "-d #{run_options.to_s} #{image_name} #{daemon_command}"
|
22
|
+
@platform.run("docker run #{all_options}").strip
|
23
|
+
end
|
24
|
+
|
25
|
+
def container_ip_address(container_id)
|
26
|
+
format = "{{ .NetworkSettings.IPAddress }}"
|
27
|
+
@platform.run("docker inspect --format '#{format}' #{container_id}").strip
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Conjure
|
2
|
+
module Provision
|
3
|
+
module Docker
|
4
|
+
class Image
|
5
|
+
attr_reader :image_name
|
6
|
+
|
7
|
+
def initialize(docker_host, image_name)
|
8
|
+
@docker_host = docker_host
|
9
|
+
@name = image_name
|
10
|
+
end
|
11
|
+
|
12
|
+
def start(command, options = {})
|
13
|
+
container_id = @docker_host.started_container_id @name, command, options[:run_options]
|
14
|
+
sleep 2
|
15
|
+
ip_address = @docker_host.container_ip_address container_id
|
16
|
+
raise "Container failed to start" unless ip_address.present?
|
17
|
+
ip_address
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "conjure/provision/docker/host"
|
2
|
+
require "conjure/provision/docker/image"
|
3
|
+
|
4
|
+
module Conjure
|
5
|
+
module Provision
|
6
|
+
module Docker
|
7
|
+
class Template
|
8
|
+
def initialize(base_image_name)
|
9
|
+
@commands = ["FROM #{base_image_name}"]
|
10
|
+
@file_data = {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def add_file(filename, remote_name)
|
14
|
+
add_file_data File.read(filename), remote_name
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_file_data(data, remote_name)
|
18
|
+
local_name = "file#{@file_data.length+1}"
|
19
|
+
@file_data[local_name] = data
|
20
|
+
@commands << "ADD #{local_name} #{remote_name}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def run(command)
|
24
|
+
@commands << "RUN #{command}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def source
|
28
|
+
@commands.join "\n"
|
29
|
+
end
|
30
|
+
|
31
|
+
def prepare_build_directory(&block)
|
32
|
+
Dir.mktmpdir do |dir|
|
33
|
+
@file_data.merge("Dockerfile" => source).each do |filename, data|
|
34
|
+
File.write "#{dir}/#{filename}", data
|
35
|
+
end
|
36
|
+
yield dir
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def build(platform)
|
41
|
+
docker_host = Host.new(platform)
|
42
|
+
image_name = prepare_build_directory do |dir|
|
43
|
+
docker_host.built_image_name dir
|
44
|
+
end
|
45
|
+
Image.new docker_host, image_name
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -1,4 +1,7 @@
|
|
1
|
-
require "conjure/provision/
|
1
|
+
require "conjure/provision/docker/template"
|
2
|
+
require "conjure/provision/local_docker"
|
3
|
+
require "conjure/provision/postgres"
|
4
|
+
require "yaml"
|
2
5
|
|
3
6
|
module Conjure
|
4
7
|
module Provision
|
@@ -8,69 +11,37 @@ module Conjure
|
|
8
11
|
@rails_env = rails_env
|
9
12
|
end
|
10
13
|
|
11
|
-
def provision
|
12
|
-
|
14
|
+
def provision(options = {})
|
15
|
+
if options[:local]
|
16
|
+
platform = LocalDocker.new
|
17
|
+
else
|
18
|
+
platform = Server.create "#{@app_name}-#{@rails_env}"
|
19
|
+
end
|
13
20
|
|
14
|
-
|
15
|
-
|
16
|
-
db_ip_address = postgres_image.start("/sbin/my_init")
|
21
|
+
database = Postgres.new(platform)
|
22
|
+
database.start
|
17
23
|
|
18
|
-
|
19
|
-
|
24
|
+
webserver = Passenger.new(platform, database, @rails_env)
|
25
|
+
webserver.start
|
26
|
+
passenger_ip = webserver.ip_address
|
20
27
|
|
21
|
-
|
28
|
+
port = platform.ip_address ? "2222" : "22"
|
29
|
+
ip_address = platform.ip_address || passenger_ip
|
30
|
+
|
31
|
+
host = "root@#{ip_address} -p #{port}"
|
32
|
+
|
33
|
+
sleep 1
|
22
34
|
remote_command host, "/etc/init.d/nginx restart"
|
23
35
|
{
|
24
|
-
:ip_address =>
|
25
|
-
:port =>
|
36
|
+
:ip_address => ip_address,
|
37
|
+
:port => port,
|
26
38
|
:user => "app",
|
27
39
|
:rails_env => @rails_env
|
28
40
|
}
|
29
41
|
end
|
30
42
|
|
31
|
-
def postgres_dockerfile(db_password)
|
32
|
-
file = Dockerfile.new("conjure/postgres93:1.0.0")
|
33
|
-
file.run "echo \"ALTER USER db PASSWORD '#{db_password}'\" >/tmp/setpass"
|
34
|
-
file.run "/sbin/my_init -- /sbin/setuser postgres sh -c \"sleep 1; psql -f /tmp/setpass\""
|
35
|
-
file.run "rm /tmp/setpass"
|
36
|
-
file.run "/sbin/my_init -- /sbin/setuser db sh -c \"sleep 1; /usr/bin/createdb #{database_name}\""
|
37
|
-
file
|
38
|
-
end
|
39
|
-
|
40
|
-
def passenger_dockerfile(db_ip_address, db_password)
|
41
|
-
public_key = File.expand_path("~/.ssh/id_rsa.pub")
|
42
|
-
raise "Error: ~/.ssh/id_rsa.pub must exist." unless File.exist?(public_key)
|
43
|
-
file = Dockerfile.new("conjure/passenger-ruby21:1.0.1")
|
44
|
-
file.add_file public_key, "/root/.ssh/authorized_keys"
|
45
|
-
file.add_file public_key, "/home/app/.ssh/authorized_keys"
|
46
|
-
file.run "chown app.app /home/app/.ssh/authorized_keys"
|
47
|
-
file.run "chown root.root /root/.ssh/authorized_keys"
|
48
|
-
file.add_file_data application_conf, "/etc/nginx/sites-enabled/application.conf"
|
49
|
-
file.add_file_data database_yml(db_ip_address, db_password), "/home/app/application/shared/config/database.yml"
|
50
|
-
file
|
51
|
-
end
|
52
|
-
|
53
|
-
def new_db_password
|
54
|
-
require "securerandom"
|
55
|
-
SecureRandom.urlsafe_base64 20
|
56
|
-
end
|
57
|
-
|
58
|
-
def database_name
|
59
|
-
"#{@app_name}_#{@rails_env}"
|
60
|
-
end
|
61
|
-
|
62
|
-
def database_yml(db_ip_address, db_password)
|
63
|
-
require "yaml"
|
64
|
-
{@rails_env => {"adapter" => "postgresql", "database" => database_name, "host" => db_ip_address, "username" => "db", "password" => db_password, "template" => "template0"}}.to_yaml
|
65
|
-
end
|
66
|
-
|
67
|
-
def application_conf
|
68
|
-
options = {listen: "80", root: "/home/app/application/current/public", passenger_enabled: "on", passenger_user: "app", passenger_ruby: "/usr/bin/ruby2.1", passenger_app_env: @rails_env}
|
69
|
-
"server {" + options.map{|k, v| " #{k} #{v};"}.join("\n") + "}\n"
|
70
|
-
end
|
71
|
-
|
72
43
|
def remote_command(host, command)
|
73
|
-
`ssh -o StrictHostKeyChecking=no #{host} #{command}`
|
44
|
+
`ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no #{host} #{command}`
|
74
45
|
end
|
75
46
|
end
|
76
47
|
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require "conjure/provision/docker/template"
|
2
|
+
require "securerandom"
|
3
|
+
|
4
|
+
module Conjure
|
5
|
+
module Provision
|
6
|
+
class Passenger
|
7
|
+
attr_reader :ip_address
|
8
|
+
|
9
|
+
def initialize(platform, database, rails_env)
|
10
|
+
@platform = platform
|
11
|
+
@database = database
|
12
|
+
@rails_env = rails_env
|
13
|
+
end
|
14
|
+
|
15
|
+
def start
|
16
|
+
@ip_address = dockerfile.build(@platform).start("/sbin/my_init", start_options)
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def start_options
|
22
|
+
{:run_options => "-p 80:80 -p 2222:22"}
|
23
|
+
end
|
24
|
+
|
25
|
+
def dockerfile
|
26
|
+
public_key = File.expand_path("~/.ssh/id_rsa.pub")
|
27
|
+
raise "Error: ~/.ssh/id_rsa.pub must exist." unless File.exist?(public_key)
|
28
|
+
file = Docker::Template.new("conjure/passenger-ruby21:1.0.1")
|
29
|
+
file.add_file public_key, "/root/.ssh/authorized_keys"
|
30
|
+
file.add_file public_key, "/home/app/.ssh/authorized_keys"
|
31
|
+
file.run "chown app.app /home/app/.ssh/authorized_keys"
|
32
|
+
file.run "chown root.root /root/.ssh/authorized_keys"
|
33
|
+
file.add_file_data nginx_conf, "/etc/nginx/sites-enabled/application.conf"
|
34
|
+
file.add_file_data database_yml, "/home/app/application/shared/config/database.yml"
|
35
|
+
file.add_file_data secrets_yml, "/home/app/application/shared/config/secrets.yml"
|
36
|
+
file
|
37
|
+
end
|
38
|
+
|
39
|
+
def database_yml
|
40
|
+
{@rails_env => @database.rails_config}.to_yaml
|
41
|
+
end
|
42
|
+
|
43
|
+
def secrets_yml
|
44
|
+
{@rails_env => {"secret_key_base" => SecureRandom.hex(64)}}.to_yaml
|
45
|
+
end
|
46
|
+
|
47
|
+
def nginx_conf
|
48
|
+
options = {
|
49
|
+
:listen => "80",
|
50
|
+
:root => "/home/app/application/current/public",
|
51
|
+
:passenger_enabled => "on",
|
52
|
+
:passenger_user => "app",
|
53
|
+
:passenger_ruby => "/usr/bin/ruby2.1",
|
54
|
+
:passenger_app_env => @rails_env,
|
55
|
+
}
|
56
|
+
"server {" + options.map{|k, v| " #{k} #{v};"}.join("\n") + "}\n"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,44 @@
|
|
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 = dockerfile.build(@platform).start("/sbin/my_init")
|
15
|
+
end
|
16
|
+
|
17
|
+
def rails_config
|
18
|
+
{
|
19
|
+
"adapter" => "postgresql",
|
20
|
+
"database" => @name,
|
21
|
+
"host" => @ip_address,
|
22
|
+
"username" => "db",
|
23
|
+
"password" => @password,
|
24
|
+
"template" => "template0",
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def dockerfile
|
31
|
+
file = Docker::Template.new("conjure/postgres93:1.0.0")
|
32
|
+
file.run "echo \"ALTER USER db PASSWORD '#{@password}'\" >/tmp/setpass"
|
33
|
+
file.run "/sbin/my_init -- /sbin/setuser postgres sh -c \"sleep 1; psql -f /tmp/setpass\""
|
34
|
+
file.run "rm /tmp/setpass"
|
35
|
+
file.run "/sbin/my_init -- /sbin/setuser db sh -c \"sleep 1; /usr/bin/createdb #{@name}\""
|
36
|
+
file
|
37
|
+
end
|
38
|
+
|
39
|
+
def new_password
|
40
|
+
SecureRandom.urlsafe_base64 20
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "securerandom"
|
2
|
+
|
1
3
|
module Conjure
|
2
4
|
module Provision
|
3
5
|
class Server
|
@@ -55,7 +57,7 @@ module Conjure
|
|
55
57
|
:name => name,
|
56
58
|
:flavor_id => "66",
|
57
59
|
:region_id => "4",
|
58
|
-
:image_id => "
|
60
|
+
:image_id => "5506141",
|
59
61
|
:private_key_path => "#{ssh_dir}/id_rsa",
|
60
62
|
:public_key_path => "#{ssh_dir}/id_rsa.pub",
|
61
63
|
}
|
@@ -66,9 +68,20 @@ module Conjure
|
|
66
68
|
end
|
67
69
|
|
68
70
|
def self.uniquify(server_name)
|
69
|
-
require "securerandom"
|
70
71
|
"#{server_name}-#{SecureRandom.hex 4}"
|
71
72
|
end
|
73
|
+
|
74
|
+
def with_directory(local_path, &block)
|
75
|
+
local_archive = remote_archive = "/tmp/archive.tar.gz"
|
76
|
+
remote_path = "/tmp/unpacked_archive"
|
77
|
+
`cd #{local_path}; tar czf #{local_archive} *`
|
78
|
+
send_file local_archive, remote_archive
|
79
|
+
run "mkdir #{remote_path}; cd #{remote_path}; tar mxzf #{remote_archive}"
|
80
|
+
yield remote_path
|
81
|
+
ensure
|
82
|
+
`rm #{local_archive}`
|
83
|
+
run "rm -Rf #{remote_path} #{remote_archive}"
|
84
|
+
end
|
72
85
|
end
|
73
86
|
end
|
74
87
|
end
|
data/lib/conjure/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: conjure
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-08-29 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fog
|
@@ -127,8 +127,12 @@ files:
|
|
127
127
|
- lib/conjure/identity.rb
|
128
128
|
- lib/conjure/provision/server.rb
|
129
129
|
- lib/conjure/provision/instance.rb
|
130
|
-
- lib/conjure/provision/
|
131
|
-
- lib/conjure/provision/
|
130
|
+
- lib/conjure/provision/passenger.rb
|
131
|
+
- lib/conjure/provision/postgres.rb
|
132
|
+
- lib/conjure/provision/docker/host.rb
|
133
|
+
- lib/conjure/provision/docker/template.rb
|
134
|
+
- lib/conjure/provision/docker/image.rb
|
135
|
+
- lib/conjure/provision/local_docker.rb
|
132
136
|
- lib/conjure/command.rb
|
133
137
|
- lib/conjure/data_set.rb
|
134
138
|
- lib/conjure/service/digital_ocean_account.rb
|
@@ -177,7 +181,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
177
181
|
version: 1.3.6
|
178
182
|
requirements: []
|
179
183
|
rubyforge_project:
|
180
|
-
rubygems_version: 1.8.
|
184
|
+
rubygems_version: 1.8.29
|
181
185
|
signing_key:
|
182
186
|
specification_version: 3
|
183
187
|
summary: Magically powerful deployment for Rails applications
|
@@ -1,20 +0,0 @@
|
|
1
|
-
module Conjure
|
2
|
-
module Provision
|
3
|
-
class DockerImage
|
4
|
-
attr_reader :image_name
|
5
|
-
|
6
|
-
def initialize(server, base_image_name)
|
7
|
-
@server = server
|
8
|
-
@image_name = base_image_name
|
9
|
-
end
|
10
|
-
|
11
|
-
def start(shell_command, options = {})
|
12
|
-
container_id = @server.run("docker run -d #{options[:run_options].to_s} #{image_name} #{shell_command}").strip
|
13
|
-
sleep 2
|
14
|
-
ip_address = @server.run("docker inspect -format '{{ .NetworkSettings.IPAddress }}' #{container_id}").strip
|
15
|
-
raise "Container failed to start" unless ip_address.present?
|
16
|
-
ip_address
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,62 +0,0 @@
|
|
1
|
-
require "conjure/provision/docker_image"
|
2
|
-
|
3
|
-
module Conjure
|
4
|
-
module Provision
|
5
|
-
class Dockerfile
|
6
|
-
def initialize(base_image_name)
|
7
|
-
@commands = ["FROM #{base_image_name}"]
|
8
|
-
@file_data = {}
|
9
|
-
end
|
10
|
-
|
11
|
-
def add_file(filename, remote_name)
|
12
|
-
add_file_data File.read(filename), remote_name
|
13
|
-
end
|
14
|
-
|
15
|
-
def add_file_data(data, remote_name)
|
16
|
-
local_name = "file#{@file_data.length+1}"
|
17
|
-
@file_data[local_name] = data
|
18
|
-
@commands << "ADD #{local_name} #{remote_name}"
|
19
|
-
end
|
20
|
-
|
21
|
-
def run(command)
|
22
|
-
@commands << "RUN #{command}"
|
23
|
-
end
|
24
|
-
|
25
|
-
def source
|
26
|
-
@commands.join "\n"
|
27
|
-
end
|
28
|
-
|
29
|
-
def prepare_build_directory(&block)
|
30
|
-
Dir.mktmpdir do |dir|
|
31
|
-
@file_data.merge("Dockerfile" => source).each do |filename, data|
|
32
|
-
File.write "#{dir}/#{filename}", data
|
33
|
-
end
|
34
|
-
yield dir
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
def upload_build_directory(server, &block)
|
39
|
-
archive = "/tmp/dockerfile.tar.gz"
|
40
|
-
build_dir = "/tmp/docker_build"
|
41
|
-
prepare_build_directory do |dir|
|
42
|
-
`cd #{dir}; tar czf #{archive} *`
|
43
|
-
server.send_file archive, "dockerfile.tar.gz"
|
44
|
-
server.run "mkdir #{build_dir}; cd #{build_dir}; tar mxzf ~/dockerfile.tar.gz"
|
45
|
-
result = yield "/tmp/docker_build"
|
46
|
-
server.run "rm -Rf #{build_dir} ~/dockerfile.tar.gz"
|
47
|
-
`rm #{archive}`
|
48
|
-
result
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
def build(server)
|
53
|
-
result = upload_build_directory(server) { |dir| server.run "docker build #{dir}" }
|
54
|
-
if match = result.match(/Successfully built ([0-9a-z]+)/)
|
55
|
-
DockerImage.new server, match[1]
|
56
|
-
else
|
57
|
-
raise "Failed to build Docker image, output was #{result}"
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|