conjure 0.2.10 → 0.3.0

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