engineyard-metadata 0.1.2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -1,45 +1,45 @@
1
1
  = engineyard-metadata
2
2
 
3
- Presents a simple, unchanging interface to get metadata about your EngineYard AppCloud instances running on Amazon EC2.
3
+ Presents a simple interface to get metadata about your EngineYard AppCloud instances running on Amazon EC2.
4
4
 
5
5
  == Purpose
6
6
 
7
- To define an unchanging interface to useful metadata (passwords, IP addresses, etc.) that is otherwise buried deep inside EngineYard's chef config files and various API calls.
7
+ To define a simple interface to useful metadata (passwords, IP addresses, etc.) that is otherwise buried deep inside EngineYard's chef config files and various API calls.
8
8
 
9
9
  == Examples
10
10
 
11
- * Get a dynamically updated list of all running app servers so that you can pool memcached over all of them. (<tt>EY::Metadata.app_servers</tt>)
12
- * Get the current database password so that you can write a script that connects to it. (<tt>EY::Metadata.database_password</tt>)
11
+ * Get a dynamically updated list of all running app servers so that you can pool memcached over all of them. (<tt>EY.metadata.app_servers</tt>)
12
+ * Get the current database password so that you can write a script that connects to it. (<tt>EY.metadata.database_password</tt>)
13
13
 
14
14
  Here's the current method list:
15
15
 
16
- EY::Metadata.app_master
17
- EY::Metadata.app_name
18
- EY::Metadata.app_servers
19
- EY::Metadata.app_slaves
20
- EY::Metadata.current_path
21
- EY::Metadata.database_host
22
- EY::Metadata.database_name
23
- EY::Metadata.database_password (only works from cloud instances)
24
- EY::Metadata.database_username
25
- EY::Metadata.db_master
26
- EY::Metadata.db_servers
27
- EY::Metadata.db_slaves
28
- EY::Metadata.environment_name
29
- EY::Metadata.mysql_command (only works from cloud instances)
30
- EY::Metadata.mysqldump_command (only works from cloud instances)
31
- EY::Metadata.present_instance_id (only works from cloud instances)
32
- EY::Metadata.present_instance_role (only works from cloud instances)
33
- EY::Metadata.present_public_hostname (only works from cloud instances)
34
- EY::Metadata.present_security_group (only works from cloud instances)
35
- EY::Metadata.repository_uri
36
- EY::Metadata.shared_path
37
- EY::Metadata.solo
38
- EY::Metadata.ssh_aliases
39
- EY::Metadata.ssh_password (only works from cloud instances)
40
- EY::Metadata.ssh_username
41
- EY::Metadata.stack_name
42
- EY::Metadata.utilities
16
+ EY.metadata.app_master
17
+ EY.metadata.app_name
18
+ EY.metadata.app_servers
19
+ EY.metadata.app_slaves
20
+ EY.metadata.current_path
21
+ EY.metadata.database_host
22
+ EY.metadata.database_name
23
+ EY.metadata.database_password (only works from cloud instances)
24
+ EY.metadata.database_username
25
+ EY.metadata.db_master
26
+ EY.metadata.db_servers
27
+ EY.metadata.db_slaves
28
+ EY.metadata.environment_name
29
+ EY.metadata.mysql_command (only works from cloud instances)
30
+ EY.metadata.mysqldump_command (only works from cloud instances)
31
+ EY.metadata.present_instance_id (only works from cloud instances)
32
+ EY.metadata.present_instance_role (only works from cloud instances)
33
+ EY.metadata.present_public_hostname (only works from cloud instances)
34
+ EY.metadata.present_security_group (only works from cloud instances)
35
+ EY.metadata.repository_uri
36
+ EY.metadata.shared_path
37
+ EY.metadata.solo
38
+ EY.metadata.ssh_aliases
39
+ EY.metadata.ssh_password (only works from cloud instances)
40
+ EY.metadata.ssh_username
41
+ EY.metadata.stack_name
42
+ EY.metadata.utilities
43
43
 
44
44
  == Use
45
45
 
@@ -53,23 +53,23 @@ When you're executing the gem from your instances, you don't have to configure a
53
53
 
54
54
  You must...
55
55
 
56
- * have <tt>~/.eyrc</tt> or set <tt>EY::Metadata.ey_cloud_token=</tt> or set <tt>ENV['EY_CLOUD_TOKEN']</tt>.
57
- * execute the gem from the local copy of your application's repo or set <tt>EY::Metadata.environment_name=</tt> or set <tt>ENV['EY_ENVIRONMENT_NAME']</tt>.
56
+ * have <tt>~/.eyrc</tt> or set <tt>EY.metadata.ey_cloud_token=</tt> or set <tt>ENV['EY_CLOUD_TOKEN']</tt>.
57
+ * execute the gem from the local copy of your application's repo or set <tt>EY.metadata.environment_name=</tt> or set <tt>ENV['EY_ENVIRONMENT_NAME']</tt>.
58
58
 
59
59
  === Where the methods are defined
60
60
 
61
- Metadata getters are defined directly on <tt>EY::Metadata</tt> (which in turn delegates out to various adapters). Even if EngineYard changes the structure of the config files or Amazon EC2's API changes, these methods will stay the same.
61
+ Metadata getters are defined directly on <tt>EY.metadata</tt> (which in turn delegates out to various adapters). Even if EngineYard changes the structure of the config files or Amazon EC2's API changes, these methods will stay the same.
62
62
 
63
63
  [...]
64
64
  >> require 'rubygems'
65
65
  [...]
66
66
  >> require 'engineyard-metadata'
67
67
  [...]
68
- >> EY::Metadata.database_host
68
+ >> EY.metadata.database_host
69
69
  => "external_db_master.compute-1.amazonaws.com"
70
- >> EY::Metadata.app_servers
70
+ >> EY.metadata.app_servers
71
71
  => [ 'app_1.compute-1.amazonaws.com' , 'app_master.compute-1.amazonaws.com' ]
72
- >> EY::Metadata.db_servers
72
+ >> EY.metadata.db_servers
73
73
  => [ 'db_master.compute-1.amazonaws.com', 'db_slave_1.compute-1.amazonaws.com' ]
74
74
  [...and many more...]
75
75
 
@@ -90,8 +90,8 @@ You can put the output of <tt>ey_ssh_aliases</tt> into <tt>~/.ssh/config</tt>:
90
90
 
91
91
  == Known issues
92
92
 
93
- * Doesn't work with multiple apps per environment.
94
- * It's not always clear what environment you're running in. For example, you say <tt>EY::Metadata.something</tt> and you're just supposed to know what environment you're in. You can use <tt>.environment_name=</tt>, but you might not remember.
93
+ * Doesn't work with multiple apps per environment. [FIXED!]
94
+ * It's not always clear what environment you're running in. For example, you say <tt>EY.metadata.something</tt> and you're just supposed to know what environment you're in. You can use <tt>.environment_name=</tt>, but you might not remember.
95
95
  * There are no factory methods. If we fully fleshed this out, it might be like <tt>my_env = EY::Environment.find('my_env')</tt> and <tt>my_app_master = my_env.app_master</tt>. Not sure that complexity would add a lot of value.
96
96
 
97
97
  == History
data/Rakefile CHANGED
@@ -12,6 +12,7 @@ begin
12
12
  gem.authors = ["Seamus Abshere"]
13
13
  gem.add_dependency 'activesupport', '>=2.3.4'
14
14
  gem.add_dependency 'nap', '>=0.4'
15
+ gem.add_dependency 'eat'
15
16
  gem.add_development_dependency "fakeweb"
16
17
  gem.add_development_dependency "fakefs"
17
18
  gem.add_development_dependency "rspec", "~>2"
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.2.0
data/bin/ey_ssh_aliases CHANGED
@@ -3,4 +3,4 @@ unless RUBY_VERSION >= '1.9'
3
3
  require 'rubygems'
4
4
  end
5
5
  require 'engineyard-metadata'
6
- puts EY::Metadata.ssh_aliases
6
+ puts EY.metadata.ssh_aliases
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{engineyard-metadata}
8
- s.version = "0.1.2"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Seamus Abshere"]
12
- s.date = %q{2010-10-21}
12
+ s.date = %q{2011-01-12}
13
13
  s.default_executable = %q{ey_ssh_aliases}
14
14
  s.description = %q{Pulls metadata from EC2 and EngineYard so that your EngineYard AppCloud (Amazon EC2) instances know about each other.}
15
15
  s.email = %q{seamus@abshere.net}
@@ -58,12 +58,14 @@ Gem::Specification.new do |s|
58
58
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
59
59
  s.add_runtime_dependency(%q<activesupport>, [">= 2.3.4"])
60
60
  s.add_runtime_dependency(%q<nap>, [">= 0.4"])
61
+ s.add_runtime_dependency(%q<eat>, [">= 0"])
61
62
  s.add_development_dependency(%q<fakeweb>, [">= 0"])
62
63
  s.add_development_dependency(%q<fakefs>, [">= 0"])
63
64
  s.add_development_dependency(%q<rspec>, ["~> 2"])
64
65
  else
65
66
  s.add_dependency(%q<activesupport>, [">= 2.3.4"])
66
67
  s.add_dependency(%q<nap>, [">= 0.4"])
68
+ s.add_dependency(%q<eat>, [">= 0"])
67
69
  s.add_dependency(%q<fakeweb>, [">= 0"])
68
70
  s.add_dependency(%q<fakefs>, [">= 0"])
69
71
  s.add_dependency(%q<rspec>, ["~> 2"])
@@ -71,6 +73,7 @@ Gem::Specification.new do |s|
71
73
  else
72
74
  s.add_dependency(%q<activesupport>, [">= 2.3.4"])
73
75
  s.add_dependency(%q<nap>, [">= 0.4"])
76
+ s.add_dependency(%q<eat>, [">= 0"])
74
77
  s.add_dependency(%q<fakeweb>, [">= 0"])
75
78
  s.add_dependency(%q<fakefs>, [">= 0"])
76
79
  s.add_dependency(%q<rspec>, ["~> 2"])
@@ -1,3 +1,6 @@
1
1
  module EY
2
2
  autoload :Metadata, 'engineyard-metadata/metadata'
3
+ def self.metadata
4
+ Metadata.instance
5
+ end
3
6
  end
@@ -1,17 +1,17 @@
1
- require 'open-uri'
1
+ require 'eat'
2
2
 
3
3
  module EY
4
- module Metadata
4
+ class Metadata
5
5
  # An adapter that reads from Amazon EC2's metadata web service, which is only available from cloud instances.
6
6
  class AmazonEc2Api
7
7
  # The present instance's Amazon Ec2 instance id.
8
8
  def present_instance_id
9
- open("http://169.254.169.254/latest/meta-data/instance-id").gets
9
+ @present_instance_id ||= eat 'http://169.254.169.254/latest/meta-data/instance-id'
10
10
  end
11
11
 
12
12
  # The present instance's Amazon Ec2 security group.
13
13
  def present_security_group
14
- open('http://169.254.169.254/latest/meta-data/security-groups').gets
14
+ @present_security_group ||= eat 'http://169.254.169.254/latest/meta-data/security-groups'
15
15
  end
16
16
  end
17
17
  end
@@ -7,62 +7,49 @@ require 'active_support/version'
7
7
  end if ActiveSupport::VERSION::MAJOR == 3
8
8
 
9
9
  module EY
10
- module Metadata
10
+ class Metadata
11
11
  # An adapter that reads from /etc/chef/dna.json, which is only available on cloud instances.
12
12
  class ChefDna
13
13
  PATH = '/etc/chef/dna.json'
14
14
 
15
15
  include SshAliasHelper
16
16
 
17
- def data # :nodoc:
18
- @data ||= ActiveSupport::JSON.decode File.read(PATH)
17
+ def dna # :nodoc:
18
+ @dna ||= ActiveSupport::JSON.decode File.read(PATH)
19
+ end
20
+
21
+ def application # :nodoc:
22
+ dna['engineyard']['environment']['apps'].detect { |a| a['name'] == EY.metadata.app_name }
19
23
  end
20
24
 
21
25
  # The present instance's role
22
26
  def present_instance_role
23
- data['instance_role']
27
+ dna['instance_role']
24
28
  end
25
29
 
26
30
  # The present instance's public hostname.
27
31
  def present_public_hostname
28
- data['engineyard']['environment']['instances'].detect { |i| i['id'] == EY::Metadata.present_instance_id }['public_hostname']
32
+ dna['engineyard']['environment']['instances'].detect { |i| i['id'] == EY.metadata.present_instance_id }['public_hostname']
29
33
  end
30
34
 
31
35
  # Currently the same as the SSH password.
32
36
  def database_password
33
- data['users'][0]['password']
37
+ dna['users'][0]['password']
34
38
  end
35
39
 
36
40
  # Currently the same as the SSH username.
37
41
  def database_username
38
- data['users'][0]['username']
42
+ dna['users'][0]['username']
39
43
  end
40
44
 
41
45
  # For newly deployed applications, equal to the application name.
42
46
  def database_name
43
- data['engineyard']['environment']['apps'][0]['database_name']
47
+ application['database_name']
44
48
  end
45
49
 
46
50
  # The git repository that you told EngineYard to use for this application.
47
51
  def repository_uri
48
- data['engineyard']['environment']['apps'][0]['repository_name']
49
- end
50
-
51
- # The name of the single app that runs in this environment.
52
- #
53
- # Warning: this gem currently doesn't support multiple apps per environment.
54
- def app_name
55
- data['engineyard']['environment']['apps'][0]['name']
56
- end
57
-
58
- # The path to the current deploy on app servers.
59
- def current_path
60
- "/data/#{app_name}/current"
61
- end
62
-
63
- # The path to the shared directory on app servers.
64
- def shared_path
65
- "/data/#{app_name}/shared"
52
+ application['repository_name']
66
53
  end
67
54
 
68
55
  # Public hostname where you should connect to the database.
@@ -74,50 +61,50 @@ module EY
74
61
 
75
62
  # SSH username.
76
63
  def ssh_username
77
- data['engineyard']['environment']['ssh_username']
64
+ dna['engineyard']['environment']['ssh_username']
78
65
  end
79
66
 
80
67
  # SSH password.
81
68
  def ssh_password
82
- data['engineyard']['environment']['ssh_password']
69
+ dna['engineyard']['environment']['ssh_password']
83
70
  end
84
71
 
85
72
  # The public hostnames of all the app servers.
86
73
  #
87
74
  # If you're on a solo app, it counts the solo as an app server.
88
75
  def app_servers
89
- data['engineyard']['environment']['instances'].select { |i| %w{ app_master app solo }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
76
+ dna['engineyard']['environment']['instances'].select { |i| %w{ app_master app solo }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
90
77
  end
91
78
 
92
79
  # The public hostnames of all the app slaves.
93
80
  def app_slaves
94
- data['engineyard']['environment']['instances'].select { |i| %w{ app }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
81
+ dna['engineyard']['environment']['instances'].select { |i| %w{ app }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
95
82
  end
96
83
 
97
84
  # The public hostnames of all the db servers.
98
85
  #
99
86
  # If you're on a solo app, it counts the solo as a db server.
100
87
  def db_servers
101
- data['engineyard']['environment']['instances'].select { |i| %w{ db_master db_slave solo }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
88
+ dna['engineyard']['environment']['instances'].select { |i| %w{ db_master db_slave solo }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
102
89
  end
103
90
 
104
91
  # The public hostnames of all the db slaves.
105
92
  def db_slaves
106
- data['engineyard']['environment']['instances'].select { |i| %w{ db_slave }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
93
+ dna['engineyard']['environment']['instances'].select { |i| %w{ db_slave }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
107
94
  end
108
95
 
109
96
  # The public hostnames of all the utility servers.
110
97
  #
111
98
  # If you're on a solo app, it counts the solo as a utility.
112
99
  def utilities
113
- data['engineyard']['environment']['instances'].select { |i| %w{ util solo }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
100
+ dna['engineyard']['environment']['instances'].select { |i| %w{ util solo }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
114
101
  end
115
102
 
116
103
  # The public hostname of the app_master.
117
104
  #
118
105
  # If you're on a solo app, it counts the solo as the app_master.
119
106
  def app_master
120
- if x = data['engineyard']['environment']['instances'].detect { |i| i['role'] == 'app_master' }
107
+ if x = dna['engineyard']['environment']['instances'].detect { |i| i['role'] == 'app_master' }
121
108
  x['public_hostname']
122
109
  else
123
110
  solo
@@ -128,7 +115,7 @@ module EY
128
115
  #
129
116
  # If you're on a solo app, it counts the solo as the app_master.
130
117
  def db_master
131
- if x = data['engineyard']['environment']['instances'].detect { |i| i['role'] == 'db_master' }
118
+ if x = dna['engineyard']['environment']['instances'].detect { |i| i['role'] == 'db_master' }
132
119
  x['public_hostname']
133
120
  else
134
121
  solo
@@ -137,7 +124,7 @@ module EY
137
124
 
138
125
  # The public hostname of the solo.
139
126
  def solo
140
- if x = data['engineyard']['environment']['instances'].detect { |i| i['role'] == 'solo' }
127
+ if x = dna['engineyard']['environment']['instances'].detect { |i| i['role'] == 'solo' }
141
128
  x['public_hostname']
142
129
  end
143
130
  end
@@ -154,12 +141,12 @@ module EY
154
141
 
155
142
  # The name of the EngineYard AppCloud environment.
156
143
  def environment_name
157
- data['environment']['name']
144
+ dna['environment']['name']
158
145
  end
159
146
 
160
147
  # The stack in use, like nginx_passenger.
161
148
  def stack_name
162
- data['engineyard']['environment']['stack_name']
149
+ dna['engineyard']['environment']['stack_name']
163
150
  end
164
151
  end
165
152
  end
@@ -4,35 +4,41 @@ require 'active_support'
4
4
  require 'active_support/version'
5
5
  %w{
6
6
  active_support/json
7
+ active_support/core_ext/enumerable
7
8
  }.each do |active_support_3_requirement|
8
9
  require active_support_3_requirement
9
10
  end if ActiveSupport::VERSION::MAJOR == 3
10
11
 
11
12
  module EY
12
- module Metadata
13
+ class Metadata
13
14
  # An adapter that reads from the public EngineYard Cloud API (https://cloud.engineyard.com). Available from anywhere.
14
15
  #
15
16
  # See README for what environment variables and/or files you need to have in place for this to work.
16
17
  class EngineYardCloudApi
18
+ attr_reader :last_used_ey_cloud_token
17
19
  URL = 'https://cloud.engineyard.com/api/v2/environments'
18
20
 
19
21
  include SshAliasHelper
20
22
 
23
+ def initialize(last_used_ey_cloud_token)
24
+ @last_used_ey_cloud_token = last_used_ey_cloud_token
25
+ end
26
+
21
27
  # Currently the same as the SSH username.
22
28
  def database_username
23
- data['ssh_username']
29
+ environment['ssh_username']
24
30
  end
25
31
 
26
32
  # The username for connecting by SSH.
27
33
  def ssh_username
28
- data['ssh_username']
34
+ environment['ssh_username']
29
35
  end
30
36
 
31
37
  # Currently the same as the app name, at least for recently-created environments.
32
38
  #
33
39
  # This is less reliable that the answer you would get running from an instance, because databases used to be named after environments.
34
40
  def database_name
35
- app_name
41
+ EY.metadata.app_name
36
42
  end
37
43
 
38
44
  # The hostname of the database host.
@@ -44,7 +50,7 @@ module EY
44
50
  #
45
51
  # If you're on a solo app, it counts the solo as the app_master.
46
52
  def db_master
47
- if x = data['instances'].detect { |i| i['role'] == 'db_master' }
53
+ if x = environment['instances'].detect { |i| i['role'] == 'db_master' }
48
54
  x['public_hostname']
49
55
  else
50
56
  solo
@@ -55,38 +61,38 @@ module EY
55
61
  #
56
62
  # If you're on a solo app, it counts the solo as an app server.
57
63
  def app_servers
58
- data['instances'].select { |i| %w{ app_master app solo }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
64
+ environment['instances'].select { |i| %w{ app_master app solo }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
59
65
  end
60
66
 
61
67
  # The public hostnames of all the db servers.
62
68
  #
63
69
  # If you're on a solo app, it counts the solo as a db server.
64
70
  def db_servers
65
- data['instances'].select { |i| %w{ db_master db_slave solo }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
71
+ environment['instances'].select { |i| %w{ db_master db_slave solo }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
66
72
  end
67
73
 
68
74
  # The public hostnames of all the utility servers.
69
75
  #
70
76
  # If you're on a solo app, it counts the solo as a utility.
71
77
  def utilities
72
- data['instances'].select { |i| %w{ util solo }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
78
+ environment['instances'].select { |i| %w{ util solo }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
73
79
  end
74
80
 
75
81
  # The public hostnames of all the app slaves.
76
82
  def app_slaves
77
- data['instances'].select { |i| %w{ app }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
83
+ environment['instances'].select { |i| %w{ app }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
78
84
  end
79
85
 
80
86
  # The public hostnames of all the db slaves.
81
87
  def db_slaves
82
- data['instances'].select { |i| %w{ db_slave }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
88
+ environment['instances'].select { |i| %w{ db_slave }.include? i['role'] }.map { |i| i['public_hostname'] }.sort
83
89
  end
84
90
 
85
91
  # The public hostname of the app_master.
86
92
  #
87
93
  # If you're on a solo app, it counts the solo as the app_master.
88
94
  def app_master
89
- if x = data['instances'].detect { |i| i['role'] == 'app_master' }
95
+ if x = environment['instances'].detect { |i| i['role'] == 'app_master' }
90
96
  x['public_hostname']
91
97
  else
92
98
  solo
@@ -95,75 +101,109 @@ module EY
95
101
 
96
102
  # The public hostname of the solo.
97
103
  def solo
98
- if x = data['instances'].detect { |i| i['role'] == 'solo' }
104
+ if x = environment['instances'].detect { |i| i['role'] == 'solo' }
99
105
  x['public_hostname']
100
106
  end
101
107
  end
102
108
 
103
109
  # The name of the EngineYard AppCloud environment.
104
110
  def environment_name
105
- data['name']
111
+ environment['name']
106
112
  end
107
113
 
108
114
  # The stack in use, like nginx_passenger.
109
115
  def stack_name
110
- data['stack_name']
116
+ environment['stack_name']
111
117
  end
112
118
 
113
119
  # The git repository that you told EngineYard to use for this application.
114
120
  def repository_uri
115
- data['apps'][0]['repository_uri']
121
+ application['repository_uri']
116
122
  end
117
-
123
+
118
124
  # A list of all the environment names belonging to this account.
119
125
  def environment_names
120
126
  environments.map { |environment| environment['name'] }
121
127
  end
122
128
 
123
- # The name of the single app that runs in this environment.
124
- #
125
- # Warning: this gem currently doesn't support multiple apps per environment.
129
+ # The name of the app we're looking at.
126
130
  def app_name
127
- data['apps'][0]['name']
131
+ application['name']
132
+ end
133
+
134
+ # Used internally to store the full list of environments that the API gives us.
135
+ def environments
136
+ return @environments if @environments.is_a? Array
137
+ raw_json = REST.get(URL, 'X-EY-Cloud-Token' => last_used_ey_cloud_token).body
138
+ raw_data = ActiveSupport::JSON.decode raw_json
139
+ @environments = raw_data['environments']
140
+ end
141
+
142
+ # Used internally to store data about the specific application we're working with.
143
+ def application
144
+ hit = if EY.metadata.preset_app_name?
145
+ catch(:found_it) do
146
+ environments.each do |e|
147
+ if hit = e['apps'].detect { |a| a['name'] == EY.metadata.app_name }
148
+ throw :found_it, hit
149
+ end
150
+ end
151
+ end
152
+ elsif possible_to_detect_app_from_environment_name?
153
+ environment['apps'][0]
154
+ elsif possible_to_detect_app_from_git_config?
155
+ catch(:found_it) do
156
+ environments.each do |e|
157
+ if hit = e['apps'].detect { |a| a['repository_uri'] == repository_uri_from_git_config }
158
+ throw :found_it, hit
159
+ end
160
+ end
161
+ end
162
+ end
163
+ raise RuntimeError, "[engineyard-metadata gem] Couldn't find a matching application. Please set EY.metadata.app_name= or ENV['EY_APP_NAME']" unless hit
164
+ hit
128
165
  end
129
166
 
130
- # The path to the current deploy on app servers.
131
- def current_path
132
- "/data/#{app_name}/current"
167
+ def repository_uri_from_git_config
168
+ return @repository_uri_from_git_config if @repository_uri_from_git_config.is_a? String
169
+ git_config_path = File.join Dir.pwd, '.git', 'config'
170
+ if File.exist? git_config_path
171
+ git_config = File.read git_config_path
172
+ git_config =~ /^\[remote.*?\burl = (.*?)\n/m
173
+ @repository_uri_from_git_config = $1
174
+ end
133
175
  end
134
176
 
135
- # The path to the shared directory on app servers.
136
- def shared_path
137
- "/data/#{app_name}/shared"
177
+ def possible_to_detect_app_from_environment_name?
178
+ environment['apps'].length == 1
138
179
  end
139
180
 
140
- # Used internally to determine whether we've decoded the API response yet.
141
- def data_loaded?
142
- defined?(@data) and @data.is_a? Hash
181
+ def possible_to_detect_environment_from_app_name?
182
+ return false unless EY.metadata.preset_app_name?
183
+ environments.sum { |e| e['apps'].sum { |a| (a['name'] == EY.metadata.app_name) ? 1 : 0 } } == 1
143
184
  end
144
185
 
145
- # Used internally to store the full list of environments that the API gives us.
146
- def environments
147
- return @environments if @environments.is_a? Array
148
- raw_json = REST.get(URL, 'X-EY-Cloud-Token' => EY::Metadata.ey_cloud_token).body
149
- raw_data = ActiveSupport::JSON.decode raw_json
150
- @environments = raw_data['environments']
186
+ def possible_to_detect_app_from_git_config?
187
+ return false unless repository_uri_from_git_config
188
+ environments.sum { |e| e['apps'].sum { |a| (a['repository_uri'] == repository_uri_from_git_config) ? 1 : 0 } } == 1
189
+ end
190
+
191
+ def possible_to_detect_environment_from_git_config?
192
+ return false unless repository_uri_from_git_config
193
+ environments.any? { |e| e['apps'].any? { |a| a['repository_uri'] == repository_uri_from_git_config } }
151
194
  end
152
195
 
153
196
  # Used internally to store data about the specific environment we're working with.
154
- def data
155
- return @data if data_loaded?
156
- matching_environments = environments.select do |environment|
157
- if EY::Metadata.environment_name
158
- environment['name'] == EY::Metadata.environment_name
159
- else
160
- environment['apps'].any? { |app| app['repository_uri'] == EY::Metadata.repository_uri }
161
- end
197
+ def environment
198
+ hit = if EY.metadata.preset_environment_name?
199
+ environments.detect { |e| e['name'] == EY.metadata.environment_name }
200
+ elsif possible_to_detect_environment_from_app_name?
201
+ environments.detect { |e| e['apps'].any? { |a| a['name'] == EY.metadata.app_name } }
202
+ elsif possible_to_detect_environment_from_git_config?
203
+ environments.detect { |e| e['apps'].any? { |a| a['repository_uri'] == repository_uri_from_git_config } }
162
204
  end
163
- raise RuntimeError, "[engineyard-metadata gem] Found too many environments: #{matching_environments.map { |environment| environments['name'] }.join(', ')}" if matching_environments.length > 1
164
- @data = matching_environments[0]
165
- raise RuntimeError, "[engineyard-metadata gem] Couldn't find an EngineYard environment with the repository uri #{repository_uri}" unless data_loaded?
166
- @data
205
+ raise RuntimeError, "[engineyard-metadata gem] Couldn't find a matching environment. Please set EY.metadata.environment_name= or ENV['EY_ENVIRONMENT_NAME']" unless hit
206
+ hit
167
207
  end
168
208
  end
169
209
  end