xway 0.0.1.alpha → 0.0.1.beta
Sign up to get free protection for your applications and to get access to all the features.
- data/.coveralls.yml +1 -0
- data/.travis.yml +3 -0
- data/README.md +16 -0
- data/Rakefile +6 -1
- data/bin/xway +1 -1
- data/lib/xway.rb +8 -2
- data/lib/xway/api.rb +25 -0
- data/lib/xway/api/endpoints.rb +45 -0
- data/lib/xway/api/http.rb +17 -0
- data/lib/xway/api/request.rb +37 -0
- data/lib/xway/api/request/body.rb +41 -0
- data/lib/xway/cli.rb +19 -0
- data/lib/xway/error.rb +7 -0
- data/lib/xway/parameter.rb +68 -0
- data/lib/xway/version.rb +1 -1
- data/spec/assets/appway-example.json +21 -0
- data/spec/assets/custom.xway +1 -0
- data/spec/integration/bin/xway_binary_spec.rb +18 -0
- data/spec/integration/lib/xway/cli_spec.rb +9 -0
- data/spec/lib/xway/api/endpoints_spec.rb +89 -0
- data/spec/lib/xway/api/http_spec.rb +35 -0
- data/spec/lib/xway/api/request/body_spec.rb +42 -0
- data/spec/lib/xway/api/request_spec.rb +22 -0
- data/spec/lib/xway/api_spec.rb +90 -0
- data/spec/lib/xway/cli_spec.rb +34 -0
- data/spec/lib/xway/error_spec.rb +6 -0
- data/spec/lib/xway/parameter_spec.rb +122 -0
- data/spec/lib/xway_spec.rb +6 -0
- data/spec/spec_helper.rb +11 -0
- data/xway.gemspec +7 -2
- metadata +104 -6
- data/spec/bin/xway_spec.rb +0 -10
data/.coveralls.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
service_name: travis-ci
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
|
3
3
|
[appway](http://github.com/threez/appway) client written in ruby
|
4
4
|
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/xway.png)](https://rubygems.org/gems/xway)
|
6
|
+
[![Travis-CI Build Status](https://secure.travis-ci.org/dpree/xway.png)](https://travis-ci.org/dpree/xway)
|
7
|
+
[![Coverage Status](https://coveralls.io/repos/dpree/xway/badge.png)](https://coveralls.io/r/dpree/xway)
|
8
|
+
[![Dependency Status](https://gemnasium.com/dpree/xway.png)](https://gemnasium.com/dpree/xway)
|
9
|
+
[![Code Climate](https://codeclimate.com/github/dpree/xway.png)](https://codeclimate.com/github/dpree/xway)
|
10
|
+
|
5
11
|
## Installation
|
6
12
|
|
7
13
|
Add this line to your application's Gemfile:
|
@@ -28,6 +34,16 @@ Or install it yourself as:
|
|
28
34
|
4. Push to the branch (`git push origin my-new-feature`)
|
29
35
|
5. Create new Pull Request
|
30
36
|
|
37
|
+
### Coding guide
|
38
|
+
|
39
|
+
* Using global methods like `Xway.parameter`
|
40
|
+
* is allowed for classes / modules defined on the same or a higher level to the `Xway` namespace
|
41
|
+
* is allowed for classes / modules defined excactly one level below the `Xway` namespace
|
42
|
+
* e.g. `Xway::Api`
|
43
|
+
* is not allowed for classes / modules defined more than one level below the `Xway` namespace
|
44
|
+
* e.g. `Xway::Api::Request`
|
45
|
+
* these classes should use dependency injection instead
|
46
|
+
|
31
47
|
# License
|
32
48
|
|
33
49
|
Copyright (c) 2013 Jens Bissinger. See [LICENSE.txt](LICENSE.txt)
|
data/Rakefile
CHANGED
data/bin/xway
CHANGED
data/lib/xway.rb
CHANGED
@@ -1,5 +1,11 @@
|
|
1
|
-
require
|
1
|
+
require 'xway/version'
|
2
|
+
require 'xway/error'
|
3
|
+
require 'xway/parameter'
|
4
|
+
require 'xway/api'
|
5
|
+
require 'xway/cli'
|
2
6
|
|
3
7
|
module Xway
|
4
|
-
|
8
|
+
def self.parameter
|
9
|
+
@parameter ||= Parameter.new.reload!
|
10
|
+
end
|
5
11
|
end
|
data/lib/xway/api.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'xway/api/request'
|
2
|
+
require 'xway/api/endpoints'
|
3
|
+
require 'xway/api/http'
|
4
|
+
|
5
|
+
module Xway
|
6
|
+
class Api
|
7
|
+
def request method_name, *args, &block
|
8
|
+
http = Http.new
|
9
|
+
request = build_request method_name
|
10
|
+
parameter[:servers].map do |server|
|
11
|
+
http.request server, request, parameter[:debug]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def parameter
|
18
|
+
Xway.parameter
|
19
|
+
end
|
20
|
+
|
21
|
+
def build_request method_name
|
22
|
+
Endpoints.new.send(method_name, parameter[:app] || {})
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Xway
|
2
|
+
class Api
|
3
|
+
class Endpoints
|
4
|
+
def list options={}
|
5
|
+
Request.new 'get', '/applications'
|
6
|
+
end
|
7
|
+
|
8
|
+
def create options={}
|
9
|
+
Request.new 'post', '/applications', options
|
10
|
+
end
|
11
|
+
|
12
|
+
def find options={app: ':name'}
|
13
|
+
Request.new 'get', "/applications/#{options[:app]}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def update options={app: ':name'}
|
17
|
+
Request.new 'put', "/applications/#{options[:app]}"
|
18
|
+
end
|
19
|
+
|
20
|
+
def delete options={app: ':name'}
|
21
|
+
Request.new 'delete', "/applications/#{options[:app]}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def log options={app: ':name'}
|
25
|
+
Request.new 'get', "/applications/#{options[:app]}/log"
|
26
|
+
end
|
27
|
+
|
28
|
+
def start options={app: ':name'}
|
29
|
+
Request.new 'post', "/applications/#{options[:app]}/start"
|
30
|
+
end
|
31
|
+
|
32
|
+
def stop options={app: ':name'}
|
33
|
+
Request.new 'post', "/applications/#{options[:app]}/stop"
|
34
|
+
end
|
35
|
+
|
36
|
+
def restart options={app: ':name'}
|
37
|
+
Request.new 'post', "/applications/#{options[:app]}/restart"
|
38
|
+
end
|
39
|
+
|
40
|
+
def redeploy options={app: ':name'}
|
41
|
+
Request.new 'post', "/applications/#{options[:app]}/redeploy"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
module Xway
|
4
|
+
class Api
|
5
|
+
class Http
|
6
|
+
def request server, request, debug=false
|
7
|
+
uri = File.join(server, request.path)
|
8
|
+
http_options = request.http_options.tap do |http_options|
|
9
|
+
http_options[:debug_output] = STDOUT if debug
|
10
|
+
end
|
11
|
+
HTTParty.send(request.method_name, uri, http_options)
|
12
|
+
rescue => e
|
13
|
+
raise Error, ["#{server} appears offline", e]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'xway/api/request/body'
|
2
|
+
|
3
|
+
module Xway
|
4
|
+
class Api
|
5
|
+
class Request
|
6
|
+
attr_reader :method_name, :path, :headers, :body
|
7
|
+
|
8
|
+
def initialize method_name, path, options={}
|
9
|
+
@method_name = method_name
|
10
|
+
@path = path
|
11
|
+
@options = options
|
12
|
+
@body = build_body
|
13
|
+
@headers = build_headers
|
14
|
+
end
|
15
|
+
|
16
|
+
def build_headers
|
17
|
+
{'X-App' => 'appway'}.tap do |headers|
|
18
|
+
headers['Content-Type'] = body.mime_type if body
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def build_body
|
23
|
+
if path = @options[:manifest]
|
24
|
+
@body = Body.new path
|
25
|
+
else
|
26
|
+
@body = nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def http_options
|
31
|
+
http_options = {headers: headers}.tap do |http_options|
|
32
|
+
http_options[:body] = body.read if body
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Xway
|
2
|
+
class Api
|
3
|
+
class Request
|
4
|
+
class Body
|
5
|
+
attr_reader :path
|
6
|
+
|
7
|
+
def initialize path
|
8
|
+
@path = path
|
9
|
+
end
|
10
|
+
|
11
|
+
def read
|
12
|
+
check_type do |extname|
|
13
|
+
if File.exists?(path)
|
14
|
+
File.read(path)
|
15
|
+
else
|
16
|
+
raise ManifestFileNotFound, "could not find file #{path}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def mime_type
|
22
|
+
check_type do |extname|
|
23
|
+
'application/json'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def check_type
|
30
|
+
extname = File.extname(path)
|
31
|
+
if extname == '.json'
|
32
|
+
yield extname
|
33
|
+
else
|
34
|
+
raise ManifestFileTypeUnsupported, \
|
35
|
+
"unsupported extension #{extname} for #{path}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/xway/cli.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Xway
|
2
|
+
class Cli
|
3
|
+
def initialize api=Api.new, out=STDOUT
|
4
|
+
@api = api
|
5
|
+
@out = out
|
6
|
+
end
|
7
|
+
|
8
|
+
def start
|
9
|
+
commands = Xway.parameter.rest
|
10
|
+
if Xway.parameter[:version]
|
11
|
+
@out.puts "xway #{VERSION}"
|
12
|
+
elsif commands.empty?
|
13
|
+
Xway.parameter.print_help!
|
14
|
+
else
|
15
|
+
@out.puts @api.request(*commands)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/xway/error.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'configliere'
|
2
|
+
|
3
|
+
module Xway
|
4
|
+
class Parameter
|
5
|
+
def reload!
|
6
|
+
@param = Configliere::Param.new
|
7
|
+
@param.define :servers, type: Array,
|
8
|
+
flag: 's',
|
9
|
+
description: 'all appway servers',
|
10
|
+
default: ['http://localhost:8000']
|
11
|
+
@param.define 'app.name', type: String,
|
12
|
+
flag: 'a',
|
13
|
+
description: 'name of your app'
|
14
|
+
@param.define 'app.manifest', type: String,
|
15
|
+
flag: 'm',
|
16
|
+
description: 'path to your app.way file'
|
17
|
+
@param.define :debug, flag: 'd',
|
18
|
+
description: 'print debug info to stdout',
|
19
|
+
default: false
|
20
|
+
@param.define :version, flag: 'v',
|
21
|
+
description: 'print version info'
|
22
|
+
@param.read global_config if File.exists? global_config
|
23
|
+
@param.read local_config if File.exists? local_config
|
24
|
+
@param.use(:commandline)
|
25
|
+
@param.resolve!
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def print_help!
|
30
|
+
reload!
|
31
|
+
@param[:help] = true
|
32
|
+
@param.resolve!
|
33
|
+
self
|
34
|
+
end
|
35
|
+
|
36
|
+
def [] key
|
37
|
+
if @param
|
38
|
+
@param[key]
|
39
|
+
else
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def rest
|
45
|
+
if @param
|
46
|
+
@param.rest
|
47
|
+
else
|
48
|
+
[]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_hash
|
53
|
+
if @param
|
54
|
+
@param.to_hash
|
55
|
+
else
|
56
|
+
{}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def global_config
|
61
|
+
ENV['XWAY_CONFIG'] || File.join(ENV['HOME'], '.xway')
|
62
|
+
end
|
63
|
+
|
64
|
+
def local_config
|
65
|
+
File.join(Dir.pwd, '.xway')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
data/lib/xway/version.rb
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
{
|
2
|
+
"name": "example",
|
3
|
+
"repo": {
|
4
|
+
"url": "git://github.com/threez/appway-example.git",
|
5
|
+
"branch": "master"
|
6
|
+
},
|
7
|
+
"packages": {
|
8
|
+
},
|
9
|
+
"user": "www-data",
|
10
|
+
"group": "www-data",
|
11
|
+
"domain": [
|
12
|
+
"^example.*",
|
13
|
+
"^example.local$"
|
14
|
+
],
|
15
|
+
"install": [
|
16
|
+
"npm install"
|
17
|
+
],
|
18
|
+
"scale": {
|
19
|
+
"web": 2
|
20
|
+
}
|
21
|
+
}
|
@@ -0,0 +1 @@
|
|
1
|
+
foo: bar
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'open3'
|
3
|
+
require 'xway/version'
|
4
|
+
|
5
|
+
class XwayBinary
|
6
|
+
attr_reader :stdin, :stdout, :stderr
|
7
|
+
def run
|
8
|
+
exe = File.expand_path('../../../bin/xway', File.dirname(__FILE__))
|
9
|
+
ENV['RUBYLIB'] = File.join(File.dirname(__FILE__), '../../../lib')
|
10
|
+
@stdin, @stdout, @stderr = Open3.popen3("#{exe} --version")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
describe XwayBinary do
|
15
|
+
before { subject.run }
|
16
|
+
its('stderr.readlines.to_s') { should_not include('xway') }
|
17
|
+
its('stdout.readlines.to_s') { should include(Xway::VERSION) }
|
18
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'xway/api/endpoints'
|
3
|
+
require 'xway/api/request'
|
4
|
+
|
5
|
+
describe Xway::Api::Endpoints do
|
6
|
+
subject('endpoints') { described_class.new }
|
7
|
+
|
8
|
+
describe 'list' do
|
9
|
+
subject { endpoints.list({}) }
|
10
|
+
its('method_name') { should eq 'get' }
|
11
|
+
its('path') { should eq '/applications' }
|
12
|
+
its('headers') { should eq('X-App' => 'appway') }
|
13
|
+
its('body') { should eq(nil) }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe 'create' do
|
17
|
+
let('manifest') { File.join(ASSETS_PATH, 'appway-example.json') }
|
18
|
+
subject { endpoints.create manifest: manifest }
|
19
|
+
its('method_name') { should eq 'post' }
|
20
|
+
its('path') { should eq '/applications' }
|
21
|
+
its('headers') { should eq('X-App' => 'appway',
|
22
|
+
'Content-Type' => 'application/json') }
|
23
|
+
its('body') { should be_kind_of(Xway::Api::Request::Body) }
|
24
|
+
end
|
25
|
+
|
26
|
+
describe 'find' do
|
27
|
+
subject { endpoints.find app: 'foo' }
|
28
|
+
its('method_name') { should eq 'get' }
|
29
|
+
its('path') { should eq '/applications/foo' }
|
30
|
+
its('headers') { should eq('X-App' => 'appway') }
|
31
|
+
its('body') { should eq(nil) }
|
32
|
+
end
|
33
|
+
|
34
|
+
describe 'update' do
|
35
|
+
subject { endpoints.update app: 'foo' }
|
36
|
+
its('method_name') { should eq 'put' }
|
37
|
+
its('path') { should eq '/applications/foo' }
|
38
|
+
its('headers') { should eq('X-App' => 'appway') }
|
39
|
+
its('body') { should eq(nil) }
|
40
|
+
end
|
41
|
+
|
42
|
+
describe 'delete' do
|
43
|
+
subject { endpoints.delete app: 'foo' }
|
44
|
+
its('method_name') { should eq 'delete' }
|
45
|
+
its('path') { should eq '/applications/foo' }
|
46
|
+
its('headers') { should eq('X-App' => 'appway') }
|
47
|
+
its('body') { should eq(nil) }
|
48
|
+
end
|
49
|
+
|
50
|
+
describe 'log' do
|
51
|
+
subject { endpoints.log app: 'foo' }
|
52
|
+
its('method_name') { should eq 'get' }
|
53
|
+
its('path') { should eq '/applications/foo/log' }
|
54
|
+
its('headers') { should eq('X-App' => 'appway') }
|
55
|
+
its('body') { should eq(nil) }
|
56
|
+
end
|
57
|
+
|
58
|
+
describe 'start' do
|
59
|
+
subject { endpoints.start app: 'foo' }
|
60
|
+
its('method_name') { should eq 'post' }
|
61
|
+
its('path') { should eq '/applications/foo/start' }
|
62
|
+
its('headers') { should eq('X-App' => 'appway') }
|
63
|
+
its('body') { should eq(nil) }
|
64
|
+
end
|
65
|
+
|
66
|
+
describe 'stop' do
|
67
|
+
subject { endpoints.stop app: 'foo' }
|
68
|
+
its('method_name') { should eq 'post' }
|
69
|
+
its('path') { should eq '/applications/foo/stop' }
|
70
|
+
its('headers') { should eq('X-App' => 'appway') }
|
71
|
+
its('body') { should eq(nil) }
|
72
|
+
end
|
73
|
+
|
74
|
+
describe 'restart' do
|
75
|
+
subject { endpoints.restart app: 'foo' }
|
76
|
+
its('method_name') { should eq 'post' }
|
77
|
+
its('path') { should eq '/applications/foo/restart' }
|
78
|
+
its('headers') { should eq('X-App' => 'appway') }
|
79
|
+
its('body') { should eq(nil) }
|
80
|
+
end
|
81
|
+
|
82
|
+
describe 'redeploy' do
|
83
|
+
subject { endpoints.redeploy app: 'foo' }
|
84
|
+
its('method_name') { should eq 'post' }
|
85
|
+
its('path') { should eq '/applications/foo/redeploy' }
|
86
|
+
its('headers') { should eq('X-App' => 'appway') }
|
87
|
+
its('body') { should eq(nil) }
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'xway/api/http'
|
3
|
+
require 'xway/error'
|
4
|
+
|
5
|
+
describe Xway::Api::Http do
|
6
|
+
let('headers') { {'X-App' => 'appway'} }
|
7
|
+
let('request') do
|
8
|
+
double('Xway::Api::Request').tap do |mock|
|
9
|
+
mock.stub('method_name').and_return('get')
|
10
|
+
mock.stub('path').and_return('/bar')
|
11
|
+
mock.stub('http_options').and_return(headers: headers)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'wraps errors' do
|
16
|
+
HTTParty.stub('get') { raise StandardError, 'foo' }
|
17
|
+
expect { subject.request 'http://foo', request }.to\
|
18
|
+
raise_error(Xway::Error)
|
19
|
+
end
|
20
|
+
|
21
|
+
describe 'calls HTTParty' do
|
22
|
+
it do
|
23
|
+
HTTParty.should_receive('get').with('http://foo/bar',
|
24
|
+
headers: headers)
|
25
|
+
subject.request 'http://foo', request
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'includes debug flag' do
|
29
|
+
HTTParty.should_receive('get').with('http://foo/bar',
|
30
|
+
headers: headers,
|
31
|
+
debug_output: STDOUT)
|
32
|
+
subject.request 'http://foo', request, true
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'xway/error'
|
3
|
+
require 'xway/api/request/body'
|
4
|
+
|
5
|
+
describe Xway::Api::Request::Body do
|
6
|
+
context 'unknown file type' do
|
7
|
+
let('path') { 'foo/bar' }
|
8
|
+
before do
|
9
|
+
File.stub('exists?').with(path).and_return(true)
|
10
|
+
end
|
11
|
+
subject { described_class.new path }
|
12
|
+
|
13
|
+
its('path') { should eq path }
|
14
|
+
it { expect{subject.mime_type}.to raise_error(Xway::ManifestFileTypeUnsupported) }
|
15
|
+
it { expect{subject.read}.to raise_error(Xway::ManifestFileTypeUnsupported) }
|
16
|
+
end
|
17
|
+
|
18
|
+
context 'known file type but not existent' do
|
19
|
+
let('path') { 'foo/bar.json' }
|
20
|
+
before do
|
21
|
+
File.stub('exists?').with(path).and_return(false)
|
22
|
+
end
|
23
|
+
subject { described_class.new path }
|
24
|
+
|
25
|
+
its('path') { should eq path }
|
26
|
+
its('mime_type') { should eq 'application/json' }
|
27
|
+
it { expect{subject.read}.to raise_error(Xway::ManifestFileNotFound) }
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'correct file' do
|
31
|
+
let('path') { 'foo/bar.json' }
|
32
|
+
before do
|
33
|
+
File.stub('exists?').with(path).and_return(true)
|
34
|
+
File.stub('read').with(path).and_return('example data')
|
35
|
+
end
|
36
|
+
subject { described_class.new path }
|
37
|
+
|
38
|
+
its('path') { should eq path }
|
39
|
+
its('mime_type') { should eq 'application/json' }
|
40
|
+
its('read') { should eq 'example data' }
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'xway/api/request'
|
3
|
+
|
4
|
+
describe Xway::Api::Request do
|
5
|
+
subject { described_class.new 'get', '/foo' }
|
6
|
+
|
7
|
+
its('method_name') { should eq 'get' }
|
8
|
+
its('path') { should eq '/foo' }
|
9
|
+
its('headers') { should eq('X-App' => 'appway') }
|
10
|
+
its('body') { should eq nil }
|
11
|
+
|
12
|
+
context 'with manifest' do
|
13
|
+
let('manifest') { File.join(ASSETS_PATH, 'appway-example.json') }
|
14
|
+
subject { described_class.new 'get', '/foo', manifest: manifest }
|
15
|
+
|
16
|
+
its('method_name') { should eq 'get' }
|
17
|
+
its('path') { should eq '/foo' }
|
18
|
+
its('headers') { should eq('X-App' => 'appway',
|
19
|
+
'Content-Type' => 'application/json') }
|
20
|
+
its('body.read') { should include('github.com/threez/appway-example') }
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'xway/api'
|
3
|
+
require 'xway/error'
|
4
|
+
|
5
|
+
describe Xway::Api do
|
6
|
+
let!('parameter') do
|
7
|
+
parameter = double('Xway::Parameter').tap do |p|
|
8
|
+
p.stub('[]').with(:servers).and_return(['http://foo',
|
9
|
+
'http://bar'])
|
10
|
+
p.stub('[]').with(:debug).and_return(false)
|
11
|
+
p.stub('[]').with(:app).and_return(nil)
|
12
|
+
end
|
13
|
+
Xway.stub('parameter').and_return(parameter)
|
14
|
+
end
|
15
|
+
|
16
|
+
subject('api') { described_class.new }
|
17
|
+
|
18
|
+
context 'mock HTTParty' do
|
19
|
+
before do
|
20
|
+
HTTParty.stub('get').and_return('list of apps')
|
21
|
+
end
|
22
|
+
|
23
|
+
subject { api.request 'list' }
|
24
|
+
|
25
|
+
it { should eq ['list of apps', 'list of apps'] }
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'mock http + endpoints' do
|
29
|
+
let!('http') do
|
30
|
+
double('Http').tap do |mock|
|
31
|
+
mock.stub('request') do |server, request, debug|
|
32
|
+
Struct\
|
33
|
+
.new(:server, :http_options, :debug)\
|
34
|
+
.new(server, request.http_options, debug)
|
35
|
+
end
|
36
|
+
Xway::Api::Http.stub('new').and_return(mock)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
let!('endpoints') do
|
40
|
+
double('Endpoints').tap do |mock|
|
41
|
+
mock.stub('foo') do |options|
|
42
|
+
Xway::Api::Request.new 'get', '/foo', options
|
43
|
+
end
|
44
|
+
Xway::Api::Endpoints.stub('new').and_return(mock)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'apps' do
|
49
|
+
describe 'builds request for each server' do
|
50
|
+
subject { api.request 'foo' }
|
51
|
+
|
52
|
+
its('first.server') { should eq('http://foo') }
|
53
|
+
its('first.http_options') { should eq(:headers => {
|
54
|
+
"X-App" => "appway"}) }
|
55
|
+
its('first.debug') { should be_false }
|
56
|
+
its('last.server') { should eq('http://bar') }
|
57
|
+
its('last.http_options') { should eq(:headers => {
|
58
|
+
"X-App" => "appway"}) }
|
59
|
+
its('last.debug') { should be_false }
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'app name + manifest' do
|
64
|
+
before do
|
65
|
+
manifest = File.join(ASSETS_PATH, 'appway-example.json')
|
66
|
+
File.stub('exists?').with(manifest).and_return(true)
|
67
|
+
File.stub('read').with(manifest).and_return('appway-example.json.data')
|
68
|
+
Xway.parameter.stub('[]').with(:app).and_return(name: 'appway-example',
|
69
|
+
manifest: manifest)
|
70
|
+
end
|
71
|
+
|
72
|
+
describe 'builds request for each server' do
|
73
|
+
subject { api.request 'foo' }
|
74
|
+
|
75
|
+
its('first.server') { should eq('http://foo') }
|
76
|
+
its('first.http_options') { should eq(:headers => {
|
77
|
+
"X-App" => "appway",
|
78
|
+
"Content-Type" => "application/json"},
|
79
|
+
:body => "appway-example.json.data") }
|
80
|
+
its('first.debug') { should be_false }
|
81
|
+
its('last.server') { should eq('http://bar') }
|
82
|
+
its('last.http_options') { should eq(:headers => {
|
83
|
+
"X-App" => "appway",
|
84
|
+
"Content-Type" => "application/json"},
|
85
|
+
:body => "appway-example.json.data") }
|
86
|
+
its('last.debug') { should be_false }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'xway/cli'
|
3
|
+
require 'xway/version'
|
4
|
+
|
5
|
+
describe Xway::Cli do
|
6
|
+
let('parameter') do
|
7
|
+
double('Xway::Parameter').tap do |mock|
|
8
|
+
mock.stub('rest').and_return([])
|
9
|
+
mock.stub('[]').with(:version).and_return(nil)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
let('api') { double('api') }
|
13
|
+
let('out') { double('stdout').tap { |o| o.stub('puts') } }
|
14
|
+
before { Xway.stub('parameter').and_return(parameter) }
|
15
|
+
subject { described_class.new api, out }
|
16
|
+
|
17
|
+
it 'prints usage per default' do
|
18
|
+
parameter.should_receive('print_help!')
|
19
|
+
subject.start
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'prints version on :version parameter' do
|
23
|
+
parameter.stub('[]').with(:version).and_return(true)
|
24
|
+
out.should_receive('puts').with("xway #{Xway::VERSION}")
|
25
|
+
subject.start
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'executes commands on api' do
|
29
|
+
api.should_receive('request').with('list').and_return('list result')
|
30
|
+
out.should_receive('puts').with('list result')
|
31
|
+
parameter.stub('rest').and_return(['list'])
|
32
|
+
subject.start
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'xway/parameter'
|
3
|
+
|
4
|
+
describe Xway::Parameter do
|
5
|
+
its('global_config') { should eq(File.join(ENV['HOME'], '.xway')) }
|
6
|
+
its('local_config') { should eq(File.join(Dir.pwd, '.xway')) }
|
7
|
+
|
8
|
+
context 'mocked Configliere::Param' do
|
9
|
+
let('param') do
|
10
|
+
double('Configliere::Param').tap do |param|
|
11
|
+
param.stub('define')
|
12
|
+
param.stub('use')
|
13
|
+
param.stub('read')
|
14
|
+
param.stub('resolve!')
|
15
|
+
param.stub('[]')
|
16
|
+
param.stub('to_hash')
|
17
|
+
param.stub('rest')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
before do
|
21
|
+
subject.stub('global_config').and_return('global-xway-conf')
|
22
|
+
subject.stub('local_config').and_return('local-xway-conf')
|
23
|
+
File.stub('exists?').with('global-xway-conf').and_return(false)
|
24
|
+
File.stub('exists?').with('local-xway-conf').and_return(false)
|
25
|
+
Configliere::Param.stub('new').and_return(param)
|
26
|
+
end
|
27
|
+
|
28
|
+
its('to_hash') { should eq({}) }
|
29
|
+
its('rest') { should eq([]) }
|
30
|
+
it { subject[:servers].should eq(nil)}
|
31
|
+
|
32
|
+
describe 'loads!' do
|
33
|
+
it 'reads global config when it exists' do
|
34
|
+
File.stub('exists?').with('global-xway-conf').and_return(true)
|
35
|
+
param.should_receive('read').with('global-xway-conf')
|
36
|
+
subject.reload!
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'reads local config when it exists' do
|
40
|
+
File.stub('exists?').with('local-xway-conf').and_return(true)
|
41
|
+
param.should_receive('read').with('local-xway-conf')
|
42
|
+
subject.reload!
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'uses commandline' do
|
46
|
+
param.should_receive('use').with(:commandline)
|
47
|
+
subject.reload!
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'calls resolve' do
|
51
|
+
param.should_receive('resolve!')
|
52
|
+
subject.reload!
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'defines servers' do
|
56
|
+
param.should_receive('define').with(:servers,
|
57
|
+
type: Array,
|
58
|
+
flag: 's',
|
59
|
+
description: 'all appway servers',
|
60
|
+
default: ['http://localhost:8000'])
|
61
|
+
subject.reload!
|
62
|
+
end
|
63
|
+
|
64
|
+
it 'defines app.name' do
|
65
|
+
param.should_receive('define').with('app.name',
|
66
|
+
type: String,
|
67
|
+
flag: 'a',
|
68
|
+
description: 'name of your app')
|
69
|
+
subject.reload!
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'defines app.manifest' do
|
73
|
+
param.should_receive('define').with('app.manifest',
|
74
|
+
type: String,
|
75
|
+
flag: 'm',
|
76
|
+
description: 'path to your app.way file')
|
77
|
+
subject.reload!
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'defines debug' do
|
81
|
+
param.should_receive('define').with(:debug,
|
82
|
+
flag: 'd',
|
83
|
+
description: 'print debug info to stdout',
|
84
|
+
default: false)
|
85
|
+
subject.reload!
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'defines version' do
|
89
|
+
param.should_receive('define').with(:version,
|
90
|
+
flag: 'v',
|
91
|
+
description: 'print version info')
|
92
|
+
subject.reload!
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'after reload!' do
|
97
|
+
before do
|
98
|
+
param.stub('[]').with(:servers).and_return('http://bar')
|
99
|
+
param.stub('to_hash').and_return(servers: ['http://bar'])
|
100
|
+
param.stub('rest').and_return([1,2,3])
|
101
|
+
subject.reload!
|
102
|
+
end
|
103
|
+
its('rest') { should eq([1,2,3]) }
|
104
|
+
its('to_hash') { should eq(servers: ['http://bar']) }
|
105
|
+
it { subject[:servers].should eq('http://bar') }
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'print_help!' do
|
109
|
+
param.should_receive('[]=').with(:help, true)
|
110
|
+
param.should_receive('resolve!')
|
111
|
+
subject.print_help!
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context 'custom XWAY_CONFIG' do
|
116
|
+
let('xway_config') { File.join(Dir.pwd, 'spec/assets/custom.xway') }
|
117
|
+
before { ENV.stub('[]').and_return(xway_config) }
|
118
|
+
|
119
|
+
its('global_config') { should eq(xway_config) }
|
120
|
+
its('local_config') { should eq(File.join(Dir.pwd, '.xway')) }
|
121
|
+
end
|
122
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
# this must before application code is required
|
2
|
+
require 'coveralls'
|
3
|
+
Coveralls.wear!
|
4
|
+
|
1
5
|
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
6
|
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
7
|
# Require this file using `require "spec_helper"` to ensure that it is only
|
@@ -15,3 +19,10 @@ RSpec.configure do |config|
|
|
15
19
|
# --seed 1234
|
16
20
|
config.order = 'random'
|
17
21
|
end
|
22
|
+
|
23
|
+
# just add the lib folder to the load path
|
24
|
+
# -> actual 'require' calls will be done within each spec (speed + modularity)
|
25
|
+
lib = File.expand_path('../lib', File.dirname(__FILE__))
|
26
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
27
|
+
|
28
|
+
ASSETS_PATH = File.expand_path('assets', File.dirname(__FILE__))
|
data/xway.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |gem|
|
|
8
8
|
gem.version = Xway::VERSION
|
9
9
|
gem.authors = ["Jens Bissinger"]
|
10
10
|
gem.email = ["mail@jens-bissinger.de"]
|
11
|
-
gem.description = %q{
|
12
|
-
gem.summary = %q{
|
11
|
+
gem.description = %q{Appway client.}
|
12
|
+
gem.summary = %q{Provides the xway command. See github.com/threez/appway.}
|
13
13
|
gem.homepage = ""
|
14
14
|
|
15
15
|
gem.files = `git ls-files`.split($/)
|
@@ -17,9 +17,14 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
|
20
|
+
gem.add_dependency 'configliere'
|
21
|
+
gem.add_dependency 'httparty'
|
22
|
+
|
23
|
+
gem.add_development_dependency 'rake'
|
20
24
|
gem.add_development_dependency 'rspec'
|
21
25
|
gem.add_development_dependency 'rspec-nc'
|
22
26
|
gem.add_development_dependency 'guard'
|
23
27
|
gem.add_development_dependency 'guard-rspec'
|
24
28
|
gem.add_development_dependency 'terminal-notifier-guard'
|
29
|
+
gem.add_development_dependency 'coveralls'
|
25
30
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: xway
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.1.
|
4
|
+
version: 0.0.1.beta
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,56 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-05-
|
12
|
+
date: 2013-05-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: configliere
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: httparty
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rake
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
14
62
|
- !ruby/object:Gem::Dependency
|
15
63
|
name: rspec
|
16
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -91,7 +139,23 @@ dependencies:
|
|
91
139
|
- - ! '>='
|
92
140
|
- !ruby/object:Gem::Version
|
93
141
|
version: '0'
|
94
|
-
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: coveralls
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ! '>='
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
type: :development
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ! '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
description: Appway client.
|
95
159
|
email:
|
96
160
|
- mail@jens-bissinger.de
|
97
161
|
executables:
|
@@ -99,8 +163,10 @@ executables:
|
|
99
163
|
extensions: []
|
100
164
|
extra_rdoc_files: []
|
101
165
|
files:
|
166
|
+
- .coveralls.yml
|
102
167
|
- .gitignore
|
103
168
|
- .rspec
|
169
|
+
- .travis.yml
|
104
170
|
- Gemfile
|
105
171
|
- Guardfile
|
106
172
|
- LICENSE.txt
|
@@ -108,8 +174,28 @@ files:
|
|
108
174
|
- Rakefile
|
109
175
|
- bin/xway
|
110
176
|
- lib/xway.rb
|
177
|
+
- lib/xway/api.rb
|
178
|
+
- lib/xway/api/endpoints.rb
|
179
|
+
- lib/xway/api/http.rb
|
180
|
+
- lib/xway/api/request.rb
|
181
|
+
- lib/xway/api/request/body.rb
|
182
|
+
- lib/xway/cli.rb
|
183
|
+
- lib/xway/error.rb
|
184
|
+
- lib/xway/parameter.rb
|
111
185
|
- lib/xway/version.rb
|
112
|
-
- spec/
|
186
|
+
- spec/assets/appway-example.json
|
187
|
+
- spec/assets/custom.xway
|
188
|
+
- spec/integration/bin/xway_binary_spec.rb
|
189
|
+
- spec/integration/lib/xway/cli_spec.rb
|
190
|
+
- spec/lib/xway/api/endpoints_spec.rb
|
191
|
+
- spec/lib/xway/api/http_spec.rb
|
192
|
+
- spec/lib/xway/api/request/body_spec.rb
|
193
|
+
- spec/lib/xway/api/request_spec.rb
|
194
|
+
- spec/lib/xway/api_spec.rb
|
195
|
+
- spec/lib/xway/cli_spec.rb
|
196
|
+
- spec/lib/xway/error_spec.rb
|
197
|
+
- spec/lib/xway/parameter_spec.rb
|
198
|
+
- spec/lib/xway_spec.rb
|
113
199
|
- spec/spec_helper.rb
|
114
200
|
- xway.gemspec
|
115
201
|
homepage: ''
|
@@ -135,8 +221,20 @@ rubyforge_project:
|
|
135
221
|
rubygems_version: 1.8.23
|
136
222
|
signing_key:
|
137
223
|
specification_version: 3
|
138
|
-
summary:
|
224
|
+
summary: Provides the xway command. See github.com/threez/appway.
|
139
225
|
test_files:
|
140
|
-
- spec/
|
226
|
+
- spec/assets/appway-example.json
|
227
|
+
- spec/assets/custom.xway
|
228
|
+
- spec/integration/bin/xway_binary_spec.rb
|
229
|
+
- spec/integration/lib/xway/cli_spec.rb
|
230
|
+
- spec/lib/xway/api/endpoints_spec.rb
|
231
|
+
- spec/lib/xway/api/http_spec.rb
|
232
|
+
- spec/lib/xway/api/request/body_spec.rb
|
233
|
+
- spec/lib/xway/api/request_spec.rb
|
234
|
+
- spec/lib/xway/api_spec.rb
|
235
|
+
- spec/lib/xway/cli_spec.rb
|
236
|
+
- spec/lib/xway/error_spec.rb
|
237
|
+
- spec/lib/xway/parameter_spec.rb
|
238
|
+
- spec/lib/xway_spec.rb
|
141
239
|
- spec/spec_helper.rb
|
142
240
|
has_rdoc:
|
data/spec/bin/xway_spec.rb
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'open3'
|
3
|
-
|
4
|
-
describe 'xway' do
|
5
|
-
it 'returns version string' do
|
6
|
-
exe = File.expand_path('../../bin/xway', File.dirname(__FILE__))
|
7
|
-
stdin, stdout, stderr = Open3.popen3("#{exe}")
|
8
|
-
stdout.readlines.to_s.should include(Xway::VERSION)
|
9
|
-
end
|
10
|
-
end
|