xlogin-apiclient 0.2.0 → 0.2.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 18a35f6ba98b58373950e71f3c3a87683087981acc457099952fe85beb474957
4
- data.tar.gz: 6501f3d09a773b2925e779d5c72a7905e9871a0e002bb99560bea537b8747cdd
3
+ metadata.gz: ba7acd60107439028cb9f8c6a77afd5dfaf6c1cf74c2232b529678b8888b6053
4
+ data.tar.gz: 32b07f46ca25f31ee09cadf2de19c5a0284bd1bb5c0a92b1d9a62b6af8a0b261
5
5
  SHA512:
6
- metadata.gz: 84722296fb0c543e96fe23629845694c76a96dbac5f6d7812b3daf3022374163f4e389110b772931517e43fa895fe3baac23e03dbd8908fadaf020986d72d41e
7
- data.tar.gz: 0ac161f727446451c8981e66e80c4c69be3821eab9cf7ad6998b95738cfba11cde028f9fa75e8d51e08f2fff16b73e5ae9c2327c762918ec7e4f66427530a800
6
+ metadata.gz: 6f985e16fe2d94d2daee92e2d060aab4007deb0cda7d7aa56338f6e0f57c86907e8ec2299860d3cf2495f1f1c92b2ab35f84b6e24ecf08a7a711ac6c6238f8b3
7
+ data.tar.gz: d8bf59fae7037c02f2488c7b2115a84a40349a5909a31b3e6ea6995fc981ec60ffba990e1575c8c206a6c938799fd6555b674eab3513d7a52a336366f134cdaa
data/bin/xloginapi ADDED
@@ -0,0 +1,6 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ require 'xlogin/apiclient'
4
+ require 'xlogin/apiclient/cli'
5
+
6
+ Xlogin::APIClient::CLI.run
@@ -1,16 +1,24 @@
1
1
  require 'json'
2
2
  require 'net/http'
3
+ require 'stringio'
3
4
  require 'addressable/uri'
5
+ require 'em-eventsource'
4
6
  require "xlogin/apiclient/version"
5
7
 
8
+
6
9
  module Xlogin
7
10
  class APIClient
11
+ DEFAULT_TIMEOUT = 60
12
+
8
13
  class Error < StandardError; end
9
14
 
10
15
  class << self
11
16
  attr_accessor :base_url
17
+ attr_accessor :timeout
12
18
  end
13
19
 
20
+ attr_reader :type, :args
21
+
14
22
  def initialize(base_url: self.class.base_url, **args)
15
23
  raise Error.new('base_url not defined') unless base_url
16
24
 
@@ -19,26 +27,50 @@ module Xlogin
19
27
  @args = args
20
28
  end
21
29
 
22
- def cmd(args)
30
+ def cmd(args, &block)
23
31
  params = {driver: @type, target: @args, command: args}
24
- resp = request(**params.transform_keys(&:to_sym))
25
- resp['payload'].join
32
+ request(:cmd, **params.transform_keys(&:to_sym), &block)
26
33
  end
27
34
 
28
35
  private
29
- def request(**params)
36
+ def request(endpoint, **params, &block)
30
37
  uri = @uri.dup
38
+ uri.path = File.join(uri.path, endpoint.to_s)
31
39
  uri.query = "q=#{URI.encode_www_form_component(JSON.generate(params))}"
32
40
 
33
- req = Net::HTTP::Get.new(uri.request_uri)
34
- req["Accept"] = "application/json"
41
+ if block
42
+ resp = StringIO.new
43
+ EM.run do
44
+ source = EventMachine::EventSource.new(uri.to_s)
45
+ source.message do |message|
46
+ data = JSON.parse(message) || {}
47
+ if chunk = data['chunk']
48
+ resp.print data['chunk']
49
+ block.call(data['chunk'])
50
+ end
51
+ end
52
+ source.error do |e|
53
+ EM.stop
54
+ end
55
+ source.start
56
+ end
57
+ return resp.string
58
+ else
59
+ req = Net::HTTP::Get.new(uri.request_uri)
60
+ req["Accept"] = "application/json"
61
+
62
+ http = Net::HTTP.new(uri.host, uri.port)
63
+ http.open_timeout = self.class.timeout || DEFAULT_TIMEOUT
64
+ http.read_timeout = self.class.timeout || DEFAULT_TIMEOUT
65
+
66
+ resp = http.request(req)
67
+ raise Error.new(resp.message) unless resp.code =~ /^2[0-9]{2}$/
35
68
 
36
- http = Net::HTTP.new(uri.host, uri.port)
37
- body = http.request(req).body
38
- resp = body ? JSON.parse(body) : {}
39
- return resp if resp['success']
69
+ data = resp.body ? JSON.parse(resp.body) : {}
70
+ raise Error.new(data['error']) unless data['success']
40
71
 
41
- raise Error.new(resp['error'])
72
+ return data['payload'].join
73
+ end
42
74
  end
43
75
  end
44
76
  end
@@ -0,0 +1,75 @@
1
+ require 'optparse'
2
+ require 'singleton'
3
+ require 'xlogin/apiclient'
4
+
5
+
6
+ XLOGIN_API_URL = ENV.fetch('XLOGIN_API_URL', 'http://127.0.0.1:8080')
7
+
8
+ module Xlogin
9
+ class APIClient
10
+
11
+ class Factory
12
+ include Singleton
13
+
14
+ def initialize
15
+ @inventory = Hash.new
16
+ end
17
+
18
+ def set_hostinfo(name, **opts)
19
+ @inventory[name] = (get_hostinfo(name) || {name: name}).merge(opts)
20
+ end
21
+
22
+ def get_hostinfo(name)
23
+ @inventory[name]
24
+ end
25
+
26
+ def method_missing(method_name, *args, **opts, &block)
27
+ super unless args.size == 2 && Addressable::URI::URIREGEX =~ args[1]
28
+
29
+ name = args[0]
30
+ uri = args[1]
31
+ type = method_name.to_s.downcase
32
+ set_hostinfo(name.to_s, type: type, uri: uri, **opts)
33
+ end
34
+ end
35
+
36
+ class CLI
37
+
38
+ def self.run(args = ARGV)
39
+ Xlogin::APIClient::CLI.new.run(args)
40
+ end
41
+
42
+ def run(args)
43
+ config = {api: XLOGIN_API_URL}
44
+ parser = OptionParser.new
45
+ parser.banner = "#{File.basename($0)} HOST [Options]"
46
+ parser.version = Xlogin::APIClient::VERSION
47
+
48
+ parser.on('-a API', '--api', String, 'The Xlogin API URL.') { |v| config[:api] = v }
49
+ parser.on('-t TYPE', '--type', String, 'The TYPE of the device.') { |v| config[:type] = v }
50
+ parser.on('-i PATH', '--inventory', String, 'The PATH to the inventory file..') { |v| config[:inventory] = v }
51
+ parser.on('-e COMMAND', '--exec', String, 'Execute commands and quit.') { |v| config[:exec] = v }
52
+
53
+ args = parser.parse!(args)
54
+ host = args.shift
55
+ hostinfo = if config[:inventory]
56
+ factory = Factory.instance
57
+ factory.instance_eval(IO.read(config[:inventory]))
58
+ factory.get_hostinfo(host) || {}
59
+ else
60
+ {type: config[:type], uri: host}
61
+ end
62
+
63
+ raise "Argument error - type='#{hostinfo[:type]}' uri='#{hostinfo[:uri]}'" unless hostinfo[:type] && hostinfo[:uri]
64
+
65
+ APIClient.base_url = config[:api]
66
+ client = APIClient.new(**hostinfo)
67
+ client.cmd(config[:exec]) { |c| $stdout.print c }
68
+ rescue => e
69
+ $stderr.puts e, '', parser
70
+ end
71
+
72
+ end
73
+ end
74
+ end
75
+
@@ -1,5 +1,5 @@
1
1
  module Xlogin
2
- module Apiclient
3
- VERSION = "0.2.0"
2
+ class APIClient
3
+ VERSION = "0.2.6"
4
4
  end
5
5
  end
@@ -5,7 +5,7 @@ require "xlogin/apiclient/version"
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "xlogin-apiclient"
8
- spec.version = Xlogin::Apiclient::VERSION
8
+ spec.version = Xlogin::APIClient::VERSION
9
9
  spec.authors = ["haccht"]
10
10
  spec.email = ["haccht@users.noreply.github.com"]
11
11
 
@@ -27,4 +27,5 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency "rake", "~> 10.0"
28
28
 
29
29
  spec.add_dependency 'addressable'
30
+ spec.add_dependency 'em-eventsource'
30
31
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xlogin-apiclient
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - haccht
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-26 00:00:00.000000000 Z
11
+ date: 2021-02-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: em-eventsource
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  description: API client for xlogin-api.
56
70
  email:
57
71
  - haccht@users.noreply.github.com
@@ -67,7 +81,9 @@ files:
67
81
  - Rakefile
68
82
  - bin/console
69
83
  - bin/setup
84
+ - bin/xloginapi
70
85
  - lib/xlogin/apiclient.rb
86
+ - lib/xlogin/apiclient/cli.rb
71
87
  - lib/xlogin/apiclient/version.rb
72
88
  - xlogin-apiclient.gemspec
73
89
  homepage: https://github.com/haccht/xlogin-apiclient.