classify_cluster 0.2.7 → 0.3.7

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile.lock ADDED
@@ -0,0 +1,21 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ classify_cluster (0.2.7)
5
+ activesupport (>= 2.3.5)
6
+ commander (~> 4.0.3)
7
+ highline (~> 1.6.1)
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ activesupport (3.0.3)
13
+ commander (4.0.3)
14
+ highline (>= 1.5.0)
15
+ highline (1.6.1)
16
+
17
+ PLATFORMS
18
+ ruby
19
+
20
+ DEPENDENCIES
21
+ classify_cluster!
data/bin/classify CHANGED
@@ -20,4 +20,17 @@ command :puppet do |c|
20
20
  ClassifyCluster::Writers::Puppet.export!(options.export, :cluster => args[0], :config_file => options.config)
21
21
  say("Success!")
22
22
  end
23
+ end
24
+
25
+ command :config do |c|
26
+ c.syntax = 'classify config <clustername> [options]'
27
+ c.description = 'Runs an interactive script to generate a cluster configuration'
28
+ c.option '--export STRING', String, 'Location to output cluster configuration'
29
+ c.option '--cluster STRING', String, 'Cluster being created'
30
+ c.option '--defaults STRING', String, 'Location to load cluster defaults'
31
+ c.option '--variables STRING', String, 'Location to load cluster variables'
32
+ c.action do |args, options|
33
+ options.default :export => ClassifyCluster::Base.default_config_file, :defaults => '', :variables => ''
34
+ ClassifyCluster::Writers::Classify.export!(ClassifyCluster::Readers::Cli.start!(options.cluster, options.defaults, options.variables))
35
+ end
23
36
  end
@@ -11,7 +11,8 @@ Gem::Specification.new do |s|
11
11
  s.homepage = "http://rubygems.org/gems/classify_cluster"
12
12
  s.summary = %q{Contains several binaries for generating capistrano and puppet configurations}
13
13
  s.description = %q{Reading from a YAML file will allow for consistent configuration between capistrano and puppet}
14
- s.add_dependency(%q<commander>, ["= 4.0.3"])
14
+ s.add_dependency(%q<commander>, ["~> 4.0.3"])
15
+ s.add_dependency(%q<highline>, ["~> 1.6.1"])
15
16
  s.add_dependency(%q<activesupport>, [">= 2.3.5"])
16
17
 
17
18
  s.rubyforge_project = "classify_cluster"
@@ -0,0 +1,27 @@
1
+ {
2
+ :socialcast_background_processor => 'resque',
3
+ 'socialcast_mode' => 'appliance',
4
+ 'socialcast_filestore' => 'riak',
5
+ 'cluster_name' => 'appliance-cluster',
6
+ 'deployment_root' => '/var/www/socialcast',
7
+ 'app_root' => '/var/www/socialcast',
8
+ 'app_shared_root' => '/var/www/socialcast',
9
+ 'app_user' => 'socialcast',
10
+ 'ssl_pem_path' => '/etc/ssl/pem',
11
+ 'app_pem_file' => 'scmc.pem',
12
+ 'cdn_disabled' => 'true',
13
+ 'solr_jvm_options' => '-server -Xmx500M -Xms64M', # Needs more granular configuration
14
+ 'rails_env' => 'production',
15
+ 'scheduler_env' => 'production',
16
+ :backup_s3_app_name => "appliance",
17
+ :newrelic_enabled => false,
18
+ :solr_newrelic_app_name => "appliance",
19
+ :newrelic_app_name => 'appliance',
20
+ :aws_access_key_id => '',
21
+ :aws_secret_access_key => '',
22
+ :s3_bucket => '',
23
+ :backup_s3_bucket => '',
24
+ :cloudkick_oauth_key => '',
25
+ :cloudkick_oauth_secret => '',
26
+ :database_encoding => 'utf8'
27
+ }
@@ -0,0 +1,33 @@
1
+ {
2
+ :socialcast_domain => "",
3
+ :database_username => '',
4
+ :database_password => '',
5
+ :database_database => '',
6
+ :database_root_password => '',
7
+ :flickr_key => '',
8
+ :flickr_secret => '',
9
+ :secret_access_key => '',
10
+ :ldap_connections => [{
11
+ 'base' => '',
12
+ 'filter_string' => '',
13
+ 'host' => '',
14
+ 'map' => {'email' => '', 'first_name' => '', 'last_name' => '', 'company_login' => ''},
15
+ 'port' => '',
16
+ 'searcher_password' => '',
17
+ 'searcher_username' => '',
18
+ 'ssl' => ''
19
+ }],
20
+ :email_dropbox_account => '',
21
+ :email_dropbox_password => '',
22
+ :email_dropbox_host => '',
23
+ :email_dropbox_port => '',
24
+
25
+ :jabber_account => '',
26
+ :jabber_password => '',
27
+
28
+ :smtp_host => "",
29
+ :smtp_port => '',
30
+ :smtp_username => '',
31
+ :smtp_password => '',
32
+ :alert_address => ''
33
+ }
@@ -3,3 +3,4 @@ require 'active_support'
3
3
  require 'classify_cluster/base'
4
4
  require 'classify_cluster/configurator'
5
5
  require 'classify_cluster/writers'
6
+ require 'classify_cluster/readers'
@@ -1,9 +1,11 @@
1
1
  module ClassifyCluster
2
2
  module Configurator
3
3
  class Cluster
4
+ SSLPEM_FILEPATH = '/etc/ssl/pem/scmc.pem'
5
+ SSLPEM_MODULE = 'loadbalancer'
4
6
  attr_reader :nodes, :name, :classes, :variables, :resources, :hostnames, :ssl_pem
5
7
  def initialize(*args, &block)
6
- @ssl_pem = {:file_path => '/etc/ssl/pem/scmc.pem', :module => 'loadbalancer'}
8
+ @ssl_pem = {}
7
9
  @nodes = {}
8
10
  @variables = {}
9
11
  @resources = []
@@ -11,25 +13,15 @@ module ClassifyCluster
11
13
  @name = args.first
12
14
  @hostnames = {}
13
15
  returned = block.call(self)
14
- @nodes.each_pair do |fqdn, node|
15
- @variables['hostnames'] = [] unless @variables['hostnames']
16
- @variables['hostnames'] << "#{fqdn}/#{node.private_ip}"
17
- end
18
- @nodes.each_pair do |fqdn, node|
19
- node.resource do |resource|
20
- resource.type 'etchosts'
21
- resource.name "hosts"
22
- resource.options({
23
- :short_name => fqdn.split('.').first,
24
- :fqdn => fqdn,
25
- :hosts => @variables['hostnames']
26
- })
27
- end
28
- end
16
+ add_hostnames
17
+ add_node_roles
29
18
  returned
30
19
  end
31
20
  def ssl_pem(file_path=nil, module_name=nil)
32
- return @ssl_pem if file_path.nil? && module_name.nil?
21
+ if file_path.nil? && module_name.nil?
22
+ @ssl_pem = {:file_path => SSLPEM_FILEPATH, :module => SSLPEM_MODULE}
23
+ return @ssl_pem
24
+ end
33
25
  @ssl_pem = {:file_path => file_path, :module => module_name}
34
26
  end
35
27
  def name(value=nil)
@@ -49,6 +41,25 @@ module ClassifyCluster
49
41
  def klass(name)
50
42
  @classes << name
51
43
  end
44
+ def add_hostnames
45
+ @nodes.each_pair do |fqdn, node|
46
+ @variables['hostnames'] = [] unless @variables['hostnames']
47
+ @variables['hostnames'] << "#{fqdn}/#{node.private_ip}"
48
+ end
49
+ end
50
+ def add_node_roles
51
+ @nodes.each_pair do |fqdn, node|
52
+ node.resource do |resource|
53
+ resource.type 'etchosts'
54
+ resource.name "hosts"
55
+ resource.options({
56
+ :short_name => fqdn.split('.').first,
57
+ :fqdn => fqdn,
58
+ :hosts => @variables['hostnames']
59
+ })
60
+ end
61
+ end
62
+ end
52
63
  end
53
64
  end
54
65
  end
@@ -1,10 +1,31 @@
1
1
  module ClassifyCluster
2
2
  module Configurator
3
+ ROLES = [
4
+ 'file',
5
+ 'scheduler',
6
+ 'app',
7
+ 'web',
8
+ 'push',
9
+ 'puppet_master',
10
+ {'munin' => ['master', 'node']},
11
+ 'cache',
12
+ {'db' => ['primary', 'backup']},
13
+ 'queue',
14
+ {'cron' => ['primary', 'backup']},
15
+ 'search',
16
+ 'worker'
17
+ ]
3
18
  class Role
19
+ begin
20
+ require 'active_support/hash_with_indifferent_access'
21
+ include ActiveSupport
22
+ rescue LoadError
23
+ end
24
+
4
25
  attr_reader :type, :options, :node, :variables
5
26
  def initialize(node, type, options={}, &block)
6
27
  @type = type
7
- @options = options.symbolize_keys
28
+ @options = HashWithIndifferentAccess.new(options)
8
29
  @node = node
9
30
  @variables = {}
10
31
  block.call(self) if block_given?
@@ -0,0 +1 @@
1
+ require 'classify_cluster/readers/cli'
@@ -0,0 +1,114 @@
1
+ require 'highline/import'
2
+
3
+ module ClassifyCluster
4
+ module Readers
5
+ class Cli
6
+ def self.start!(cluster_name, defaults_path='', variables_path='')
7
+ say("Welcome to classify cluster cli configurator!")
8
+
9
+ defaults={}
10
+ variables={}
11
+ File.open(defaults_path, 'r') do |file|
12
+ defaults = eval(file.read)
13
+ end if File.exists?(defaults_path)
14
+
15
+ File.open(variables_path, 'r') do |file|
16
+ variables = eval(file.read)
17
+ end if File.exists?(variables_path)
18
+ say "Configure cluster wide"
19
+ cluster_config = gather_cluster_info(cluster_name, defaults, variables)
20
+ say "Configure nodes"
21
+ nodes = []
22
+ ask("How many nodes: ", Integer).times do |i|
23
+ gather_node_info!(cluster_config)
24
+ end
25
+ puts cluster_config.inspect
26
+ cluster_config
27
+ end
28
+
29
+ def self.gather_value(key, value, indent=0)
30
+ case value
31
+ when Array
32
+ answers = []
33
+ ask("#{"\t"*indent}How many #{key.to_s}: ", Integer).times do |i|
34
+ answers << gather_value(key, value.first, 1)
35
+ say "Configured #{i+1} #{key.to_s}"
36
+ end
37
+ answers
38
+ when Hash
39
+ ask("#{"\t"*indent}<%= @key %>: ", lambda {|ans| ans =~ /^\{\s*['|:].+$/ ? eval(ans) : ans}) do |q|
40
+ q.gather = value
41
+ end
42
+ when Integer
43
+ ask("#{"\t"*indent}#{key.to_s}: ", Integer)
44
+ else
45
+ ask("#{"\t"*indent}#{key.to_s}: ")
46
+ end
47
+ end
48
+
49
+ def self.gather_node_info!(cluster_config)
50
+ hostname = ask("Hostname: ")
51
+ ip = ask("Ip: ")
52
+ role_names = ClassifyCluster::Configurator::ROLES.map { |k| k.is_a?(Hash) ? k.keys.first : k }
53
+
54
+ cluster_config.node(hostname, ip) do |node|
55
+ more_roles = true
56
+ while more_roles
57
+ types = {}
58
+ role_name = ask("Role [#{role_names.join(', ')}]: ", role_names)
59
+ if ClassifyCluster::Configurator::ROLES.reject { |k| !k.is_a?(Hash) }.map(&:keys).flatten.include?(role_name)
60
+ possible_types = ClassifyCluster::Configurator::ROLES.reject { |k| !k.is_a?(Hash) || !k.has_key?(role_name)}[0][role_name]
61
+ more_types = true
62
+ while more_types
63
+ type = ask("Type [#{possible_types.join(', ')}]: ", possible_types)
64
+ possible_types -= [type]
65
+ types[type] = true
66
+ more_types = possible_types.size > 0 && agree("More types? ")
67
+ end
68
+ end
69
+ node.role role_name.to_sym, types do |role|
70
+ while agree("Role variables?")
71
+ name = ask("name: ")
72
+ value = ask("value: ")
73
+ role.variable name, value
74
+ end
75
+ end
76
+ role_names -= [role_name]
77
+ more_roles = role_names.size > 0 && agree("More roles? ")
78
+ end
79
+ end
80
+ end
81
+
82
+ def self.gather_cluster_info(cluster_name, defaults={}, variables={})
83
+ cluster_name = ask("Cluster Name (no spaces): ") do |q|
84
+ q.validate = /^\w.*/
85
+ end unless cluster_name
86
+
87
+ ClassifyCluster::Configurator::Cluster.new(cluster_name) do |cluster_config|
88
+ file_path = ask("Ssl pem path: ") do |q|
89
+ q.validate{ |a| File.exists?(a) }
90
+ q.default = ClassifyCluster::Configurator::Cluster::SSLPEM_FILEPATH
91
+ end
92
+ module_name = ask("Puppet module to move it to: ") do |q|
93
+ q.default = ClassifyCluster::Configurator::Cluster::SSLPEM_MODULE
94
+ end
95
+ cluster_config.ssl_pem(file_path, module_name)
96
+
97
+ defaults.each_pair do |key, value|
98
+ cluster_config.variable key, value
99
+ end
100
+ variables.each_pair do |key, value|
101
+ cluster_config.variable key, gather_value(key, value)
102
+ end
103
+
104
+ klasses = ask("Classes: (q to stop)") do |q|
105
+ q.gather = 'q'
106
+ end
107
+ klasses.delete_if {|klass| klass.nil? || klass.empty?}.each do |klass|
108
+ cluster_config.klass klass
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -1,3 +1,3 @@
1
1
  module ClassifyCluster
2
- VERSION = "0.2.7"
2
+ VERSION = "0.3.7"
3
3
  end
@@ -1,2 +1,3 @@
1
1
  require 'classify_cluster/writers/capistrano'
2
- require 'classify_cluster/writers/puppet'
2
+ require 'classify_cluster/writers/puppet'
3
+ require 'classify_cluster/writers/classify'
@@ -0,0 +1,25 @@
1
+ module ClassifyCluster
2
+ module Writers
3
+ class Classify
4
+ def self.export!(classify_configurator)
5
+ File.open('/etc/cluster.rb', 'w') do |file|
6
+ output file, "# Autogenerated on #{Time.now.to_s}"
7
+ output file, "cluster :\"#{classify_configurator.name}\" do |cluster|"
8
+
9
+ classify_configurator.classes.each do |klass|
10
+ output file, "cluster.klass #{klass.inspect}", 1
11
+ end
12
+ classify_configurator.variables.each_pair do |key, variable|
13
+ output file, "cluster.variable #{key.inspect}, #{variable.inspect}", 1
14
+ end
15
+
16
+ output file, "end"
17
+ end
18
+ end
19
+
20
+ def self.output(file, str, indent=0)
21
+ file.write("#{"\s"*(indent*4)}#{str}\n")
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,9 +1,10 @@
1
1
  require 'fileutils'
2
+
2
3
  module ClassifyCluster
3
4
  module Writers
4
5
  class Puppet
5
6
  def self.export!(export_to_folder, options={})
6
- options.reverse_merge! :config_file => ClassifyCluster::Base.default_config_file
7
+ options = {:config_file => ClassifyCluster::Base.default_config_file}.merge(options)
7
8
  config = ClassifyCluster::Configurator::Configuration.new(options[:config_file])
8
9
  config.clusters.each_pair do |name, cluster|
9
10
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: classify_cluster
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 29
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 2
8
+ - 3
9
9
  - 7
10
- version: 0.2.7
10
+ version: 0.3.7
11
11
  platform: ruby
12
12
  authors:
13
13
  - Sean Cashin
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-14 00:00:00 -08:00
18
+ date: 2011-02-04 00:00:00 -08:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -24,7 +24,7 @@ dependencies:
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - "="
27
+ - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  hash: 57
30
30
  segments:
@@ -35,9 +35,25 @@ dependencies:
35
35
  type: :runtime
36
36
  version_requirements: *id001
37
37
  - !ruby/object:Gem::Dependency
38
- name: activesupport
38
+ name: highline
39
39
  prerelease: false
40
40
  requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 13
46
+ segments:
47
+ - 1
48
+ - 6
49
+ - 1
50
+ version: 1.6.1
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: activesupport
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
41
57
  none: false
42
58
  requirements:
43
59
  - - ">="
@@ -49,7 +65,7 @@ dependencies:
49
65
  - 5
50
66
  version: 2.3.5
51
67
  type: :runtime
52
- version_requirements: *id002
68
+ version_requirements: *id003
53
69
  description: Reading from a YAML file will allow for consistent configuration between capistrano and puppet
54
70
  email:
55
71
  - sean@socialcast.com
@@ -62,11 +78,14 @@ extra_rdoc_files: []
62
78
  files:
63
79
  - .gitignore
64
80
  - Gemfile
81
+ - Gemfile.lock
65
82
  - README
66
83
  - Rakefile
67
84
  - bin/classify
68
85
  - classify_cluster.gemspec
69
86
  - examples/cluster.rb
87
+ - examples/defaults.rb
88
+ - examples/variables.rb
70
89
  - lib/classify_cluster.rb
71
90
  - lib/classify_cluster/base.rb
72
91
  - lib/classify_cluster/configurator.rb
@@ -75,9 +94,12 @@ files:
75
94
  - lib/classify_cluster/configurator/node.rb
76
95
  - lib/classify_cluster/configurator/resource.rb
77
96
  - lib/classify_cluster/configurator/role.rb
97
+ - lib/classify_cluster/readers.rb
98
+ - lib/classify_cluster/readers/cli.rb
78
99
  - lib/classify_cluster/version.rb
79
100
  - lib/classify_cluster/writers.rb
80
101
  - lib/classify_cluster/writers/capistrano.rb
102
+ - lib/classify_cluster/writers/classify.rb
81
103
  - lib/classify_cluster/writers/puppet.rb
82
104
  has_rdoc: true
83
105
  homepage: http://rubygems.org/gems/classify_cluster