flydata 0.0.1.nc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,35 @@
1
+ module Flydata
2
+ module Command
3
+ class Base
4
+ def initialize
5
+ @api_client = ApiClient.instance
6
+ end
7
+ def flydata; @api_client end
8
+
9
+ # retrieve models on servers
10
+ def retrieve_data_entries
11
+ data_entries = flydata.get('/data_entries')
12
+ unless flydata.response.code == 200
13
+ raise "Failed to retrieve data_entries"
14
+ end
15
+ data_entries
16
+ end
17
+
18
+ # print console
19
+ def newline; puts end
20
+ def ask_yes_no(message)
21
+ loop do
22
+ ans = ask("#{message} (yes/no): ")
23
+ if ans.size > 0
24
+ case ans[0].downcase
25
+ when 'y'; return true
26
+ when 'n'; return false
27
+ end
28
+ end
29
+ say(" ! Please answer y[es] or n[o]")
30
+ newline
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,9 @@
1
+ module Flydata
2
+ module Command
3
+ class Crontab < Base
4
+ def run(args='')
5
+ Flydata::Cron.new.update args
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,39 @@
1
+ module Flydata
2
+ module Command
3
+ class Login < Base
4
+ LOGIN_TRIAL_TIMES=3
5
+ def run
6
+ ret = login(LOGIN_TRIAL_TIMES)
7
+ raise "Login failed #{LOGIN_TRIAL_TIMES} times." unless ret
8
+ ret
9
+ end
10
+
11
+ private
12
+ def login(times=3)
13
+ 1.upto(times) do |i|
14
+ begin
15
+ return true if login_once
16
+ rescue Exception => e
17
+ puts e
18
+ end
19
+ end
20
+ false
21
+ end
22
+ def login_once
23
+ # Ask login info
24
+ email = ask("FlyData Email: ")
25
+ password = ask("FlyData password: ") {|q| q.echo = false}
26
+ flydata.credentials = Flydata::Credentials.new(email, password)
27
+ # Auth request
28
+ flydata.post('/users/sign_in')
29
+ if flydata.response.code == 201 # 201: Created
30
+ say("Login succeeded!")
31
+ flydata.credentials.authenticate!
32
+ return true
33
+ end
34
+ say("Login failed!")
35
+ false
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,10 @@
1
+ module Flydata
2
+ module Command
3
+ class Restart < Base
4
+ def run
5
+ sender = Flydata::Command::Sender.new
6
+ sender.restart
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,29 @@
1
+ module Flydata
2
+ module Command
3
+ class Routine < Base
4
+ def run
5
+ print "#{Time.now} "
6
+ unless flydata.credentials.authenticated?
7
+ raise "Authentication error. Please login."
8
+ end
9
+ log_paths = retrieve_log_paths
10
+ log_paths and log_paths.size() > 0 and log_paths.each { |path|
11
+ if File.exist?(path) and File.writable?(path)
12
+ puts "Start - #{path}. "
13
+ Flydata::LogMonitor.new(path).setup.rotate
14
+ else
15
+ puts "Skip - #{path}. System cannot access this path."
16
+ end
17
+ }
18
+ end
19
+
20
+ private
21
+ def retrieve_log_paths
22
+ data_entries = retrieve_data_entries
23
+ data_entries.map {|e|
24
+ e['log_path'] if e['log_deletion']
25
+ }.compact
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,92 @@
1
+ module Flydata
2
+ module Command
3
+ class Sender < Base
4
+ FLYDATA_HOME=Flydata::HOME_DIR
5
+ def start
6
+ if process_exist?
7
+ say("Process exist. Please stop process first.")
8
+ return
9
+ end
10
+
11
+ retry_count = 10
12
+ 1.upto(retry_count) do |i|
13
+ break if server_ready?
14
+ say("Waiting server side active... (#{i}/#{retry_count})")
15
+ sleep 30
16
+ end
17
+
18
+ say('Starting sender process.')
19
+ Dir.chdir(FLYDATA_HOME){
20
+ system("fluentd -d #{FLYDATA_HOME}/flydata.pid -l #{FLYDATA_HOME}/flydata.log -c #{FLYDATA_HOME}/flydata.conf")
21
+ }
22
+
23
+ sleep 5
24
+
25
+ data_port = flydata.data_port.get
26
+ data_port_id = data_port['id']
27
+
28
+ retry_count = 10
29
+ ready = false
30
+ 1.upto(retry_count) do |i|
31
+ ready ||= client_ready?
32
+ if ready and uploaded_successfully?(data_port_id)
33
+ say('Done.')
34
+ say("Go to your Dashboard! http://#{Flydata::FLYDATA_API_HOST}")
35
+ return true
36
+ end
37
+ say("Waiting client side active... (#{i}/#{retry_count})")
38
+ sleep 30
39
+ end
40
+
41
+ say('Something wrong..')
42
+ false
43
+ end
44
+ def stop
45
+ unless process_exist?
46
+ say("Process doesn't exist.")
47
+ return true
48
+ end
49
+
50
+ say('Stopping sender process.')
51
+ if system("kill `cat #{FLYDATA_HOME}/flydata.pid`")
52
+ say('Done.')
53
+ return true
54
+ else
55
+ say('Something wrong..')
56
+ end
57
+ false
58
+ end
59
+ def restart
60
+ if process_exist?
61
+ say('Restarting sender process.')
62
+ if system("kill -HUP `cat #{FLYDATA_HOME}/flydata.pid`")
63
+ say('Done.')
64
+ return true
65
+ else
66
+ say('Something wrong..')
67
+ end
68
+ else
69
+ say("Process doesn't exist.")
70
+ start
71
+ end
72
+ end
73
+
74
+ private
75
+ def server_ready?
76
+ data_port = flydata.data_port.get
77
+ data_port['server_status'] == 'active'
78
+ end
79
+ def client_ready?
80
+ process_exist?
81
+ end
82
+ def process_exist?
83
+ process_count = `ps aux|grep -v grep|grep "\\.flydata/flydata\\.conf"|grep fluentd|wc -l`.to_i
84
+ process_count > 0
85
+ end
86
+ def uploaded_successfully?(data_port_id)
87
+ res = flydata.get("/data_ports/#{data_port_id}/tail.json")
88
+ res and res['logs'] and res['logs'].size > 0
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,73 @@
1
+ module Flydata
2
+ module Command
3
+ class Setlogdel < Base
4
+ def run
5
+ Flydata::Command::Login.new.run unless flydata.credentials.authenticated?
6
+ # Choose target data_entry
7
+ data_entry = choose_data_entry
8
+ return unless data_entry
9
+ # Confirm and update
10
+ if confirm_setting data_entry
11
+ set_log_deletion data_entry
12
+ end
13
+ end
14
+
15
+ private
16
+ def choose_data_entry
17
+ data_entries = retrieve_data_entries
18
+ if data_entries.size < 1
19
+ puts("There are no registered entries.")
20
+ puts("You need to create a data entry by flydata setup command.")
21
+ return nil
22
+ end
23
+ choices = data_entries.map {|e|
24
+ "#{e['name']}\t#{e['log_path']}\t -- Log deletion:#{boolToOnOff e['log_deletion']}"
25
+ }
26
+ choices << "Cancel"
27
+
28
+ choice = nil
29
+ say('Please select your log path for setting log deletion.')
30
+ newline
31
+ choose do |menu|
32
+ menu.index = :letter
33
+ menu.index_suffix = ") "
34
+ menu.prompt = "Select item to change log deletion setting: "
35
+ menu.choices(*choices) {|item| choice = item.split(' ')[0]}
36
+ end
37
+ newline
38
+ data_entries.select{|e| e['log_path'] == choice}.first
39
+ end
40
+ def confirm_setting(data_entry)
41
+ cur_flag = data_entry['log_deletion']
42
+ loop do
43
+ say "Target log path: #{data_entry['log_path']}"
44
+ say "Now changing log deletion setting: #{boolToOnOff cur_flag} -> #{boolToOnOff !cur_flag}"
45
+ ans = ask "Are you sure? (yes/no): "
46
+ if ans.size > 0
47
+ case ans[0].downcase
48
+ when 'y'; return true
49
+ when 'n'; return false
50
+ end
51
+ end
52
+ say " ! Please answer y[es] or n[o]"
53
+ newline
54
+ end
55
+ end
56
+ def boolToOnOff(bool)
57
+ bool ? 'ON' : 'OFF'
58
+ end
59
+ def set_log_deletion(data_entry)
60
+ param = {
61
+ :data_entry => {
62
+ 'log_deletion' => !data_entry['log_deletion']
63
+ }
64
+ }
65
+ url = "/data_entries/#{data_entry['id']}"
66
+ ret = flydata.put(url, param)
67
+ raise 'Failed to update the log deletion setting.' unless ret['success']
68
+ Flydata::Command::Crontab.new.run if !data_entry['log_deletion']
69
+ puts "Update succeeded!"
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,101 @@
1
+ module Flydata
2
+ module Command
3
+ class Setup < Base
4
+ LOG_PATH_EXAMPLES=
5
+ %w(/var/log/httpd/access_log /var/log/apache2/access.log
6
+ /var/log/httpd-access.log /var/log/apache2/access_log
7
+ /var/log/messages /var/log/maillog /var/log/mysql/error.log
8
+ /home/*/deploy/shared/log/*.log)
9
+ OTHER = '-- None of above --'
10
+
11
+ # readline settings for asking log path
12
+ Readline.completion_append_character = "/"
13
+ Readline.completion_proc = Proc.new do |str|
14
+ Dir[str+'*'].grep( /^#{Regexp.escape(str)}/ )
15
+ end
16
+
17
+ def run
18
+ # login
19
+ Flydata::Command::Login.new.run unless flydata.credentials.authenticated?
20
+
21
+ # choose entries
22
+ unless shown = show_registered_entries and not more_entry?
23
+ begin
24
+ show_registered_entries unless shown
25
+ shown = false
26
+ path = choose_log_path_from_examples
27
+ case path
28
+ when OTHER; ask_log_path
29
+ else; create_log_entry(path, ask_log_deletion)
30
+ end
31
+ newline
32
+ end while more_entry?
33
+ end
34
+
35
+ # start client process
36
+ Flydata::Command::Sender.new.restart
37
+ end
38
+
39
+ private
40
+ def show_registered_entries
41
+ data_entries = retrieve_data_entries
42
+ @last_fetched_entries = data_entries
43
+ if data_entries and data_entries.size > 0
44
+ puts('Registered entries. ')
45
+ data_entries.each { |data_entry|
46
+ say(" - #{data_entry['name']}\t#{data_entry['log_path']}")
47
+ }
48
+ true
49
+ else
50
+ false
51
+ end
52
+ end
53
+ def choose_log_path_from_examples
54
+ candidates = (`ls #{LOG_PATH_EXAMPLES.join(' ')} 2>/dev/null`).split(/\s+/)
55
+ candidates = candidates.find_all{|path| File.readable?(path)}
56
+ if @last_fetched_entries
57
+ candidates = candidates - @last_fetched_entries.map{|v| v['log_path']}
58
+ end
59
+ return OTHER unless candidates.size > 0
60
+ candidates << OTHER
61
+ choice = nil
62
+ say('Please select your log path for sending FlyData')
63
+ newline
64
+ choose do |menu|
65
+ menu.index = :letter
66
+ menu.index_suffix = ") "
67
+ menu.prompt = "Your log path: "
68
+ menu.choices(*candidates) {|item| choice = item}
69
+ end
70
+ newline
71
+ choice
72
+ end
73
+ def ask_log_path
74
+ path = nil
75
+ loop do
76
+ path = Readline.readline("Enter the absolute path of your log (return to cancel): ")
77
+ return if path.empty?
78
+ break if FileTest.file?(path) and FileTest.readable?(path)
79
+ say(" ! #{path} is not a readable file!")
80
+ newline
81
+ end
82
+ create_log_entry(path, ask_log_deletion)
83
+ end
84
+ def ask_log_deletion
85
+ say("** Log deletion setting **")
86
+ say("Flydata has a log deletion feature that flydata will delete old log archives uploaded by flydata automatically.")
87
+ say("Flydata will delete logs whose last modified timestamp is 7 days ago.")
88
+ ask_yes_no("Set auto log deletion mode?")
89
+ end
90
+ def create_log_entry(path, log_deletion)
91
+ data_port = flydata.data_port.get
92
+ flydata.data_entry.create(data_port_id: data_port['id'], log_path: path, log_deletion: log_deletion)
93
+ Flydata::Command::Crontab.new.run if log_deletion
94
+ say("Process successfuly!") if flydata.response.code == 200
95
+ end
96
+ def more_entry?
97
+ ask_yes_no("Do you want to add more log path?")
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,10 @@
1
+ module Flydata
2
+ module Command
3
+ class Start < Base
4
+ def run
5
+ sender = Flydata::Command::Sender.new
6
+ sender.start
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ module Flydata
2
+ module Command
3
+ class Stop < Base
4
+ def run
5
+ sender = Flydata::Command::Sender.new
6
+ sender.stop
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,52 @@
1
+ module Flydata
2
+ class Credentials
3
+ include Helpers
4
+ attr_reader :user, :password
5
+ def initialize(user=nil, password=nil)
6
+ read_credentials
7
+ if user && password
8
+ @user = user
9
+ @password = password
10
+ elsif !(@authenticated)
11
+ @user = ENV['FLYDATA_LOGIN']
12
+ @password = ENV['FLYDATA_PASSWORD']
13
+ end
14
+ end
15
+ def authenticate!
16
+ @authenticated = true
17
+ write_credentials
18
+ end
19
+ def authenticated?
20
+ @authenticated
21
+ end
22
+ def write_credentials
23
+ dir = File.dirname(credentials_file)
24
+ FileUtils.mkdir_p(dir)
25
+ File.delete(credentials_file) if FileTest.exists?(credentials_file)
26
+ File.open(credentials_file, 'w', 0400) do |out|
27
+ out.puts @user
28
+ out.puts encode(@password)
29
+ end
30
+ FileUtils.chmod(0700, dir)
31
+ end
32
+ def read_credentials
33
+ if FileTest.exist?(credentials_file)
34
+ File.open(credentials_file, 'r') do |f|
35
+ @user = f.gets.chomp
36
+ @password = decode(f.gets.chomp)
37
+ @authenticated = true if @user and @password
38
+ end
39
+ end
40
+ end
41
+ private
42
+ def credentials_file
43
+ File.join(home_directory, '.flydata', 'credentials')
44
+ end
45
+ def encode(str)
46
+ str.unpack('H*') # want to change more complecated? still useful for shoulder hacking.
47
+ end
48
+ def decode(str)
49
+ [str].pack('H*')
50
+ end
51
+ end
52
+ end