shnell 0.1.0 → 0.2.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 (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
-