ey_resolver 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ class EY::Resolver
2
+ module Mock
3
+ require 'ey_resolver/mock/models'
4
+ end
5
+ end
@@ -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,12 @@
1
+ require 'dm-core'
2
+
3
+ class Account
4
+ include DataMapper::Resource
5
+
6
+ property :id, Serial
7
+ property :name, String
8
+
9
+ belongs_to :user
10
+ has n, :environments
11
+ has n, :apps
12
+ 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,10 @@
1
+ require 'dm-core'
2
+
3
+ class User
4
+ include DataMapper::Resource
5
+
6
+ property :id, Serial
7
+ property :name, String
8
+
9
+ has n, :accounts
10
+ 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,5 @@
1
+ module EY
2
+ class Resolver
3
+ VERSION = "0.1.0"
4
+ end
5
+ 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