sumodev 0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :rubygems
2
+
3
+ gem 'thor'
4
+ gem 'activesupport'
data/Gemfile.lock ADDED
@@ -0,0 +1,16 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (3.2.6)
5
+ i18n (~> 0.6)
6
+ multi_json (~> 1.0)
7
+ i18n (0.6.0)
8
+ multi_json (1.3.6)
9
+ thor (0.15.4)
10
+
11
+ PLATFORMS
12
+ ruby
13
+
14
+ DEPENDENCIES
15
+ activesupport
16
+ thor
data/bin/sumo ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require File.expand_path(File.dirname(__FILE__) + '/../lib/sumodev')
3
+
4
+ Sumodev.start
@@ -0,0 +1,44 @@
1
+ module Sumodev::Actions
2
+ def copy_dest_file original, destination
3
+ from = File.expand_path(original, self.destination_root)
4
+ to = File.expand_path(destination, self.destination_root)
5
+
6
+ say_status :copy, relative_to_original_destination_root(to), true
7
+
8
+ unless options[:pretend]
9
+ FileUtils.cp from, to
10
+ end
11
+ end
12
+
13
+ def replace_in_file file, replacements
14
+ return unless behavior == :invoke
15
+
16
+ path = File.expand_path(file, self.destination_root)
17
+ say_status :replace, relative_to_original_destination_root(path), true
18
+
19
+ unless options[:pretend]
20
+ content = File.binread(path)
21
+ replacements.each do |match, replace|
22
+ content.gsub!(match, replace.to_s)
23
+ File.open(path, 'wb') {|f| f.write(content)}
24
+ end
25
+ end
26
+ end
27
+
28
+ def git(commands = {})
29
+ if commands.respond_to?(:each)
30
+ commands.each do |cmd, options|
31
+ run "git #{cmd} #{options}"
32
+ end
33
+ else
34
+ run "git #{commands}"
35
+ end
36
+ end
37
+
38
+ def git_track(message, &block)
39
+ block.call if block
40
+
41
+ git :add => '.'
42
+ git :commit => "-m \"#{message}\""
43
+ end
44
+ end
@@ -0,0 +1,25 @@
1
+ require 'active_support/core_ext/class'
2
+ require 'sumodev/command'
3
+
4
+ class Sumodev::Application < Sumodev::Command
5
+ include Thor::Actions
6
+
7
+ class << self
8
+ attr_accessor :login, :host, :log_file
9
+ end
10
+
11
+ desc 'log', "Opens the relevant log file"
12
+ def log
13
+ remote "less #{self.class.log_file}"
14
+ end
15
+
16
+ desc 'console', "Starts the Rails console"
17
+ def console
18
+ remote "\"cd production && rails console production\""
19
+ end
20
+
21
+ private
22
+ def remote command
23
+ run "ssh -t #{self.class.login}@#{self.class.host} #{command}" # -t forces TTY allocation
24
+ end
25
+ end
@@ -0,0 +1,5 @@
1
+ class Sumodev::Command < Thor
2
+ def self.banner(task, namespace = true, subcommand = false)
3
+ "#{basename} #{task.formatted_usage(self, true, subcommand)}"
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ require 'sumodev/application'
2
+
3
+ class Sumodev::Commands::Factr < Sumodev::Application
4
+ self.login = "factr"
5
+ self.host = "app01.factr.be"
6
+ self.log_file = "/home/factr/production/log/production.log"
7
+ end
@@ -0,0 +1,31 @@
1
+ require 'sumodev/command'
2
+ require 'sumodev/generators/fork/v3'
3
+
4
+ class Sumodev::Commands::Fork < Sumodev::Command
5
+ namespace :fork
6
+
7
+ desc 'create CLIENT NAME', "Create a new Fork app"
8
+ method_option :multilanguage,
9
+ :type => :boolean,
10
+ :default => false,
11
+ :aliases => '-m'
12
+
13
+ method_option :fork_repository,
14
+ :type => :string,
15
+ :default => "git://github.com/sumocoders/forkcms.git"
16
+
17
+ method_option :branch,
18
+ :type => :string,
19
+ :default => 'master',
20
+ :aliases => '-b'
21
+
22
+ method_option :default_language,
23
+ :type => :string,
24
+ :default => 'nl',
25
+ :aliases => '-l'
26
+
27
+ def create(client, name)
28
+ fork_generator = Sumodev::Generators::Fork::V3.new([client, name], options)
29
+ fork_generator.invoke_all
30
+ end
31
+ end
@@ -0,0 +1,119 @@
1
+ require 'sumodev/command'
2
+ require 'net/ssh'
3
+ require 'net/scp'
4
+ require 'thor/group'
5
+
6
+ class Sumodev::Commands::Push < Thor::Group
7
+ argument :server, :type => :string
8
+
9
+ class_option :group
10
+
11
+ Jan = {:groups => ['admin', 'developer', 'root'], :identity => 'jan@defv.be', :key => 'AAAAB3NzaC1kc3MAAACBAP41tq+1L7MqdI2+ugo0wq5IDcLSWpXXxSqHwrDVpqLcNNjpCd1QMnJ0ZY0HaRZ9YVwMFzu/cyDTgD9JZnQjcBjNhKfgOC2GX3IEsJAEM/O2kzmikTK4xFqIeeTdIqqICxlMimrFNqKoXJARueNlPITwGkkEiLy9EydTs9Cj3cHHAAAAFQD7RLZI6BtwVjgRe4XPXZdJBFN2CwAAAIEAvWaJjP0vueLwDYB2FDIm8VT8Wm4glne9Ilo0hylM2HVffdCICqjIIjn+bcYTg3SfzQcXcUYsk1sKQ0nKdICOl+dfiQs3/rTW3NNner1UewDeas9nSJN3e2Y4hyXS1tI9UOXzN76XHJM8GBz7RAhFB4ZHKVeZHsyrG2yXKiQTO8IAAACAUcAms34UNsbBLGZ3MOPJ18A2aYr6ju+N2VPkSd74sC1K6E0DSda/xJPKffZUPCWqmEdjhkXDvnNq73R4YG9x8dvXGCSzdSXMJfr9lYQNt9PT8D18UVUuZHgC8PjKEL7Xw8xbd2yOp58SADMpEZdKSMmhHsgFuW1T2TKGM72Pmd4=', :protocol => 'dss'}
12
+ Tijs = {:groups => ['admin', 'developer', 'root'], :identity => 'tijs@sumocoders.be', :key => 'AAAAB3NzaC1yc2EAAAABIwAAAQEAueoZUITVE/YVZVZVi4cngE7FPK5+a3mt0mTtELdFM4JmXg7UmrQ1On2IwIdHw5Cq+VnrutRgWvQkfp+WaC2tzOrlzccpMeMv5lTRH7bRp6qR4FivJ/Aq7YeUrNJpzncUVTwyeHrveuhfCxEQoOIM2gN0Y54NGDTOp01D7GHApsYkObsw/3N7jgQVoL6xKPwRTMI52tFzUlkv+df78vx87X7bYK05dO4Ol8U0yFyKlV17+BEM4UuI/aTXhkNsBVNCqiksaqQwEGDK8IqyrNFYhbRwYDunTXc8zdd6imYfEJUSNdjOzTXUNUc15ssTMBsGpfvF/2bhYRlHuRWZP9BUqw==', :protocol => 'rsa'}
13
+ Jens = {:groups => ['admin', 'root'], :identity => 'jens@dehaese.eu', :key => 'AAAAB3NzaC1yc2EAAAABIwAAAIEAojZQXjhcy3fpHNEBqlj2C3EV+G+vOTSBvcn+U3Sq7eml+NrQqGoasAvC+c6bajJTRB0ZujynsUAWghDM43zY1SIbZl6PC0jdZg7qGjzlpOFdG96b84agiE6Dnz8Mjnb6846tJdslRV2Yyc9Y8iSgW3s3mszmW2hqHpZ4EqbVuPc=', :protocol => 'rsa'}
14
+ Sam = {:groups => ['developer'], :identity => 'sam@sumocoders.be', :key => 'AAAAB3NzaC1yc2EAAAADAQABAAABAQDQ82XZ/2xJcaaba2fxZs41ciID9IT3bkoalfKmM7AJN/EHz70XuB0ghzA64gGTbKbyT9YyC0EgbbWr8dG52nJMy4g6tnPM8Ns/17WMkBDanhVCdzXy5RUlXcmqMsf+VQQUPtToXu0i4XqOCSVE0YJpfQmzqxyspoQqMO4D96S6uE2797kWGw/4ez7bkx5Ub8+gkgj718iyZy4qVD4VSF8bNxLhHHmUVp1gm0e5rki1uF4hPMQG8tuO+tJhg50LuCpmUe6tCX8CEYWTDTfaj5LCaSf9S7wUrZlk6VwtQSC8BOY+liCSDt9VonCaQudGSBpKtYN7vFk1/FGvyxdcxVSn', :protocol => 'rsa'}
15
+ Niels = {:groups => ['developer'], :identity => 'niels@sumocoders.be', :key => 'AAAAB3NzaC1yc2EAAAABIwAAAQEA3BAs8M+BuSsYwG0LsrrXmMveVgCd3mZOqvUFjJtWwO5ahzRPEDuT9eJGlwJwmVKk5aV76v/8ZFTJ/zgxYoGJF02j1tXaCyaDTnkRwS3AetFq3ZncIwLFgRDYgd+qI42E9VJg7WVXQKR+2jTusRFTZCfqp7/4sVZSWwKrbA8b5jEPWhgqSb8ZWGsbIQfFAXDQwr6gftkSOR9ABfXt3ULy2aGmtiZKQhxiIL7/0YT2xPtLshpWe7U9Y0nH5CFWOTDHILmzBYnVqvksEiFg+r4dtLPLAeGCwCo5ZSe8ae9JWyNtXELPNKi7Ds06ghtcSKuMrgYhdz9539JZYhy5IWtYNQ==', :protocol => 'rsa'}
16
+ Mathias = {:groups => ['developer'], :identity => 'mathias@sumocoders.be', :key => 'AAAAB3NzaC1yc2EAAAADAQABAAABAQDLBHWXILbcsYfoDYCgJq4B3Q9ElcZq0hRWo8otXWsOP1pYU8Kq2thWbIB+RkuZr8Y7DMI2XtGXSquWJdx0Beddxt+yVoE/eReorVuB74bnEVXYtcZ8+mNHU6paC1T4XHMWjEXSgaEaSPdxnQxPPzQ+YDuJkYWaCrLxDyWe4sqio0R5SA5CasTkei5dHIfIzj8a16JvTj/FlbNrGHzdSwWY04QoSRdN3rpWJ4krzlHz5NIJmBhUxW15d9NgmKPGJYHmUyY1nfXdb82/zUS1vt6A/46hMJzRXhQuxzNVNBFN2q8d/bXhsNW6AZ467auWO3NLBUOfGHMX+Ga6FQiyCdhd', :protocol => 'rsa'}
17
+
18
+ def replace_keys
19
+ connect do |ssh|
20
+ say "Pushing SSH keys to #{login}@#{host}"
21
+ ssh.exec! 'mkdir -p ~/.ssh; touch ~/.ssh/authorized_keys'
22
+ keys_file = ssh.scp.download!('.ssh/authorized_keys')
23
+
24
+ authorized_keys = AuthorizedKeys.new(keys_file)
25
+
26
+ authorized_users.each do |user|
27
+ say "Adding #{user[:identity]}"
28
+ authorized_keys.add user
29
+ end
30
+
31
+ ssh.scp.upload(authorized_keys.to_io, '.ssh/authorized_keys')
32
+ end
33
+ end
34
+
35
+ private
36
+ def login
37
+ server[/(.*)@/, 1] || 'root'
38
+ end
39
+
40
+ def host
41
+ server[/^(?:.+@)?(.*)(?::.+)?/, 1]
42
+ end
43
+
44
+ def pass
45
+ @pass ||= ask_password("No valid SSH key found, please enter the password\nPass: ")
46
+ end
47
+
48
+ def port
49
+ server[/:(.+)/, 1] || 22
50
+ end
51
+
52
+ def users
53
+ [Jan, Tijs, Jens, Niels, Sam, Mathias]
54
+ end
55
+
56
+ def authorized_users
57
+ if group = options.fetch('group', nil)
58
+ users.select do |u|
59
+ u[:groups].member?(group)
60
+ end
61
+ else
62
+ users
63
+ end
64
+ end
65
+
66
+ def connect
67
+ options = {:port => port}
68
+ options[:password] = pass if @needs_pass
69
+
70
+ Net::SSH.start(host, login, options) do |ssh|
71
+ yield ssh
72
+ end
73
+ rescue Net::SSH::AuthenticationFailed
74
+ @needs_pass = true
75
+ @pass = nil
76
+ retry
77
+ end
78
+
79
+ def ask_password(message)
80
+ HighLine.new.ask(message) do |q|
81
+ q.echo = false
82
+ end
83
+ end
84
+
85
+ class AuthorizedKeys
86
+ attr_reader :contents
87
+
88
+ def initialize(file_contents)
89
+ @contents = parse!(file_contents)
90
+ end
91
+
92
+ def add key
93
+ @contents[key[:key]] = key
94
+ end
95
+
96
+ def remove key
97
+ @contents.delete(key[:key])
98
+ end
99
+
100
+ def to_s
101
+ @contents.collect do |identity, k|
102
+ "#{k[:optional]}ssh-#{k[:protocol]} #{k[:key]} #{k[:identity]}\n"
103
+ end.join
104
+ end
105
+
106
+ def to_io
107
+ StringIO.new(to_s)
108
+ end
109
+
110
+ private
111
+ def parse! (file)
112
+ file.split(/\n/).inject({}) do |hash, line|
113
+ #hash[$4] = {:optional => $1, :protocol => $2, :key => $3, :identity => $4} if line =~ /^([^#]*?)ssh-(dss|rsa) (.*) ((.*?)@(.*))/
114
+ hash[$3] = {:optional => $1, :protocol => $2, :key => $3, :identity => $4} if line =~ /^(\S*)ssh-(dss|rsa) (\S*)(?: (\S*))?$/
115
+ hash
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,45 @@
1
+ require 'sumodev/command'
2
+ require 'thor/group'
3
+
4
+ class Sumodev::Commands::Ssh < Thor::Group
5
+ argument :server, :type => :string
6
+
7
+ class_option :login
8
+
9
+ include Thor::Actions
10
+
11
+ Servers = {
12
+ :web1 => {:login => 'root', :host => 'web01.crsolutions.be'},
13
+ :web2 => {:login => 'root', :host => 'web02.crsolutions.be'},
14
+ :mysql => {:login => 'root', :host => 'mysql01.crsolutions.be'},
15
+ :mail => {:login => 'root', :host => 'mail.crsolutions.be'},
16
+ :mail2 => {:login => 'root', :host => 'mail02.crsolutions.be'},
17
+ :factr => {:login => 'factr', :host => 'app01.factr.be'},
18
+ :sumodev => {login: 'sites', :host => 'dev.sumocoders.eu'}
19
+ }
20
+
21
+ def check_ssh_key
22
+ if Dir.glob(ENV["HOME"] + "/.ssh/id_[rd]sa").none?
23
+ # No SSH key installed
24
+ if yes?("No SSH key installed! Do you want me to generate one for you?")
25
+ run "ssh-keygen -t rsa -f #{ENV["HOME"]}/.ssh/id_rsa"
26
+ end
27
+ end
28
+ end
29
+
30
+ def connect
31
+ server_details = Servers[server.to_sym]
32
+
33
+ if server_details
34
+ login = options.fetch(:login, server_details[:login])
35
+ host = server_details[:host]
36
+
37
+ run "ssh #{login}@#{host}"
38
+ else
39
+ say "No such server definition"
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ end
@@ -0,0 +1,6 @@
1
+ require 'sumodev/actions'
2
+
3
+ class Sumodev::Generator < Thor::Group
4
+ include Thor::Actions
5
+ include Sumodev::Actions
6
+ end
@@ -0,0 +1,77 @@
1
+ require 'sumodev/generator'
2
+ require 'sumodev/generators/general/capistrano'
3
+
4
+ module Sumodev::Generators
5
+ module Fork
6
+ class V3 < Sumodev::Generator
7
+ argument :client, :type => :string
8
+ argument :name, :type => :string
9
+
10
+ class_option :fork_repository, :default => "git://github.com/sumocoders/forkcms.git"
11
+ class_option :branch, :default => 'master'
12
+ class_option :multilanguage, :default => false, :type => :boolean
13
+ class_option :default_language, :default => 'nl'
14
+
15
+ attr_accessor :destination_dir
16
+
17
+ def create_root
18
+ self.destination_root = self.destination_dir = Pathname.pwd + client + name
19
+ FileUtils.mkdir_p destination_dir
20
+ FileUtils.chdir destination_dir
21
+ end
22
+
23
+ def checkout_fork
24
+ git :clone => "#{options[:fork_repository]} ."
25
+ git :checkout => "origin/#{options[:branch]}"
26
+ FileUtils.rm_rf '.git'
27
+ end
28
+
29
+ def initialize_repo
30
+ git :init
31
+ git_track 'Initial commit'
32
+ end
33
+
34
+ def setup_globals
35
+ git_track 'Setting up globals' do
36
+ copy_dest_file 'library/globals.base.php', 'library/globals.php'
37
+ copy_dest_file 'library/globals_frontend.base.php', 'library/globals_frontend.php'
38
+ copy_dest_file 'library/globals_backend.base.php', 'library/globals_backend.php'
39
+
40
+ replace_in_file 'library/globals.php', {
41
+ "'<debug-mode>'" => 'true',
42
+ "<spoon-debug-email>" => 'bugs@sumocoders.be',
43
+ "<database-name>" => name,
44
+ "<database-hostname>" => 'localhost',
45
+ "<database-port>" => '3306',
46
+ "<database-username>" => config[:db][:username],
47
+ "<database-password>" => config[:db][:password],
48
+ "<site-domain>" => "#{name}.#{client}.dev",
49
+ "'<site-multilanguage>'" => options[:multilanguage].to_s,
50
+ "<action-group-tag>" => '@actiongroup',
51
+ "<action-rights-level>" => 7,
52
+ "<path-www>" => destination_dir + "default_www",
53
+ "<path-library>" => destination_dir + "library"
54
+ }
55
+
56
+ replace_in_file 'library/globals_frontend.php', {
57
+ '<site-default-language>' => options[:default_language]
58
+ }
59
+ end
60
+ end
61
+
62
+ include Sumodev::Generators::General::Capistrano
63
+
64
+ private
65
+ # Config
66
+ def config
67
+ # TODO - Fetch this from ~/.sumorc OR ~/.my.cnf
68
+ {
69
+ :db => {
70
+ :username => 'root',
71
+ :password => 'root'
72
+ }
73
+ }
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,24 @@
1
+ require 'active_support/concern'
2
+ require 'sumodev/actions'
3
+
4
+ module Sumodev::Generators
5
+ module General
6
+ module Capistrano
7
+ include Thor::Actions
8
+ include Sumodev::Actions
9
+
10
+ extend ActiveSupport::Concern
11
+
12
+ included do
13
+ create_task :generate_capfile
14
+ source_paths << File.dirname(__FILE__) + '/templates/'
15
+ end
16
+
17
+ def generate_capfile
18
+ git_track "Added Capfile" do
19
+ template 'Capfile', 'Capfile'
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,10 @@
1
+ load 'deploy' if respond_to?(:namespace) # cap2 differentiator
2
+ # Capfile
3
+ set :client, "<%= client %>"
4
+ set :project, "<%= name %>"
5
+ set :repository, "git@git.sumocoders.be/<%= "#{client}_#{name}" %>.git"
6
+ set :branch, 'master'
7
+
8
+ require 'forkcms_3_deploy'
9
+ require 'forkcms_3_deploy/defaults'
10
+ require 'sumodev_deploy'
@@ -0,0 +1,3 @@
1
+ module Sumodev
2
+ VERSION = 0.1
3
+ end
data/lib/sumodev.rb ADDED
@@ -0,0 +1,17 @@
1
+ require 'thor'
2
+ require 'thor/group'
3
+
4
+ class Sumodev < Thor
5
+ module Commands
6
+ autoload :Fork, 'sumodev/commands/fork'
7
+ autoload :Ssh, 'sumodev/commands/ssh'
8
+ autoload :Factr, 'sumodev/commands/factr'
9
+ autoload :Push, 'sumodev/commands/push'
10
+ end
11
+
12
+ register Commands::Fork, 'fork', 'fork <command>', 'All commands concerning Fork applications'
13
+ register Commands::Ssh, 'ssh', 'ssh <server>', 'SSH access to servers'
14
+ register Commands::Factr, 'factr', 'factr <command>', 'All commands concerning Factr'
15
+ register Commands::Push, 'push', 'push <server>', 'Push the SSH keys to the server'
16
+ end
17
+
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sumodev
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jan De Poorter
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-04 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activesupport
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: thor
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: A command line tool to access all things you want
47
+ email: jan@sumocoders.be
48
+ executables:
49
+ - sumo
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - lib/sumodev/actions.rb
54
+ - lib/sumodev/application.rb
55
+ - lib/sumodev/command.rb
56
+ - lib/sumodev/commands/factr.rb
57
+ - lib/sumodev/commands/fork.rb
58
+ - lib/sumodev/commands/push.rb
59
+ - lib/sumodev/commands/ssh.rb
60
+ - lib/sumodev/generator.rb
61
+ - lib/sumodev/generators/fork/v3.rb
62
+ - lib/sumodev/generators/general/capistrano.rb
63
+ - lib/sumodev/generators/general/templates/Capfile
64
+ - lib/sumodev/version.rb
65
+ - lib/sumodev.rb
66
+ - bin/sumo
67
+ - Gemfile
68
+ - Gemfile.lock
69
+ homepage:
70
+ licenses: []
71
+ post_install_message:
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ none: false
77
+ requirements:
78
+ - - ! '>='
79
+ - !ruby/object:Gem::Version
80
+ version: '0'
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubyforge_project:
89
+ rubygems_version: 1.8.24
90
+ signing_key:
91
+ specification_version: 3
92
+ summary: SumoCoders Developers gem
93
+ test_files: []
94
+ has_rdoc: