flydata 0.0.1.nc1

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,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