ey_resolver 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/Gemfile +14 -0
- data/README.md +32 -0
- data/Rakefile +14 -0
- data/ey_resolver.gemspec +25 -0
- data/lib/ey_resolver.rb +12 -0
- data/lib/ey_resolver/abstract_resolver.rb +61 -0
- data/lib/ey_resolver/account_resolver.rb +47 -0
- data/lib/ey_resolver/app_env_resolver.rb +57 -0
- data/lib/ey_resolver/app_resolver.rb +52 -0
- data/lib/ey_resolver/environment_resolver.rb +67 -0
- data/lib/ey_resolver/examiner.rb +143 -0
- data/lib/ey_resolver/mock.rb +5 -0
- data/lib/ey_resolver/mock/models.rb +13 -0
- data/lib/ey_resolver/mock/models/account.rb +12 -0
- data/lib/ey_resolver/mock/models/app.rb +18 -0
- data/lib/ey_resolver/mock/models/app_environment.rb +16 -0
- data/lib/ey_resolver/mock/models/environment.rb +16 -0
- data/lib/ey_resolver/mock/models/user.rb +10 -0
- data/lib/ey_resolver/query.rb +68 -0
- data/lib/ey_resolver/version.rb +5 -0
- data/spec/account_resolver_spec.rb +120 -0
- data/spec/app_env_resolver_spec.rb +159 -0
- data/spec/app_resolver_spec.rb +128 -0
- data/spec/environment_resolver_spec.rb +166 -0
- data/spec/spec_helper.rb +84 -0
- metadata +139 -0
@@ -0,0 +1,13 @@
|
|
1
|
+
module EY::Resolver::Mock
|
2
|
+
require 'ey_resolver/mock/models/user'
|
3
|
+
require 'ey_resolver/mock/models/account'
|
4
|
+
require 'ey_resolver/mock/models/app'
|
5
|
+
require 'ey_resolver/mock/models/environment'
|
6
|
+
require 'ey_resolver/mock/models/app_environment'
|
7
|
+
|
8
|
+
require 'dm-migrations'
|
9
|
+
require 'dm-aggregates'
|
10
|
+
DataMapper.setup(:default, "sqlite::memory:")
|
11
|
+
DataMapper.finalize
|
12
|
+
DataMapper.auto_migrate!
|
13
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'gitable'
|
2
|
+
require 'dm-core'
|
3
|
+
|
4
|
+
class App
|
5
|
+
include DataMapper::Resource
|
6
|
+
|
7
|
+
property :id, Serial
|
8
|
+
property :name, String
|
9
|
+
property :repository_uri, String
|
10
|
+
|
11
|
+
belongs_to :account
|
12
|
+
has n, :app_environments
|
13
|
+
has n, :environments, :through => :app_environments
|
14
|
+
|
15
|
+
def gitable_uri
|
16
|
+
Gitable::URI.parse(repository_uri)
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
|
3
|
+
class AppEnvironment
|
4
|
+
include DataMapper::Resource
|
5
|
+
|
6
|
+
property :id, Serial
|
7
|
+
property :app_id, Integer
|
8
|
+
property :environment_id, Integer
|
9
|
+
|
10
|
+
belongs_to :app
|
11
|
+
belongs_to :environment
|
12
|
+
|
13
|
+
def inspect
|
14
|
+
"#<AppEnvironment app:#{app.name} env:#{environment.name}>"
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'dm-core'
|
2
|
+
|
3
|
+
class Environment
|
4
|
+
include DataMapper::Resource
|
5
|
+
|
6
|
+
property :id, Serial
|
7
|
+
property :name, String
|
8
|
+
|
9
|
+
belongs_to :account
|
10
|
+
has n, :app_environments
|
11
|
+
has n, :apps, :through => :app_environments
|
12
|
+
|
13
|
+
def inspect
|
14
|
+
"#<Environment name:#{name} account:#{account.name}>"
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'gitable'
|
2
|
+
|
3
|
+
class EY::Resolver
|
4
|
+
class Query
|
5
|
+
|
6
|
+
def initialize(params)
|
7
|
+
self.query = params
|
8
|
+
end
|
9
|
+
|
10
|
+
def account_name() query[:account_name] end
|
11
|
+
def app_name() query[:app_name] end
|
12
|
+
def environment_name() query[:environment_name] end
|
13
|
+
def remotes() query[:remotes] end
|
14
|
+
|
15
|
+
def count_matches(&block)
|
16
|
+
query.count(&block)
|
17
|
+
end
|
18
|
+
|
19
|
+
def app_constrained?
|
20
|
+
app_name || remotes
|
21
|
+
end
|
22
|
+
|
23
|
+
def app_unconstrained?
|
24
|
+
!app_constrained?
|
25
|
+
end
|
26
|
+
|
27
|
+
def env_constrained?
|
28
|
+
environment_name || app_name || remotes
|
29
|
+
end
|
30
|
+
|
31
|
+
def env_unconstrained?
|
32
|
+
!env_constrained?
|
33
|
+
end
|
34
|
+
|
35
|
+
# The only case where an unconstrained set would return a single record is if
|
36
|
+
# there is only one possible candidate. If we don't have an app name or a
|
37
|
+
# repository_uri at all, then how do we know it's the right one anyway?
|
38
|
+
def unconstrained?
|
39
|
+
query.all? { |k,v| v.nil? || v.empty? || v.to_s.empty? }
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
attr_reader :query
|
45
|
+
|
46
|
+
def query=(params)
|
47
|
+
@query = {}
|
48
|
+
params.each do |key,val|
|
49
|
+
if converted = convert_value(key,val)
|
50
|
+
@query[key.to_sym] = converted
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
@query.delete(:remotes) if @query[:app_name]
|
55
|
+
@query.freeze
|
56
|
+
end
|
57
|
+
|
58
|
+
def convert_value(key, val)
|
59
|
+
if key.to_sym == :remotes
|
60
|
+
return nil if val.nil? || val.empty?
|
61
|
+
val.reject {|uri| uri.to_s.empty? }.map { |uri| Gitable::URI.parse_when_valid(uri) }.compact
|
62
|
+
else
|
63
|
+
norm = val.to_s.gsub(/[^\w-]+/,'')
|
64
|
+
norm.empty? ? nil : norm
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EY::Resolver::AppEnvResolver do
|
4
|
+
|
5
|
+
def account_resolver(*args)
|
6
|
+
EY::Resolver.account_resolver(user, to_query(args))
|
7
|
+
end
|
8
|
+
|
9
|
+
def accounts(*models)
|
10
|
+
models.map { |model| model[:account] }
|
11
|
+
end
|
12
|
+
|
13
|
+
before(:all) do
|
14
|
+
# More correct names, even though it doesn't matter
|
15
|
+
@ey = @production
|
16
|
+
@me = @me_dup
|
17
|
+
@no = @account
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "#matches" do
|
21
|
+
it "return empty if the conditions are empty" do
|
22
|
+
account_resolver( ).matches.should == []
|
23
|
+
account_resolver(nil, nil, nil, []).matches.should == []
|
24
|
+
account_resolver('', '', '', [''] ).matches.should == []
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns empty when there is no account match" do
|
28
|
+
account_resolver('gibberish').matches.should == []
|
29
|
+
end
|
30
|
+
|
31
|
+
it "ignore app name if it doesn't match" do
|
32
|
+
account_resolver('me', 'bigapp').matches.should == accounts(@me)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "finds account with no apps" do
|
36
|
+
account_resolver("no").matches.should == accounts(@no)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "ignores environment" do
|
40
|
+
account_resolver(nil, 'big', 'gibberish').matches.should == accounts(@ey)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "returns more matches when there is more than one match" do
|
44
|
+
account_resolver(nil, nil, nil, ["git://github.com/repo/dup.git"]).matches.should == accounts(@ey, @me)
|
45
|
+
account_resolver('e').matches.should == accounts(@ey, @me)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "returns one deployment whene there is only one match" do
|
49
|
+
account_resolver('ey' ).matches.should == accounts(@ey)
|
50
|
+
account_resolver(nil, "bigapp").matches.should == accounts(@ey)
|
51
|
+
account_resolver(nil, "app" ).matches.should == accounts(@ey, @me)
|
52
|
+
account_resolver("ey", "app" ).matches.should == accounts(@ey)
|
53
|
+
account_resolver("me" ).matches.should == accounts(@me)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "uses repo as a hint but doesn't require it" do
|
57
|
+
account_resolver("ey", nil, nil, ["git://github.com/repo/app.git"]).matches.should == accounts(@ey)
|
58
|
+
account_resolver("me", nil, nil, ["git://github.com/repo/big.git"]).matches.should == accounts(@me)
|
59
|
+
account_resolver("no", nil, nil, ["git://github.com/repo/hug.git", "git://github.com/repo/big.git"]).matches.should == accounts(@no)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "doesn't care about case" do
|
63
|
+
account_resolver("EY", "big").matches.should == accounts(@ey)
|
64
|
+
account_resolver("ey", "BiG").matches.should == accounts(@ey)
|
65
|
+
end
|
66
|
+
|
67
|
+
it "returns the match when an app is specified even when there is a repo" do
|
68
|
+
account_resolver("ey", "bigapp", nil, ["git://github.com/repo/app.git"]).matches.should == accounts(@ey)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "returns the specific match even if there is a partial match" do
|
72
|
+
account_resolver('e', 'app').matches.should == accounts(@ey, @me)
|
73
|
+
account_resolver(nil, "app").matches.should == accounts(@ey, @me)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "scopes searches under the correct account" do
|
77
|
+
account_resolver("ey", "dup").matches.should == accounts(@ey)
|
78
|
+
account_resolver("me", "dup").matches.should == accounts(@me)
|
79
|
+
account_resolver("ey", nil, nil, ["git://github.com/repo/dup.git"]).matches.should == accounts(@ey)
|
80
|
+
account_resolver("me", nil, nil, ["git://github.com/repo/dup.git"]).matches.should == accounts(@me)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "#errors" do
|
85
|
+
it "no account" do
|
86
|
+
account_resolver('gibberish', 'app', 'production').errors.should ==
|
87
|
+
[%|No account found matching "gibberish".|]
|
88
|
+
end
|
89
|
+
|
90
|
+
it "no app" do
|
91
|
+
account_resolver(nil, 'gibberish', 'app_dup').errors.should ==
|
92
|
+
[%|No application found matching "gibberish".|]
|
93
|
+
end
|
94
|
+
|
95
|
+
it "no env" do
|
96
|
+
account_resolver('ey', 'app', 'gibberish').errors.should ==
|
97
|
+
[%|No environment found matching "gibberish".|]
|
98
|
+
end
|
99
|
+
|
100
|
+
it "no account or app" do
|
101
|
+
account_resolver('gibberish', 'gibberish', nil).errors.should == [
|
102
|
+
%|No account found matching "gibberish".|,
|
103
|
+
%|No application found matching "gibberish".|,
|
104
|
+
]
|
105
|
+
end
|
106
|
+
|
107
|
+
it "no account or app or env" do
|
108
|
+
account_resolver('gibberish', 'gibberish', 'gibberish').errors.should == [
|
109
|
+
%|No account found matching "gibberish".|,
|
110
|
+
%|No application found matching "gibberish".|,
|
111
|
+
%|No environment found matching "gibberish".|,
|
112
|
+
]
|
113
|
+
end
|
114
|
+
|
115
|
+
it "repo not found" do
|
116
|
+
account_resolver(nil, nil, nil, ["git://fake.com/fake/fake.git"]).errors.should ==
|
117
|
+
[%|No application found matching remotes:\n\tgit://fake.com/fake/fake.git|]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe EY::Resolver::AppEnvResolver do
|
4
|
+
|
5
|
+
def app_env_resolver(*args)
|
6
|
+
EY::Resolver.app_env_resolver(user, to_query(args))
|
7
|
+
end
|
8
|
+
|
9
|
+
def app_envs(*models)
|
10
|
+
models.map { |model| model[:app_env] }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#matches" do
|
14
|
+
it "raises if the conditions are empty" do
|
15
|
+
app_env_resolver( ).matches.should == []
|
16
|
+
app_env_resolver(nil, nil, nil, []).matches.should == []
|
17
|
+
app_env_resolver('', '', '', [''] ).matches.should == []
|
18
|
+
end
|
19
|
+
|
20
|
+
it "raises if the conditions do not include an app or remotes" do
|
21
|
+
app_env_resolver(nil, nil, 'app_dup' ).matches.should == []
|
22
|
+
app_env_resolver('ey', nil, nil ).matches.should == []
|
23
|
+
app_env_resolver('ey', nil, 'app_dup' ).matches.should == []
|
24
|
+
app_env_resolver('ey', nil, 'app_dup', []).matches.should == []
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns empty when there is no account match" do
|
28
|
+
app_env_resolver('gibberish', 'app', 'production').matches.should == []
|
29
|
+
end
|
30
|
+
|
31
|
+
it "returns empty when there is no app match" do
|
32
|
+
app_env_resolver(nil, 'gibberish', 'app_dup').matches.should == []
|
33
|
+
end
|
34
|
+
|
35
|
+
it "returns empty when there is no environment match" do
|
36
|
+
app_env_resolver(nil, 'app', 'gibberish').matches.should == []
|
37
|
+
end
|
38
|
+
|
39
|
+
it "returns empty when no matches" do
|
40
|
+
app_env_resolver(nil, 'bigapp', 'app_dup').matches.should == []
|
41
|
+
app_env_resolver(nil, nil, 'app_dup', ["git://github.com/repo/app.git"]).matches.should == []
|
42
|
+
end
|
43
|
+
|
44
|
+
it "returns more matches when there is more than one match" do
|
45
|
+
app_env_resolver(nil, "app", nil, nil ).matches.should == app_envs(@production, @staging)
|
46
|
+
app_env_resolver("ey", "app", nil, nil ).matches.should == app_envs(@production, @staging)
|
47
|
+
app_env_resolver(nil, nil, nil, ["git://github.com/repo/app.git"]).matches.should == app_envs(@production, @staging)
|
48
|
+
app_env_resolver(nil, nil, nil, ["git://github.com/repo/hug.git", "git://github.com/repo/big.git"]).matches.should == app_envs(@hugeprod, @big)
|
49
|
+
app_env_resolver(nil, nil, nil, ["git://github.com/repo/dup.git"]).matches.should == app_envs(@ey_dup, @sumo, @me_dup)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "returns one deployment whene there is only one match" do
|
53
|
+
app_env_resolver("ey", "big", nil, nil ).matches.should == app_envs(@big)
|
54
|
+
app_env_resolver(nil, nil, 'production', ["git://github.com/repo/app.git"]).matches.should == app_envs(@production)
|
55
|
+
app_env_resolver(nil, 'app', "production", nil ).matches.should == app_envs(@production)
|
56
|
+
app_env_resolver(nil, nil, 'staging', ["git://github.com/repo/app.git"]).matches.should == app_envs(@staging)
|
57
|
+
app_env_resolver(nil, nil, nil, ["git://github.com/repo/big.git"]).matches.should == app_envs(@big)
|
58
|
+
app_env_resolver(nil, nil, 'bigapp', ["git://github.com/repo/hug.git", "git://github.com/repo/big.git"]).matches.should == app_envs(@big)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "doesn't care about case" do
|
62
|
+
app_env_resolver("EY", "big").matches.should == app_envs(@big)
|
63
|
+
app_env_resolver("ey", "BiG").matches.should == app_envs(@big)
|
64
|
+
end
|
65
|
+
|
66
|
+
it "returns the match when an app is specified even when there is a repo" do
|
67
|
+
app_env_resolver("ey", "bigapp", nil, ["git://github.com/repo/app.git"]).matches.should == app_envs(@big)
|
68
|
+
end
|
69
|
+
|
70
|
+
it "returns the specific match even if there is a partial match" do
|
71
|
+
app_env_resolver(nil, 'app', 'app_staging').matches.should == app_envs(@staging)
|
72
|
+
app_env_resolver(nil, "app", "staging" ).matches.should == app_envs(@staging)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "scopes searches under the correct account" do
|
76
|
+
app_env_resolver("ey", "dup", "dup", nil ).matches.should == app_envs(@ey_dup)
|
77
|
+
app_env_resolver("me", nil, "dup", ["git://github.com/repo/dup.git"]).matches.should == app_envs(@me_dup)
|
78
|
+
app_env_resolver("me", nil, nil, ["git://github.com/repo/dup.git"]).matches.should == app_envs(@me_dup)
|
79
|
+
app_env_resolver("me", "dup", nil, nil ).matches.should == app_envs(@me_dup)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "#errors" do
|
84
|
+
|
85
|
+
it "no constraints" do
|
86
|
+
app_env_resolver().errors.should ==
|
87
|
+
[%|Must search by account name, app name, remotes, or environment name.|]
|
88
|
+
end
|
89
|
+
|
90
|
+
it "no app constraints" do
|
91
|
+
app_env_resolver('ey').errors.should ==
|
92
|
+
[%|App name or repository remotes required.|]
|
93
|
+
end
|
94
|
+
|
95
|
+
it "no account" do
|
96
|
+
app_env_resolver('gibberish', 'app', 'production').errors.should ==
|
97
|
+
[%|No account found matching "gibberish".|]
|
98
|
+
end
|
99
|
+
|
100
|
+
it "no app" do
|
101
|
+
app_env_resolver(nil, 'gibberish', 'app_dup').errors.should ==
|
102
|
+
[%|No application found matching "gibberish".|]
|
103
|
+
end
|
104
|
+
|
105
|
+
it "app found, but not on account" do
|
106
|
+
app_env_resolver('no', 'bigapp', 'app_dup').errors.should == [
|
107
|
+
%|Application "bigapp" found, but does not exist in account "no".|,
|
108
|
+
%|Environment "app_dup" found, but does not exist in account "no".|,
|
109
|
+
]
|
110
|
+
end
|
111
|
+
|
112
|
+
it "no env" do
|
113
|
+
app_env_resolver('ey', 'app', 'gibberish').errors.should ==
|
114
|
+
[%|No environment found matching "gibberish".|]
|
115
|
+
end
|
116
|
+
|
117
|
+
it "no env on account" do
|
118
|
+
app_env_resolver('me', 'other', 'production').errors.should ==
|
119
|
+
[%|Environment "production" found, but does not exist in account "me".|]
|
120
|
+
end
|
121
|
+
|
122
|
+
it "no account or app" do
|
123
|
+
app_env_resolver('gibberish', 'gibberish', nil).errors.should == [
|
124
|
+
%|No account found matching "gibberish".|,
|
125
|
+
%|No application found matching "gibberish".|,
|
126
|
+
]
|
127
|
+
end
|
128
|
+
|
129
|
+
it "no account or app or env" do
|
130
|
+
app_env_resolver('gibberish', 'gibberish', 'gibberish').errors.should == [
|
131
|
+
%|No account found matching "gibberish".|,
|
132
|
+
%|No application found matching "gibberish".|,
|
133
|
+
%|No environment found matching "gibberish".|,
|
134
|
+
]
|
135
|
+
end
|
136
|
+
|
137
|
+
it "repo not found" do
|
138
|
+
app_env_resolver(nil, nil, nil, ["git://fake.com/fake/fake.git"]).errors.should ==
|
139
|
+
[%|No application found matching remotes:\n\tgit://fake.com/fake/fake.git|]
|
140
|
+
end
|
141
|
+
|
142
|
+
it "repo not found in account" do
|
143
|
+
app_env_resolver('ey', nil, nil, ["git://github.com/repo/oth.git"]).errors.should ==
|
144
|
+
[%|Application "other" found, but does not exist in account "ey".|]
|
145
|
+
end
|
146
|
+
|
147
|
+
it "app and environment not associated" do
|
148
|
+
app_env_resolver('ey', 'bigapp', 'app_dup').errors.should ==
|
149
|
+
[%|Application "bigapp" and environment "app_dup" are not associated.|]
|
150
|
+
app_env_resolver(nil, nil, 'app_dup', ["git://github.com/repo/app.git"]).errors.should ==
|
151
|
+
[%|Application "app" and environment "app_dup" are not associated.|]
|
152
|
+
end
|
153
|
+
|
154
|
+
it "app (by repo) does not have an environment" do
|
155
|
+
app_env_resolver(nil, nil, nil, ["git://github.com/repo/noe.git"]).errors.should ==
|
156
|
+
[%|No environment found for applications matching remotes:\n\tgit://github.com/repo/noe.git|]
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|