conjure 0.1.3 → 0.1.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 +5 -0
- data/README.md +6 -9
- data/lib/conjure/config.rb +17 -1
- data/lib/conjure/service/cloud_server.rb +0 -1
- data/lib/conjure/service/database/mysql.rb +2 -4
- data/lib/conjure/service/database/postgres.rb +2 -4
- data/lib/conjure/service/docker_host.rb +6 -0
- data/lib/conjure/service/docker_shell.rb +46 -0
- data/lib/conjure/service/forwarded_shell.rb +25 -0
- data/lib/conjure/service/rails_codebase.rb +13 -29
- data/lib/conjure/service/rails_server.rb +2 -5
- data/lib/conjure/service/remote_shell.rb +1 -6
- data/lib/conjure/service/repository_link.rb +47 -0
- data/lib/conjure/service/volume.rb +28 -0
- data/lib/conjure/version.rb +1 -1
- metadata +6 -2
data/History.md
CHANGED
data/README.md
CHANGED
@@ -43,7 +43,7 @@ and then running `bundle`, OR by installing it directly:
|
|
43
43
|
|
44
44
|
Then add a file to your Rails project called
|
45
45
|
`config/conjure.yml`. This should be a YAML file with the following
|
46
|
-
fields
|
46
|
+
fields:
|
47
47
|
|
48
48
|
* `digitalocean_client_id` and `digitalocean_api_key`: These
|
49
49
|
credentials are available after logging in to your Digital Ocean
|
@@ -52,20 +52,17 @@ fields (all fields are required):
|
|
52
52
|
* `digitalocean_region`: The geographic region for deploying new
|
53
53
|
cloud servers. If unsure, use "New York 1".
|
54
54
|
|
55
|
-
* `private_key_file` and `public_key_file
|
56
|
-
(relative to your project's
|
57
|
-
private and public SSH keys
|
58
|
-
|
59
|
-
|
60
|
-
private key to the server during deployment.
|
55
|
+
* `private_key_file` and `public_key_file` (optional): Pathnames to
|
56
|
+
local files (absolute paths, or relative to your project's
|
57
|
+
`config` directory) that contain the private and public SSH keys
|
58
|
+
to use for deployment. If these aren't specified, Conjure will try
|
59
|
+
to find identity files in `~/.ssh`.
|
61
60
|
|
62
61
|
Here's an example conjure.yml file:
|
63
62
|
|
64
63
|
digitalocean_client_id: XXXXXXXX
|
65
64
|
digitalocean_api_key: XXXXXXXX
|
66
65
|
digitalocean_region: New York 1
|
67
|
-
private_key_file: conjure_key
|
68
|
-
public_key_file: conjure_key.pub
|
69
66
|
|
70
67
|
Finally, tell Conjure to deploy your app:
|
71
68
|
|
data/lib/conjure/config.rb
CHANGED
@@ -10,6 +10,7 @@ module Conjure
|
|
10
10
|
|
11
11
|
def initialize(options)
|
12
12
|
@options = options
|
13
|
+
find_default_keys unless @options["private_key"]
|
13
14
|
end
|
14
15
|
|
15
16
|
def method_missing(name)
|
@@ -19,7 +20,22 @@ module Conjure
|
|
19
20
|
|
20
21
|
def file_contents(name)
|
21
22
|
name = @options[name.to_s] if name.is_a? Symbol
|
22
|
-
|
23
|
+
name = File.join(@options["config_path"], name) unless name[0] == "/"
|
24
|
+
File.open name, "rb", &:read
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def find_default_keys
|
30
|
+
private_key_paths = ["~/.ssh/id_rsa", "~/.ssh/id_dsa", "~/.ssh/identity"]
|
31
|
+
private_key_paths.each do |path|
|
32
|
+
path = File.expand_path(path)
|
33
|
+
if File.exists?(path) and File.exists?("#{path}.pub")
|
34
|
+
@options["private_key_file"] = path
|
35
|
+
@options["public_key_file"] = "#{path}.pub"
|
36
|
+
return
|
37
|
+
end
|
38
|
+
end
|
23
39
|
end
|
24
40
|
end
|
25
41
|
end
|
@@ -9,9 +9,8 @@ module Conjure
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def base_image
|
12
|
-
@base_image ||= @host.
|
12
|
+
@base_image ||= @host.shell.prepare(
|
13
13
|
label: "mysql",
|
14
|
-
base_image: "ubuntu",
|
15
14
|
setup_commands: [
|
16
15
|
"apt-get install -y mysql-server mysql-client"
|
17
16
|
],
|
@@ -19,9 +18,8 @@ module Conjure
|
|
19
18
|
end
|
20
19
|
|
21
20
|
def server_image
|
22
|
-
@server_image ||=
|
21
|
+
@server_image ||= base_image.prepare(
|
23
22
|
label: "mysqlserver",
|
24
|
-
base_image: base_image,
|
25
23
|
setup_commands: [
|
26
24
|
"/usr/sbin/mysqld & sleep 5; echo \"GRANT ALL ON *.* TO root@'%' IDENTIFIED BY '' WITH GRANT OPTION\" | /usr/bin/mysql",
|
27
25
|
],
|
@@ -8,9 +8,8 @@ module Conjure
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def base_image
|
11
|
-
@base_image ||= @host.
|
11
|
+
@base_image ||= @host.shell.prepare(
|
12
12
|
label: "postgres",
|
13
|
-
base_image: "ubuntu",
|
14
13
|
setup_commands: [
|
15
14
|
"apt-get install -y python-software-properties software-properties-common",
|
16
15
|
"add-apt-repository -y ppa:pitti/postgresql",
|
@@ -21,9 +20,8 @@ module Conjure
|
|
21
20
|
end
|
22
21
|
|
23
22
|
def server_image
|
24
|
-
@server_image ||=
|
23
|
+
@server_image ||= base_image.prepare(
|
25
24
|
label: "pgserver",
|
26
|
-
base_image: base_image,
|
27
25
|
setup_commands: [
|
28
26
|
"service postgresql start; su postgres -c 'createuser -d -r -s root; createdb -O root root'; service postgresql stop",
|
29
27
|
"echo 'host all all 0.0.0.0/0 trust' >>/etc/postgresql/9.2/main/pg_hba.conf",
|
@@ -66,6 +66,10 @@ module Conjure
|
|
66
66
|
def containers
|
67
67
|
ContainerSet.new :host => self
|
68
68
|
end
|
69
|
+
|
70
|
+
def shell
|
71
|
+
DockerShell.new :docker_host => self
|
72
|
+
end
|
69
73
|
end
|
70
74
|
|
71
75
|
class ImageSet
|
@@ -79,6 +83,8 @@ module Conjure
|
|
79
83
|
end
|
80
84
|
|
81
85
|
class Image
|
86
|
+
attr_reader :host_volumes
|
87
|
+
|
82
88
|
def initialize(host, options)
|
83
89
|
@host = host
|
84
90
|
@label = options[:label]
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Conjure
|
2
|
+
module Service
|
3
|
+
class DockerShell
|
4
|
+
attr_reader :docker_host
|
5
|
+
|
6
|
+
def initialize(options)
|
7
|
+
@docker_host = options[:docker_host]
|
8
|
+
@image = options[:image]
|
9
|
+
end
|
10
|
+
|
11
|
+
def prepare(options)
|
12
|
+
self.class.new(
|
13
|
+
:docker_host => @docker_host,
|
14
|
+
:image => @docker_host.images.create(image_options.merge options),
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
def command(*args)
|
19
|
+
(@image || default_image).command *args
|
20
|
+
end
|
21
|
+
|
22
|
+
def run(*args)
|
23
|
+
(@image || default_image).run *args
|
24
|
+
end
|
25
|
+
|
26
|
+
def stop(*args)
|
27
|
+
(@image || default_image).stop *args
|
28
|
+
end
|
29
|
+
|
30
|
+
def image_options
|
31
|
+
{
|
32
|
+
:base_image => (@image || default_image_name),
|
33
|
+
:host_volumes => (@image.host_volumes if @image),
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def default_image
|
38
|
+
@default_image ||= @docker_host.images.create(image_options)
|
39
|
+
end
|
40
|
+
|
41
|
+
def default_image_name
|
42
|
+
"ubuntu"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Conjure
|
2
|
+
module Service
|
3
|
+
class ForwardedShell
|
4
|
+
def initialize(options)
|
5
|
+
@shell = options[:shell].prepare(
|
6
|
+
:label => "forwarded",
|
7
|
+
:setup_commands => [
|
8
|
+
"apt-get install -y openssh-server",
|
9
|
+
"mkdir -p /var/run/sshd",
|
10
|
+
"mkdir -p /root/.ssh; echo '#{options[:public_key]}' > /root/.ssh/authorized_keys",
|
11
|
+
"chmod 600 /root/.ssh/authorized_keys"
|
12
|
+
],
|
13
|
+
)
|
14
|
+
end
|
15
|
+
|
16
|
+
def command(c)
|
17
|
+
container = @shell.run "/usr/sbin/sshd -D -e"
|
18
|
+
escaped_command = @shell.docker_host.shell_escape c
|
19
|
+
ssh_command = "ssh -A -o StrictHostKeyChecking=no #{container.ip_address} '#{escaped_command}'"
|
20
|
+
result = @shell.docker_host.server.run ssh_command
|
21
|
+
result.stdout
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -7,20 +7,6 @@ module Conjure
|
|
7
7
|
@app_name = app_name
|
8
8
|
@rails_environment = rails_environment
|
9
9
|
@host = host
|
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
|
-
@image = @host.images.create(
|
13
|
-
label: "codebase",
|
14
|
-
base_image: "ubuntu",
|
15
|
-
setup_commands: [
|
16
|
-
"apt-get install -y git",
|
17
|
-
"mkdir -p /root/.ssh; echo '#{github_private_key}' > /root/.ssh/id_rsa",
|
18
|
-
"mkdir -p /root/.ssh; echo '#{github_public_key}' > /root/.ssh/id_rsa.pub",
|
19
|
-
"chmod -R go-rwx /root/.ssh",
|
20
|
-
"echo 'Host github.com\\n\\tStrictHostKeyChecking no\\n' >> /root/.ssh/config",
|
21
|
-
],
|
22
|
-
host_volumes: {"/rails_app" => "/#{app_name}"},
|
23
|
-
)
|
24
10
|
end
|
25
11
|
|
26
12
|
def database_yml
|
@@ -37,34 +23,33 @@ module Conjure
|
|
37
23
|
end
|
38
24
|
|
39
25
|
def install
|
40
|
-
|
26
|
+
repository_link.update
|
41
27
|
configure_database
|
42
28
|
configure_logs
|
43
29
|
end
|
44
30
|
|
45
|
-
def
|
46
|
-
@
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
31
|
+
def repository_link
|
32
|
+
@repository_link ||= RepositoryLink.new(
|
33
|
+
:volume => volume,
|
34
|
+
:branch => @branch,
|
35
|
+
:origin_url => @github_url,
|
36
|
+
:public_key => Conjure.config.file_contents(:public_key_file).gsub("\n", "\\n"),
|
37
|
+
)
|
52
38
|
end
|
53
39
|
|
54
|
-
def
|
55
|
-
|
56
|
-
@image.command "cd #{@app_name}; git reset --hard; git checkout #{@branch}; git pull"
|
40
|
+
def volume
|
41
|
+
@volume ||= Volume.new(:docker_host => @host, :host_path => "/rails_app", :container_path => "/#{@app_name}")
|
57
42
|
end
|
58
43
|
|
59
44
|
def configure_database
|
60
45
|
Conjure.log "[ repo] Generating database.yml"
|
61
|
-
|
46
|
+
volume.write "config/database.yml", database_yml
|
62
47
|
end
|
63
48
|
|
64
49
|
def configure_logs
|
65
50
|
Conjure.log "[ repo] Configuring application logger"
|
66
51
|
setup = 'Rails.logger = Logger.new "#{Rails.root}/log/#{Rails.env}.log"'
|
67
|
-
|
52
|
+
volume.write "config/initializers/z_conjure_logger.rb", setup
|
68
53
|
end
|
69
54
|
|
70
55
|
def database_name
|
@@ -72,8 +57,7 @@ module Conjure
|
|
72
57
|
end
|
73
58
|
|
74
59
|
def gem_names
|
75
|
-
|
76
|
-
gemfile.scan(/gem ['"]([^'"]+)['"]/).flatten
|
60
|
+
volume.read("Gemfile").scan(/gem ['"]([^'"]+)['"]/).flatten
|
77
61
|
end
|
78
62
|
|
79
63
|
def database
|
@@ -8,9 +8,8 @@ module Conjure
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def base_image
|
11
|
-
@base_image ||= @host.
|
11
|
+
@base_image ||= @host.shell.prepare(
|
12
12
|
label: "rails_base",
|
13
|
-
base_image: "ubuntu",
|
14
13
|
setup_commands: [
|
15
14
|
"apt-get install -y curl git",
|
16
15
|
"curl -L https://get.rvm.io | bash -s stable",
|
@@ -35,14 +34,12 @@ module Conjure
|
|
35
34
|
end
|
36
35
|
|
37
36
|
def server_image
|
38
|
-
@server_image ||=
|
37
|
+
@server_image ||= base_image.prepare(
|
39
38
|
label: "rails_server",
|
40
|
-
base_image: base_image,
|
41
39
|
ports: [80],
|
42
40
|
environment: {
|
43
41
|
PATH:"/usr/local/rvm/gems/ruby-1.9.3-p448@global/bin:/usr/local/rvm/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
44
42
|
},
|
45
|
-
host_volumes: {"/rails_app" => "/#{@app_name}"},
|
46
43
|
)
|
47
44
|
end
|
48
45
|
|
@@ -42,17 +42,12 @@ module Conjure
|
|
42
42
|
def session
|
43
43
|
session_options = {
|
44
44
|
:auth_methods => ["publickey"],
|
45
|
-
:key_data => key_data,
|
46
|
-
:keys_only => true,
|
47
45
|
:paranoid => false,
|
46
|
+
:forward_agent => true,
|
48
47
|
}
|
49
48
|
@session ||= self.class.ssh_service.start @options[:ip_address], @options[:username], session_options
|
50
49
|
end
|
51
50
|
|
52
|
-
def key_data
|
53
|
-
File.read @options[:private_key_path] if @options[:private_key_path]
|
54
|
-
end
|
55
|
-
|
56
51
|
def poll_stream(stream, &block)
|
57
52
|
yield stream.sysread(1) if IO.select([stream], nil, nil, 0.01)
|
58
53
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Conjure
|
2
|
+
module Service
|
3
|
+
class RepositoryLink
|
4
|
+
def initialize(options)
|
5
|
+
@volume = options[:volume]
|
6
|
+
@branch = options[:branch]
|
7
|
+
@origin_url = options[:origin_url]
|
8
|
+
@public_key = options[:public_key]
|
9
|
+
end
|
10
|
+
|
11
|
+
def update
|
12
|
+
code_checked_out ? fetch_code_updates : checkout_code
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def code_checked_out
|
18
|
+
git_shell.command("[ -d #{code_path}/.git ] && echo yes; true").strip == "yes"
|
19
|
+
end
|
20
|
+
|
21
|
+
def checkout_code
|
22
|
+
Conjure.log "[ repo] Checking out code from git"
|
23
|
+
git_shell.command "git clone -b #{@branch} #{@origin_url} #{code_path}"
|
24
|
+
end
|
25
|
+
|
26
|
+
def fetch_code_updates
|
27
|
+
Conjure.log "[ repo] Fetching code updates from git"
|
28
|
+
git_shell.command "cd #{code_path}; git reset --hard; git checkout #{@branch}; git pull"
|
29
|
+
end
|
30
|
+
|
31
|
+
def code_path
|
32
|
+
@volume.container_path
|
33
|
+
end
|
34
|
+
|
35
|
+
def git_shell
|
36
|
+
@git_shell ||= ForwardedShell.new(:shell => @volume.shell.prepare({
|
37
|
+
label: "git",
|
38
|
+
setup_commands: [
|
39
|
+
"apt-get install -y git",
|
40
|
+
"mkdir -p /root/.ssh",
|
41
|
+
"echo 'Host github.com\\n\\tStrictHostKeyChecking no\\n' >> /root/.ssh/config",
|
42
|
+
],
|
43
|
+
}), :public_key => @public_key)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Conjure
|
2
|
+
module Service
|
3
|
+
class Volume
|
4
|
+
attr_reader :docker_host, :container_path
|
5
|
+
|
6
|
+
def initialize(options)
|
7
|
+
@docker_host = options[:docker_host]
|
8
|
+
@host_path = options[:host_path]
|
9
|
+
@container_path = options[:container_path]
|
10
|
+
end
|
11
|
+
|
12
|
+
def read(filename)
|
13
|
+
shell.command "cat #{@container_path}/#{filename}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def write(filename, data)
|
17
|
+
shell.command "echo '#{data}' >#{@container_path}/#{filename}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def shell
|
21
|
+
@shell ||= @docker_host.shell.prepare(
|
22
|
+
:label => "volume",
|
23
|
+
:host_volumes => {@host_path => @container_path},
|
24
|
+
)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
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.1.
|
4
|
+
version: 0.1.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: 2013-11-
|
12
|
+
date: 2013-11-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fog
|
@@ -104,10 +104,14 @@ files:
|
|
104
104
|
- lib/conjure/service/rails_server.rb
|
105
105
|
- lib/conjure/service/rails_codebase.rb
|
106
106
|
- lib/conjure/service/rails_application.rb
|
107
|
+
- lib/conjure/service/forwarded_shell.rb
|
108
|
+
- lib/conjure/service/repository_link.rb
|
109
|
+
- lib/conjure/service/volume.rb
|
107
110
|
- lib/conjure/service/database/postgres.rb
|
108
111
|
- lib/conjure/service/database/mysql.rb
|
109
112
|
- lib/conjure/service/remote_shell.rb
|
110
113
|
- lib/conjure/service/docker_host.rb
|
114
|
+
- lib/conjure/service/docker_shell.rb
|
111
115
|
- lib/conjure/service/database.rb
|
112
116
|
- lib/conjure/config.rb
|
113
117
|
- lib/conjure/version.rb
|