require 'json' require 'zip/zip' require 'uri' require File.join(File.dirname(__FILE__),'console','rhoconnect_api') module Rhoconnect module TaskHelper def post(path,params) req = Net::HTTP.new($host,$port) resp = req.post(path, params.to_json, 'Content-Type' => 'application/json') print_resp(resp, resp.is_a?(Net::HTTPSuccess) ? true : false) end def print_resp(resp,success=true) if success puts "=> OK" else puts "=> FAILED" end puts "=> " + resp.body if resp and resp.body and resp.body.length > 0 end def archive(path) File.join(path,File.basename(path))+'.zip' end def ask(msg) print msg STDIN.gets.chomp end def load_settings(file) begin $settings = YAML.load_file(file) rescue Exception => e puts "Error opening settings file #{file}: #{e}." puts e.backtrace.join("\n") raise e end end def rhoconnect_socket "/tmp/rhoconnect.dtach" end def rhoconnect_pid "/tmp/rhoconnect.pid" end def windows? RUBY_PLATFORM =~ /(win|w)32$/ end def ruby19? RUBY_VERSION =~ /1.9/ end def jruby? defined?(JRUBY_VERSION) end def thin? begin require 'thin' 'rackup -s thin' rescue LoadError nil end end def mongrel? begin require 'mongrel' 'rackup -s mongrel' rescue LoadError nil end end def report_missing_server msg =<<-EOF Could not find 'thin' or 'mongrel' on your system. Please install one: gem install thin or gem install mongrel EOF puts msg exit 1 end # def jetty_rackup? # 'jruby -S jetty-rackup' # end def trinidad? 'jruby -S trinidad -p 9292 -r config.ru' end end end namespace :rhoconnect do include Rhoconnect::TaskHelper include RhoconnectApi task :config do $settings = load_settings(File.join('settings','settings.yml')) $env = (ENV['RHO_ENV'] || ENV['RACK_ENV'] || :development).to_sym uri = URI.parse($settings[$env][:syncserver]) $url = "#{uri.scheme}://#{uri.host}" $url = "#{$url}:#{uri.port}" if uri.port && uri.port != 80 $host = uri.host $port = uri.port $appname = $settings[$env][:syncserver].split('/').last $token_file = File.join(ENV['HOME'],'.rhoconnect_token') $token = File.read($token_file) if File.exist?($token_file) end task :dtach_installed do if !windows? and (`which dtach` == '') puts "WARNING: dtach not installed or not on path, some tasks will not work!" puts " Install with '[sudo] rake dtach:install'" exit end end desc "Reset the rhoconnect database (you will need to run rhoconnect:get_token afterwards)" task :reset => :config do confirm = ask " Are you sure? Resetting will remove all data!\n It will also return an error code to all\n existing devices when they connect! (yes/no): " if confirm == 'yes' RhoconnectApi.reset($url,$token) puts "Database reset." else puts "Cancelling." end end desc "Fetches current api token from rhoconnect" task :get_token => :config do password = '' login = ask "admin login: " begin system "stty -echo" password = ask "\nadmin password: " system "stty echo" rescue NoMethodError, Interrupt system "stty echo" exit end puts '' begin $token = RhoconnectApi.get_token($url,login,password) rescue puts "Login failed." exit end File.open($token_file,'w') {|f| f.write $token} puts "Token is saved in: #{$token_file}" end desc "Clean rhoconnect, get token, and create new user" task :clean_start => [:get_token, :reset, :get_token, :create_user] desc "Alias for `rake rhoconnect:stop; rake rhoconnect:start`" task :restart => [:stop, :start] desc "Creates and subscribes user for application in rhoconnect" task :create_user => :config do password = '' login = ask "new user login: " begin system "stty -echo" password = ask "\nnew user password: " system "stty echo" rescue NoMethodError, Interrupt system "stty echo" exit end puts '' RhoconnectApi.create_user($url,$token,login,password) end desc "Deletes a user from rhoconnect" task :delete_user => :config do login = ask "user to delete: " RhoconnectApi.delete_user($url,$token,login) end desc "Deletes a device from rhoconnect" task :delete_device => :config do user_id = ask "device's user_id: " device_id = ask "device to delete: " RhoconnectApi.delete_client($url,$token,user_id,device_id) end desc "Sets the admin password" task :set_admin_password => :get_token do new_pass,new_pass_confirm = '','' begin system "stty -echo" new_pass = ask "\nnew admin password: " new_pass_confirm = ask "\nconfirm new admin password: " system "stty echo" rescue NoMethodError, Interrupt system "stty echo" exit end if new_pass == '' puts "\nNew password can't be empty." elsif new_pass == new_pass_confirm puts "" post("/api/update_user", {:app_name => $appname, :api_token => $token, :attributes => {:new_password => new_pass}}) else puts "\nNew password and confirmation must match." end end desc "Reset source refresh time" task :reset_refresh => :config do user = ask "user: " source_name = ask "source name: " RestClient.post("#{$url}/api/set_refresh_time", {:api_token => $token, :user_name => user, :source_name => source_name}) end begin require 'rspec/core/rake_task' require 'rcov/rcovtask' unless (windows? || ruby19?) desc "Run source adapter specs" task :spec do files = File.join('spec','**','*_spec.rb') RSpec::Core::RakeTask.new('rhoconnect:spec') do |t| t.pattern = FileList[files] t.rspec_opts = %w(-fn -b --color) unless (windows? || ruby19?) t.rcov = true t.rcov_opts = ['--exclude', 'spec/*,gems/*'] end end end rescue LoadError if windows? puts "rspec not available. Install it with: " puts "gem install rspec\n\n" else puts "rspec / rcov not available. Install it with: " puts "gem install rspec rcov\n\n" end end desc "Start rhoconnect server" task :start => :dtach_installed do cmd = (jruby?) ? trinidad? : (thin? || mongrel? || report_missing_server) if windows? puts 'Starting rhoconnect...' system("#{cmd} config.ru") elsif jruby? puts 'Starting rhoconnect in jruby environment...' system("#{cmd}") else puts 'Detach with Ctrl+\ Re-attach with rake rhoconnect:attach' sleep 2 sh "dtach -A #{rhoconnect_socket} #{cmd} config.ru -P #{rhoconnect_pid}" end end desc "run rhoconnect console" task :console, :environment do |t, args| if RedisRunner.running? #load development environment by default ENV['RACK_ENV'] = args[:environment] || 'development' sh "irb -rubygems -r #{File.join(File.dirname(__FILE__),'console')} -r #{File.dirname(__FILE__)} -r application" else puts "Redis is not running. Please start it by running 'rake redis:start' command." end end desc "Stop rhoconnect server" task :stop => :dtach_installed do sh "cat #{rhoconnect_pid} | xargs kill -3" unless windows? end desc "Attach to rhoconnect console" task :attach => :dtach_installed do sh "dtach -a #{rhoconnect_socket}" unless windows? end desc "Launch the web console in a browser - uses :syncserver: in settings.yml" task :web => :config do windows? ? sh("start #{$url}") : sh("open #{$url}") end desc "Flush data store - WARNING: THIS REMOVES ALL DATA IN RHOCONNECT" task :flushdb => :config do puts "*** WARNING: THIS WILL REMOVE ALL DATA FROM YOUR REDIS STORE ***" confirm = ask "Are you sure (please answer yes/no)? " if confirm == 'yes' Redis.new.flushdb puts "Database flushed..." else puts "Aborted..." end end desc "Generate a cryptographically secure secret session key" task :secret do begin require 'securerandom' puts SecureRandom.hex(64) rescue LoadError puts "Missing secure random generator. Try running `rake secret` in a rails application instead." end end desc "Build executable WAR file to be used in Java App Servers" task :war do if jruby? then puts "building the WAR file" if not File::exists? "config/warble.rb" puts "generating Warbler's config file" includeDirs = [] Dir.mkdir('config') if not File.exists?('config') aFile = File.new("config/warble.rb", "w+") if aFile includeDirs = FileList['*'].exclude do |entry| entry if (not File.directory? entry) || (entry == 'spec') end configFile = "Warbler::Config.new do |config|\n" + "config.dirs = %w(#{includeDirs.join(' ')})\n" + "config.includes = FileList[\"./*\"]\n" + "config.excludes = FileList[\"./*.war\",'spec']\nend" aFile.write("#{configFile}") aFile.close else puts "Unable to create config/warble.rb file!" end end # build the executable WAR using the config/warble.rb file ENV['BUNDLE_WITHOUT'] = ['development','test'].join(':') sh 'warble executable war' else puts "Cannot build WAR files outside of JRuby environment!" end end end task :default => ['rhoconnect:spec'] load File.join(File.dirname(__FILE__),'..','..','tasks','redis.rake')