ey_resolver 0.1.0
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.
- 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
|