vpsb 1.0.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 (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
+