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 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