puppet-filebucket-util/bucket-tool

308 lines
6.7 KiB
Ruby

#!/usr/bin/ruby
# BEGIN: Helper Functions
def usage
puts "#{__FILE__} [ACTION <arg>] [<flags>]
Description:
This utlity is meant to be used to interact with & manage the filebucket on P4 nodes due to the
utility for that `puppet filebucket -l <action>` being nonfunctional.
This implements the same functionality (minus the puppet tie-in) and will allow the user to
search the filebucket and restore from it.
Actions:
search <term> : Search for bucket entries matching a portion of the filepath
list : List all Bucket entries
list-files : List all files/paths that have been backed up to the bucket
get <entry-hash> : Get the content of a specific entry (by hash)
Global Flags:
-d | --debug : Set debug flag
-h | --help : This help message
Author:
Name: Tristan Ancelet
Email: tristan.ancelet@acumera.com
Phone (Work) #: +1 (337) 965-1855
"
end
def log (message, level = 0)
if $DEBUG == true or $CONFIG[:log_file] != ""
if message == ""
puts "log was called without providing a message"
exit
end
case level
when 0
level="INFO"
when 1
level="WARN"
when 2
level="CRIT"
else
level="UNDF"
end
datestamp=Time.now
log_message="#{datestamp} : #{$HOSTNAME} : #{level} : #{caller[0]} : #{message}"
if $CONFIG[:log_file] != ""
File.open($CONFIG[:log_file],'a') do |file|
file.write("#{log_message}\n")
end
else
puts log_message
end
end
end
# END: Helper Functions
# BEGIN: Variables
if not (ARGV & ['-h', '--help']).empty?
usage
exit
end
if ENV["USER"] != 'root'
puts "This script should only be run by root (permissions issues). Please rerun it as root or prepend \"sudo\""
exit
end
$DEBUG=false
$CONFIG = Hash.new
$CONFIG[:bucket_dir]=` sudo puppet agent --configprint clientbucketdir `.strip()
$CONFIG[:action]=""
$CONFIG[:search_term]=""
$CONFIG[:log_file]=""
File.open('/etc/hostname') do |file|
$HOSTNAME=file.read().strip()
end
FLAG_REGEX=/\-+\S+/
# END: Variables
# BEGIN: Handle CLI Args
if ARGV.count == 0
puts "No arguments were provided"
usage
exit
end
if not (ARGV & ['-d', '--debug']).empty?
$DEBUG=true
end
i=0
case ARGV[i]
when 'search'
$CONFIG[:action]='search'
log "$CONFIG[:action] was set to #{ARGV[i]}"
log "user provided search action ARGV[i.next] == #{ARGV[i.next]}"
if ARGV[i.next] != "" and not ARGV[i.next] =~ FLAG_REGEX
$CONFIG[:search_term]=ARGV[i.next]
log "search_term was set to #{ARGV[i.next]}"
i+=2
else
puts "Flag[#{ARGV[i]}] : Argument[#{ARGV[i.next]}] : Either the argument was not provided or it was a flag"
usage
exit
end
when 'get'
$CONFIG[:action] = 'get'
log "$CONFIG[:action] was set to #{ARGV[i]}"
log "user provided get action ARGV[i.next] == #{ARGV[i.next]}"
if ARGV[i.next] != "" and not ARGV[i.next] =~ FLAG_REGEX
$CONFIG[:search_term]=ARGV[i.next]
log "search_term was set to #{ARGV[i.next]}"
i+=2
else
puts "Flag[#{ARGV[i]}] : Argument[#{ARGV[i.next]}] : Either the argument was not provided or it was a flag"
usage
exit
end
when 'list'
$CONFIG[:action] = 'list'
log "$CONFIG[:action] was set to #{ARGV[i]}"
i+=1
when 'list-files'
$CONFIG[:action] = 'list-files'
log "$CONFIG[:action] was set to #{ARGV[i]}"
i+=1
else
puts "#{ARGV[i]} is not a valid action. Please make sure you use a valid action as the first argument of the script"
usage
exit
end
## BEGIN: Checks
if $CONFIG[:action] == ""
puts "Action was not provided"
end
case $CONFIG[:action]
when 'search', 'get'
if $CONFIG[:search_term] == ""
puts "Search Term was not provided"
usage
exit
end
end
## END: Checks
# END: Handle CLI Args
# BEGIN: Classes
class BucketEntry
attr_reader :hash, :filepaths, :mtime
def initialize (entry_dir)
@entry_dir = entry_dir
@hash = File.basename(entry_dir)
@filepaths = Array.new
File.open("#{entry_dir}/paths") do |file|
file.read().split(/\n/).each do |path|
log "BucketEntry[#{@hash}] adding #{path} to @filepaths"
@filepaths.push(path)
end
end
@mtime = File.mtime(entry_dir)
log "BucketEntry was created from #{entry_dir}"
end
def path_include? (path_string)
log "BucketEntry[#{hash}] was called with #{path_string}"
@filepaths.each.any? {|path| path.include? path_string}
end
def infostring
"Entry [#{@hash}]:
Paths: #{@filepaths.join(',')}
MTIME: #{@mtime}
"
end
def inline_info
"#{@mtime} : #{@hash} : #{@filepaths.join(',')}"
end
def content
log "BucketEntry[#{@hash}] getting contents"
File.open("#{@entry_dir}/contents",'r') do |file|
file.read()
end
end
end
class Bucket
attr_reader :bucketdir, :entries
def initialize (clientbucketdir)
log "Bucket is being created from #{clientbucketdir}"
@bucketdir = clientbucketdir
@entries = Hash.new
load_bucket
end
def load_bucket
log "Bucket[#{@bucketdir}] is loading entries"
Dir["#{@bucketdir}/**/paths"].each.map{|path| File.dirname(path)}.each do |directory|
log "\"#{directory}\" was grabbed from bucket directory. Making new BucketEntry"
entry = BucketEntry.new(directory)
@entries[entry.hash]=entry
log "BucketEntry[#{entry.hash}] was added to @entries Size=#{@entries.count()}"
end
log "Bucket[#{@bucketdir}] was loaded"
end
end
# END: Classes
# BEGIN: Work Functions
def search_entries_paths (bucket)
log "user entered"
bucket.entries.each_value do |entry|
log "checking Entry[#{entry.hash}]"
if entry.path_include? $CONFIG[:search_term]
puts entry.inline_info
end
end
end
def get_content_of_entry_hash (bucket)
log "user entered"
if bucket.entries.has_key? $CONFIG[:search_term]
puts bucket.entries[$CONFIG[:search_term]].content
else
puts "There were no entries corresponding to #{$CONFIG[:search_term]}"
exit
end
end
def list_all_entries (bucket)
puts bucket.entries.each_value.each.map{|entry| entry.inline_info}.sort.join("\n")
end
def list_entry_files (bucket)
filenames = Array.new
bucket.entries.each_value do |entry|
entry.filepaths.each do |path|
if not filenames.include? path
filenames.push(path)
end
end
end
puts filenames.sort.join("\n")
end
# END: Work Functions
# BEGIN: Work
if __FILE__ == $0
bucket = Bucket.new($CONFIG[:bucket_dir])
case $CONFIG[:action]
when 'search'
search_entries_paths bucket
when 'get'
get_content_of_entry_hash bucket
when 'list'
list_all_entries bucket
when 'list-files'
list_entry_files bucket
end
end
# END: Work