conjure 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/History.md CHANGED
@@ -1,3 +1,8 @@
1
+ ### Version 0.1.1
2
+ 2013-11-05
3
+
4
+ * Support Docker 0.6.5
5
+
1
6
  ### Version 0.1.0
2
7
  2013-10-24
3
8
 
data/lib/conjure.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Conjure
2
2
 
3
- VERSION = "0.1.0" unless defined?(VERSION)
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
@@ -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.create self.application_options
54
+ Service::RailsApplication.new self.application_options
55
55
  end
56
56
 
57
57
  def github_url
@@ -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
- OpenStruct.new data
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
@@ -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 < Basic
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
- server.ssh "mkdir -p #{dir_names.join ' '}" if dir_names.any?
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
- puts " [cloud] Using existing server #{@name}" if server
42
+ Conjure.log " [cloud] Using existing server #{@name}" if server
42
43
  server
43
44
  end
44
45
 
45
46
  def new_server
46
- puts " [cloud] Launching new server #{@name}"
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 < Basic
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.create @server_name
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
- puts "[docker] Installing docker"
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
- puts "[docker] Using installed #{path}" if path
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
- puts " [scp] #{options[:files].inspect}" if VERBOSE and options[:files]
46
- puts " [ssh] #{full_command}" if VERBOSE
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
- puts "[docker] Starting #{@label}"
113
- run_options = @host_volumes ? host_volume_options(@host_volumes) : ""
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
- puts "[docker] #{@label} is running at #{running_container.ip_address}"
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
- puts "[docker] Building #{@label} image"
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 += " "+host_volume_options(@host_volumes) if @host_volumes
161
- file_options += " -i" if options[:stream_stdin]
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.join " "
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
- puts "[docker] Stopping #{options[:image_name]}"
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
@@ -2,7 +2,7 @@ require "vagrant"
2
2
 
3
3
  module Conjure
4
4
  module Service
5
- class MachineInstance < Basic
5
+ class MachineInstance
6
6
  def start
7
7
  @config_path = File.expand_path "../../../../config", __FILE__
8
8
  load_environment
@@ -1,6 +1,6 @@
1
1
  module Conjure
2
2
  module Service
3
- class PostgresDatabase < Basic
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
- puts "[export] #{File.size file} bytes exported to #{file}"
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
- puts "[import] #{File.size file} bytes imported from #{file}"
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 < Basic
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
- puts "[deploy] Deploying #{@name}:#{@branch} to #{@environment}"
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
- puts "[deploy] Application deployed to #{docker.ip_address}"
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.create "#{@name}-#{@environment}"
23
+ @docker ||= Service::DockerHost.new "#{@name}-#{@environment}"
24
24
  end
25
25
 
26
26
  def database
27
- @database ||= Service::PostgresDatabase.create docker, "#{@name}_#{@environment}"
27
+ @database ||= Service::PostgresDatabase.new docker, "#{@name}_#{@environment}"
28
28
  end
29
29
 
30
30
  def codebase
31
- @codebase ||= Service::RailsCodebase.create docker, @origin, @branch, @name, database.ip_address, @environment
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.create docker, @name, @environment
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 < Basic
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 = file_contents(Conjure.config.private_key_file).gsub("\n", "\\n")
11
- github_public_key = file_contents(Conjure.config.public_key_file).gsub("\n", "\\n")
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
- puts "[ repo] Checking out code from git"
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
- puts "[ repo] Fetching code updates from git"
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
- puts "[ repo] Generating database.yml"
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
- puts "[ repo] Configuring application logger"
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 < Basic
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
- puts "[ rails] Installing gems"
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
- puts "[ rails] Checking the database status"
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
- puts "[ rails] Migrating the database"
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
- puts "[ rails] Setting up the database"
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
- def initialize(options)
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 => File.read(@options[:private_key_path]),
45
+ :key_data => key_data,
41
46
  :keys_only => true,
42
47
  :paranoid => false,
43
48
  }
44
- @session ||= Net::SSH.start @options[:ip_address], @options[:username], session_options
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.0
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-10-25 00:00:00.000000000 Z
12
+ date: 2013-11-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fog