awshucks 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. data/CHANGES +4 -0
  2. data/LICENSE +19 -0
  3. data/README +32 -0
  4. data/Rakefile +14 -0
  5. data/TODO +143 -0
  6. data/bin/awshucks +10 -0
  7. data/lib/awshucks.rb +29 -0
  8. data/lib/awshucks/cli.rb +76 -0
  9. data/lib/awshucks/command.rb +98 -0
  10. data/lib/awshucks/commands.rb +3 -0
  11. data/lib/awshucks/commands/backup.rb +59 -0
  12. data/lib/awshucks/commands/backups.rb +25 -0
  13. data/lib/awshucks/commands/help.rb +22 -0
  14. data/lib/awshucks/commands/list.rb +39 -0
  15. data/lib/awshucks/commands/new_config.rb +36 -0
  16. data/lib/awshucks/commands/reset_metadata_cache.rb +38 -0
  17. data/lib/awshucks/commands/restore.rb +54 -0
  18. data/lib/awshucks/config.rb +83 -0
  19. data/lib/awshucks/ext.rb +23 -0
  20. data/lib/awshucks/file_info.rb +23 -0
  21. data/lib/awshucks/file_store.rb +111 -0
  22. data/lib/awshucks/gemspec.rb +48 -0
  23. data/lib/awshucks/scanner.rb +58 -0
  24. data/lib/awshucks/specification.rb +128 -0
  25. data/lib/awshucks/version.rb +18 -0
  26. data/resources/awshucks.yml +21 -0
  27. data/spec/awshucks_spec.rb +7 -0
  28. data/spec/cli_spec.rb +130 -0
  29. data/spec/command_spec.rb +111 -0
  30. data/spec/commands/backup_spec.rb +164 -0
  31. data/spec/commands/backups_spec.rb +41 -0
  32. data/spec/commands/help_spec.rb +42 -0
  33. data/spec/commands/list_spec.rb +77 -0
  34. data/spec/commands/new_config_spec.rb +102 -0
  35. data/spec/commands/reset_metadata_cache_spec.rb +93 -0
  36. data/spec/commands/restore_spec.rb +219 -0
  37. data/spec/config_spec.rb +152 -0
  38. data/spec/ext_spec.rb +28 -0
  39. data/spec/file_info_spec.rb +45 -0
  40. data/spec/file_store_spec.rb +352 -0
  41. data/spec/scanner_spec.rb +106 -0
  42. data/spec/spec_helper.rb +36 -0
  43. data/spec/specification_spec.rb +41 -0
  44. metadata +121 -0
@@ -0,0 +1,164 @@
1
+ require File.join(File.dirname(__FILE__),"..","spec_helper.rb")
2
+
3
+ describe Awshucks::BackupCommand do
4
+ it "has 'backup' as the command" do
5
+ Awshucks::BackupCommand.command.should == 'backup'
6
+ end
7
+ end
8
+
9
+ describe Awshucks::BackupCommand, '#execute, with no command-line argument' do
10
+
11
+ before(:each) do
12
+ @config = mock('config')
13
+ @config.stub!(:connection)
14
+ @config.stub!(:bucket).and_return('bucket')
15
+
16
+ @backup = mock('backup')
17
+ @backup.stub!(:location).and_return('/primary/backup')
18
+ @backup.stub!(:name).and_return('test backup')
19
+
20
+ @config.should_receive(:backups).and_return([@backup, @backup])
21
+
22
+ @file_store = mock("mock file store")
23
+ @file_store.stub!(:save_cache)
24
+ Awshucks::FileStore.should_receive(:new).twice.and_return(@file_store)
25
+
26
+ @command = Awshucks::BackupCommand.new
27
+
28
+ @old_stdout, $stdout = $stdout, StringIO.new
29
+ end
30
+
31
+ after(:each) do
32
+ $stdout = @old_stdout
33
+ end
34
+
35
+ it "scans the filesystem for all configured backup locations" do
36
+ Awshucks::Scanner.should_receive(:each_file).twice
37
+ @command.execute([], @config)
38
+ end
39
+
40
+ it "prints out each backup as it runs" do
41
+ Awshucks::Scanner.stub!(:each_file)
42
+ @command.execute([], @config)
43
+ $stdout.string.should =~ /backing up \/primary\/backup.*backing up/m
44
+ end
45
+
46
+ it "saves each file store's cache when it's done using them" do
47
+ Awshucks::Scanner.stub!(:each_file)
48
+ @file_store.should_receive(:save_cache).twice
49
+ @command.execute([], @config)
50
+ end
51
+
52
+ end
53
+
54
+ describe Awshucks::BackupCommand, '#execute, with an invalid backup specified' do
55
+
56
+ before(:each) do
57
+ @old_stderr, $stderr = $stderr, StringIO.new
58
+ @config = mock('config')
59
+
60
+ @command = Awshucks::BackupCommand.new
61
+ end
62
+
63
+ after(:each) do
64
+ $stderr = @old_stderr
65
+ end
66
+
67
+ it "prints out an error" do
68
+ @config.should_receive(:backup).with('test').and_raise(Awshucks::UnknownBackupError.new('test'))
69
+ @command.execute(['test'], @config)
70
+ $stderr.string.should_not be_empty
71
+ end
72
+ end
73
+
74
+ describe Awshucks::BackupCommand, '#execute, with a single backup specified' do
75
+
76
+ before(:each) do
77
+ @config = mock('config')
78
+ @config.stub!(:connection)
79
+ @config.stub!(:bucket).and_return('bucket')
80
+
81
+ @backup = mock('backup')
82
+ @backup.stub!(:location).and_return('/primary/backup')
83
+ @backup.stub!(:name).and_return('test backup')
84
+
85
+ @config.should_receive(:backup).with('test').and_return(@backup)
86
+
87
+ @file_store = mock("mock file store")
88
+ @file_store.stub!(:save_cache)
89
+ Awshucks::FileStore.stub!(:new).and_return(@file_store)
90
+
91
+ @info = mock('file info')
92
+ @info.stub!(:filename).and_return 'file'
93
+ @info.stub!(:mtime).and_return Time.now
94
+ @info.stub!(:size).and_return 12345
95
+
96
+ @command = Awshucks::BackupCommand.new
97
+
98
+ @old_stdout, $stdout = $stdout, StringIO.new
99
+ end
100
+
101
+ after(:each) do
102
+ $stdout = @old_stdout
103
+ end
104
+
105
+ it "scans the filesystem at the configurated location" do
106
+ Awshucks::Scanner.should_receive(:each_file).with('/primary/backup')
107
+ @command.execute(['test'], @config)
108
+ end
109
+
110
+ it "will not store the file if the same as the file store's" do
111
+ Awshucks::Scanner.should_receive(:each_file).with('/primary/backup').and_yield(@info)
112
+ @file_store.should_receive(:different_from?).and_return(false)
113
+
114
+ @file_store.should_not_receive(:store)
115
+
116
+ @command.execute(['test'], @config)
117
+ end
118
+
119
+ it "prints out a status message if the file hasn't been changed" do
120
+ Awshucks::Scanner.stub!(:each_file).and_yield(@info)
121
+ @file_store.should_receive(:different_from?).and_return(false)
122
+
123
+ @command.execute(['test'], @config)
124
+
125
+ $stdout.string.should =~ /file.*unchanged/
126
+ end
127
+
128
+ it "stores the file if it's different from the file store" do
129
+ sum = 'this is a pretend md5 sum'
130
+
131
+ Awshucks::Scanner.should_receive(:each_file).with('/primary/backup').and_yield(@info)
132
+ @file_store.stub!(:different_from?).and_return(true)
133
+ @file_store.should_receive(:store).with(@info)
134
+
135
+ @command.execute(['test'], @config)
136
+ end
137
+
138
+ it "prints out a message for each file uploaded" do
139
+ Awshucks::Scanner.stub!(:each_file).and_yield(@info)
140
+ @file_store.stub!(:different_from?).and_return(true)
141
+ @file_store.stub!(:store)
142
+
143
+ @command.execute(['test'], @config)
144
+ $stdout.string.should =~ /file.*uploading/
145
+ end
146
+
147
+ it "saves the metadata cache when it's done" do
148
+ Awshucks::Scanner.stub!(:each_file)
149
+ @file_store.should_receive(:save_cache)
150
+ @command.execute(['test'], @config)
151
+
152
+ end
153
+
154
+ it "saves the metadata cache even if an exception is raised" do
155
+ Awshucks::Scanner.stub!(:each_file).and_raise(SystemExit)
156
+ @file_store.should_receive(:save_cache)
157
+ lambda {@command.execute(['test'], @config)}.should raise_error(SystemExit)
158
+ end
159
+
160
+ end
161
+
162
+ # describe Awshucks::BackupCommand, '#execute, when the dry run option is set' do
163
+ # it "shouldn't do anything"
164
+ # end
@@ -0,0 +1,41 @@
1
+ require File.join(File.dirname(__FILE__),"..","spec_helper.rb")
2
+
3
+ describe Awshucks::BackupsCommand do
4
+ it "has 'backups' as the command" do
5
+ Awshucks::BackupsCommand.command.should == 'backups'
6
+ end
7
+ end
8
+
9
+ describe Awshucks::BackupsCommand, '#execute' do
10
+
11
+ before(:each) do
12
+ @config = mock('config')
13
+
14
+ @backup = mock('backup')
15
+ @backup.stub!(:name).and_return('test_backup', 'secondary_backup')
16
+ @backup.stub!(:location).and_return('/primary/backup', '/secondary')
17
+
18
+ @config.should_receive(:backups).and_return([@backup, @backup])
19
+
20
+ @command = Awshucks::BackupsCommand.new
21
+
22
+ @old_stdout, $stdout = $stdout, StringIO.new
23
+ end
24
+
25
+ after(:each) do
26
+ $stdout = @old_stdout
27
+ end
28
+
29
+ it "prints out the backup configuration name" do
30
+ @command.execute([], @config)
31
+ $stdout.string.should =~ /test_backup:/
32
+ $stdout.string.should =~ /secondary_backup:/
33
+ end
34
+
35
+ it "prints out the location for each backup" do
36
+ @command.execute([], @config)
37
+ $stdout.string.should =~ /location:.*\/primary\/backup/
38
+ $stdout.string.should =~ /location:.*\/secondary/
39
+ end
40
+
41
+ end
@@ -0,0 +1,42 @@
1
+ require File.join(File.dirname(__FILE__),"..","spec_helper.rb")
2
+
3
+ describe Awshucks::HelpCommand do
4
+ it "has 'help' as the command" do
5
+ Awshucks::HelpCommand.command.should == 'help'
6
+ end
7
+ end
8
+
9
+ describe Awshucks::HelpCommand, '#execute' do
10
+
11
+ before(:each) do
12
+ @cmd = mock('command')
13
+ @config = mock('config')
14
+ @old_stdout, $stdout = $stdout, StringIO.new
15
+ @old_stderr, $stderr = $stderr, StringIO.new
16
+ @help = Awshucks::HelpCommand.new
17
+ end
18
+
19
+ after(:each) do
20
+ $stdout = @old_stdout
21
+ $stderr = @old_stderr
22
+ end
23
+
24
+ it "displays the main help message if the args list is empty" do
25
+ @config.should_receive(:help_message)
26
+ @help.execute([], @config)
27
+ end
28
+
29
+ it "displays usage for the provided command in args" do
30
+ Awshucks::Command.stub!(:commands).and_return({'pretend' => @cmd})
31
+ @cmd.should_receive(:option_string).and_return('pretend options output string')
32
+ @help.execute(['pretend'], @config)
33
+ $stdout.string.should include('pretend options output string')
34
+ end
35
+
36
+ it "prints an error if the provided command isn't found" do
37
+ Awshucks::Command.stub!(:commands).and_return({})
38
+ @help.execute(['pretend'], @config)
39
+ $stderr.string.should =~ /pretend/
40
+ end
41
+
42
+ end
@@ -0,0 +1,77 @@
1
+ require File.join(File.dirname(__FILE__),"..","spec_helper.rb")
2
+
3
+ describe Awshucks::ListCommand do
4
+ it "has 'list' as the command" do
5
+ Awshucks::ListCommand.command.should == 'list'
6
+ end
7
+ end
8
+
9
+ describe Awshucks::ListCommand, '#execute, with no backup configuration specified' do
10
+
11
+ before(:each) do
12
+ @config = mock('config')
13
+ @config.stub!(:connection).and_return nil
14
+ @config.stub!(:bucket).and_return('testbucket')
15
+
16
+ @file_store = mock(Awshucks::FileStore)
17
+ Awshucks::FileStore.should_receive(:new).twice.with(nil, 'testbucket', 'testbackup').and_return(@file_store)
18
+
19
+ @list = Awshucks::ListCommand.new
20
+
21
+ @backup = mock('backup information')
22
+ @backup.stub!(:location).and_return('test_location')
23
+ @backup.stub!(:name).and_return('testbackup')
24
+
25
+ @old_stdout, $stdout = $stdout, StringIO.new
26
+ end
27
+
28
+ after(:each) do
29
+ $stdout = @old_stdout
30
+ end
31
+
32
+ it "lists the files for each backup" do
33
+ @config.should_receive(:backups).and_return([@backup, @backup])
34
+ @file_store.should_receive(:each_file).twice.and_yield('test/file')
35
+ @list.execute([], @config)
36
+ end
37
+
38
+ end
39
+
40
+ describe Awshucks::ListCommand, '#execute, with a backup configuration specified' do
41
+
42
+ before(:each) do
43
+ @config = mock('config')
44
+ @config.stub!(:connection).and_return nil
45
+ @config.stub!(:bucket).and_return('testbucket')
46
+
47
+ @file_store = mock(Awshucks::FileStore)
48
+
49
+ @list = Awshucks::ListCommand.new
50
+
51
+ @backup = mock('backup information')
52
+ @backup.stub!(:location).and_return('test_location')
53
+ @backup.stub!(:name).and_return('testbackup')
54
+
55
+ @old_stderr, $stderr = $stderr, StringIO.new
56
+ @old_stdout, $stdout = $stdout, StringIO.new
57
+ end
58
+
59
+ after(:each) do
60
+ $stderr = @old_stderr
61
+ $stdout = @old_stdout
62
+ end
63
+
64
+ it "lists each file for the backup" do
65
+ @config.should_receive(:backup).with('testbackup').and_return(@backup)
66
+ Awshucks::FileStore.should_receive(:new).with(nil, 'testbucket', 'testbackup').and_return(@file_store)
67
+ @file_store.should_receive(:each_file).and_yield('file')
68
+
69
+ @list.execute(['testbackup'], @config)
70
+ end
71
+
72
+ it "prints a warning if the backup config isn't found" do
73
+ @config.stub!(:backup).and_raise(Awshucks::UnknownBackupError.new('foo'))
74
+ @list.execute(['foo'], @config)
75
+ end
76
+
77
+ end
@@ -0,0 +1,102 @@
1
+ require File.join(File.dirname(__FILE__),"..","spec_helper.rb")
2
+
3
+ describe Awshucks::NewConfigCommand do
4
+ it "has 'new_config' as the command" do
5
+ Awshucks::NewConfigCommand.command.should == 'new_config'
6
+ end
7
+ end
8
+
9
+ describe Awshucks::NewConfigCommand, '#execute' do
10
+
11
+ before(:each) do
12
+ @command = Awshucks::NewConfigCommand.new
13
+ @old_stdout, $stdout = $stdout, StringIO.new
14
+ @old_stderr, $stderr = $stderr, StringIO.new
15
+ end
16
+
17
+ after(:each) do
18
+ $stdout = @old_stdout
19
+ $stderr = @old_stderr
20
+ FileUtils.rm(dummy_file_path('awshucks.yml')) if File.exists?(dummy_file_path('awshucks.yml'))
21
+ end
22
+
23
+ it "copies awshucks.yml from the resources directory to the current working directory" do
24
+ FileUtils.should_receive(:cp).with(
25
+ File.join(Awshucks::RESOURCE_DIR, 'awshucks.yml'),
26
+ dummy_file_path('awshucks.yml')
27
+ )
28
+ Dir.chdir(dummy_fs_path) do
29
+ @command.execute([], nil)
30
+ end
31
+
32
+ end
33
+
34
+ it "refuses to overwrite the file if it already exists" do
35
+ FileUtils.should_not_receive(:cp)
36
+ FileUtils.touch(dummy_file_path('awshucks.yml'))
37
+ Dir.chdir(dummy_fs_path) do
38
+ @command.execute([], nil)
39
+ end
40
+ end
41
+
42
+ it "complains if the file already exists" do
43
+ FileUtils.should_not_receive(:cp)
44
+ FileUtils.touch(dummy_file_path('awshucks.yml'))
45
+ Dir.chdir(dummy_fs_path) do
46
+ @command.execute([], nil)
47
+ end
48
+ $stderr.string.should include(File.join(dummy_file_path('awshucks.yml')))
49
+ end
50
+
51
+ # it "overwrites the existing file if the --force option is specified" do
52
+ # FileUtils.touch(dummy_file_path('awshucks.yml'))
53
+ # FileUtils.should_receive(:cp).with(
54
+ # File.join(Awshucks::RESOURCE_DIR, 'awshucks.yml'),
55
+ # File.join(dummy_fs_path, 'awshucks.yml')
56
+ # )
57
+ # Dir.chdir(dummy_fs_path) do
58
+ # @command.execute(['-f'], nil)
59
+ # end
60
+ # $stderr.string.should be_empty
61
+ # end
62
+
63
+ it "prints out the path where it's creating the new config file" do
64
+ FileUtils.stub!(:cp)
65
+ Dir.chdir(dummy_fs_path) do
66
+ @command.execute([], nil)
67
+ end
68
+ $stdout.string.should include(File.join(dummy_fs_path, 'awshucks.yml'))
69
+ end
70
+
71
+ end
72
+
73
+ describe Awshucks::NewConfigCommand, '#execute' do
74
+
75
+ before(:each) do
76
+ @command = Awshucks::NewConfigCommand.new
77
+ @old_stdout, $stdout = $stdout, StringIO.new
78
+ end
79
+
80
+ after(:each) do
81
+ $stdout = @old_stdout
82
+ end
83
+
84
+ it "copies awshucks.yml from the resources directory to the specified path" do
85
+ FileUtils.should_receive(:cp).with(
86
+ File.join(Awshucks::RESOURCE_DIR, 'awshucks.yml'),
87
+ File.join(dummy_fs_path, 'foo/test.yml')
88
+ )
89
+ Dir.chdir(dummy_fs_path) do
90
+ @command.execute(['foo/test.yml'], nil)
91
+ end
92
+ end
93
+
94
+ it "prints out the path where it's creating the new config file" do
95
+ FileUtils.stub!(:cp)
96
+ Dir.chdir(dummy_fs_path) do
97
+ @command.execute(['foo/test.yml'], nil)
98
+ end
99
+ $stdout.string.should include(File.join(dummy_fs_path, 'foo/test.yml'))
100
+ end
101
+
102
+ end
@@ -0,0 +1,93 @@
1
+ require File.join(File.dirname(__FILE__),"..","spec_helper.rb")
2
+
3
+ describe Awshucks::ResetMetadataCacheCommand do
4
+ it "has 'reset_metadata_cache' as the command" do
5
+ Awshucks::ResetMetadataCacheCommand.command.should == 'reset_metadata_cache'
6
+ end
7
+ end
8
+
9
+ describe Awshucks::BackupsCommand, '#execute with no arguments' do
10
+
11
+ before(:each) do
12
+ @config = mock('config')
13
+ @config.stub!(:connection)
14
+ @config.stub!(:bucket).and_return('bucket')
15
+
16
+ @backup = mock('backup')
17
+ @backup.stub!(:location).and_return('/primary/backup')
18
+ @backup.stub!(:name).and_return('test backup')
19
+
20
+ @config.should_receive(:backups).and_return([@backup, @backup])
21
+
22
+ @file_store = mock("mock file store")
23
+ @file_store.should_receive(:reset_cache).twice
24
+ Awshucks::FileStore.should_receive(:new).twice.and_return(@file_store)
25
+
26
+ @command = Awshucks::ResetMetadataCacheCommand.new
27
+
28
+ @old_stdout, $stdout = $stdout, StringIO.new
29
+ end
30
+
31
+ after(:each) do
32
+ $stdout = @old_stdout
33
+ end
34
+
35
+ it "instantiates a file store for each backup and invokes reset_cache on each" do
36
+ @command.execute([], @config)
37
+ end
38
+
39
+ end
40
+
41
+ describe Awshucks::BackupsCommand, '#execute with a backup configuration specified' do
42
+
43
+ before(:each) do
44
+ @config = mock('config')
45
+ @config.stub!(:connection)
46
+ @config.stub!(:bucket).and_return('bucket')
47
+
48
+ @backup = mock('backup')
49
+ @backup.stub!(:location).and_return('/primary/backup')
50
+ @backup.stub!(:name).and_return('test backup')
51
+
52
+ @config.should_receive(:backup).and_return(@backup)
53
+
54
+ @file_store = mock("mock file store")
55
+ @file_store.should_receive(:reset_cache)
56
+ Awshucks::FileStore.should_receive(:new).and_return(@file_store)
57
+
58
+ @command = Awshucks::ResetMetadataCacheCommand.new
59
+ @old_stdout, $stdout = $stdout, StringIO.new
60
+ end
61
+
62
+ after(:each) do
63
+ $stdout = @old_stdout
64
+ end
65
+
66
+ it "instantiates a file store for the given backup configuration and calls reset_cache" do
67
+ @command.execute(['test_backup'], @config)
68
+ end
69
+
70
+ end
71
+
72
+ describe Awshucks::BackupsCommand, '#execute with an invalid backup configuration specified' do
73
+
74
+ before(:each) do
75
+ @config = mock('config')
76
+ @config.stub!(:connection)
77
+ @config.stub!(:bucket).and_return('bucket')
78
+
79
+ @command = Awshucks::ResetMetadataCacheCommand.new
80
+ @old_stderr, $stderr = $stderr, StringIO.new
81
+ end
82
+
83
+ after(:each) do
84
+ $stderr = @old_stderr
85
+ end
86
+
87
+ it "prints out an error message" do
88
+ @config.should_receive(:backup).with('invalid').and_raise(Awshucks::UnknownBackupError.new('invalid'))
89
+ @command.execute(['invalid'], @config)
90
+ $stderr.string.should_not be_empty
91
+ end
92
+
93
+ end