conjure 0.2.10 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/History.md +8 -0
  2. data/README.md +35 -76
  3. data/lib/conjure.rb +1 -12
  4. data/lib/conjure/delayed_job.rb +39 -0
  5. data/lib/conjure/digital_ocean/droplet.rb +5 -2
  6. data/lib/conjure/docker/host.rb +75 -0
  7. data/lib/conjure/docker/template.rb +71 -0
  8. data/lib/conjure/instance.rb +31 -76
  9. data/lib/conjure/passenger.rb +123 -0
  10. data/lib/conjure/postgres.rb +67 -0
  11. data/lib/conjure/rails_application.rb +32 -0
  12. data/lib/conjure/server.rb +41 -0
  13. data/lib/conjure/swap.rb +28 -0
  14. data/lib/conjure/{provision/templates → templates}/application-no-ssl.conf.erb +2 -1
  15. data/lib/conjure/{provision/templates → templates}/application-ssl.conf.erb +2 -1
  16. data/lib/conjure/version.rb +1 -1
  17. metadata +12 -41
  18. data/lib/conjure/application.rb +0 -35
  19. data/lib/conjure/command.rb +0 -74
  20. data/lib/conjure/command_target.rb +0 -25
  21. data/lib/conjure/config.rb +0 -44
  22. data/lib/conjure/data_set.rb +0 -7
  23. data/lib/conjure/identity.rb +0 -25
  24. data/lib/conjure/log.rb +0 -26
  25. data/lib/conjure/provider.rb +0 -26
  26. data/lib/conjure/provision.rb +0 -1
  27. data/lib/conjure/provision/docker/host.rb +0 -32
  28. data/lib/conjure/provision/docker/image.rb +0 -55
  29. data/lib/conjure/provision/docker/template.rb +0 -55
  30. data/lib/conjure/provision/instance.rb +0 -52
  31. data/lib/conjure/provision/local_docker.rb +0 -16
  32. data/lib/conjure/provision/passenger.rb +0 -111
  33. data/lib/conjure/provision/postgres.rb +0 -70
  34. data/lib/conjure/provision/server.rb +0 -78
  35. data/lib/conjure/service/cloud_server.rb +0 -112
  36. data/lib/conjure/service/database.rb +0 -25
  37. data/lib/conjure/service/database/mysql.rb +0 -69
  38. data/lib/conjure/service/database/postgres.rb +0 -77
  39. data/lib/conjure/service/digital_ocean_account.rb +0 -31
  40. data/lib/conjure/service/docker_host.rb +0 -259
  41. data/lib/conjure/service/docker_shell.rb +0 -46
  42. data/lib/conjure/service/forwarded_shell.rb +0 -25
  43. data/lib/conjure/service/rails_codebase.rb +0 -67
  44. data/lib/conjure/service/rails_console.rb +0 -10
  45. data/lib/conjure/service/rails_log_view.rb +0 -14
  46. data/lib/conjure/service/rails_server.rb +0 -91
  47. data/lib/conjure/service/rake_task.rb +0 -11
  48. data/lib/conjure/service/remote_file_set.rb +0 -24
  49. data/lib/conjure/service/remote_shell.rb +0 -73
  50. data/lib/conjure/service/repository_link.rb +0 -52
  51. data/lib/conjure/service/volume.rb +0 -28
  52. data/lib/conjure/target.rb +0 -19
  53. data/lib/conjure/view/application_view.rb +0 -42
  54. 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
@@ -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
@@ -1,7 +0,0 @@
1
- module Conjure
2
- class DataSet
3
- def self.find(options = {})
4
- []
5
- end
6
- end
7
- end
@@ -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
@@ -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
@@ -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
@@ -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,16 +0,0 @@
1
- module Conjure
2
- module Provision
3
- class LocalDocker
4
- def run(command)
5
- `#{command}`
6
- end
7
-
8
- def with_directory(path)
9
- yield path
10
- end
11
-
12
- def ip_address
13
- end
14
- end
15
- end
16
- 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