classify_cluster 0.2.7 → 0.3.7

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