shnell 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (7) hide show
  1. data/bin/shnell +97 -20
  2. data/lib/backup.rb +149 -0
  3. data/lib/shnell.rb +1 -1
  4. metadata +7 -9
  5. data/.gitignore +0 -21
  6. data/Rakefile +0 -33
  7. data/shnell.gemspec +0 -52
data/bin/shnell CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  require 'rubygems'
4
4
  require 'commander/import'
5
- require File.join(File.dirname(__FILE__), '../lib', 'shnell')
5
+ require 'filander'
6
+ require File.join(File.dirname(__FILE__), '../lib/shnell')
6
7
 
7
8
  program :name, 'shnell'
8
9
  program :version, Shnell::VERSION
@@ -11,24 +12,66 @@ program :help, 'Author', 'Johannes Jörg Schmidt, TF <schmidt@netzmerk.com>'
11
12
 
12
13
  default_command :help
13
14
 
14
- SCRIPTS_ROOT = Pathname.new(Dir.pwd)
15
+ SCRIPTS_ROOT = Pathname.new(Dir.pwd)
16
+ CONFIG_FILENAME = File.join(SCRIPTS_ROOT, "config.yml")
17
+
18
+ def scripts(pattern = nil)
19
+ if pattern
20
+ exp = "**/*#{pattern}*.rb"
21
+ else
22
+ exp = '**/*.rb'
23
+ end
24
+ Dir[SCRIPTS_ROOT.join(exp)].select { |f| File.basename(f) != 'backup.rb' }.sort
25
+ end
26
+
27
+ def backup_scripts(pattern = nil)
28
+ if pattern
29
+ exp = "**/*#{pattern}*/backup.rb"
30
+ else
31
+ exp = '**/backup.rb'
32
+ end
33
+ Dir[SCRIPTS_ROOT.join(exp)].sort
34
+ end
35
+
36
+ def say_script(filename, message, quiet = false)
37
+ return if quiet
38
+ name = Pathname.new(filename).relative_path_from(SCRIPTS_ROOT)
39
+ message = "#{message} #{name.sub(/\.rb$/, '')}..."
40
+ message = $terminal.color(message, :bold) if defined? $terminal
41
+ say message
42
+ end
15
43
 
16
44
  command :list do |c|
17
- c.syntax = 'shnell list [pattern]'
18
- c.description = 'List available scripts.'
45
+ c.syntax = 'shnell list [scrips|backups] [pattern]'
46
+ c.description = 'List available scripts and backups.'
47
+
48
+ c.example "List all available scripts and backups", "shnell list"
49
+ c.example "List all available backups", "shnell list backups"
50
+ c.example "List all available scripts", "shnell list scripts"
51
+ c.example 'List available scripts which include "ruby"', "shnell list scripts ruby"
19
52
 
20
53
  c.action do |args, options|
54
+ name = args.shift
21
55
  pattern = args.shift
22
-
23
- if pattern
24
- exp = "**/*#{pattern}*.rb"
56
+ if name == "scripts"
57
+ scripts(pattern).each do |f|
58
+ path = Pathname.new(f)
59
+ name = path.relative_path_from(SCRIPTS_ROOT)
60
+ puts name.sub(/\.rb$/, '')
61
+ end
62
+ elsif name == "backups"
63
+ backup_scripts(pattern).each do |f|
64
+ path = Pathname.new(f)
65
+ name = path.relative_path_from(SCRIPTS_ROOT)
66
+ puts name.sub(/\.rb$/, '')
67
+ end
25
68
  else
26
- exp = '**/*.rb'
27
- end
28
- Dir[SCRIPTS_ROOT.join(exp)].sort.each do |f|
29
- path = Pathname.new(f)
30
- name = path.relative_path_from(SCRIPTS_ROOT)
31
- puts name.sub(/\.rb$/, '')
69
+ all = scripts(pattern) + backup_scripts(pattern)
70
+ all.sort.each do |f|
71
+ path = Pathname.new(f)
72
+ name = path.relative_path_from(SCRIPTS_ROOT)
73
+ puts name.sub(/\.rb$/, '')
74
+ end
32
75
  end
33
76
  end
34
77
  end
@@ -42,12 +85,17 @@ command :run do |c|
42
85
  c.option '-q', '--quiet', 'Supress status output'
43
86
  c.option '-s', '--skip', 'Skip files that already exist'
44
87
 
88
+ c.example 'Run script "./basic/apache.rb"', "shnell run basic/apache"
89
+ c.example "Run all available scripts", "shnell run all"
90
+ c.example 'Run available scripts which include "ruby"', "shnell run all ruby"
91
+ c.example "Dry run all available scripts (make no changes)", "shnell run all --pretend"
92
+
45
93
  c.action do |args, options|
46
94
  $:.unshift SCRIPTS_ROOT
47
95
  script = args.shift
48
- require 'filander'
49
96
  include Filander
50
97
 
98
+ Filander.quiet = options.quiet
51
99
  behavior = :ask
52
100
  behavior = :skip if options.skip
53
101
  behavior = :pretend if options.pretend
@@ -55,17 +103,46 @@ command :run do |c|
55
103
  Filander.behavior = behavior
56
104
 
57
105
  if script == "all"
58
- Dir[File.join(SCRIPTS_ROOT, '**/*.rb')].sort.each do |file|
59
- name = Pathname.new(file).relative_path_from(SCRIPTS_ROOT)
60
- message = "Running #{name.sub(/\.rb$/, '')}..."
61
- message = $terminal.color(message, :bold) if defined? $terminal
62
- say message
106
+ pattern = args.shift
107
+
108
+ scripts(pattern).each do |file|
109
+ say_script file, "Running", options.quiet
63
110
  Filander.source_root = file.sub(/\.rb$/, '')
64
111
  require file
65
112
  end
66
- else
113
+ elsif script
67
114
  Filander.source_root = File.join(SCRIPTS_ROOT, script)
68
115
  require script
116
+ else
117
+ say "No script set."
118
+ end
119
+ end
120
+ end
121
+
122
+ command :backup do |c|
123
+ c.syntax = 'shnell backup script'
124
+ c.description = 'Run a backup script.'
125
+
126
+ c.option '-q', '--quiet', 'Supress status output'
127
+
128
+ c.action do |args, options|
129
+ script = args.shift
130
+
131
+ require File.join(File.dirname(__FILE__), '../lib/backup')
132
+ include Backup
133
+
134
+ if script == "all"
135
+ pattern = args.shift
136
+
137
+ backup_scripts(pattern).each do |file|
138
+ say_script file, "Backup", options.quiet
139
+ require file
140
+ end
141
+ elsif script
142
+ require script
143
+ else
144
+ say "No backup script set."
69
145
  end
70
146
  end
71
147
  end
148
+
@@ -0,0 +1,149 @@
1
+ require 'net/ftp'
2
+ require 'yaml'
3
+
4
+ module Backup
5
+ include Filander
6
+
7
+ class BackupScript
8
+ class << self
9
+ def backup(name, &block)
10
+ backup = self.new(name)
11
+ backup.prepare
12
+ backup.instance_eval(&block)
13
+ backup.backup!
14
+ backup.finish
15
+ end
16
+
17
+ def restore(name, &block)
18
+ backup = self.new(name)
19
+ backup.instance_eval(&block)
20
+ backup.restore!
21
+ backup.finish
22
+ end
23
+ end
24
+
25
+ def initialize(service)
26
+ @service_root = service
27
+ @service_name = File.basename(service)
28
+ @database = @service_name.gsub(/[-\.]/, '_')
29
+ @tempdir = File.join("/tmp", @service_name)
30
+ @tarball = "#{@tempdir}.tar.bz2"
31
+ @directories = []
32
+ @databases = []
33
+ end
34
+
35
+ def prepare
36
+ backup_cmd "mkdir -p #{@tempdir}"
37
+ end
38
+
39
+ def directory(filename)
40
+ report :directory, filename
41
+ @directories << filename
42
+ end
43
+
44
+ def database(database = @database)
45
+ report :database, database
46
+ @databases << database
47
+ end
48
+
49
+ def backup!
50
+ @directories.each do |filename|
51
+ filename = File.join(@service_root, filename)
52
+ backup_cmd "cp -r #{filename} #{@tempdir}/"
53
+ end
54
+ @databases.each do |database|
55
+ backup_cmd "mysqldump -u#{db_user} #{"-p#{db_password}" if db_password != ''} #{database} > #{File.join(@tempdir, "#{database}.sql")}"
56
+ end
57
+ backup_cmd "tar -C /tmp -cjf #{@tarball} #{@service_name}"
58
+ Net::FTP.open(ftp_host) do |ftp|
59
+ ftp.login ftp_user, ftp_password
60
+ ftp.putbinaryfile @tarball
61
+ end
62
+ end
63
+
64
+ def restore!
65
+ Net::FTP.open(ftp_host) do |ftp|
66
+ ftp.login ftp_user, ftp_password
67
+ ftp.getbinaryfile @tarball
68
+ end
69
+ backup_cmd "tar -C /tmp -xf #{@tarball}"
70
+ @databases.each do |database|
71
+ backup_cmd "mysql -u#{db_user} #{"-p#{db_password}" if db_password != ''} #{database} < #{File.join(@tempdir, "#{database}.sql")}"
72
+ end
73
+ @directories.each do |filename|
74
+ source = File.join(@tempdir, filename)
75
+ dest = File.join(@service_root, filename)
76
+ backup_cmd "cp -r #{source} #{dest}"
77
+ end
78
+ end
79
+
80
+ def finish
81
+ backup_cmd "rm -rf #{@tempdir}"
82
+ backup_cmd "rm #{@tarball}"
83
+ end
84
+
85
+ private
86
+
87
+ def backup_cmd(command)
88
+ system command
89
+ end
90
+
91
+ def db_user
92
+ read_config(:db, :user)
93
+ end
94
+
95
+ def db_password
96
+ read_config(:db, :password)
97
+ end
98
+
99
+ def ftp_host
100
+ read_config(:ftp, :host)
101
+ end
102
+
103
+ def ftp_user
104
+ read_config(:ftp, :user)
105
+ end
106
+
107
+ def ftp_password
108
+ read_config(:ftp, :password)
109
+ end
110
+
111
+ def read_config(scope, key)
112
+ hash = config[scope.to_s] || {}
113
+ value = hash[key.to_s]
114
+ if value.nil?
115
+ question = "Give me the #{scope} #{key}:"
116
+ value = if key.to_s =~ /password/
117
+ ask(question) { |q| q.echo = "*" }
118
+ else
119
+ ask(question)
120
+ end
121
+ write_config scope, key, value
122
+ end
123
+ value
124
+ end
125
+
126
+ def write_config(scope, key, value)
127
+ hash = config
128
+ hash[scope.to_s] ||= {}
129
+ hash[scope.to_s].update key.to_s => value
130
+ File.open(CONFIG_FILENAME, "w") do |file|
131
+ file << YAML.dump(hash)
132
+ end
133
+ end
134
+
135
+ def config
136
+ content = File.read(CONFIG_FILENAME) rescue nil
137
+ return {} unless content
138
+ YAML.load(content)
139
+ end
140
+ end
141
+
142
+ def backup(filename, &block)
143
+ BackupScript.backup filename, &block
144
+ end
145
+
146
+ def restore(filename, &block)
147
+ BackupScript.restore filename, &block
148
+ end
149
+ end
@@ -1,3 +1,3 @@
1
1
  module Shnell
2
- VERSION = '0.1.0'
2
+ VERSION = '0.2.0'
3
3
  end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
7
+ - 2
8
8
  - 0
9
- version: 0.1.0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Johannes J. Schmidt
@@ -40,9 +40,9 @@ dependencies:
40
40
  - !ruby/object:Gem::Version
41
41
  segments:
42
42
  - 0
43
- - 4
43
+ - 5
44
44
  - 0
45
- version: 0.4.0
45
+ version: 0.5.0
46
46
  type: :runtime
47
47
  version_requirements: *id002
48
48
  description: Ease Server Setup and Configuration
@@ -55,13 +55,11 @@ extra_rdoc_files:
55
55
  - LICENSE
56
56
  - README.rdoc
57
57
  files:
58
- - .gitignore
59
- - LICENSE
60
- - README.rdoc
61
- - Rakefile
62
58
  - bin/shnell
59
+ - lib/backup.rb
63
60
  - lib/shnell.rb
64
- - shnell.gemspec
61
+ - LICENSE
62
+ - README.rdoc
65
63
  has_rdoc: true
66
64
  homepage: http://github.com/jo/shnell
67
65
  licenses: []
data/.gitignore DELETED
@@ -1,21 +0,0 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- rdoc
19
- pkg
20
-
21
- ## PROJECT::SPECIFIC
data/Rakefile DELETED
@@ -1,33 +0,0 @@
1
- require 'rubygems'
2
- require 'rake'
3
- require File.join(File.dirname(__FILE__), 'lib', 'shnell')
4
-
5
- begin
6
- require 'jeweler'
7
- Jeweler::Tasks.new do |gem|
8
- gem.name = "shnell"
9
- gem.version = Shnell::VERSION
10
- gem.summary = %Q{Server Setup and Configuration tools}
11
- gem.description = %Q{Ease Server Setup and Configuration}
12
- gem.email = "schmidt@netzmerk.com"
13
- gem.homepage = "http://github.com/jo/shnell"
14
- gem.authors = ["Johannes J. Schmidt"]
15
- gem.add_dependency "commander", ">= 4.0.2"
16
- gem.add_dependency "filander", ">= 0.4.0"
17
- end
18
- Jeweler::GemcutterTasks.new
19
- rescue LoadError
20
- puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
21
- end
22
-
23
- task :default => :test
24
-
25
- require 'rake/rdoctask'
26
- Rake::RDocTask.new do |rdoc|
27
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
28
-
29
- rdoc.rdoc_dir = 'rdoc'
30
- rdoc.title = "shnell #{version}"
31
- rdoc.rdoc_files.include('README*')
32
- rdoc.rdoc_files.include('lib/**/*.rb')
33
- end
@@ -1,52 +0,0 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
- # -*- encoding: utf-8 -*-
5
-
6
- Gem::Specification.new do |s|
7
- s.name = %q{shnell}
8
- s.version = "0.1.0"
9
-
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Johannes J. Schmidt"]
12
- s.date = %q{2010-04-08}
13
- s.default_executable = %q{shnell}
14
- s.description = %q{Ease Server Setup and Configuration}
15
- s.email = %q{schmidt@netzmerk.com}
16
- s.executables = ["shnell"]
17
- s.extra_rdoc_files = [
18
- "LICENSE",
19
- "README.rdoc"
20
- ]
21
- s.files = [
22
- ".gitignore",
23
- "LICENSE",
24
- "README.rdoc",
25
- "Rakefile",
26
- "bin/shnell",
27
- "lib/shnell.rb",
28
- "shnell.gemspec"
29
- ]
30
- s.homepage = %q{http://github.com/jo/shnell}
31
- s.rdoc_options = ["--charset=UTF-8"]
32
- s.require_paths = ["lib"]
33
- s.rubygems_version = %q{1.3.6}
34
- s.summary = %q{Server Setup and Configuration tools}
35
-
36
- if s.respond_to? :specification_version then
37
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
38
- s.specification_version = 3
39
-
40
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
41
- s.add_runtime_dependency(%q<commander>, [">= 4.0.2"])
42
- s.add_runtime_dependency(%q<filander>, [">= 0.4.0"])
43
- else
44
- s.add_dependency(%q<commander>, [">= 4.0.2"])
45
- s.add_dependency(%q<filander>, [">= 0.4.0"])
46
- end
47
- else
48
- s.add_dependency(%q<commander>, [">= 4.0.2"])
49
- s.add_dependency(%q<filander>, [">= 0.4.0"])
50
- end
51
- end
52
-