braavos 0.0.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.
@@ -0,0 +1,48 @@
1
+ class Braavos::Storage::File < Braavos::Storage::StorageBase
2
+
3
+ def load_file(location)
4
+ Braavos.logger.debug("load_file: #{location}")
5
+ File.read(location)
6
+ end
7
+
8
+ # Returns a recursive listing of {"name" => true} if directory and {"name" => *file size*} if file
9
+ def list_dir(location)
10
+ Braavos.logger.debug("list_dir: #{location}")
11
+ listing = Dir["#{location}/**/*"].inject({}) do |h,i|
12
+ h[i] = File.size?(i) if not File.directory?(i)
13
+ h
14
+ end
15
+ Braavos.logger.debug("\t#{listing}")
16
+ listing
17
+ end
18
+
19
+ def clear_result(location)
20
+ FileUtils.rm_f File.join(location, "_FAILED")
21
+ end
22
+
23
+ def has_success?(location)
24
+ path = File.join(location, "_COMPLETED")
25
+ list_dir(location).size > 0 &&
26
+ File.exists?(path)
27
+ end
28
+
29
+ def script_path(location)
30
+ @mkdir_cache ||= Hash.new do |h, key|
31
+ FileUtils.mkdir_p(key)
32
+ h[key] = true
33
+ end
34
+
35
+ @mkdir_cache[File.dirname(location)]
36
+ location
37
+ end
38
+
39
+ def write_file(location, contents)
40
+ script_path(location) # for mkdir -p
41
+ if contents.is_a?(Hash) && contents.include?(:file)
42
+ FileUtils.cp(contents[:file], location)
43
+ else
44
+ File.open(location, 'w') do |f| f.write contents end
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,41 @@
1
+ class Braavos::Storage::S3 < Braavos::Storage::StorageBase
2
+
3
+ attr_reader :s3
4
+
5
+ def initialize
6
+ @s3 = AWS::S3.new
7
+ end
8
+
9
+ def load_file(location)
10
+ s3.buckets[Braavos.config.bucket_name].objects[location].read
11
+ end
12
+
13
+ def list_dir(location)
14
+ Braavos.logger.debug("S3 list_dir: #{Braavos.config.bucket_name}/#{location}")
15
+ listing = s3.buckets[Braavos.config.bucket_name].objects.with_prefix("#{location}/").inject({}) do |h,i|
16
+ h[i.key] = 0 if not i.key.end_with?('_$folder$') # disable i.content_length due to performance
17
+ h
18
+ end
19
+ Braavos.logger.debug("\t#{listing}")
20
+ listing
21
+ end
22
+
23
+ def has_success?(location)
24
+ path = File.join(location, "_COMPLETED")
25
+ list_dir(location).size > 0 &&
26
+ s3.buckets[Braavos.config.bucket_name].objects[path].exists?
27
+ end
28
+
29
+ def clear_result(location)
30
+ path = File.join(location, "_FAILED")
31
+ s3.buckets[Braavos.config.bucket_name].objects[path].delete
32
+ end
33
+
34
+ def script_path(location)
35
+ File.join(Braavos.config.bucket_name, location)
36
+ end
37
+
38
+ def write_file(location, contents)
39
+ s3.buckets[Braavos.config.bucket_name].objects[location].write(contents)
40
+ end
41
+ end
@@ -0,0 +1,48 @@
1
+ class Braavos::Storage::StorageBase
2
+
3
+
4
+ def get_cluster
5
+ @cluster ||= JSON.parse(load_file(File.join(Braavos.config.backup_path, 'cluster.json')))
6
+ end
7
+
8
+ def verify_cluster(write_mode)
9
+ cluster = get_cluster
10
+ if write_mode
11
+ if Braavos.config.name != cluster['name']
12
+ raise "Mismatching name (expecting: #{Braavos.config.name}, found: #{cluster['name']})"
13
+ end
14
+ if Braavos.config.environment != cluster['environment']
15
+ raise "Mismatching environment (expecting: #{Braavos.config.environment}, found: #{cluster['environment']})"
16
+ end
17
+ end
18
+ end
19
+
20
+ def find_node_id(force_node_id=nil)
21
+ @node_id = force_node_id if force_node_id
22
+ @node_id ||= -> do
23
+ cluster = get_cluster
24
+ instance_id = Braavos::Service.instance_id
25
+ cluster['nodes'].each do |node_id, node_info|
26
+ if node_info['instance_id'] == instance_id
27
+ return node_id
28
+ end
29
+ end
30
+ raise "Node not found: #{instance_id}"
31
+ end.call
32
+ end
33
+
34
+ # TODO: option for --completed --pending, maybe return size here
35
+ def list_backups(node_id)
36
+ result = {full: [], incr: []}
37
+ listing = list_dir(Braavos.config.backup_path)
38
+ listing.each do |l, z|
39
+ if match = l.match(/\/(full|incr)\/(\w+)\/#{node_id}\/_COMPLETED\Z/)
40
+ path, name = match.captures
41
+ result[path.to_sym] << name
42
+ end
43
+ end
44
+ result
45
+ end
46
+
47
+
48
+ end
@@ -0,0 +1,49 @@
1
+ require 'erb'
2
+
3
+ class Braavos::Template
4
+
5
+ attr_accessor :template_paths
6
+
7
+ def initialize(template_paths)
8
+ @template_paths = template_paths
9
+ end
10
+
11
+ def load_template(template, params={})
12
+ content = find_template(template)
13
+ raise "Unable to find template: #{template} in path: #{template_paths}" unless content
14
+ result_template(content, params)
15
+ end
16
+
17
+ def result_template(template, params)
18
+ ns = Namespace.new(params.merge(config: Braavos.config))
19
+ ERB.new(template).result(ns.get_binding)
20
+ end
21
+
22
+ private
23
+
24
+ # http://stackoverflow.com/questions/1338960/ruby-templates-how-to-pass-variables-into-inlined-erb
25
+ class Namespace
26
+ def initialize(hash)
27
+ hash.each do |key, value|
28
+ singleton_class.send(:define_method, key) { value }
29
+ end
30
+ end
31
+
32
+ def get_binding
33
+ binding
34
+ end
35
+ end
36
+
37
+ def find_template(template)
38
+ content = nil
39
+ template_paths.each do |path|
40
+ file_path = File.join(path, template)
41
+ if File.exists?(file_path)
42
+ content = File.read(file_path)
43
+ break
44
+ end
45
+ end
46
+ content
47
+ end
48
+
49
+ end
@@ -0,0 +1,3 @@
1
+ class Braavos
2
+ VERSION = "0.0.7"
3
+ end
@@ -0,0 +1 @@
1
+ exec nodetool clearsnapshot $1 -t $2
@@ -0,0 +1 @@
1
+ exec nodetool snapshot $1 -t $2
@@ -0,0 +1,4 @@
1
+ KEYSPACE=$1
2
+ OUTPUT_LOC=$2
3
+
4
+ echo "describe keyspace $KEYSPACE" | cqlsh <%= local_host_ip %> > $OUTPUT_LOC/$KEYSPACE.cql
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -e
4
+
5
+ DEST_DIR=$1
6
+ shift
7
+ DATA_DIR=$1
8
+ shift
9
+
10
+ cd ${DATA_DIR} && tar zcf ${DEST_DIR}/system.tgz $*
11
+
12
+ nodetool ring > ${DEST_DIR}/ring.txt
13
+ nodetool info > ${DEST_DIR}/info.txt
14
+ nodetool cfstats > ${DEST_DIR}/cfstats.txt
15
+ nodetool status > ${DEST_DIR}/status.txt
16
+ nodetool compactionstats > ${DEST_DIR}/compactionstats.txt
17
+ nodetool netstats > ${DEST_DIR}/netstats.txt
18
+ nodetool gossipinfo > ${DEST_DIR}/gossipinfo.txt
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -e
4
+
5
+ FILE_LOC=$1
6
+ DEST_LOC=$2
7
+ PROCESS_LOC=${FILE_LOC}
8
+
9
+ <% if config.storage_backing == 's3' %>
10
+
11
+ PROCESS_LOC=<%= config.temp_loc %>/braavos-cassdown-$$.${RANDOM}.tgz
12
+
13
+ function getTimeoutCmd() {
14
+ if hash timeout &> /dev/null
15
+ then
16
+ echo timeout
17
+ else
18
+ echo gtimeout
19
+ fi
20
+ }
21
+
22
+ trap "echo Caught kill for ${FILE_LOC}; rm ${PROCESS_LOC}; exit 1" SIGHUP SIGINT SIGTERM
23
+
24
+ # Install GNU coreutils for `timeout`
25
+ # s3cmd can hang indefinitely due to network constraints
26
+ # So kill after timeout of 2 minutes, an ideal timeout when run on EC2
27
+ $(getTimeoutCmd) 120 s3cmd get s3://${FILE_LOC} ${PROCESS_LOC}
28
+ if [ $? -eq 124 ]; then
29
+ # Timeout occurred, try one more time.
30
+ echo Timed Out! Retrying download of ${FILE_LOC}
31
+ s3cmd get s3://${FILE_LOC} ${PROCESS_LOC}
32
+ fi
33
+
34
+ <% end %>
35
+
36
+ echo Expanding ${FILE_LOC} to ${DEST_LOC}
37
+ mkdir -p ${DEST_LOC}
38
+ zcat -q ${PROCESS_LOC} | tar -xC ${DEST_LOC}
39
+
40
+ <% if config.storage_backing == 's3' %>
41
+
42
+ rm ${PROCESS_LOC}
43
+
44
+ <% end %>
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env bash
2
+
3
+ set -e
4
+
5
+ FILE_LOC=$1
6
+ START_LOC=$(pwd)
7
+ DEST_LOC=$2
8
+ TMP_FILE=<%= config.temp_loc %>/braavos-cassup-$$.${RANDOM}.tgz
9
+
10
+ trap "echo Caught kill for ${FILE_LOC}; rm ${TMP_FILE}; exit 1" SIGHUP SIGINT SIGTERM
11
+
12
+ BASE=$(dirname $FILE_LOC)
13
+ FILE_PART=$(basename $FILE_LOC)
14
+
15
+ echo Processing $FILE_PART in $BASE to ${DEST_LOC}
16
+ cd $BASE && tar zcf $TMP_FILE ${FILE_PART}-*
17
+
18
+ <% if config.storage_backing == 'file' %>
19
+
20
+ mv $TMP_FILE $START_LOC/$DEST_LOC
21
+
22
+ <% elsif config.storage_backing == 's3' %>
23
+
24
+ s3cmd put ${TMP_FILE} s3://${DEST_LOC}
25
+ rm ${TMP_FILE}
26
+
27
+ <% end %>
@@ -0,0 +1,34 @@
1
+ require 'test_helper'
2
+
3
+ class Braavos::CommandTest < MiniTest::Spec
4
+ attr_accessor :command, :file
5
+
6
+ before do
7
+ Braavos.logger.level = Logger::WARN
8
+ @file = Tempfile.new "braavos_command_test"
9
+ @command = Braavos::Command.new
10
+ end
11
+
12
+ after do
13
+ file.close
14
+ file.unlink
15
+ end
16
+
17
+ def test_simple
18
+ command.execute("echo $* >> #{file.path}", ['a', 'b', 'c'])
19
+ result = file.read
20
+ assert_equal "a b c\n", result
21
+ end
22
+
23
+ def test_arguments
24
+ command.execute("echo $1 >> #{file.path}", ['a', 'b', 'c'])
25
+ result = file.read
26
+ assert_equal "a\n", result
27
+ end
28
+
29
+ def test_system
30
+ command.execute("echo $* >> #{file.path}", ['a', 'b', 'c'])
31
+ result = file.read
32
+ assert result
33
+ end
34
+ end
@@ -0,0 +1,66 @@
1
+ require 'test_helper'
2
+
3
+ class Braavos::ConfigTest < MiniTest::Spec
4
+
5
+ def default_config
6
+ {temp_loc: '/tmp'}
7
+ end
8
+
9
+ def test_regular_backup_path
10
+ c = default_config.merge(name: 'neville', environment: 'env', service: 'cassandra')
11
+ config = Braavos::Config.new(c)
12
+
13
+ assert_equal "neville/env/cassandra", config.backup_path
14
+ end
15
+
16
+ def test_prefixed_backup_path
17
+ c = default_config.merge(name: 'neville', environment: 'env', service: 'cassandra', backup_prefix: '/Users/nevillek/backup/')
18
+ config = Braavos::Config.new(c)
19
+
20
+ assert_equal "/Users/nevillek/backup/neville/env/cassandra", config.backup_path
21
+
22
+ c = default_config.merge(name: 'neville', environment: 'env', service: 'cassandra', backup_prefix: 'Users/nevillek/backup')
23
+ config = Braavos::Config.new(c)
24
+
25
+ assert_equal "Users/nevillek/backup/neville/env/cassandra", config.backup_path
26
+
27
+ c = default_config.merge(name: 'neville', environment: 'env', service: 'cassandra', backup_prefix: '')
28
+ config = Braavos::Config.new(c)
29
+
30
+ assert_equal "neville/env/cassandra", config.backup_path
31
+ end
32
+
33
+ def test_service_cassandra
34
+ c = default_config.merge(name: 'neville', environment: 'env', service: 'cassandra')
35
+ config = Braavos::Config.new(c)
36
+
37
+ assert config.service_class == Braavos::Service::Cassandra
38
+ end
39
+
40
+ def test_service_es
41
+ c = default_config.merge(name: 'neville', environment: 'env', service: 'elasticsearch')
42
+ config = Braavos::Config.new(c)
43
+
44
+ assert config.service_class == Braavos::Service::Elasticsearch
45
+ end
46
+
47
+ def test_storage_s3
48
+ c = default_config.merge(name: 'neville', environment: 'env', service: 'cassandra')
49
+ config = Braavos::Config.new(c)
50
+
51
+ assert config.storage_class == Braavos::Storage::S3
52
+
53
+ c = default_config.merge(name: 'neville', environment: 'env', service: 'cassandra', storage_backing: 's3')
54
+ config = Braavos::Config.new(c)
55
+
56
+ assert config.storage_class == Braavos::Storage::S3
57
+ end
58
+
59
+ def test_storage_file
60
+ c = default_config.merge(name: 'neville', environment: 'env', service: 'cassandra', storage_backing: 'file')
61
+ config = Braavos::Config.new(c)
62
+
63
+ assert config.storage_class == Braavos::Storage::File
64
+ end
65
+
66
+ end
@@ -0,0 +1,29 @@
1
+ require 'test_helper'
2
+
3
+ class Braavos::ParallelTest < MiniTest::Spec
4
+ attr_accessor :parallel, :file
5
+
6
+ before do
7
+ Braavos.logger.level = Logger::WARN
8
+ @file = Tempfile.new "braavos_parallel_test"
9
+ @parallel = Braavos::Parallel.new
10
+ end
11
+
12
+ after do
13
+ file.close
14
+ file.unlink
15
+ end
16
+
17
+ def test_simple
18
+ result = parallel.execute("echo $1 >> #{file.path}", ['a', 'b', 'c'])
19
+ result = file.read
20
+ assert_equal ['a', 'b', 'c'], result.lines.map(&:chomp).sort
21
+ end
22
+
23
+ def test_multiple_inputs
24
+ parallel.execute("echo $* >> #{file.path}", [['a', 'apple'], ['b', 'ball'], ['c', 'crawl']])
25
+ result = file.read
26
+ assert_equal ['a apple', 'b ball', 'c crawl'], result.lines.map(&:chomp).sort
27
+ end
28
+
29
+ end
@@ -0,0 +1,36 @@
1
+ require 'test_helper'
2
+
3
+ class Braavos::TemplateTest < MiniTest::Spec
4
+ attr_accessor :template
5
+
6
+ before do
7
+ @template = Braavos::Template.new(['test/template'])
8
+ end
9
+
10
+ def test_result_simple
11
+ result = template.result_template('Hello <%= name %>, Welcome to <%= place %>!', name: 'Neville', place: 'Home')
12
+
13
+ assert_equal 'Hello Neville, Welcome to Home!', result
14
+ end
15
+
16
+ def test_result_missing
17
+
18
+ assert_raises NameError do
19
+ result = template.result_template('Hello <%= name %>, Welcome to <%= place %>!', place: 'Home')
20
+ end
21
+
22
+ end
23
+
24
+ def test_simple_template
25
+ result = template.load_template('simple.txt.erb', name: 'Neville', place: 'Home')
26
+
27
+ assert_equal 'Hello Neville, Welcome to Home!', result
28
+ end
29
+
30
+ def test_nested_dir
31
+ result = template.load_template('nested/inner.sh.erb')
32
+
33
+ assert_equal "#!/bin/bash", result
34
+ end
35
+
36
+ end