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,25 +0,0 @@
|
|
1
|
-
module Conjure
|
2
|
-
class CommandTarget
|
3
|
-
def initialize(options = {})
|
4
|
-
@origin = options[:origin]
|
5
|
-
@branch = options[:branch] || "master"
|
6
|
-
@rails_env = options[:rails_env] || "production"
|
7
|
-
end
|
8
|
-
|
9
|
-
def application
|
10
|
-
@application ||= Application.find(:path => Dir.pwd, :origin => @origin)
|
11
|
-
end
|
12
|
-
|
13
|
-
def existing_instance
|
14
|
-
@existing_instance ||= application.instances.first
|
15
|
-
end
|
16
|
-
|
17
|
-
def new_instance
|
18
|
-
@new_instance ||= Instance.new(
|
19
|
-
:origin => application.origin,
|
20
|
-
:branch => @branch,
|
21
|
-
:rails_environment => @rails_env,
|
22
|
-
)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/lib/conjure/config.rb
DELETED
@@ -1,44 +0,0 @@
|
|
1
|
-
module Conjure
|
2
|
-
class Config
|
3
|
-
def self.load(root_path)
|
4
|
-
require "ostruct"
|
5
|
-
config_path = File.join root_path, "config", "conjure.yml"
|
6
|
-
if File.exists? config_path
|
7
|
-
data = YAML.load_file config_path
|
8
|
-
data["config_path"] = File.dirname config_path
|
9
|
-
else
|
10
|
-
data = {}
|
11
|
-
end
|
12
|
-
new data
|
13
|
-
end
|
14
|
-
|
15
|
-
def initialize(options)
|
16
|
-
@options = options
|
17
|
-
find_default_keys unless @options["private_key"]
|
18
|
-
end
|
19
|
-
|
20
|
-
def method_missing(name)
|
21
|
-
@options[name.to_s]
|
22
|
-
end
|
23
|
-
|
24
|
-
def file_contents(name)
|
25
|
-
name = @options[name.to_s] if name.is_a? Symbol
|
26
|
-
name = File.join(@options["config_path"], name) unless name[0] == "/"
|
27
|
-
File.open name, "rb", &:read
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def find_default_keys
|
33
|
-
private_key_paths = ["~/.ssh/id_rsa", "~/.ssh/id_dsa", "~/.ssh/identity"]
|
34
|
-
private_key_paths.each do |path|
|
35
|
-
path = File.expand_path(path)
|
36
|
-
if File.exists?(path) and File.exists?("#{path}.pub")
|
37
|
-
@options["private_key_file"] = path
|
38
|
-
@options["public_key_file"] = "#{path}.pub"
|
39
|
-
return
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
data/lib/conjure/data_set.rb
DELETED
data/lib/conjure/identity.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
module Conjure
|
2
|
-
class Identity
|
3
|
-
require "digest/md5"
|
4
|
-
|
5
|
-
def initialize(config)
|
6
|
-
@config = config
|
7
|
-
end
|
8
|
-
|
9
|
-
def private_key_path
|
10
|
-
Pathname.new(@config.config_path).join @config.private_key_file
|
11
|
-
end
|
12
|
-
|
13
|
-
def public_key_path
|
14
|
-
Pathname.new(@config.config_path).join @config.public_key_file
|
15
|
-
end
|
16
|
-
|
17
|
-
def public_key_data
|
18
|
-
File.open(public_key_path, "rb") { |file| file.read }
|
19
|
-
end
|
20
|
-
|
21
|
-
def unique_identifier
|
22
|
-
"conjure_#{Digest::MD5.hexdigest(public_key_data)[0..7]}"
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
data/lib/conjure/log.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
module Conjure
|
2
|
-
class Log
|
3
|
-
class << self
|
4
|
-
attr_accessor :level
|
5
|
-
attr_accessor :capture
|
6
|
-
attr_reader :history
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.info(message)
|
10
|
-
if @capture
|
11
|
-
@history ||= ""
|
12
|
-
@history << "#{message}\n"
|
13
|
-
else
|
14
|
-
puts message
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.debug(message)
|
19
|
-
info message if @level == :debug
|
20
|
-
end
|
21
|
-
|
22
|
-
def self.clear
|
23
|
-
@history = ""
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
data/lib/conjure/provider.rb
DELETED
@@ -1,26 +0,0 @@
|
|
1
|
-
module Conjure
|
2
|
-
module Provider
|
3
|
-
def self.included(base)
|
4
|
-
base.extend ClassMethods
|
5
|
-
end
|
6
|
-
|
7
|
-
def self.all(service_type)
|
8
|
-
providers(service_type).map{|block| block.call}.flatten.compact
|
9
|
-
end
|
10
|
-
|
11
|
-
def self.register_provider(service_type, &block)
|
12
|
-
providers(service_type) << block
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.providers(service_type)
|
16
|
-
@providers ||= {}
|
17
|
-
@providers[service_type] ||= []
|
18
|
-
end
|
19
|
-
|
20
|
-
module ClassMethods
|
21
|
-
def provides(service_type, &block)
|
22
|
-
Conjure::Provider.register_provider(service_type, &block)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
data/lib/conjure/provision.rb
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
require "conjure/provision/instance"
|
@@ -1,32 +0,0 @@
|
|
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 = "#{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
|
@@ -1,55 +0,0 @@
|
|
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_volume(options = {})
|
13
|
-
@docker_host.started_container_id @name, "/bin/true", daemon_options(options)
|
14
|
-
end
|
15
|
-
|
16
|
-
def start_daemon(command, options = {})
|
17
|
-
container_id = @docker_host.started_container_id @name, command, daemon_options(options)
|
18
|
-
sleep 2
|
19
|
-
ip_address = @docker_host.container_ip_address container_id
|
20
|
-
raise "Container failed to start" unless ip_address.present?
|
21
|
-
ip_address
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
def volume_options(options)
|
27
|
-
"-d " + run_options(options)
|
28
|
-
end
|
29
|
-
|
30
|
-
def daemon_options(options)
|
31
|
-
"-d --restart=always " + run_options(options)
|
32
|
-
end
|
33
|
-
|
34
|
-
def run_options(options)
|
35
|
-
[
|
36
|
-
mapped_options("--link", options[:linked_containers]),
|
37
|
-
("--name #{options[:name]}" if options[:name]),
|
38
|
-
mapped_options("-p", options[:ports]),
|
39
|
-
listed_options("--volumes-from", options[:volume_containers]),
|
40
|
-
].flatten.compact.join(" ")
|
41
|
-
end
|
42
|
-
|
43
|
-
def listed_options(command, values)
|
44
|
-
values ||= []
|
45
|
-
values.map { |v| "#{command} #{v}" }
|
46
|
-
end
|
47
|
-
|
48
|
-
def mapped_options(command, values)
|
49
|
-
values ||= {}
|
50
|
-
values.map { |from, to| "#{command} #{from}:#{to}" }
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
@@ -1,55 +0,0 @@
|
|
1
|
-
require "conjure/provision/docker/host"
|
2
|
-
require "conjure/provision/docker/image"
|
3
|
-
require "tmpdir"
|
4
|
-
|
5
|
-
module Conjure
|
6
|
-
module Provision
|
7
|
-
module Docker
|
8
|
-
class Template
|
9
|
-
def initialize(base_image_name)
|
10
|
-
@commands = ["FROM #{base_image_name}"]
|
11
|
-
@file_data = {}
|
12
|
-
end
|
13
|
-
|
14
|
-
def add_file(filename, remote_name)
|
15
|
-
add_file_data File.read(filename), remote_name
|
16
|
-
end
|
17
|
-
|
18
|
-
def add_file_data(data, remote_name)
|
19
|
-
local_name = "file#{@file_data.length+1}"
|
20
|
-
@file_data[local_name] = data
|
21
|
-
@commands << "ADD #{local_name} #{remote_name}"
|
22
|
-
end
|
23
|
-
|
24
|
-
def run(command)
|
25
|
-
@commands << "RUN #{command}"
|
26
|
-
end
|
27
|
-
|
28
|
-
def volume(name)
|
29
|
-
@commands << "VOLUME #{name}"
|
30
|
-
end
|
31
|
-
|
32
|
-
def source
|
33
|
-
@commands.join "\n"
|
34
|
-
end
|
35
|
-
|
36
|
-
def prepare_build_directory(&block)
|
37
|
-
Dir.mktmpdir do |dir|
|
38
|
-
@file_data.merge("Dockerfile" => source).each do |filename, data|
|
39
|
-
File.write "#{dir}/#{filename}", data
|
40
|
-
end
|
41
|
-
yield dir
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def build(platform)
|
46
|
-
docker_host = Host.new(platform)
|
47
|
-
image_name = prepare_build_directory do |dir|
|
48
|
-
docker_host.built_image_name dir
|
49
|
-
end
|
50
|
-
Image.new docker_host, image_name
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
@@ -1,52 +0,0 @@
|
|
1
|
-
require "conjure/provision/docker/template"
|
2
|
-
require "conjure/provision/local_docker"
|
3
|
-
require "conjure/provision/server"
|
4
|
-
require "conjure/provision/postgres"
|
5
|
-
require "conjure/provision/passenger"
|
6
|
-
require "yaml"
|
7
|
-
|
8
|
-
module Conjure
|
9
|
-
module Provision
|
10
|
-
class Instance
|
11
|
-
def initialize(app_name, rails_env, options = {})
|
12
|
-
@app_name = app_name
|
13
|
-
@rails_env = rails_env
|
14
|
-
@options = options
|
15
|
-
end
|
16
|
-
|
17
|
-
def provision(options = {})
|
18
|
-
if options[:local]
|
19
|
-
platform = LocalDocker.new
|
20
|
-
else
|
21
|
-
platform = Server.create "#{@app_name}-#{@rails_env}", @options
|
22
|
-
end
|
23
|
-
|
24
|
-
database = Postgres.new(platform)
|
25
|
-
database.start
|
26
|
-
|
27
|
-
webserver = Passenger.new(platform, database, @rails_env, @options)
|
28
|
-
webserver.start
|
29
|
-
passenger_ip = webserver.ip_address
|
30
|
-
|
31
|
-
port = platform.ip_address ? "2222" : "22"
|
32
|
-
ip_address = platform.ip_address || passenger_ip
|
33
|
-
|
34
|
-
host = "root@#{ip_address} -p #{port}"
|
35
|
-
|
36
|
-
sleep 1
|
37
|
-
remote_command host, "/etc/init.d/nginx restart"
|
38
|
-
{
|
39
|
-
:ip_address => ip_address,
|
40
|
-
:port => port,
|
41
|
-
:user => "app",
|
42
|
-
:rails_env => @rails_env,
|
43
|
-
:pending_files => webserver.pending_files,
|
44
|
-
}
|
45
|
-
end
|
46
|
-
|
47
|
-
def remote_command(host, command)
|
48
|
-
`ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no #{host} #{command}`
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
@@ -1,111 +0,0 @@
|
|
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, options)
|
10
|
-
@platform = platform
|
11
|
-
@database = database
|
12
|
-
@rails_env = rails_env
|
13
|
-
@nginx_directives = options[:nginx_directives] || {}
|
14
|
-
@system_packages = options[:system_packages] || []
|
15
|
-
@rubygems_version = options[:rubygems_version]
|
16
|
-
@use_ssl = !!options[:ssl_hostname]
|
17
|
-
@ssl_hostname = options[:ssl_hostname] || "unknown"
|
18
|
-
end
|
19
|
-
|
20
|
-
def start
|
21
|
-
@ip_address = server_template.build(@platform).start_daemon("/sbin/my_init", start_options)
|
22
|
-
end
|
23
|
-
|
24
|
-
def pending_files
|
25
|
-
return [] unless @use_ssl
|
26
|
-
[
|
27
|
-
"/etc/ssl/certs/application.crt",
|
28
|
-
"/etc/ssl/certs/root_and_intermediates.crt",
|
29
|
-
"/etc/ssl/private/application.key",
|
30
|
-
"/etc/ssl/dhparam.pem",
|
31
|
-
]
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def start_options
|
37
|
-
{
|
38
|
-
:linked_containers => @database.container_link,
|
39
|
-
:name => "passenger",
|
40
|
-
:ports => {80 => 80, 443 => 443, 2222 => 22},
|
41
|
-
:volume_containers => [data_container_name],
|
42
|
-
}
|
43
|
-
end
|
44
|
-
|
45
|
-
def data_container_name
|
46
|
-
data_template.build(@platform).start_volume(:name => "passenger_data")
|
47
|
-
"passenger_data"
|
48
|
-
end
|
49
|
-
|
50
|
-
def data_template
|
51
|
-
file = Docker::Template.new("conjure/passenger-ruby22:1.0.0")
|
52
|
-
file.add_file_data database_yml, "/home/app/application/shared/config/database.yml"
|
53
|
-
file.add_file_data secrets_yml, "/home/app/application/shared/config/secrets.yml"
|
54
|
-
file.volume "/home/app/application"
|
55
|
-
file
|
56
|
-
end
|
57
|
-
|
58
|
-
def server_template
|
59
|
-
public_key = File.expand_path("~/.ssh/id_rsa.pub")
|
60
|
-
raise "Error: ~/.ssh/id_rsa.pub must exist." unless File.exist?(public_key)
|
61
|
-
file = Docker::Template.new("conjure/passenger-ruby22:1.0.1")
|
62
|
-
file.run apt_command if apt_command
|
63
|
-
file.run rubygems_command if rubygems_command
|
64
|
-
file.add_file public_key, "/root/.ssh/authorized_keys"
|
65
|
-
file.add_file public_key, "/home/app/.ssh/authorized_keys"
|
66
|
-
file.run "chown app.app /home/app/.ssh/authorized_keys"
|
67
|
-
file.run "chown root.root /root/.ssh/authorized_keys"
|
68
|
-
file.add_file_data nginx_conf, "/etc/nginx/sites-available/application-no-ssl.conf"
|
69
|
-
file.add_file_data nginx_ssl_conf, "/etc/nginx/sites-available/application-ssl.conf"
|
70
|
-
which_config = @use_ssl ? "application-ssl" : "application-no-ssl"
|
71
|
-
file.run "ln -s /etc/nginx/sites-available/#{which_config}.conf /etc/nginx/sites-enabled/application.conf"
|
72
|
-
file
|
73
|
-
end
|
74
|
-
|
75
|
-
def apt_command
|
76
|
-
if @system_packages.any?
|
77
|
-
"apt-get update && apt-get install -y #{@system_packages.join ' '}"
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def rubygems_command
|
82
|
-
if @rubygems_version
|
83
|
-
target_source = "/usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb"
|
84
|
-
"sed -i '23d' #{target_source} && gem update --system #{@rubygems_version}"
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def database_yml
|
89
|
-
{@rails_env => @database.rails_config}.to_yaml
|
90
|
-
end
|
91
|
-
|
92
|
-
def secrets_yml
|
93
|
-
{@rails_env => {"secret_key_base" => SecureRandom.hex(64)}}.to_yaml
|
94
|
-
end
|
95
|
-
|
96
|
-
def nginx_conf
|
97
|
-
render_template "application-no-ssl.conf"
|
98
|
-
end
|
99
|
-
|
100
|
-
def nginx_ssl_conf
|
101
|
-
render_template "application-ssl.conf"
|
102
|
-
end
|
103
|
-
|
104
|
-
def render_template(name)
|
105
|
-
template_path = File.join File.dirname(__FILE__), "templates", "#{name}.erb"
|
106
|
-
template_data = File.read template_path
|
107
|
-
Erubis::Eruby.new(template_data).result :rails_env => @rails_env, :ssl_hostname => @ssl_hostname
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|