require 'rubygems' require 'rest_client' require 'zip' require 'zip/zipfilesystem' require 'zip/zip' require 'open-uri' module Factor module Client class Client attr_accessor :host def initialize(host="http://localhost:3000") #def initialize(host="http://factor.io") @host=host end def register(email,password) end def login(email, password) end def login_token(token) @token=token end def load_workflows(engine,&code) code.call("downloading workflow list") workflows = rest_get("workflows") code.call("downloaded #{workflows.size} workflows") workflows.each do |workflow_info| code.call("parsing '#{workflow_info['name']}'") workflow_definition = JSON.parse(workflow_info['definition']) code.call("loading '#{workflow_info['name']}' into runtime") workflow=Factor::Runtime::Workflow.new(workflow_definition) engine.load_workflow(workflow) code.call("loading complete for '#{workflow_info['name']}'") end engine end def load_credentials(engine,&code) code.call("downloading credential list") credentials = rest_get("credentials") code.call("loading credentials") engine.load_credentials(credentials) engine end def load_channels(engine,&code) # get list of channels code.call("downloading channels list") channels = rest_get("channels") #load each channel channels.each do |channel| code.call("downloading '#{channel['zip_url']}'") # URI of the zip file containing the module uri = URI.parse(channel['zip_url']) # temp file to store the zip for download temp_file = Tempfile.new([uri.to_s.gsub(/\W+/,'-'), '.zip'], :encoding => 'ascii-8bit') # temp directory where zip will be decompressed unzip_dir=temp_file.path[0..-5] # download open(uri.to_s,"rb") do |bin| temp_file.print bin.read end temp_file.close code.call("unzipping '#{channel['name']}'") # unzip download zip into unzipped directory unzip(temp_file.path,unzip_dir) code.call("loading '#{channel['zip_url']}' into engine") Dir.glob("#{unzip_dir}/**/*.rb").each do |file| engine.load_channel(file) end end engine end def set_credential(key,value) # this is a PUT not POST because it is technically editing, not creating a new one rest_put("credentials",{:key=>key,:value=>value}) end def get_credential(key="") rest_get("credentials",{:key=>key}) end def remove_credential(key="") rest_delete("credentials",{:key=>key}) end # workflows def add_workflow(key,definition) rest_post("workflows",{:name=>key,:definition=>definition}) end def get_workflows() rest_get("workflows") end def remove_workflow(name="") rest_delete("workflows",{:name=>name}) end # channels def add_channel(key,path) file=zip(path) rest_post("channels",{:name=>key,:zip=>file}) end def get_channels() rest_get("channels") end def remove_channel(name="") rest_delete("channels",{:name=>name}) end private def fix_github_zip_archive(file) Zip::ZipFile.open(file.path) do |zip| basedir = zip.entries.first.name zip.remove zip.entries.first zip.each do |entry| target = entry.name.sub(/^#{basedir}/,'') if entry.directory? zip.dir.mkdir(target) else zip.file.open(entry.name) do |istream| zip.file.open(target, 'w') do |ostream| ostream.write istream.read end end end zip.remove entry end end end def unzip(zip, unzip_dir, remove_after = false) Zip::ZipFile.open(zip) do |zip_file| zip_file.each do |f| f_path=File.join(unzip_dir, f.name) FileUtils.mkdir_p(File.dirname(f_path)) zip_file.extract(f, f_path) unless File.exist?(f_path) end end FileUtils.rm(zip) if remove_after end def zip(directory) path=directory.dup path.sub!(%r[/$],'') zip_path = File.join(path,File.basename(path))+'.zip' FileUtils.rm zip_path, :force=>true Zip::ZipFile.open(zip_path, 'w') do |zip| Dir["#{path}/**/**"].reject{|f|f==zip_path}.each do |file| zip.add(file.sub(path+'/',''),file) end end File.open(zip_path,'r') end def rest_get(path,params={}) params["auth_token"]=@token param_string=params.map{|key,value| "#{key}=#{value}"}.join("&") JSON.parse(RestClient.get("#{@host}/#{path}.json?#{param_string}")) end def rest_put(path,params={}) params["auth_token"]=@token JSON.parse(RestClient.put("#{@host}/#{path}.json",params)) end def rest_post(path,params={}) #params["auth_token"]=@token JSON.parse(RestClient.post("#{@host}/#{path}.json?auth_token=#{@token}",params)) end def rest_delete(path,params={}) params["auth_token"]=@token param_string=params.map{|key,value| "#{key}=#{value}"}.join("&") JSON.parse(RestClient.delete("#{@host}/#{path}.json?#{param_string}")) end end end end