conjure 0.1.0 → 0.1.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.
- data/History.md +5 -0
- data/lib/conjure.rb +5 -1
- data/lib/conjure/command.rb +1 -1
- data/lib/conjure/config.rb +15 -1
- data/lib/conjure/service.rb +0 -11
- data/lib/conjure/service/cloud_server.rb +10 -4
- data/lib/conjure/service/docker_host.rb +23 -19
- data/lib/conjure/service/machine_instance.rb +1 -1
- data/lib/conjure/service/postgres_database.rb +3 -3
- data/lib/conjure/service/rails_application.rb +7 -7
- data/lib/conjure/service/rails_codebase.rb +7 -7
- data/lib/conjure/service/rails_server.rb +6 -6
- data/lib/conjure/service/remote_shell.rb +12 -3
- metadata +2 -2
data/History.md
CHANGED
data/lib/conjure.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Conjure
|
2
2
|
|
3
|
-
VERSION = "0.1.
|
3
|
+
VERSION = "0.1.1" unless defined?(VERSION)
|
4
4
|
autoload :Command, "conjure/command"
|
5
5
|
autoload :Config, "conjure/config"
|
6
6
|
autoload :Service, "conjure/service"
|
@@ -8,4 +8,8 @@ module Conjure
|
|
8
8
|
def self.config
|
9
9
|
@config ||= Config.load Dir.pwd
|
10
10
|
end
|
11
|
+
|
12
|
+
def self.log(message)
|
13
|
+
puts message
|
14
|
+
end
|
11
15
|
end
|
data/lib/conjure/command.rb
CHANGED
@@ -51,7 +51,7 @@ module Conjure
|
|
51
51
|
def application
|
52
52
|
self.application_options ||= {}
|
53
53
|
self.application_options[:origin] ||= github_url
|
54
|
-
Service::RailsApplication.
|
54
|
+
Service::RailsApplication.new self.application_options
|
55
55
|
end
|
56
56
|
|
57
57
|
def github_url
|
data/lib/conjure/config.rb
CHANGED
@@ -5,7 +5,21 @@ module Conjure
|
|
5
5
|
config_path = File.join root_path, "config", "conjure.yml"
|
6
6
|
data = YAML.load_file config_path
|
7
7
|
data["config_path"] = File.dirname config_path
|
8
|
-
|
8
|
+
new data
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(options)
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_missing(name)
|
16
|
+
return @options[name.to_s] if @options.has_key? name.to_s
|
17
|
+
super
|
18
|
+
end
|
19
|
+
|
20
|
+
def file_contents(name)
|
21
|
+
name = @options[name.to_s] if name.is_a? Symbol
|
22
|
+
File.open File.join(@options["config_path"], name), "rb", &:read
|
9
23
|
end
|
10
24
|
end
|
11
25
|
end
|
data/lib/conjure/service.rb
CHANGED
@@ -9,15 +9,4 @@ module Conjure
|
|
9
9
|
autoload :PostgresDatabase, "conjure/service/postgres_database"
|
10
10
|
autoload :RemoteShell, "conjure/service/remote_shell"
|
11
11
|
end
|
12
|
-
|
13
|
-
class Basic
|
14
|
-
def self.create(*args)
|
15
|
-
new(*args)
|
16
|
-
end
|
17
|
-
|
18
|
-
def file_contents(file_path)
|
19
|
-
file_path = File.join Conjure.config.config_path, file_path
|
20
|
-
`cat #{file_path}`
|
21
|
-
end
|
22
|
-
end
|
23
12
|
end
|
@@ -1,7 +1,8 @@
|
|
1
1
|
module Conjure
|
2
2
|
module Service
|
3
|
-
class CloudServer
|
3
|
+
class CloudServer
|
4
4
|
require "fog"
|
5
|
+
require "digest/md5"
|
5
6
|
|
6
7
|
def initialize(name)
|
7
8
|
@name = name
|
@@ -17,7 +18,7 @@ module Conjure
|
|
17
18
|
|
18
19
|
def upload_files(files)
|
19
20
|
dir_names = files.map{|local_path, remote_path| File.dirname remote_path}.uniq
|
20
|
-
|
21
|
+
run "mkdir -p #{dir_names.join ' '}" if dir_names.any?
|
21
22
|
files.each{|local_path, remote_path| server.scp local_path, remote_path}
|
22
23
|
end
|
23
24
|
|
@@ -38,12 +39,12 @@ module Conjure
|
|
38
39
|
|
39
40
|
def existing_server
|
40
41
|
server = connection.servers.find{|s| s.name == @name }
|
41
|
-
|
42
|
+
Conjure.log " [cloud] Using existing server #{@name}" if server
|
42
43
|
server
|
43
44
|
end
|
44
45
|
|
45
46
|
def new_server
|
46
|
-
|
47
|
+
Conjure.log " [cloud] Launching new server #{@name}"
|
47
48
|
connection.servers.bootstrap bootstrap_options.merge(fog_credentials)
|
48
49
|
end
|
49
50
|
|
@@ -81,6 +82,7 @@ module Conjure
|
|
81
82
|
end
|
82
83
|
|
83
84
|
def set_fog_credentials
|
85
|
+
Fog.credential = fog_key_identifier
|
84
86
|
Fog.credentials.merge! fog_credentials
|
85
87
|
end
|
86
88
|
|
@@ -99,6 +101,10 @@ module Conjure
|
|
99
101
|
}
|
100
102
|
end
|
101
103
|
|
104
|
+
def fog_key_identifier
|
105
|
+
"conjure_#{Digest::MD5.hexdigest(File.read public_key_file)[0..7]}"
|
106
|
+
end
|
107
|
+
|
102
108
|
def remote_shell
|
103
109
|
@remote_shell ||= RemoteShell.new(
|
104
110
|
:ip_address => server.public_ip_address,
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Conjure
|
2
2
|
module Service
|
3
|
-
class DockerHost
|
3
|
+
class DockerHost
|
4
4
|
VERBOSE = false
|
5
5
|
|
6
6
|
def initialize(server_name)
|
@@ -8,7 +8,7 @@ module Conjure
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def server
|
11
|
-
@server ||= Service::CloudServer.
|
11
|
+
@server ||= Service::CloudServer.new @server_name
|
12
12
|
end
|
13
13
|
|
14
14
|
def ip_address
|
@@ -16,7 +16,7 @@ module Conjure
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def new_docker_path
|
19
|
-
|
19
|
+
Conjure.log "[docker] Installing docker"
|
20
20
|
server.run "dd if=/dev/zero of=/root/swapfile bs=1024 count=524288"
|
21
21
|
server.run "mkswap /root/swapfile; swapon /root/swapfile"
|
22
22
|
server.run "curl https://get.docker.io/gpg | apt-key add -"
|
@@ -29,7 +29,7 @@ module Conjure
|
|
29
29
|
def existing_docker_path
|
30
30
|
path = server.run("which docker").stdout.to_s.strip
|
31
31
|
path = nil if path == ""
|
32
|
-
|
32
|
+
Conjure.log "[docker] Using installed #{path}" if path
|
33
33
|
path
|
34
34
|
end
|
35
35
|
|
@@ -42,8 +42,8 @@ module Conjure
|
|
42
42
|
full_command = "#{docker_path} #{command}"
|
43
43
|
full_command = "nohup #{full_command}" if options[:nohup]
|
44
44
|
full_command = "echo '#{shell_escape options[:stdin]}' | #{full_command}" if options[:stdin]
|
45
|
-
|
46
|
-
|
45
|
+
Conjure.log " [scp] #{options[:files].inspect}" if VERBOSE and options[:files]
|
46
|
+
Conjure.log " [ssh] #{full_command}" if VERBOSE
|
47
47
|
result = server.run full_command, :stream_stdin => options[:stream_stdin], :files => options[:files], &block
|
48
48
|
raise "Docker error: #{result.stdout} #{result.stderr}" unless result.status == 0
|
49
49
|
result.stdout
|
@@ -109,16 +109,17 @@ module Conjure
|
|
109
109
|
|
110
110
|
def run(command = "")
|
111
111
|
unless running_container
|
112
|
-
|
113
|
-
run_options =
|
112
|
+
Conjure.log "[docker] Starting #{@label}"
|
113
|
+
run_options = host_volume_options(@host_volumes)
|
114
|
+
run_options += port_options(@ports)
|
114
115
|
command = shell_command command if command != ""
|
115
|
-
container_id = @host.command("run #{run_options} -d #{installed_image_name} #{command}").strip
|
116
|
+
container_id = @host.command("run #{run_options.join ' '} -d #{installed_image_name} #{command}").strip
|
116
117
|
if(!running_container)
|
117
118
|
output = @host.command "logs #{container_id}"
|
118
119
|
raise "Docker: #{@label} daemon exited with: #{output}"
|
119
120
|
end
|
120
121
|
end
|
121
|
-
|
122
|
+
Conjure.log "[docker] #{@label} is running at #{running_container.ip_address}"
|
122
123
|
running_container
|
123
124
|
end
|
124
125
|
|
@@ -137,7 +138,6 @@ module Conjure
|
|
137
138
|
lines = ["FROM #{base_image_name}"]
|
138
139
|
lines += @environment.map{|k, v| "ENV #{k} #{v}"} if @environment
|
139
140
|
lines += @setup_commands.map{|c| "RUN #{c}"}
|
140
|
-
lines << "EXPOSE #{@ports.map{|p| "#{p}:#{p}"}.join ' '}" if @ports.to_a.any?
|
141
141
|
lines << "VOLUME #{@volumes.inspect}" if @volumes.to_a.any?
|
142
142
|
lines << "ENTRYPOINT #{@daemon_command}" if @daemon_command
|
143
143
|
lines.join "\n"
|
@@ -149,24 +149,28 @@ module Conjure
|
|
149
149
|
|
150
150
|
def build
|
151
151
|
destroy_instances
|
152
|
-
|
152
|
+
Conjure.log "[docker] Building #{@label} image"
|
153
153
|
raise_build_errors(@host.command "build -t #{expected_image_name} -", stdin: dockerfile)
|
154
154
|
@host.containers.destroy_all_stopped
|
155
155
|
end
|
156
156
|
|
157
157
|
def command(command, options = {}, &block)
|
158
158
|
destroy_instances
|
159
|
-
file_options = options[:files] ? "-v /files:/files" :
|
160
|
-
file_options +=
|
161
|
-
file_options
|
162
|
-
@host.command "run #{file_options} #{installed_image_name} #{shell_command command}", :stream_stdin => options[:stream_stdin], :files => files_hash(options[:files]), &block
|
159
|
+
file_options = options[:files] ? ["-v /files:/files"] : []
|
160
|
+
file_options += host_volume_options(@host_volumes)
|
161
|
+
file_options << "-i" if options[:stream_stdin]
|
162
|
+
@host.command "run #{file_options.join ' '} #{installed_image_name} #{shell_command command}", :stream_stdin => options[:stream_stdin], :files => files_hash(options[:files]), &block
|
163
163
|
end
|
164
164
|
|
165
165
|
def host_volume_options(host_volumes)
|
166
|
-
host_volumes.map do |host_path, container_path|
|
166
|
+
host_volumes.to_a.map do |host_path, container_path|
|
167
167
|
@host.ensure_host_directory host_path
|
168
168
|
"-v=#{host_path}:#{container_path}:rw"
|
169
|
-
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def port_options(ports)
|
173
|
+
ports.to_a.map {|port| "-p=#{port}:#{port}" }
|
170
174
|
end
|
171
175
|
|
172
176
|
def files_hash(files_array)
|
@@ -212,7 +216,7 @@ module Conjure
|
|
212
216
|
|
213
217
|
def destroy_all(options)
|
214
218
|
while container = find(:image_name => options[:image_name]) do
|
215
|
-
|
219
|
+
Conjure.log "[docker] Stopping #{options[:image_name]}"
|
216
220
|
host.command "stop #{container.id}"
|
217
221
|
host.command "rm #{container.id}"
|
218
222
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Conjure
|
2
2
|
module Service
|
3
|
-
class PostgresDatabase
|
3
|
+
class PostgresDatabase
|
4
4
|
def initialize(host, db_name)
|
5
5
|
@host = host
|
6
6
|
@db_name = db_name
|
@@ -49,12 +49,12 @@ module Conjure
|
|
49
49
|
File.open file, "w" do |f|
|
50
50
|
f.write base_image.command("#{bin_path}/pg_dump #{client_options} #{@db_name}")
|
51
51
|
end
|
52
|
-
|
52
|
+
Conjure.log "[export] #{File.size file} bytes exported to #{file}"
|
53
53
|
end
|
54
54
|
|
55
55
|
def import(file)
|
56
56
|
base_image.command "#{bin_path}/psql #{client_options} -d #{@db_name} -f /files/#{File.basename file}", files: [file]
|
57
|
-
|
57
|
+
Conjure.log "[import] #{File.size file} bytes imported from #{file}"
|
58
58
|
end
|
59
59
|
|
60
60
|
def client_options
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Conjure
|
2
2
|
module Service
|
3
|
-
class RailsApplication
|
3
|
+
class RailsApplication
|
4
4
|
def initialize(options)
|
5
5
|
@origin = options[:origin]
|
6
6
|
@name = name_from_origin @origin
|
@@ -10,29 +10,29 @@ module Conjure
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def deploy
|
13
|
-
|
13
|
+
Conjure.log "[deploy] Deploying #{@name}:#{@branch} to #{@environment}"
|
14
14
|
unless @test
|
15
15
|
database.run
|
16
16
|
codebase.install
|
17
17
|
rails.run
|
18
|
-
|
18
|
+
Conjure.log "[deploy] Application deployed to #{docker.ip_address}"
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
22
|
def docker
|
23
|
-
@docker ||= Service::DockerHost.
|
23
|
+
@docker ||= Service::DockerHost.new "#{@name}-#{@environment}"
|
24
24
|
end
|
25
25
|
|
26
26
|
def database
|
27
|
-
@database ||= Service::PostgresDatabase.
|
27
|
+
@database ||= Service::PostgresDatabase.new docker, "#{@name}_#{@environment}"
|
28
28
|
end
|
29
29
|
|
30
30
|
def codebase
|
31
|
-
@codebase ||= Service::RailsCodebase.
|
31
|
+
@codebase ||= Service::RailsCodebase.new docker, @origin, @branch, @name, database.ip_address, @environment
|
32
32
|
end
|
33
33
|
|
34
34
|
def rails
|
35
|
-
@rails ||= Service::RailsServer.
|
35
|
+
@rails ||= Service::RailsServer.new docker, @name, @environment
|
36
36
|
end
|
37
37
|
|
38
38
|
def name_from_origin(origin)
|
@@ -1,14 +1,14 @@
|
|
1
1
|
module Conjure
|
2
2
|
module Service
|
3
|
-
class RailsCodebase
|
3
|
+
class RailsCodebase
|
4
4
|
def initialize(host, github_url, branch, app_name, database_ip_address, rails_environment)
|
5
5
|
@github_url = github_url
|
6
6
|
@branch = branch
|
7
7
|
@app_name = app_name
|
8
8
|
@database_ip_address = database_ip_address
|
9
9
|
@rails_environment = rails_environment
|
10
|
-
github_private_key =
|
11
|
-
github_public_key =
|
10
|
+
github_private_key = Conjure.config.file_contents(:private_key_file).gsub("\n", "\\n")
|
11
|
+
github_public_key = Conjure.config.file_contents(:public_key_file).gsub("\n", "\\n")
|
12
12
|
@image = host.images.create(
|
13
13
|
label: "codebase",
|
14
14
|
base_image: "ubuntu",
|
@@ -47,22 +47,22 @@ module Conjure
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def checkout_code
|
50
|
-
|
50
|
+
Conjure.log "[ repo] Checking out code from git"
|
51
51
|
@image.command "git clone -b #{@branch} #{@github_url}"
|
52
52
|
end
|
53
53
|
|
54
54
|
def fetch_code_updates
|
55
|
-
|
55
|
+
Conjure.log "[ repo] Fetching code updates from git"
|
56
56
|
@image.command "cd #{@app_name}; git reset --hard; git checkout #{@branch}; git pull"
|
57
57
|
end
|
58
58
|
|
59
59
|
def configure_database
|
60
|
-
|
60
|
+
Conjure.log "[ repo] Generating database.yml"
|
61
61
|
@image.command "echo '#{database_yml}' >/#{@app_name}/config/database.yml"
|
62
62
|
end
|
63
63
|
|
64
64
|
def configure_logs
|
65
|
-
|
65
|
+
Conjure.log "[ repo] Configuring application logger"
|
66
66
|
setup = 'Rails.logger = Logger.new "#{Rails.root}/log/#{Rails.env}.log"'
|
67
67
|
@image.command "echo '#{setup}' >/#{@app_name}/config/initializers/z_conjure_logger.rb"
|
68
68
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Conjure
|
2
2
|
module Service
|
3
|
-
class RailsServer
|
3
|
+
class RailsServer
|
4
4
|
def initialize(host, app_name, rails_environment)
|
5
5
|
@host = host
|
6
6
|
@app_name = app_name
|
@@ -53,7 +53,7 @@ module Conjure
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def install_gems
|
56
|
-
|
56
|
+
Conjure.log "[ rails] Installing gems"
|
57
57
|
base_image.command "cd #{@app_name}; bundle --deployment"
|
58
58
|
end
|
59
59
|
|
@@ -62,17 +62,17 @@ module Conjure
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def database_exists
|
65
|
-
|
65
|
+
Conjure.log "[ rails] Checking the database status"
|
66
66
|
base_image.command("cd #{@app_name}; bundle exec rake db:version; true").include? "Current version:"
|
67
67
|
end
|
68
68
|
|
69
69
|
def migrate_database
|
70
|
-
|
70
|
+
Conjure.log "[ rails] Migrating the database"
|
71
71
|
base_image.command "cd #{@app_name}; bundle exec rake db:migrate"
|
72
72
|
end
|
73
73
|
|
74
74
|
def initialize_database
|
75
|
-
|
75
|
+
Conjure.log "[ rails] Setting up the database"
|
76
76
|
base_image.command "cd #{@app_name}; bundle exec rake db:setup"
|
77
77
|
end
|
78
78
|
|
@@ -105,7 +105,7 @@ module Conjure
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def ruby_version
|
108
|
-
file_contents("../.ruby-version").strip
|
108
|
+
Conjure.config.file_contents("../.ruby-version").strip
|
109
109
|
end
|
110
110
|
|
111
111
|
def apt_packages_required_for_gems
|
@@ -3,7 +3,12 @@ module Conjure
|
|
3
3
|
class RemoteShell
|
4
4
|
require "net/ssh"
|
5
5
|
|
6
|
-
|
6
|
+
class << self
|
7
|
+
attr_accessor :ssh_service
|
8
|
+
end
|
9
|
+
@ssh_service = Net::SSH
|
10
|
+
|
11
|
+
def initialize(options = {})
|
7
12
|
@options = options
|
8
13
|
end
|
9
14
|
|
@@ -37,11 +42,15 @@ module Conjure
|
|
37
42
|
def session
|
38
43
|
session_options = {
|
39
44
|
:auth_methods => ["publickey"],
|
40
|
-
:key_data =>
|
45
|
+
:key_data => key_data,
|
41
46
|
:keys_only => true,
|
42
47
|
:paranoid => false,
|
43
48
|
}
|
44
|
-
@session ||=
|
49
|
+
@session ||= self.class.ssh_service.start @options[:ip_address], @options[:username], session_options
|
50
|
+
end
|
51
|
+
|
52
|
+
def key_data
|
53
|
+
File.read @options[:private_key_path] if @options[:private_key_path]
|
45
54
|
end
|
46
55
|
|
47
56
|
def poll_stream(stream, &block)
|
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.1.
|
4
|
+
version: 0.1.1
|
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: 2013-
|
12
|
+
date: 2013-11-05 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fog
|