vpsb 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/Gemfile +20 -0
  4. data/Gemfile.lock +175 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +62 -0
  7. data/Rakefile +2 -0
  8. data/bin/vpsb +10 -0
  9. data/lib/vpsb/ask_support.rb +27 -0
  10. data/lib/vpsb/base_ask_resource.rb +40 -0
  11. data/lib/vpsb/base_resource.rb +13 -0
  12. data/lib/vpsb/base_task.rb +32 -0
  13. data/lib/vpsb/commands/base.rb +68 -0
  14. data/lib/vpsb/commands/build.rb +61 -0
  15. data/lib/vpsb/commands/cook.rb +27 -0
  16. data/lib/vpsb/commands/deploy.rb +25 -0
  17. data/lib/vpsb/commands/help_messages.rb +23 -0
  18. data/lib/vpsb/commands/init.rb +52 -0
  19. data/lib/vpsb/commands/setup.rb +23 -0
  20. data/lib/vpsb/core.rb +41 -0
  21. data/lib/vpsb/helpers/file_replace.rb +20 -0
  22. data/lib/vpsb/helpers/ssh.rb +117 -0
  23. data/lib/vpsb/resources/app_bags_json.rb +38 -0
  24. data/lib/vpsb/resources/app_env_variables.rb +24 -0
  25. data/lib/vpsb/resources/app_host.rb +12 -0
  26. data/lib/vpsb/resources/app_name.rb +11 -0
  27. data/lib/vpsb/resources/app_nginx_use_ssl.rb +12 -0
  28. data/lib/vpsb/resources/base_path.rb +10 -0
  29. data/lib/vpsb/resources/db_postgres_json.rb +62 -0
  30. data/lib/vpsb/resources/db_postgres_pass.rb +11 -0
  31. data/lib/vpsb/resources/db_postgres_version.rb +21 -0
  32. data/lib/vpsb/resources/db_postgresql_bags_json.rb +20 -0
  33. data/lib/vpsb/resources/deploy_bags_json.rb +36 -0
  34. data/lib/vpsb/resources/deploy_config.rb +32 -0
  35. data/lib/vpsb/resources/deploy_keychain.rb +19 -0
  36. data/lib/vpsb/resources/deploy_pass.rb +11 -0
  37. data/lib/vpsb/resources/deploy_ssh_keys.rb +20 -0
  38. data/lib/vpsb/resources/deploy_to_known_hosts.rb +13 -0
  39. data/lib/vpsb/resources/do_api_key.rb +14 -0
  40. data/lib/vpsb/resources/do_client_id.rb +8 -0
  41. data/lib/vpsb/resources/do_droplet_ssh_key.rb +15 -0
  42. data/lib/vpsb/resources/do_host.rb +8 -0
  43. data/lib/vpsb/resources/do_host_ip.rb +8 -0
  44. data/lib/vpsb/resources/do_image.rb +16 -0
  45. data/lib/vpsb/resources/do_region.rb +16 -0
  46. data/lib/vpsb/resources/do_size.rb +16 -0
  47. data/lib/vpsb/resources/do_ssh_path.rb +15 -0
  48. data/lib/vpsb/resources/do_ssh_pub_path.rb +15 -0
  49. data/lib/vpsb/resources/es_cluster_name.rb +9 -0
  50. data/lib/vpsb/resources/es_json.rb +50 -0
  51. data/lib/vpsb/resources/es_memlock.rb +18 -0
  52. data/lib/vpsb/resources/es_node_name.rb +8 -0
  53. data/lib/vpsb/resources/es_nofile.rb +18 -0
  54. data/lib/vpsb/resources/es_version.rb +21 -0
  55. data/lib/vpsb/resources/has_do_account.rb +19 -0
  56. data/lib/vpsb/resources/hostname.rb +12 -0
  57. data/lib/vpsb/resources/knife_rb_path.rb +10 -0
  58. data/lib/vpsb/resources/local_ssh_path.rb +15 -0
  59. data/lib/vpsb/resources/local_ssh_pub.rb +13 -0
  60. data/lib/vpsb/resources/monit_role_json.rb +33 -0
  61. data/lib/vpsb/resources/newrelic_lic.rb +8 -0
  62. data/lib/vpsb/resources/node_json.rb +31 -0
  63. data/lib/vpsb/resources/packages_bags_json.rb +20 -0
  64. data/lib/vpsb/resources/packages_list.rb +18 -0
  65. data/lib/vpsb/resources/rails_app_path.rb +11 -0
  66. data/lib/vpsb/resources/read_do_api_access.rb +21 -0
  67. data/lib/vpsb/resources/ruby_version.rb +21 -0
  68. data/lib/vpsb/resources/server_app_path.rb +11 -0
  69. data/lib/vpsb/resources/ssh_helper.rb +10 -0
  70. data/lib/vpsb/resources/unicorn_worker_processes.rb +18 -0
  71. data/lib/vpsb/resources/unicorn_worker_timeout.rb +18 -0
  72. data/lib/vpsb/resources/web_role_json.rb +92 -0
  73. data/lib/vpsb/resources.rb +4 -0
  74. data/lib/vpsb/shell_support.rb +7 -0
  75. data/lib/vpsb/tasks/apps_bags.rb +33 -0
  76. data/lib/vpsb/tasks/create_droplet.rb +51 -0
  77. data/lib/vpsb/tasks/db_postgres_bags.rb +32 -0
  78. data/lib/vpsb/tasks/db_postgres_role.rb +32 -0
  79. data/lib/vpsb/tasks/deploy_bags.rb +32 -0
  80. data/lib/vpsb/tasks/deploy_config.rb +19 -0
  81. data/lib/vpsb/tasks/do_api_access.rb +52 -0
  82. data/lib/vpsb/tasks/droplet_ssh_keys.rb +22 -0
  83. data/lib/vpsb/tasks/droplet_ssh_update_config.rb +20 -0
  84. data/lib/vpsb/tasks/es_role.rb +32 -0
  85. data/lib/vpsb/tasks/monit_role.rb +32 -0
  86. data/lib/vpsb/tasks/node.rb +32 -0
  87. data/lib/vpsb/tasks/packages_bags.rb +32 -0
  88. data/lib/vpsb/tasks/web_role.rb +32 -0
  89. data/lib/vpsb/version.rb +3 -0
  90. data/lib/vpsb.rb +16 -0
  91. data/spec/spec_helper.rb +22 -0
  92. data/vpsb.gemspec +30 -0
  93. metadata +263 -0
@@ -0,0 +1,16 @@
1
+ module Vpsb
2
+ module Resources
3
+ class DoSize < BaseResource
4
+ include AskSupport
5
+ include ShellSupport
6
+ res :do_size
7
+
8
+ def call(core)
9
+ puts "Loading list of available disc sizes"
10
+ in_dir(core.get(:server_app_path), 'knife digital_ocean size list')
11
+ answer = ask { puts 'What size? Enter its id (default: 66)' }.strip
12
+ answer.empty? ? '66' : answer
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,15 @@
1
+ module Vpsb
2
+ module Resources
3
+ class DoSshPath < BaseResource
4
+ attr_reader :core
5
+
6
+ include AskSupport
7
+
8
+ res :do_ssh_path
9
+
10
+ def call(core)
11
+ core.get(:ssh_helper).ask_for_ssh_path
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module Vpsb
2
+ module Resources
3
+ class DoSshPubPath < BaseResource
4
+ attr_reader :core
5
+
6
+ include AskSupport
7
+
8
+ res :do_ssh_pub_path
9
+
10
+ def call(core)
11
+ core.get(:do_ssh_path) + '/id_rsa'
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,9 @@
1
+ module Vpsb
2
+ module Resources
3
+ class EsClusterName < BaseAskResource
4
+ res :es_cluster_name
5
+ question 'Elasticsearch cluster name (default: base)?'
6
+ default 'base'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,50 @@
1
+ module Vpsb
2
+ module Resources
3
+ class EsJson < BaseResource
4
+ res :es_json
5
+
6
+ def call(data)
7
+ template(data)
8
+ end
9
+
10
+ private
11
+
12
+ def template(data)
13
+ {
14
+ name: "es",
15
+ description: "Elasticsearch Server Role",
16
+ chef_type: "role",
17
+ json_class: "Chef::Role",
18
+ default_attributes: {
19
+ java: {
20
+
21
+ install_flavor: "openjdk",
22
+ jdk_version: "7"
23
+ },
24
+ elasticsearch: {
25
+ version: data.get(:es_version),
26
+ cluster: { name: data.get(:es_cluster_name) },
27
+ limits: { nofile: data.get(:es_nofile).to_i, memlock: data.get(:es_memlock).to_i},
28
+ bootstrap: { mlockall: false},
29
+ discovery: { zen: { ping: { timeout: "3s" } } },
30
+ logging: { discovery: "TRACE", "index.indexing.slowlog" => "INFO, index_indexing_slow_log_file"},
31
+ "node.name" => data.get(:es_node_name),
32
+ "node.master" => true,
33
+ "node.data"=> true,
34
+ "http.port" => "9200",
35
+ "transport.tcp.port" => "9300",
36
+ "transport.tcp.compress" => "true",
37
+ "index.search.slowlog.threshold.query.trace" => "1ms"
38
+ }
39
+ },
40
+ run_list: [
41
+ "recipe[apt]",
42
+ "recipe[java]",
43
+ "recipe[vim]",
44
+ "recipe[elasticsearch]"
45
+ ]
46
+ }
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,18 @@
1
+ module Vpsb
2
+ module Resources
3
+ class EsMemlock < BaseAskResource
4
+ res :es_memlock
5
+ question 'Elasticsearch memory limit (Default 256)?'
6
+ default '256'
7
+
8
+ private
9
+
10
+ def validate
11
+ Proc.new do |answer|
12
+ next true if answer.empty?
13
+ answer.to_i > 0
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,8 @@
1
+ module Vpsb
2
+ module Resources
3
+ class EsNodeName < BaseAskResource
4
+ res :es_node_name
5
+ question 'Elasticsearch node name (example: es.google.com)?'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,18 @@
1
+ module Vpsb
2
+ module Resources
3
+ class EsNofile < BaseAskResource
4
+ res :es_nofile
5
+ question 'Elasticsearch open files limit (Default 1024)?'
6
+ default '1024'
7
+
8
+ private
9
+
10
+ def validate
11
+ Proc.new do |answer|
12
+ next true if answer.empty?
13
+ answer.to_i > 0
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,21 @@
1
+ module Vpsb
2
+ module Resources
3
+ class EsVersion < BaseAskResource
4
+ res :es_version
5
+ question 'Elasticsearch version (Default 1.2.0)?'
6
+ default '1.2.0'
7
+
8
+ private
9
+
10
+ def validate
11
+ Proc.new do |answer|
12
+ next true if answer.strip.empty?
13
+ parts = answer.split('.')
14
+ next false if parts.length != 3
15
+ next false if (parts[0] + parts[1]).to_i <= 1
16
+ true
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ module Vpsb
2
+ module Resources
3
+ class HasDoAccount < BaseResource
4
+ include AskSupport
5
+
6
+ res :has_do_account
7
+
8
+ def call(core)
9
+ ask_to_confirm("Do you have account on DigitalOcean?") do |has_account|
10
+ unless has_account
11
+ ask { puts 'Create new account via link: https://www.digitalocean.com/?refcode=71281f14ac3c. Press Enter when ready to continue' }
12
+ end
13
+ end
14
+
15
+ true
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,12 @@
1
+ module Vpsb
2
+ module Resources
3
+ class Hostname < BaseAskResource
4
+ res :hostname
5
+ # question 'What is server hostname (example: google.com)?'
6
+
7
+ def call(core)
8
+ core.get(:do_host_ip)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ module Vpsb
2
+ module Resources
3
+ class KnifeRbPath < BaseResource
4
+ res :knife_rb_path
5
+ def call(core)
6
+ core.get(:server_app_path) + '/.chef/knife.rb'
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,15 @@
1
+ require 'fileutils'
2
+
3
+ module Vpsb
4
+ module Resources
5
+ class LocalSshPath < BaseResource
6
+ include AskSupport
7
+
8
+ res :local_ssh_path
9
+
10
+ def call(core)
11
+ core.get(:ssh_helper).local_ssh_path
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,13 @@
1
+ module Vpsb
2
+ module Resources
3
+ class LocalSshPub < BaseResource
4
+ include AskSupport
5
+
6
+ res :local_ssh_pub
7
+
8
+ def call(core)
9
+ Vcore.get(:ssh_helper).local_ssh_pub
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,33 @@
1
+ module Vpsb
2
+ module Resources
3
+ class MonitRoleJson < BaseResource
4
+ res :monit_role_json
5
+
6
+ def call(data)
7
+ template(data)
8
+ end
9
+
10
+ private
11
+
12
+ def template(data)
13
+ {
14
+ name: "monit",
15
+ description: "Monit Server Role",
16
+ chef_type: "role",
17
+ json_class: "Chef::Role",
18
+ default_attributes: {
19
+ new_relic:{
20
+ license_key: data.get(:newrelic_lic),
21
+ hostname: data.get(:hostname),
22
+ keyserver:"keyserver.ubuntu.com"
23
+ }
24
+ },
25
+ run_list: [
26
+ "recipe[apt]",
27
+ "recipe[newrelic-sysmond]"
28
+ ]
29
+ }
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,8 @@
1
+ module Vpsb
2
+ module Resources
3
+ class NewrelicLic < BaseAskResource
4
+ res :newrelic_lic
5
+ question 'What is newrelic license key ?'
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,31 @@
1
+ module Vpsb
2
+ module Resources
3
+ class NodeJson < BaseResource
4
+ res :node_json
5
+
6
+ def call(data)
7
+ template(data)
8
+ end
9
+
10
+ private
11
+
12
+ def template(data)
13
+ {
14
+ chef_client:{
15
+ encrypted_data_bag_secret: "~/chef-solo/data_bag_key"
16
+ },
17
+ run_list: run_list(data)
18
+ }
19
+ end
20
+
21
+ def run_list(data)
22
+ list = %w{recipe[chef-solo-search] role[base]}
23
+ list << "role[es]" if data.present?(:es_json)
24
+ list << "role[db]" if data.present?(:db_postgres_json)
25
+ list << "role[web]"
26
+ list << "role[monit]" if data.present?(:monit_role_json)
27
+ list
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,20 @@
1
+ module Vpsb
2
+ module Resources
3
+ class PackagesBagsJson < BaseResource
4
+ res :packages_bags_json
5
+
6
+ def call(data)
7
+ template(data)
8
+ end
9
+
10
+ private
11
+
12
+ def template(data)
13
+ {
14
+ id: "packages",
15
+ apps: data.get(:packages_list)
16
+ }
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ module Vpsb
2
+ module Resources
3
+ class PackagesList < BaseAskResource
4
+ res :packages_list
5
+ question 'Package list to instalation from apt-get (example: mc, htop)?'
6
+ private
7
+
8
+ def finalize(answer)
9
+ return [] if answer.empty?
10
+ answer.split(',').join(' ').split(' ').compact.uniq
11
+ end
12
+
13
+ def validate
14
+ Proc.new { true }
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ module Vpsb
2
+ module Resources
3
+ class RailsAppPath < BaseResource
4
+ res :rails_app_path
5
+
6
+ def call(core)
7
+ core.get(:base_path) + '/bootstrap_rails_app_in_do'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,21 @@
1
+ module Vpsb
2
+ module Resources
3
+ class ReadDoApiAccess < BaseResource
4
+ include AskSupport
5
+
6
+ res :read_do_api_access
7
+
8
+ def call(core)
9
+ if core.data[:do_client_id].nil? && core.data[:do_client_id].nil?
10
+ ask { puts 'Visit https://cloud.digitalocean.com/api_access and generate API access key' }
11
+ end
12
+ core.data[:do_client_id] = ask_loop { puts 'Paste your client id: ' }
13
+ core.data[:do_api_key] = ask_loop { puts 'Paste your api key: ' }
14
+ end
15
+
16
+ def valid?
17
+ true
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module Vpsb
2
+ module Resources
3
+ class RubyVersion < BaseAskResource
4
+ res :ruby_version
5
+ question 'What version of ruby you want to install (Default 2.1.2)?'
6
+ default '2.1.2'
7
+
8
+ private
9
+
10
+ def validate
11
+ Proc.new do |answer|
12
+ next true if answer.strip.empty?
13
+ parts = answer.split('.')
14
+ next false if parts.length != 3
15
+ next false if (parts[0] + parts[1]).to_i < 18
16
+ true
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ module Vpsb
2
+ module Resources
3
+ class ServerAppPath < BaseResource
4
+ res :server_app_path
5
+
6
+ def call(core)
7
+ core.get(:base_path) + '/bootstrap_server_app_in_do'
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ module Vpsb
2
+ module Resources
3
+ class SshHelper < BaseResource
4
+ res :ssh_helper
5
+ def call(core)
6
+ Vpsb::Helpers::Ssh.new
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,18 @@
1
+ module Vpsb
2
+ module Resources
3
+ class UnicornWorkerProcesses < BaseAskResource
4
+ res :unicorn_worker_processes
5
+ question 'How many unicorn worker processes setup (Default 4)?'
6
+ default '4'
7
+
8
+ private
9
+
10
+ def validate
11
+ Proc.new do |answer|
12
+ next true if answer.empty?
13
+ answer.to_i > 0
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ module Vpsb
2
+ module Resources
3
+ class UnicornWorkerTimeout < BaseAskResource
4
+ res :unicorn_worker_timeout
5
+ question 'What unicoren worker timeout setup (Default 30)?'
6
+ default '30'
7
+
8
+ private
9
+
10
+ def validate
11
+ Proc.new do |answer|
12
+ next true if answer.empty?
13
+ answer.to_i > 0
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,92 @@
1
+ module Vpsb
2
+ module Resources
3
+ class WebRoleJson < BaseResource
4
+ res :web_role_json
5
+
6
+ def call(data)
7
+ template(data)
8
+ end
9
+
10
+ private
11
+
12
+ def template(data)
13
+ {
14
+ name: "web",
15
+ description: "Web Server Role",
16
+ chef_type: "role",
17
+ json_class: "Chef::Role",
18
+ default_attributes: {
19
+ build_essential: {
20
+ compiletime: true
21
+ },
22
+ rvm:{
23
+ user_autolibs: "disabled",
24
+ rvm_gem_options: "--rdoc --ri",
25
+ default_ruby: data.get(:ruby_version),
26
+ rubies: [ data.get(:ruby_version) ],
27
+ user_installs:[
28
+ {
29
+ user: "deploy",
30
+ default_ruby: data.get(:ruby_version),
31
+ rubies: [ data.get(:ruby_version) ],
32
+ global_gems: [
33
+ {name: "bundler"},
34
+ {name: "rake"}
35
+ ]
36
+ }
37
+ ]
38
+ },
39
+ nginx:{
40
+ version: "1.4.1",
41
+ user: "www-data",
42
+ default_site_enabled: false,
43
+ source: {use_existing_user: true},
44
+ init_style: "init",
45
+ binary: "/opt/nginx/sbin",
46
+ modules: [
47
+ "http_stub_status_module",
48
+ "http_ssl_module",
49
+ "http_gzip_static_module"
50
+ ],
51
+ gzip_types: [
52
+ "text/plain",
53
+ "text/html",
54
+ "text/css",
55
+ "text/xml",
56
+ "text/javascript",
57
+ "application/json",
58
+ "application/x-javascript",
59
+ "application/xml",
60
+ "application/xml+rss"
61
+ ]
62
+ },
63
+ unicorn: {
64
+ options: { backlog: "64" },
65
+ preload_app: true,
66
+ worker_processes: data.get(:unicorn_worker_processes),
67
+ worker_timeout: data.get(:unicorn_worker_timeout)
68
+ }
69
+ },
70
+ run_list: [
71
+ "recipe[unattended-upgrades]",
72
+ "recipe[base]",
73
+ "recipe[nodejs]",
74
+ "recipe[nodejs::npm]",
75
+ "recipe[base::user_deploy]",
76
+ "recipe[apt]",
77
+ "recipe[build-essential]",
78
+ "recipe[rvm::user]",
79
+ "recipe[nginx]",
80
+ "recipe[nginx::source]",
81
+ "recipe[simple_iptables]",
82
+ "recipe[base::iptables]",
83
+ "recipe[runit]",
84
+ "recipe[unicorn]",
85
+ "recipe[base::webapps]",
86
+ "recipe[base::components]"
87
+ ]
88
+ }
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,4 @@
1
+ module Vpsb
2
+ module Resources
3
+ end
4
+ end
@@ -0,0 +1,7 @@
1
+ module Vpsb
2
+ module ShellSupport
3
+ def in_dir(where, what)
4
+ system("cd #{where} && #{what}")
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,33 @@
1
+ require 'json'
2
+ module Vpsb
3
+ module Tasks
4
+ class AppsBags < BaseTask
5
+ include AskSupport
6
+ PATH = 'bootstrap_server_app_in_do/data_bags/configs/webapps.json'
7
+
8
+ prepare_squence :app_name, :app_host, :unicorn_worker_processes, :unicorn_worker_timeout
9
+ prepare_squence :app_env_variables, :app_bags_json
10
+
11
+ def call
12
+ prepare
13
+
14
+ ask_loop(proc {|r| process(r)}) do
15
+ ap preparation_results
16
+ p "Save this configuration y[es]/n[o]?"
17
+ end
18
+
19
+ Vpsb::Helpers::FileReplace.replace_json(PATH, core.get(:app_bags_json))
20
+ end
21
+
22
+ private
23
+
24
+ def process(result)
25
+ return true if result[0].to_s.downcase == 'y'
26
+ reprepare
27
+ false
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+