kensa 1.2.0rc7 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -1
- data/Gemfile +5 -4
- data/Gemfile.lock +21 -27
- data/README.md +1 -1
- data/Rakefile +18 -10
- data/bin/kensa +10 -30
- data/kensa.gemspec +27 -20
- data/lib/heroku/kensa.rb +7 -9
- data/lib/heroku/kensa/check.rb +499 -0
- data/lib/heroku/kensa/client.rb +67 -89
- data/lib/heroku/kensa/git.rb +39 -0
- data/lib/heroku/kensa/manifest.rb +41 -8
- data/lib/heroku/kensa/screen.rb +37 -0
- data/lib/heroku/kensa/sso.rb +22 -22
- data/lib/heroku/kensa/version.rb +1 -2
- data/test/all_check_test.rb +25 -0
- data/test/create_test.rb +40 -6
- data/test/deprovision_check_test.rb +39 -0
- data/test/helper.rb +74 -11
- data/test/init_test.rb +54 -0
- data/test/manifest_check_test.rb +94 -0
- data/test/manifest_test.rb +37 -33
- data/test/plan_change_check_test.rb +31 -0
- data/test/provision_check_test.rb +51 -0
- data/test/provision_response_check_test.rb +81 -0
- data/test/resources/runner.rb +1 -0
- data/test/resources/server.rb +227 -0
- data/test/sso_check_test.rb +58 -0
- data/test/sso_test.rb +113 -53
- metadata +97 -91
- data/test.rb +0 -1
- data/test/deprovision_test.rb +0 -30
- data/test/lib/dependencies.rb +0 -12
- data/test/lib/formatter.rb +0 -84
- data/test/lib/http.rb +0 -60
- data/test/lib/response.rb +0 -12
- data/test/manifest_generation_test.rb +0 -32
- data/test/plan_change_test.rb +0 -30
- data/test/provision_test.rb +0 -84
- data/test/resources/provider_server.rb +0 -81
- data/test/resources/views/index.haml +0 -6
- data/test/sso_launch_test.rb +0 -130
data/lib/heroku/kensa/version.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'test/helper'
|
2
|
+
|
3
|
+
class AllCheckTest < Test::Unit::TestCase
|
4
|
+
include Heroku::Kensa
|
5
|
+
|
6
|
+
setup do
|
7
|
+
@data = Manifest.new(:method => :get).skeleton
|
8
|
+
@data['api']['password'] = 'secret'
|
9
|
+
@data['api']['test'] += "working"
|
10
|
+
@file = File.dirname(__FILE__) + "/resources/runner.rb"
|
11
|
+
end
|
12
|
+
|
13
|
+
def check; AllCheck; end
|
14
|
+
|
15
|
+
test "valid on script exit 0" do
|
16
|
+
@data[:args] = ["ruby #{@file}"]
|
17
|
+
assert_valid
|
18
|
+
end
|
19
|
+
|
20
|
+
test "invalid on script exit non 0" do
|
21
|
+
@data[:args] = ["ruby #{@file} fail"]
|
22
|
+
assert_invalid
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/test/create_test.rb
CHANGED
@@ -1,12 +1,46 @@
|
|
1
|
-
|
2
|
-
require 'test/lib/dependencies'
|
1
|
+
require 'test/helper'
|
3
2
|
|
4
3
|
class CreateTest < Test::Unit::TestCase
|
5
|
-
|
6
|
-
|
4
|
+
include Heroku::Kensa
|
5
|
+
|
6
|
+
def setup
|
7
|
+
stub(Git).run
|
8
|
+
any_instance_of Client do |client|
|
9
|
+
stub(client).init
|
10
|
+
end
|
11
|
+
stub(Dir).chdir
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_requires_app_name
|
15
|
+
assert_raise Client::CommandInvalid do
|
16
|
+
kensa "create my_addon"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_requires_template
|
21
|
+
assert_raise Client::CommandInvalid do
|
22
|
+
kensa "create --template foo"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_assumes_heroku_template
|
27
|
+
kensa "create my_addon --template sinatra"
|
28
|
+
assert_received Git do |git|
|
29
|
+
git.run("git clone git://github.com/heroku/kensa-create-sinatra my_addon")
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_assumes_github
|
34
|
+
kensa "create my_addon --template heroku/sinatra"
|
35
|
+
assert_received Git do |git|
|
36
|
+
git.run("git clone git://github.com/heroku/sinatra my_addon")
|
37
|
+
end
|
7
38
|
end
|
8
39
|
|
9
|
-
def
|
10
|
-
kensa "create"
|
40
|
+
def test_allows_full_url
|
41
|
+
kensa "create my_addon --template git://heroku.com/sinatra.git"
|
42
|
+
assert_received Git do |git|
|
43
|
+
git.run("git clone git://heroku.com/sinatra.git my_addon")
|
44
|
+
end
|
11
45
|
end
|
12
46
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'test/helper'
|
2
|
+
|
3
|
+
class DeprovisionCheckTest < Test::Unit::TestCase
|
4
|
+
include Heroku::Kensa
|
5
|
+
|
6
|
+
%w{get post}.each do |method|
|
7
|
+
context "with SSO #{method}" do
|
8
|
+
setup do
|
9
|
+
@data = Manifest.new(:method => method).skeleton.merge :id => 123
|
10
|
+
@responses = [
|
11
|
+
[200, ""],
|
12
|
+
[401, ""],
|
13
|
+
]
|
14
|
+
end
|
15
|
+
|
16
|
+
def check ; DeprovisionCheck ; end
|
17
|
+
|
18
|
+
test "valid on 200" do
|
19
|
+
assert_valid do |check|
|
20
|
+
kensa_stub :delete, check, @responses
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
test "status other than 200" do
|
25
|
+
@responses[0] = [500, ""]
|
26
|
+
assert_invalid do |check|
|
27
|
+
kensa_stub :delete, check, @responses
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
test "runs auth check" do
|
32
|
+
@responses[1] = [200, ""]
|
33
|
+
assert_invalid do |check|
|
34
|
+
kensa_stub :delete, check, @responses
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/test/helper.rb
CHANGED
@@ -1,21 +1,84 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
1
|
+
require 'heroku/kensa'
|
2
|
+
require 'heroku/kensa/client'
|
3
|
+
require 'contest'
|
3
4
|
require 'timecop'
|
4
5
|
require 'rr'
|
5
|
-
require '
|
6
|
-
require 'lib/heroku/kensa'
|
7
|
-
require 'test/resources/provider_server'
|
6
|
+
require 'yajl'
|
8
7
|
|
9
8
|
class Test::Unit::TestCase
|
10
9
|
include RR::Adapters::TestUnit
|
11
10
|
|
12
|
-
def
|
13
|
-
|
14
|
-
Artifice.activate_with(ProviderServer.new(manifest))
|
11
|
+
def kensa(command)
|
12
|
+
Heroku::Kensa::Client.new(command.split, :silent => true).run!
|
15
13
|
end
|
16
14
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
15
|
+
def read_json(filename)
|
16
|
+
Yajl::Parser.parse(File.open(filename).read)
|
17
|
+
end
|
18
|
+
|
19
|
+
#this prepends a prefix for the provider server
|
20
|
+
#in test/resources/server.rb
|
21
|
+
def use_provider_endpoint(name, type = 'base')
|
22
|
+
if @data['api']['test'].is_a? Hash
|
23
|
+
url = @data['api']['test']["#{type}_url"]
|
24
|
+
path = URI.parse(url).path
|
25
|
+
@data['api']['test']["#{type}_url"] = url.sub(path, "/#{name}#{path}")
|
26
|
+
else
|
27
|
+
@data['api']['test'] += "#{name}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def trace!
|
32
|
+
@screen = Heroku::Kensa::IOScreen.new(STDOUT)
|
33
|
+
end
|
34
|
+
|
35
|
+
def screen
|
36
|
+
@screen ||= Heroku::Kensa::IOScreen.new(StringIO.new("", 'w+'))
|
37
|
+
end
|
38
|
+
|
39
|
+
# call trace! in your test before the
|
40
|
+
# assert to see the output
|
41
|
+
def assert_valid(data=@data, &blk)
|
42
|
+
check = create_check(data, &blk)
|
43
|
+
result = check.call
|
44
|
+
assert result, screen.to_s
|
45
|
+
end
|
46
|
+
|
47
|
+
def assert_invalid(data=@data, &blk)
|
48
|
+
check = create_check(data, &blk)
|
49
|
+
result = check.call
|
50
|
+
assert !result, screen.to_s
|
51
|
+
end
|
52
|
+
|
53
|
+
def create_check(data, &blk)
|
54
|
+
check = self.check.new(data, screen)
|
55
|
+
blk.call(check) if blk
|
56
|
+
check
|
57
|
+
end
|
58
|
+
|
59
|
+
module Headerize
|
60
|
+
attr_accessor :headers
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_json(data, headers={})
|
64
|
+
body = Yajl::Encoder.encode(data)
|
65
|
+
add_headers(body, headers)
|
66
|
+
end
|
67
|
+
|
68
|
+
def add_headers(o, headers={})
|
69
|
+
o.extend Headerize
|
70
|
+
o.headers = {}
|
71
|
+
o.headers["Content-Type"] ||= "application/json"
|
72
|
+
o.headers.merge!(headers)
|
73
|
+
o
|
74
|
+
end
|
75
|
+
|
76
|
+
def kensa_stub(meth, o, returns)
|
77
|
+
o.instance_eval { @returns = Array(returns) }
|
78
|
+
eval <<-EVAL
|
79
|
+
def o.#{meth}(*args)
|
80
|
+
@returns.shift or fail("Nothing else to return from stub'ed method")
|
81
|
+
end
|
82
|
+
EVAL
|
20
83
|
end
|
21
84
|
end
|
data/test/init_test.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'test/helper'
|
2
|
+
require 'fakefs/safe'
|
3
|
+
|
4
|
+
class InitTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
FakeFS.activate!
|
7
|
+
@filename = 'addon-manifest.json'
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
File.unlink(@filename) if @filename && File.exist?(@filename)
|
12
|
+
FakeFS.deactivate!
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_init_default_so_sso_post
|
16
|
+
kensa "init"
|
17
|
+
manifest = read_json(@filename)
|
18
|
+
%w{test production}.each do |env|
|
19
|
+
%w{base_url sso_url}.each do |url|
|
20
|
+
assert manifest['api'][env][url] =~ /^http/
|
21
|
+
end
|
22
|
+
end
|
23
|
+
assert !File.exist?('.env')
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_init_uses_file_flag
|
27
|
+
@filename = 'foo.json'
|
28
|
+
|
29
|
+
kensa "init -f #{@filename}"
|
30
|
+
assert !File.exist?('./addon-manifest.json')
|
31
|
+
assert !File.exist?('.env')
|
32
|
+
manifest = read_json(@filename)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_init_uses_sso_flag
|
36
|
+
kensa "init --sso get"
|
37
|
+
manifest = read_json(@filename)
|
38
|
+
%w{test production}.each do |env|
|
39
|
+
assert manifest['api'][env] =~ /^http/
|
40
|
+
end
|
41
|
+
assert !File.exist?('.env')
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_init_with_env_flag
|
45
|
+
kensa "init --foreman"
|
46
|
+
env = File.open(".env").read
|
47
|
+
manifest = read_json(@filename)
|
48
|
+
assert manifest['api']['test']['base_url'] =~ /:5000/
|
49
|
+
assert manifest['api']['test']['sso_url'] =~ /:5000/
|
50
|
+
assert env.include?("SSO_SALT=#{manifest['api']['sso_salt']}\n")
|
51
|
+
assert env.include?("HEROKU_USERNAME=#{manifest['id']}\n")
|
52
|
+
assert env.include?("HEROKU_PASSWORD=#{manifest['api']['password']}")
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'test/helper'
|
2
|
+
|
3
|
+
class ManifestCheckTest < Test::Unit::TestCase
|
4
|
+
include Heroku::Kensa
|
5
|
+
|
6
|
+
def check ; ManifestCheck ; end
|
7
|
+
|
8
|
+
%w{get post}.each do |method|
|
9
|
+
context "with sso #{method}" do
|
10
|
+
setup { @data = Manifest.new(:method => method).skeleton }
|
11
|
+
|
12
|
+
test "is valid if no errors" do
|
13
|
+
assert_valid
|
14
|
+
end
|
15
|
+
|
16
|
+
test "has an id" do
|
17
|
+
@data.delete("id")
|
18
|
+
assert_invalid
|
19
|
+
end
|
20
|
+
|
21
|
+
test "api key exists" do
|
22
|
+
@data.delete("api")
|
23
|
+
assert_invalid
|
24
|
+
end
|
25
|
+
|
26
|
+
test "api is a Hash" do
|
27
|
+
@data["api"] = ""
|
28
|
+
assert_invalid
|
29
|
+
end
|
30
|
+
|
31
|
+
test "api has a password" do
|
32
|
+
@data["api"].delete("password")
|
33
|
+
assert_invalid
|
34
|
+
end
|
35
|
+
|
36
|
+
test "api contains test" do
|
37
|
+
@data["api"].delete("test")
|
38
|
+
assert_invalid
|
39
|
+
end
|
40
|
+
|
41
|
+
test "api contains production" do
|
42
|
+
@data["api"].delete("production")
|
43
|
+
assert_invalid
|
44
|
+
end
|
45
|
+
|
46
|
+
test "api contains production of https" do
|
47
|
+
if method == 'get'
|
48
|
+
@data["api"]["production"] = "http://foo.com"
|
49
|
+
else
|
50
|
+
@data["api"]["production"]['base_url'] = "http://foo.com"
|
51
|
+
end
|
52
|
+
assert_invalid
|
53
|
+
end
|
54
|
+
|
55
|
+
if method == 'post'
|
56
|
+
test "sso contains production of https" do
|
57
|
+
@data["api"]["production"]['sso_url'] = "http://foo.com"
|
58
|
+
assert_invalid
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
test "api contains config_vars array" do
|
63
|
+
@data["api"]["config_vars"] = "test"
|
64
|
+
assert_invalid
|
65
|
+
end
|
66
|
+
|
67
|
+
test "api contains at least one config var" do
|
68
|
+
@data["api"]["config_vars"].clear
|
69
|
+
assert_invalid
|
70
|
+
end
|
71
|
+
|
72
|
+
test "all config vars are in upper case" do
|
73
|
+
@data["api"]["config_vars"] << 'MYADDON_invalid_var'
|
74
|
+
assert_invalid
|
75
|
+
end
|
76
|
+
|
77
|
+
test "assert config var prefixes match addon id" do
|
78
|
+
@data["api"]["config_vars"] << 'MONGO_URL'
|
79
|
+
assert_invalid
|
80
|
+
end
|
81
|
+
|
82
|
+
test "replaces dashes for underscores on the config var check" do
|
83
|
+
@data["id"] = "MY-ADDON"
|
84
|
+
@data["api"]["config_vars"] = ["MY_ADDON_URL"]
|
85
|
+
assert_valid
|
86
|
+
end
|
87
|
+
|
88
|
+
test "username is deprecated" do
|
89
|
+
@data["api"]["username"] = "heroku"
|
90
|
+
assert_invalid
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/test/manifest_test.rb
CHANGED
@@ -1,51 +1,55 @@
|
|
1
|
-
$:.unshift(File.expand_path("../..",__FILE__))
|
2
1
|
require 'test/helper'
|
2
|
+
|
3
3
|
class ManifestTest < Test::Unit::TestCase
|
4
|
+
include Heroku::Kensa
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
end
|
6
|
+
context 'GET manifest' do
|
7
|
+
setup { @manifest = Manifest.new(:method => :get) }
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
end
|
9
|
+
test 'have sso salt' do
|
10
|
+
assert_not_nil @manifest.skeleton['api']['sso_salt']
|
11
|
+
end
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
test 'generates a new sso salt every time' do
|
14
|
+
assert @manifest.skeleton['api']['sso_salt'] != Manifest.new.skeleton['api']['sso_salt']
|
15
|
+
end
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
test 'has an api password' do
|
18
|
+
assert_not_nil @manifest.skeleton['api']['password']
|
19
|
+
end
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
test 'generates a new password every time' do
|
22
|
+
assert @manifest.skeleton['api']['password'] != Manifest.new.skeleton['api']['password']
|
23
|
+
end
|
25
24
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
else
|
30
|
-
url = manifest["api"]["production"]
|
25
|
+
test 'uses get format' do
|
26
|
+
assert_equal @manifest.skeleton['api']['test'], 'http://localhost:4567/'
|
27
|
+
assert_equal @manifest.skeleton['api']['production'], 'https://yourapp.com/'
|
31
28
|
end
|
32
|
-
assert url.match(%r{\Ahttps://}), "Production environment must communicate over HTTPS."
|
33
29
|
end
|
34
30
|
|
35
|
-
|
36
|
-
manifest
|
37
|
-
|
31
|
+
context "POST manifest" do
|
32
|
+
setup { @manifest = Manifest.new(:method => :post) }
|
33
|
+
|
34
|
+
test 'uses post format for test url' do
|
35
|
+
assert_equal @manifest.skeleton['api']['test']['base_url'], 'http://localhost:4567/heroku/resources'
|
36
|
+
assert_equal @manifest.skeleton['api']['test']['sso_url'], 'http://localhost:4566/sso/login'
|
38
37
|
end
|
39
|
-
end
|
40
38
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
assert var.match(%r{\A#{id}_}), "All config vars must be prefixed with the add-on ID (#{id}), #{var} is not."
|
39
|
+
test 'uses post format for test url' do
|
40
|
+
assert_equal @manifest.skeleton['api']['production']['base_url'], 'https://yourapp.com/heroku/resources'
|
41
|
+
assert_equal @manifest.skeleton['api']['production']['sso_url'], 'https://yourapp.com/sso/login'
|
45
42
|
end
|
46
43
|
end
|
47
44
|
|
48
|
-
|
49
|
-
|
45
|
+
context 'manifest without sso' do
|
46
|
+
setup do
|
47
|
+
options = { :sso => false, :filename => 'test.txt' }
|
48
|
+
@manifest = Manifest.new options
|
49
|
+
end
|
50
|
+
|
51
|
+
test 'exclude sso salt' do
|
52
|
+
assert_nil @manifest.skeleton['api']['sso_salt']
|
53
|
+
end
|
50
54
|
end
|
51
55
|
end
|