cloudfinder-ec2 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitattributes +29 -0
- data/.gitignore +22 -0
- data/.rspec +3 -0
- data/.travis.yml +4 -0
- data/CONTRIBUTING.md +43 -0
- data/Gemfile +8 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +29 -0
- data/README.md +138 -0
- data/Rakefile +18 -0
- data/bin/cloudfinder +63 -0
- data/cloudfinder-ec2.gemspec +28 -0
- data/lib/cloudfinder-ec2.rb +8 -0
- data/lib/cloudfinder-ec2/cluster.rb +88 -0
- data/lib/cloudfinder-ec2/clusterfinder.rb +97 -0
- data/lib/cloudfinder-ec2/command/list.rb +72 -0
- data/lib/cloudfinder-ec2/consts.rb +6 -0
- data/lib/cloudfinder-ec2/detector.rb +69 -0
- data/lib/cloudfinder-ec2/instance.rb +34 -0
- data/lib/cloudfinder-ec2/version.rb +5 -0
- data/spec/cloudfinder-ec2/cluster_spec.rb +164 -0
- data/spec/cloudfinder-ec2/clusterfinder_spec.rb +265 -0
- data/spec/cloudfinder-ec2/command/list_spec.rb +131 -0
- data/spec/cloudfinder-ec2/detector_spec.rb +152 -0
- data/spec/cloudfinder-ec2/instance_spec.rb +30 -0
- data/spec/cloudfinder-ec2_spec.rb +5 -0
- data/spec/spec_helper.rb +15 -0
- metadata +149 -0
data/.gitattributes
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Autodetect text files, normalize to LF on commit
|
2
|
+
* text=auto
|
3
|
+
|
4
|
+
# Explicitly define files which should be LF when checked out and on commit
|
5
|
+
*.md text eol=lf
|
6
|
+
*.sh text eol=lf
|
7
|
+
*.rb text eol=lf diff=ruby
|
8
|
+
*.php text eol=lf diff=php
|
9
|
+
*.yml text eol=lf
|
10
|
+
*.sql text eol=lf
|
11
|
+
*.xml text eol=lf
|
12
|
+
*.xsd text eol=lf
|
13
|
+
*.css text eol=lf
|
14
|
+
*.js text eol=lf
|
15
|
+
*.pem text eol=lf
|
16
|
+
LICENSE text eol=lf
|
17
|
+
README text eol=lf
|
18
|
+
|
19
|
+
# Declare files that will always have CRLF line endings on checkout (still stored LF)
|
20
|
+
*.bat text eol=crlf
|
21
|
+
|
22
|
+
# Denote all files that are truly binary and should not be modified.
|
23
|
+
*.png binary
|
24
|
+
*.jpg binary
|
25
|
+
*.gif binary
|
26
|
+
*.ttf binary
|
27
|
+
*.swf binary
|
28
|
+
*.zip binary
|
29
|
+
*.sqlite binary
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
/.vagrant
|
2
|
+
# rcov generated
|
3
|
+
coverage
|
4
|
+
coverage.data
|
5
|
+
|
6
|
+
# rdoc generated
|
7
|
+
rdoc
|
8
|
+
|
9
|
+
# yard generated
|
10
|
+
doc
|
11
|
+
.yardoc
|
12
|
+
|
13
|
+
# bundler
|
14
|
+
.bundle
|
15
|
+
|
16
|
+
# jeweler generated
|
17
|
+
pkgtmp/
|
18
|
+
tmp/
|
19
|
+
|
20
|
+
# Don't include Gemfile.lock in gems
|
21
|
+
Gemfile.lock
|
22
|
+
pkg/
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
We love pull requests. Here's a quick guide:
|
2
|
+
|
3
|
+
1. Fork the repo, and make your changes.
|
4
|
+
|
5
|
+
2. Once you're ready to submit, rebase your branch against our master branch to
|
6
|
+
maintain a clean history and ensure you're up to date with all the most recent
|
7
|
+
changes.
|
8
|
+
|
9
|
+
3. Run the tests. We only take pull requests with passing tests, and it's great
|
10
|
+
to know that you have a clean slate: `bundle && rake`
|
11
|
+
|
12
|
+
4. Add a test for your change. Only refactoring and documentation changes
|
13
|
+
require no new tests. If you are adding functionality or fixing a bug, we need
|
14
|
+
a test!
|
15
|
+
|
16
|
+
5. Make the test pass.
|
17
|
+
|
18
|
+
6. Push to your fork and submit a pull request.
|
19
|
+
|
20
|
+
|
21
|
+
At this point you're waiting on us. We like to at least comment on, if not
|
22
|
+
accept, pull requests within three business days (and, typically, one business
|
23
|
+
day). We may suggest some changes or improvements or alternatives. Your pull request
|
24
|
+
will be built by [Travis](https://travis-ci.org/edbookfest/cloudfinder-ec2) first -
|
25
|
+
if the build fails please fix that first.
|
26
|
+
|
27
|
+
Some things that will increase the chance that your pull request is accepted,
|
28
|
+
taken straight from the Ruby on Rails guide:
|
29
|
+
|
30
|
+
* Include tests that fail without your code, and pass with it
|
31
|
+
* Update the documentation, the surrounding one, examples elsewhere, guides,
|
32
|
+
whatever is affected by your contribution
|
33
|
+
|
34
|
+
Syntax:
|
35
|
+
|
36
|
+
* Two spaces, no tabs.
|
37
|
+
* No trailing whitespace. Blank lines should not have any space.
|
38
|
+
* Prefer &&/|| over and/or.
|
39
|
+
* MyClass.my_method(my_arg) not my_method( my_arg ) or my_method my_arg.
|
40
|
+
* a = b and not a=b.
|
41
|
+
* Follow the conventions you see used in the source already.
|
42
|
+
|
43
|
+
And in case we didn't emphasize it enough: we love tests!
|
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
Copyright (c) 2015 Edinburgh International Book Festival Ltd, a
|
2
|
+
a company limited by guarantee (no SC 79939) with charitable status
|
3
|
+
(SC 010120). Registered office 5a Charlotte Square, Edinburgh, EH2 4DR.
|
4
|
+
|
5
|
+
All rights reserved.
|
6
|
+
|
7
|
+
Redistribution and use in source and binary forms, with or without modification, are
|
8
|
+
permitted provided that the following conditions are met:
|
9
|
+
|
10
|
+
1. Redistributions of source code must retain the above copyright notice, this list
|
11
|
+
of conditions and the following disclaimer.
|
12
|
+
|
13
|
+
2. Redistributions in binary form must reproduce the above copyright notice, this
|
14
|
+
list of conditions and the following disclaimer in the documentation and/or other
|
15
|
+
materials provided with the distribution.
|
16
|
+
|
17
|
+
3. Neither the name of the copyright holder nor the names of its contributors may
|
18
|
+
be used to endorse or promote products derived from this software without specific
|
19
|
+
prior written permission.
|
20
|
+
|
21
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
22
|
+
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
23
|
+
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
24
|
+
SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
25
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
26
|
+
OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
27
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
28
|
+
TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
29
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
# Cloudfinder::EC2
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/edbookfest/cloudfinder-ec2.png)](https://travis-ci.org/edbookfest/cloudfinder-ec2)
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/edbookfest/cloudfinder-ec2/badge.png?branch=master)](https://coveralls.io/r/edbookfest/cloudfinder-ec2)
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/cloudfinder-ec2.png)](http://badge.fury.io/rb/cloudfinder-ec2)
|
6
|
+
[![Code Climate](https://codeclimate.com/github/edbookfest/cloudfinder-ec2.png)](https://codeclimate.com/github/edbookfest/cloudfinder-ec2)
|
7
|
+
[![Dependency Status](https://gemnasium.com/edbookfest/cloudfinder-ec2.png)](https://gemnasium.com/edbookfest/cloudfinder-ec2)
|
8
|
+
|
9
|
+
Uses EC2 instance tags to locate all the running instances in a given cluster, grouped by role.
|
10
|
+
|
11
|
+
## Tagging your instances
|
12
|
+
|
13
|
+
An instance can belong to a single cluster, with a single role. These are identified based on two EC2 tags with the
|
14
|
+
keys `cloudfinder-cluster` and the `cloudfinder-role`. Add the tags to your instances using the AWS API, command line
|
15
|
+
tools, console, or as part of an auto-scaling-group launch configuration.
|
16
|
+
|
17
|
+
## API credentials
|
18
|
+
|
19
|
+
cloudfinder-ec2 needs access to a set of AWS credentials with read-only access to your EC2 instances. When running
|
20
|
+
on EC2, the best way to provide this is with an instance IAM role. Local AWS credentials files and environment
|
21
|
+
variables are also supported. For further information on credential management see the
|
22
|
+
[aws-sdk documentation](http://docs.aws.amazon.com/sdkforruby/api/index.html#Credentials)
|
23
|
+
|
24
|
+
## Cluster detection
|
25
|
+
|
26
|
+
By default, cloudfinder-ec2 will query the EC2 instance metadata API to attempt to detect the name and EC2 region
|
27
|
+
of the cluster containing the running instance.
|
28
|
+
|
29
|
+
If you are running outside EC2, or want to load details of a different cluster (for example if you are running
|
30
|
+
the command on an EC2 server that is not part of the cluster you're interested in) you can specify the cluster
|
31
|
+
name and region to load.
|
32
|
+
|
33
|
+
If you do not provide a cluster name and region, and you are not on EC2, then the command will fail.
|
34
|
+
|
35
|
+
## Usage
|
36
|
+
|
37
|
+
### As a shell command
|
38
|
+
|
39
|
+
Install the cloudfinder-ec2 binary by adding the gem to your system in the usual way
|
40
|
+
(`gem install cloudfinder-ec2`).
|
41
|
+
|
42
|
+
Running `cloudfinder-ec2 list` will output a JSON hash of the running cluster, grouped by role, which
|
43
|
+
looks something like this:
|
44
|
+
|
45
|
+
```json
|
46
|
+
{
|
47
|
+
"cluster_name": "production",
|
48
|
+
"roles": {
|
49
|
+
"loadbalancer": [
|
50
|
+
{
|
51
|
+
"instance_id": "i-00000001",
|
52
|
+
"public_ip": "46.137.96.1",
|
53
|
+
"public_dns": "ec2-46-137-96-1.eu-west-1.compute.amazonaws.com",
|
54
|
+
"private_dns": "ip-10-248-183-1.eu-west-1.compute.internal",
|
55
|
+
"private_ip": "10.248.183.1",
|
56
|
+
"role": "loadbalancer"
|
57
|
+
}
|
58
|
+
],
|
59
|
+
"app-server": [
|
60
|
+
{
|
61
|
+
"instance_id": "i-00000002",
|
62
|
+
"public_ip": "54.74.200.2",
|
63
|
+
"public_dns": "ec2-54-74-200-2.eu-west-1.compute.amazonaws.com",
|
64
|
+
"private_dns": "ip-10-56-18-2.eu-west-1.compute.internal",
|
65
|
+
"private_ip": "10.56.18.2",
|
66
|
+
"role": "app-server"
|
67
|
+
},
|
68
|
+
{
|
69
|
+
"instance_id": "i-00000003",
|
70
|
+
"public_ip": "54.74.200.3",
|
71
|
+
"public_dns": "ec2-54-74-200-3.eu-west-1.compute.amazonaws.com",
|
72
|
+
"private_dns": "ip-10-56-18-3.eu-west-1.compute.internal",
|
73
|
+
"private_ip": "10.56.18.3",
|
74
|
+
"role": "app-server"
|
75
|
+
}
|
76
|
+
],
|
77
|
+
"db-server": [
|
78
|
+
{
|
79
|
+
"instance_id": "i-00000004",
|
80
|
+
"public_ip": "54.220.216.4",
|
81
|
+
"public_dns": "ec2-54-220-216-4.eu-west-1.compute.amazonaws.com",
|
82
|
+
"private_dns": "ip-10-86-141-4.eu-west-1.compute.internal",
|
83
|
+
"private_ip": "10.86.141.4",
|
84
|
+
"role": "db-server"
|
85
|
+
}
|
86
|
+
]
|
87
|
+
}
|
88
|
+
}
|
89
|
+
```
|
90
|
+
|
91
|
+
This output is designed to be piped to a file or captured by any other process that needs information about
|
92
|
+
the composition of a given cluster.
|
93
|
+
|
94
|
+
### As a library
|
95
|
+
|
96
|
+
You can also use cloudfinder-ec2 as a gem within your ruby application. Add it to your project's Gemfile, and
|
97
|
+
then:
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
require 'cloudfinder-ec2'
|
101
|
+
cluster = Cloudfinder::EC2::Clusterfinder.new.find(cluster_name: 'production', region: 'eu-west-1)
|
102
|
+
# returns a Cloudfinder::EC2::Cluster instance with useful methods to interact with your cluster
|
103
|
+
|
104
|
+
if cluster.running?
|
105
|
+
puts cluster.list_roles
|
106
|
+
puts cluster.has_role?(:db)
|
107
|
+
puts cluster.list_role_instances(:db)
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
You can also autodetect the cluster if required. This will throw an exception if the instance metadata is
|
112
|
+
not available (eg because you are not on an EC2 instance).
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
require 'cloudfinder-ec2'
|
116
|
+
puts Cloudfinder::EC2::Clusterfinder.new.detect_cluster # {cluster_name: 'production', region: 'eu-west-1'}
|
117
|
+
```
|
118
|
+
|
119
|
+
### Within a chef recipe
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
chef_gem 'cloudfinder-ec2'
|
123
|
+
require 'cloudfinder-ec2'
|
124
|
+
# and use as a library as above
|
125
|
+
```
|
126
|
+
|
127
|
+
## Limitations
|
128
|
+
|
129
|
+
* Exceptions raised by the instance metadata service and/or AWS API are allowed to bubble, there is no
|
130
|
+
retry or recovery within the library.
|
131
|
+
* Currently we only fetch a single page of results from the AWS API. If you have more instances that fit
|
132
|
+
in a single describe instances call, you probably need a more sophisticated cluster discovery tool
|
133
|
+
* We only search for cluster instances in a single AWS region - again if you have multi-region clusters
|
134
|
+
you may be better with a more sophisticated tool
|
135
|
+
|
136
|
+
## Copyright
|
137
|
+
|
138
|
+
Copyright (c) 2015 Edinburgh International Book Festival Ltd. See LICENSE.txt for further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
# Change to the directory of this file.
|
7
|
+
Dir.chdir(File.expand_path("../", __FILE__))
|
8
|
+
|
9
|
+
# This installs the tasks that help with gem creation and
|
10
|
+
# publishing.
|
11
|
+
Bundler::GemHelper.install_tasks
|
12
|
+
|
13
|
+
require 'rspec/core/rake_task'
|
14
|
+
RSpec::Core::RakeTask.new do |t|
|
15
|
+
t.pattern = "spec/**/*_spec.rb"
|
16
|
+
end
|
17
|
+
|
18
|
+
task :default => :spec
|
data/bin/cloudfinder
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'cloudfinder-ec2'
|
3
|
+
require 'slop'
|
4
|
+
|
5
|
+
opts = Slop.new strict: true, help: true do
|
6
|
+
banner (<<-eos).gsub(/^ +/m, '')
|
7
|
+
Finds running EC2 instances using cloudfinder-cluster and cloudfinder-role tags
|
8
|
+
|
9
|
+
Requires credentials authorised for read-only access to the AWS API - by default
|
10
|
+
will look in:
|
11
|
+
|
12
|
+
* ENV['AWS_ACCESS_KEY_ID'] and ENV['AWS_SECRET_ACCESS_KEY'] (not recommended)
|
13
|
+
* a credentials file at ~/.aws/credentials
|
14
|
+
* an instance's configured IAM role when running on EC2 (recommended)
|
15
|
+
|
16
|
+
Credentials are more fully documented at
|
17
|
+
http://docs.aws.amazon.com/sdkforruby/api/index.html#Credentials
|
18
|
+
eos
|
19
|
+
|
20
|
+
command :list do
|
21
|
+
description 'Output details of the running cluster as JSON'
|
22
|
+
banner (<<-eos).gsub(/^ +/m, '')
|
23
|
+
Display the details of a running cluster as JSON
|
24
|
+
------------------------------------------------
|
25
|
+
Usage: cloudfinder-ec2 list [--cluster-name=production] [--region=eu-west-1]
|
26
|
+
|
27
|
+
By default, attempts to autodetect the name and/or region of the cluster from the EC2
|
28
|
+
metadata of this instance. If this is not an EC2 instance this will fail.
|
29
|
+
|
30
|
+
If you specify both the --cluster-name and --region arguments then autodetection will
|
31
|
+
be skipped.
|
32
|
+
eos
|
33
|
+
|
34
|
+
on '--cluster-name', 'Name of the cluster to load instead of autodetecting', argument: :optional
|
35
|
+
on '--region', 'EC2 region to search instead of autodetecting', argument: :optional
|
36
|
+
|
37
|
+
run do |opts|
|
38
|
+
Cloudfinder::EC2::Command::List.factory.execute(
|
39
|
+
cluster_name: opts['cluster-name'],
|
40
|
+
region: opts['region']
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
on '--version', 'Display the version' do
|
46
|
+
puts Cloudfinder::EC2::VERSION
|
47
|
+
end
|
48
|
+
|
49
|
+
# Treat running without a command as an error
|
50
|
+
run do
|
51
|
+
raise(Slop::InvalidCommandError, 'ERROR: You must specify the cloudfinder-command to run')
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
# Run the command
|
57
|
+
begin
|
58
|
+
opts.parse
|
59
|
+
rescue Slop::Error => e
|
60
|
+
STDERR.puts e.message
|
61
|
+
puts ''
|
62
|
+
puts opts # print help
|
63
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'cloudfinder-ec2/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "cloudfinder-ec2"
|
8
|
+
gem.version = Cloudfinder::EC2::VERSION
|
9
|
+
gem.authors = ["Andrew Coulton"]
|
10
|
+
gem.email = ["andrew@ingenerator.com"]
|
11
|
+
gem.license = 'BSD-3-Clause'
|
12
|
+
gem.description = 'Uses EC2 instance tags to locate all the running instances in a given cluster, grouped by role.'
|
13
|
+
gem.summary = gem.description
|
14
|
+
gem.homepage = "https://github.com/edbookfest/cloudfinder-ec2"
|
15
|
+
|
16
|
+
gem.files = `git ls-files`.split($/)
|
17
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
18
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
19
|
+
gem.require_paths = ["lib"]
|
20
|
+
|
21
|
+
gem.add_dependency 'aws-sdk', '~>2.0'
|
22
|
+
gem.add_dependency 'slop', '~>3.6'
|
23
|
+
|
24
|
+
gem.add_development_dependency 'rake'
|
25
|
+
gem.add_development_dependency 'rspec'
|
26
|
+
gem.add_development_dependency 'guard'
|
27
|
+
gem.add_development_dependency 'guard-rspec'
|
28
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
require 'aws-sdk'
|
2
|
+
require 'cloudfinder-ec2/version'
|
3
|
+
require 'cloudfinder-ec2/consts'
|
4
|
+
require 'cloudfinder-ec2/instance'
|
5
|
+
require 'cloudfinder-ec2/cluster'
|
6
|
+
require 'cloudfinder-ec2/clusterfinder'
|
7
|
+
require 'cloudfinder-ec2/detector'
|
8
|
+
require 'cloudfinder-ec2/command/list'
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Cloudfinder
|
2
|
+
module EC2
|
3
|
+
class Cluster
|
4
|
+
|
5
|
+
attr_reader(:cluster_name)
|
6
|
+
|
7
|
+
# @param [Hash] args containing the cluster name and the instances
|
8
|
+
# @return [Cloudfinder::EC2::Cluster]
|
9
|
+
def initialize(args)
|
10
|
+
@cluster_name = args[:cluster_name]
|
11
|
+
@instances = args[:instances]
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [bool]
|
15
|
+
def empty?
|
16
|
+
instances.empty?
|
17
|
+
end
|
18
|
+
|
19
|
+
# @return [bool]
|
20
|
+
def running?
|
21
|
+
!empty?
|
22
|
+
end
|
23
|
+
|
24
|
+
# @param [symbol] role
|
25
|
+
# @return [bool]
|
26
|
+
def has_role?(role)
|
27
|
+
list_roles.include?(role)
|
28
|
+
end
|
29
|
+
|
30
|
+
# @param [string] instance_id
|
31
|
+
# @return [bool]
|
32
|
+
def has_instance?(instance_id)
|
33
|
+
instances.any? { |instance| instance.instance_id == instance_id }
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_instance(instance_id)
|
37
|
+
found_instances = instances.select { |instance| instance.instance_id == instance_id }
|
38
|
+
raise(RangeError, "#{instance_id} is not part of the #{@cluster_name} cluster") if found_instances.empty?
|
39
|
+
found_instances.first
|
40
|
+
end
|
41
|
+
|
42
|
+
# @return [Array<symbol>]
|
43
|
+
def list_roles
|
44
|
+
instances.group_by { |instance| instance.role }.keys
|
45
|
+
end
|
46
|
+
|
47
|
+
# @param [symbol] role
|
48
|
+
# @return [Array<Cloudfinder::EC2::Instance>]
|
49
|
+
def list_role_instances(role)
|
50
|
+
instances.select { |instance| instance.role === role }
|
51
|
+
end
|
52
|
+
|
53
|
+
# Return the current cluster as a simple nested hash, suitable for rendering to JSON or similar
|
54
|
+
#
|
55
|
+
# {
|
56
|
+
# cluster_name: 'production',
|
57
|
+
# roles: {
|
58
|
+
# db: [
|
59
|
+
# {instance_id: 'i-00000001', public_ip: '123.456.789.123',...}
|
60
|
+
# ]
|
61
|
+
# }
|
62
|
+
# }
|
63
|
+
#
|
64
|
+
# @return [Hash]
|
65
|
+
def to_hash
|
66
|
+
hash = {
|
67
|
+
cluster_name: @cluster_name,
|
68
|
+
roles: {}
|
69
|
+
}
|
70
|
+
|
71
|
+
instances.each do |instance|
|
72
|
+
hash[:roles][instance.role] = [] unless hash[:roles][instance.role]
|
73
|
+
hash[:roles][instance.role] << instance.to_hash
|
74
|
+
end
|
75
|
+
|
76
|
+
hash
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
# @return [Array<Cloudfinder::EC2::Instance>]
|
82
|
+
def instances
|
83
|
+
@instances
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|