phase 0.0.2 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Makefile +6 -10
- data/VERSION +1 -1
- data/bin/phase +2 -1
- data/lib/phase/adapter.rb +19 -0
- data/lib/phase/adapters/abstract/base.rb +23 -0
- data/lib/phase/adapters/abstract/load_balancer.rb +27 -0
- data/lib/phase/adapters/abstract/network.rb +29 -0
- data/lib/phase/adapters/abstract/server.rb +29 -0
- data/lib/phase/adapters/abstract.rb +4 -0
- data/lib/phase/adapters/aws/load_balancer.rb +43 -0
- data/lib/phase/adapters/aws/network.rb +41 -0
- data/lib/phase/adapters/aws/server.rb +54 -0
- data/lib/phase/adapters/aws/subnet.rb +49 -0
- data/lib/phase/adapters/aws.rb +4 -28
- data/lib/phase/cli/all.rb +3 -3
- data/lib/phase/cli/keys.rb +1 -1
- data/lib/phase/cli/logs.rb +1 -1
- data/lib/phase/cli/{utils → mixins}/loggable.rb +1 -1
- data/lib/phase/cli/mosh.rb +1 -1
- data/lib/phase/cli/ssh.rb +9 -8
- data/lib/phase/cli/status.rb +28 -28
- data/lib/phase/cli.rb +13 -8
- data/lib/phase/configuration.rb +7 -3
- data/lib/phase/dsl.rb +17 -7
- data/lib/phase/version.rb +1 -1
- data/lib/phase.rb +25 -14
- data/phase.gemspec +3 -2
- data/spec/dsl_spec.rb +19 -0
- data/spec/spec_helper.rb +2 -0
- metadata +32 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eb2f988f05568590899c7ae5f3d4455c775af120
|
4
|
+
data.tar.gz: 1f04b470293e4276ee7f3583ca8346d57bd00769
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74f5bf568f42b2f10abc042a06493cfc965d0266562142ec027f865e8ed06bd3509c37b50bd4f5e5c77032824c2b17b61258143e382882f13a2cdf30de342428
|
7
|
+
data.tar.gz: 4611698b760898ee8e8589b0c7ec00fc1a872433426122f4d22a2c864d9da6d80c49cb4d2c7c53ff67ea0b93a10fd35529051221c79c4e80cabced72230cefb3
|
data/Makefile
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
VERSION=$(shell cat VERSION)
|
2
2
|
|
3
3
|
.PHONY: default all clean install
|
4
|
-
default:
|
5
|
-
all: build
|
4
|
+
default: all
|
5
|
+
all: reset build
|
6
6
|
|
7
7
|
build: lib/phase/version.rb
|
8
8
|
gem build phase.gemspec
|
@@ -11,12 +11,8 @@ lib/phase/version.rb:
|
|
11
11
|
mkdir -p $(@D)
|
12
12
|
@echo 'module Phase\n VERSION = "$(VERSION)"\nend' > $@
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
rbenv rehash
|
14
|
+
reset:
|
15
|
+
rm lib/phase/version.rb
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
clean:
|
22
|
-
rm -rf lib/phase/version.rb
|
17
|
+
push:
|
18
|
+
gem push phase-$(VERSION).gem
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.4
|
data/bin/phase
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
module Phase
|
2
|
+
class << self
|
3
|
+
def load_balancers
|
4
|
+
adapter.const_get("LoadBalancer")
|
5
|
+
end
|
6
|
+
|
7
|
+
def networks
|
8
|
+
adapter.const_get("Network")
|
9
|
+
end
|
10
|
+
|
11
|
+
def servers
|
12
|
+
adapter.const_get("Server")
|
13
|
+
end
|
14
|
+
|
15
|
+
def subnets
|
16
|
+
adapter.const_get("Subnet")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Phase
|
2
|
+
module Adapters
|
3
|
+
module Abstract
|
4
|
+
class Base
|
5
|
+
|
6
|
+
attr_reader :resource
|
7
|
+
|
8
|
+
def initialize(resource)
|
9
|
+
@resource = resource
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
private
|
14
|
+
|
15
|
+
def api
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Phase
|
2
|
+
module Adapters
|
3
|
+
module Abstract
|
4
|
+
class LoadBalancer < Base
|
5
|
+
|
6
|
+
def deregister_server(server_id, options = {})
|
7
|
+
raise NotImplementedError
|
8
|
+
end
|
9
|
+
|
10
|
+
def register_server(server_id, options = {})
|
11
|
+
raise NotImplementedError
|
12
|
+
end
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def all(balancer_id)
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
|
19
|
+
def find(balancer_id)
|
20
|
+
raise NotImplementedError
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Phase
|
2
|
+
module Adapters
|
3
|
+
module Abstract
|
4
|
+
class Network < Base
|
5
|
+
|
6
|
+
def servers
|
7
|
+
raise NotImplementedError
|
8
|
+
end
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def all(network_id)
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
|
15
|
+
def find(network_id)
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def api
|
22
|
+
raise NotImplementedError
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Phase
|
2
|
+
module Adapters
|
3
|
+
module Abstract
|
4
|
+
class Server < Base
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def all
|
8
|
+
raise NotImplementedError
|
9
|
+
end
|
10
|
+
|
11
|
+
def find(server_id)
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
|
15
|
+
def where(options = {})
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def api
|
22
|
+
raise NotImplementedError
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module Phase
|
2
|
+
module Adapters
|
3
|
+
module AWS
|
4
|
+
class LoadBalancer < ::Phase::Adapters::Abstract::LoadBalancer
|
5
|
+
|
6
|
+
# @param [String] server_id The ID of the instance to deregister
|
7
|
+
# @return [AWS::Server] The deregistered EC2 instance
|
8
|
+
def deregister_server(server_id, options = {})
|
9
|
+
end
|
10
|
+
|
11
|
+
# @param [String] server_id The ID of the instance to register
|
12
|
+
# @return [AWS::Server] The registered EC2 instance
|
13
|
+
def register_server(server_id, options = {})
|
14
|
+
end
|
15
|
+
|
16
|
+
# @return [Array<AWS::Server>] The EC2 instances registered to this ELB instance
|
17
|
+
def servers
|
18
|
+
Server.all(instance_ids: resource.instances)
|
19
|
+
end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
# @return [Array<AWS::LoadBalancer>] All known ELB instances
|
23
|
+
def all
|
24
|
+
api.load_balancers.all.map {|balancer| new(balancer) }
|
25
|
+
end
|
26
|
+
|
27
|
+
# @param [String] balancer_name The name of the requested ELB instance
|
28
|
+
# @return [AWS::LoadBalancer] The requested ELB instance
|
29
|
+
def find(balancer_name)
|
30
|
+
new(api.load_balancers.get(balancer_name))
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def api
|
36
|
+
@api ||= ::Fog::AWS::ELB.new(region: ::Phase.config.aws_region)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Phase
|
2
|
+
module Adapters
|
3
|
+
module AWS
|
4
|
+
class Network < ::Phase::Adapters::Abstract::Network
|
5
|
+
|
6
|
+
# @param [Hash] options Filtering options
|
7
|
+
# @see Phase::Adapters::AWS::Server.where Additional filter documentation
|
8
|
+
# @return [Array<AWS::Server>] The AWS instances within this VPC
|
9
|
+
def servers(options = {})
|
10
|
+
options[:vpc_id] = resource.id
|
11
|
+
Server.where(options)
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [Array<Fog::Compute::AWS::Subnet>] The subnets within this VPC
|
15
|
+
def subnets
|
16
|
+
Subnet.where(vpc_id: resource.id)
|
17
|
+
end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
# @return [Array<AWS::Network>] All known VPC instances
|
21
|
+
def all
|
22
|
+
api.vpcs.all.map {|network| new(network) }
|
23
|
+
end
|
24
|
+
|
25
|
+
# @param [String] network_id The ID of the requested VPC
|
26
|
+
# @return [AWS::Network, nil] The requested VPC
|
27
|
+
def find(network_id)
|
28
|
+
new(api.vpcs.get(network_id))
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def api
|
34
|
+
@api ||= ::Fog::Compute::AWS.new(region: ::Phase.config.aws_region)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module Phase
|
2
|
+
module Adapters
|
3
|
+
module AWS
|
4
|
+
class Server < ::Phase::Adapters::Abstract::Server
|
5
|
+
|
6
|
+
class << self
|
7
|
+
# @return [Array<AWS::Server>] All known EC2 instances
|
8
|
+
def all
|
9
|
+
where
|
10
|
+
end
|
11
|
+
|
12
|
+
# @param [String] instance_id The ID of the requested EC2 instance
|
13
|
+
# @return [AWS::Server] The requested EC2 instance
|
14
|
+
def find(instance_id, options = {})
|
15
|
+
new(api.servers.get(instance_id))
|
16
|
+
end
|
17
|
+
|
18
|
+
# @param [Hash] options Filtering options
|
19
|
+
# @option options [String] :vpc_id The ID of a VPC
|
20
|
+
# @option options [String] :name The value of the 'Name' tag
|
21
|
+
# @option options [String] :role The value of the 'Role' tag
|
22
|
+
# @option options [String] :environment The value of the 'Environment' tag
|
23
|
+
# @option options [Array<String>] :instance_ids A list of specific instance IDs
|
24
|
+
# @option options [String] :subnet_id The ID of a subnet
|
25
|
+
# @return [Array<AWS::Server>] All EC2 instances matching the optional filters
|
26
|
+
def where(options = {})
|
27
|
+
filters = {}
|
28
|
+
|
29
|
+
filters["vpc-id"] = options.delete(:vpc_id) if options[:vpc_id]
|
30
|
+
filters["tag:Name"] = options.delete(:name) if options[:name]
|
31
|
+
filters["instance-ids"] = options.delete(:ids) if options[:ids]
|
32
|
+
filters["subnet-id"] = options.delete(:subnet_id) if options[:subnet_id]
|
33
|
+
|
34
|
+
filters["tag:Role"] = options.delete(:role) if options[:role]
|
35
|
+
filters["tag:Environment"] = options.delete(:environment) if options[:environment]
|
36
|
+
|
37
|
+
if options.any?
|
38
|
+
raise ArgumentError, "Unknown filters '#{options.keys.join(", ")}'!"
|
39
|
+
end
|
40
|
+
|
41
|
+
api.servers.all(filters).map {|server| new(server) }
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def api
|
47
|
+
@api ||= ::Fog::Compute::AWS.new(region: ::Phase.config.aws_region)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Phase
|
2
|
+
module Adapters
|
3
|
+
module AWS
|
4
|
+
class Subnet < ::Phase::Adapters::Abstract::Base
|
5
|
+
|
6
|
+
# @param [Hash] options Filtering options
|
7
|
+
# @see Phase::Adapters::AWS::Server.where Additional filter documentation
|
8
|
+
# @return [Array<AWS::Server>] The AWS instances within this VPC
|
9
|
+
def servers(options = {})
|
10
|
+
options[:subnet_id] = resource.subnet_id
|
11
|
+
Server.where(options)
|
12
|
+
end
|
13
|
+
|
14
|
+
class << self
|
15
|
+
# @return [Array<AWS::Subnet>] All known subnets
|
16
|
+
def all
|
17
|
+
where
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param [String] subnet_id The ID of the requested subnet
|
21
|
+
# @return [AWS::Subnet, nil] The requested subnet
|
22
|
+
def find(subnet_id)
|
23
|
+
new(api.subnets.get(subnet_id))
|
24
|
+
end
|
25
|
+
|
26
|
+
# @param [Hash] options Filtering options
|
27
|
+
# @option options [String] :vpc_id The ID of a VPC
|
28
|
+
# @option options [String] :name The value of the 'Name' tag
|
29
|
+
# @return [Array<AWS::Subnet>] All subnets matching the optional filters
|
30
|
+
def where(options = {})
|
31
|
+
filters = {}
|
32
|
+
|
33
|
+
filters["vpc-id"] = options[:vpc_id] if options[:vpc_id]
|
34
|
+
filters["tag:Name"] = options[:name] if options[:name]
|
35
|
+
|
36
|
+
api.subnets.all(filters).map {|subnet| new(subnet) }
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def api
|
42
|
+
@api ||= ::Fog::Compute::AWS.new(region: ::Phase.config.aws_region)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/phase/adapters/aws.rb
CHANGED
@@ -1,28 +1,4 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
require "fog/aws"
|
6
|
-
|
7
|
-
def find_servers(options = {})
|
8
|
-
query = {}
|
9
|
-
|
10
|
-
if options[:role]
|
11
|
-
query["tag:Role"] = options[:role]
|
12
|
-
end
|
13
|
-
|
14
|
-
ec2.servers.all(query).map do |h|
|
15
|
-
{
|
16
|
-
hostname: h.dns_name,
|
17
|
-
user: "orca"
|
18
|
-
}
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def ec2
|
23
|
-
@ec2 ||= ::Fog::Compute::AWS.new(region: ::Phase.config.aws_region)
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
1
|
+
require 'phase/adapters/aws/load_balancer'
|
2
|
+
require 'phase/adapters/aws/network'
|
3
|
+
require 'phase/adapters/aws/server'
|
4
|
+
require 'phase/adapters/aws/subnet'
|
data/lib/phase/cli/all.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
require "phase/cli/
|
1
|
+
require "phase/cli/mixins/loggable"
|
2
2
|
|
3
|
-
require "phase/cli/
|
3
|
+
require "phase/cli/command"
|
4
4
|
|
5
5
|
require "phase/cli/env"
|
6
6
|
require "phase/cli/keys"
|
7
7
|
require "phase/cli/logs"
|
8
|
-
require "phase/cli/mosh"
|
9
8
|
require "phase/cli/ssh"
|
9
|
+
require "phase/cli/mosh"
|
10
10
|
require "phase/cli/status"
|
data/lib/phase/cli/keys.rb
CHANGED
data/lib/phase/cli/logs.rb
CHANGED
data/lib/phase/cli/mosh.rb
CHANGED
data/lib/phase/cli/ssh.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Phase
|
2
|
-
module
|
2
|
+
module CLI
|
3
3
|
class SSH < Command
|
4
|
+
include Mixins::Loggable
|
4
5
|
|
5
6
|
command :ssh do |c|
|
6
7
|
c.syntax = "phase ssh [-i instance_id] [-n instance_name] [-r instance_role] [-u user] [-c conn_str] [username@instance_name|instance_id]"
|
@@ -13,7 +14,7 @@ module Phase
|
|
13
14
|
|
14
15
|
c.description = "Connects to the the specified instance via SSH."
|
15
16
|
c.action do |args, options|
|
16
|
-
options.default role:
|
17
|
+
options.default role: ::Phase.config.bastion_role, conn: "ssh -A"
|
17
18
|
new(args, options).run
|
18
19
|
end
|
19
20
|
end
|
@@ -22,8 +23,8 @@ module Phase
|
|
22
23
|
|
23
24
|
def run
|
24
25
|
parse_connection_string
|
25
|
-
log "connecting to instance #{ instance.id }..."
|
26
|
-
exec "#{ options.conn } #{ username }@#{ instance.dns_name }"
|
26
|
+
log "connecting to instance #{ instance.resource.id }..."
|
27
|
+
exec "#{ options.conn } #{ username }@#{ instance.resource.dns_name }"
|
27
28
|
end
|
28
29
|
|
29
30
|
private
|
@@ -48,11 +49,11 @@ module Phase
|
|
48
49
|
def instance
|
49
50
|
@instance ||= begin
|
50
51
|
if options.id
|
51
|
-
instance =
|
52
|
+
instance = ::Phase::Adapters::AWS::Server.find(options.id)
|
52
53
|
elsif options.name
|
53
|
-
instance =
|
54
|
-
|
55
|
-
instance =
|
54
|
+
instance = ::Phase::Adapters::AWS::Server.where(name: options.name).first
|
55
|
+
elsif options.role
|
56
|
+
instance = ::Phase::Adapters::AWS::Server.where(role: options.role).first
|
56
57
|
end
|
57
58
|
|
58
59
|
fail "no instance found." if instance.nil?
|
data/lib/phase/cli/status.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Phase
|
2
|
-
module
|
2
|
+
module CLI
|
3
3
|
class Status < Command
|
4
4
|
|
5
5
|
command :status do |c|
|
@@ -11,10 +11,10 @@ module Phase
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def run
|
14
|
-
@vpcs =
|
15
|
-
@subnets =
|
16
|
-
@servers =
|
17
|
-
@elbs =
|
14
|
+
@vpcs = ::Phase::Adapters::AWS::Network.all
|
15
|
+
@subnets = ::Phase::Adapters::AWS::Subnet.all
|
16
|
+
@servers = ::Phase::Adapters::AWS::Server.all
|
17
|
+
@elbs = ::Phase::Adapters::AWS::LoadBalancer.all
|
18
18
|
|
19
19
|
print_vpc_tables
|
20
20
|
print_servers_table
|
@@ -25,30 +25,30 @@ module Phase
|
|
25
25
|
table = ::Terminal::Table.new(title: "VPC Status")
|
26
26
|
|
27
27
|
add_section_headers(table, ["VPC ID", "Name", "State", "CIDR Block", "Tenancy"])
|
28
|
-
color = vpc.state == "available" ? :green : :light_red
|
28
|
+
color = vpc.resource.state == "available" ? :green : :light_red
|
29
29
|
add_row(table, color, [
|
30
|
-
vpc.id,
|
31
|
-
vpc.tags["Name"] || vpc.tags["name"],
|
32
|
-
vpc.state,
|
33
|
-
vpc.cidr_block,
|
34
|
-
vpc.tenancy
|
30
|
+
vpc.resource.id,
|
31
|
+
vpc.resource.tags["Name"] || vpc.resource.tags["name"],
|
32
|
+
vpc.resource.state,
|
33
|
+
vpc.resource.cidr_block,
|
34
|
+
vpc.resource.tenancy
|
35
35
|
])
|
36
36
|
|
37
37
|
subnets = @subnets.select do |subnet|
|
38
|
-
subnet.vpc_id == vpc.id
|
38
|
+
subnet.resource.vpc_id == vpc.resource.id
|
39
39
|
end
|
40
40
|
|
41
41
|
return unless subnets.any?
|
42
42
|
|
43
43
|
add_section_headers(table, ["Subnet ID", "Name", "State", "CIDR Block", "Availability Zone"])
|
44
44
|
subnets.each do |subnet|
|
45
|
-
color = subnet.ready? ? :green : :light_red
|
45
|
+
color = subnet.resource.ready? ? :green : :light_red
|
46
46
|
add_row(table, color, [
|
47
|
-
subnet.subnet_id,
|
48
|
-
subnet.tag_set["Name"] || subnet.tag_set["name"],
|
49
|
-
subnet.state,
|
50
|
-
subnet.cidr_block,
|
51
|
-
subnet.availability_zone
|
47
|
+
subnet.resource.subnet_id,
|
48
|
+
subnet.resource.tag_set["Name"] || subnet.resource.tag_set["name"],
|
49
|
+
subnet.resource.state,
|
50
|
+
subnet.resource.cidr_block,
|
51
|
+
subnet.resource.availability_zone
|
52
52
|
])
|
53
53
|
end
|
54
54
|
|
@@ -58,23 +58,23 @@ module Phase
|
|
58
58
|
|
59
59
|
def print_servers_table
|
60
60
|
table = ::Terminal::Table.new(title: "Instances")
|
61
|
-
groups = @servers.group_by
|
61
|
+
groups = @servers.group_by {|s| s.resource.subnet_id }
|
62
62
|
|
63
63
|
add_section_headers(table, ["ID", "Name", "Type", "State", "Public IP", "Private IP", "Subnet Name"])
|
64
64
|
|
65
65
|
groups.each_pair do |subnet_id, servers|
|
66
66
|
servers.each do |server|
|
67
|
-
color = server.ready? ? :green : :light_red
|
68
|
-
subnet = @subnets.find { |s| s.subnet_id == subnet_id }
|
69
|
-
subnet_name = subnet.tag_set["Name"] || subnet.tag_set["name"] if subnet
|
67
|
+
color = server.resource.ready? ? :green : :light_red
|
68
|
+
subnet = @subnets.find { |s| s.resource.subnet_id == subnet_id }
|
69
|
+
subnet_name = subnet.resource.tag_set["Name"] || subnet.resource.tag_set["name"] if subnet
|
70
70
|
|
71
71
|
add_row(table, color, [
|
72
|
-
server.id,
|
73
|
-
server.tags["Name"] || server.tags["name"],
|
74
|
-
server.flavor_id,
|
75
|
-
server.state,
|
76
|
-
server.public_ip_address,
|
77
|
-
server.private_ip_address,
|
72
|
+
server.resource.id,
|
73
|
+
server.resource.tags["Name"] || server.resource.tags["name"],
|
74
|
+
server.resource.flavor_id,
|
75
|
+
server.resource.state,
|
76
|
+
server.resource.public_ip_address,
|
77
|
+
server.resource.private_ip_address,
|
78
78
|
subnet_name
|
79
79
|
])
|
80
80
|
end
|
data/lib/phase/cli.rb
CHANGED
@@ -1,16 +1,21 @@
|
|
1
1
|
require "commander"
|
2
|
-
require "phase/cli/all"
|
3
2
|
|
4
3
|
module Phase
|
5
|
-
|
6
|
-
|
4
|
+
module CLI
|
5
|
+
class Application
|
6
|
+
include ::Commander::Methods
|
7
|
+
|
8
|
+
def run
|
9
|
+
program :name, "Phase"
|
10
|
+
program :version, ::Phase::VERSION
|
11
|
+
program :description, "Phase controller."
|
7
12
|
|
8
|
-
|
9
|
-
program :name, "Phase"
|
10
|
-
program :version, ::Phase::VERSION
|
11
|
-
program :description, "Phase controller."
|
13
|
+
always_trace!
|
12
14
|
|
13
|
-
|
15
|
+
run!
|
16
|
+
end
|
14
17
|
end
|
15
18
|
end
|
16
19
|
end
|
20
|
+
|
21
|
+
require "phase/cli/all"
|
data/lib/phase/configuration.rb
CHANGED
@@ -5,15 +5,19 @@ module Phase
|
|
5
5
|
:bastion_role,
|
6
6
|
:bastion_user,
|
7
7
|
|
8
|
-
:aws_region
|
8
|
+
:aws_region,
|
9
|
+
|
10
|
+
:adapter
|
9
11
|
|
10
12
|
def initialize
|
11
13
|
@use_bastions = false
|
12
|
-
@bastion_role =
|
13
|
-
@bastion_user =
|
14
|
+
@bastion_role = "ssh"
|
15
|
+
@bastion_user = "orca"
|
14
16
|
|
15
17
|
@aws_region = "us-east-1"
|
16
18
|
|
19
|
+
@adapter = ::Phase::Adapters::AWS
|
20
|
+
|
17
21
|
::SSHKit.config.backend = SSH::Backend
|
18
22
|
|
19
23
|
configure_from_yml if defined?(::Rails) && yml_present?
|
data/lib/phase/dsl.rb
CHANGED
@@ -1,21 +1,31 @@
|
|
1
1
|
module Phase
|
2
2
|
module DSL
|
3
3
|
|
4
|
-
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
4
|
+
# @param [String] role_name The value of the 'Role' tag
|
5
|
+
# @param [String] environment The value of the 'Environment' tag
|
6
|
+
# @param [Hash] options SSHKit concurrency options
|
7
|
+
# @see SSHKit::Coordinator for concurrency options
|
8
|
+
# @return [void]
|
9
|
+
def on_role(role_name, environment = "staging", options = {}, &block)
|
10
|
+
servers = ::Phase::Adapters::AWS::Server.where(role: role_name, environment: environment)
|
11
|
+
on(servers.map {|s| s.resource.private_ip_address }, options, &block)
|
12
|
+
end
|
8
13
|
|
14
|
+
#
|
9
15
|
def on(destination_ips, options = {}, &block)
|
10
|
-
|
16
|
+
server = ::Phase::Adapters::AWS::Server.where(role: ::Phase.config.bastion_role).first
|
17
|
+
raise ArgumentError, "no servers found" unless server
|
11
18
|
|
12
|
-
|
19
|
+
bastion_host = "#{ ::Phase.config.bastion_user }@#{ server.resource.dns_name }"
|
20
|
+
coordinator = SSH::Coordinator.new(bastion_host)
|
13
21
|
|
14
|
-
destination_ips.each do |ip|
|
22
|
+
Array(destination_ips).each do |ip|
|
15
23
|
coordinator.each(options) do
|
16
24
|
on_remote_host(ip) { instance_exec(&block) }
|
17
25
|
end
|
18
26
|
end
|
27
|
+
|
28
|
+
true
|
19
29
|
end
|
20
30
|
|
21
31
|
def run_locally(&block)
|
data/lib/phase/version.rb
CHANGED
data/lib/phase.rb
CHANGED
@@ -1,21 +1,24 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
|
8
|
-
|
1
|
+
require 'terminal-table'
|
2
|
+
require 'active_support'
|
3
|
+
require 'progressbar'
|
4
|
+
require 'colorize'
|
5
|
+
require 'fog'
|
6
|
+
require 'capistrano'
|
7
|
+
require 'sshkit'
|
8
|
+
|
9
|
+
require 'dotenv'
|
9
10
|
::Dotenv.load if defined?(::Dotenv)
|
10
11
|
|
11
|
-
require
|
12
|
+
require 'phase/adapter'
|
13
|
+
require 'phase/adapters/abstract'
|
14
|
+
require 'phase/adapters/aws'
|
12
15
|
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
16
|
+
require 'phase/ssh/backend'
|
17
|
+
require 'phase/ssh/command'
|
18
|
+
require 'phase/ssh/coordinator'
|
16
19
|
|
17
|
-
require
|
18
|
-
require
|
20
|
+
require 'phase/configuration'
|
21
|
+
require 'phase/version'
|
19
22
|
|
20
23
|
|
21
24
|
module Phase
|
@@ -29,6 +32,14 @@ module Phase
|
|
29
32
|
@@config = nil
|
30
33
|
end
|
31
34
|
|
35
|
+
def configure(&block)
|
36
|
+
yield config
|
37
|
+
end
|
38
|
+
|
39
|
+
def adapter
|
40
|
+
config.adapter
|
41
|
+
end
|
42
|
+
|
32
43
|
end
|
33
44
|
|
34
45
|
config
|
data/phase.gemspec
CHANGED
@@ -28,6 +28,7 @@ Gem::Specification.new do |spec|
|
|
28
28
|
spec.add_runtime_dependency 'colorize', '~> 0.7'
|
29
29
|
spec.add_runtime_dependency 'dotenv', '~> 0.11'
|
30
30
|
|
31
|
-
spec.add_development_dependency
|
32
|
-
spec.add_development_dependency
|
31
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
32
|
+
spec.add_development_dependency 'rake', '~> 10.1'
|
33
|
+
spec.add_development_dependency 'rspec', '~> 3.1'
|
33
34
|
end
|
data/spec/dsl_spec.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'phase/dsl'
|
3
|
+
require 'fog'
|
4
|
+
|
5
|
+
describe ::Phase::DSL do
|
6
|
+
describe "looking up bastion IPs" do
|
7
|
+
let(:dns_name) { "server1.orcahealth.com" }
|
8
|
+
let(:fog_server) { ::Fog::Compute::AWS.new(region: "us-east-1").servers.new(dns_name: dns_name) }
|
9
|
+
let(:server) { ::Phase::Adapters::AWS::Server.new(fog_server) }
|
10
|
+
|
11
|
+
it "should query AWS for servers" do
|
12
|
+
server_api = object_double("Phase::Adapters::AWS::Server", where: [server]).as_stubbed_const
|
13
|
+
|
14
|
+
on_role("ssh") {}
|
15
|
+
|
16
|
+
expect(server_api).to have_received(:where).with(role: "ssh")
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: phase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piers Mainwaring
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-12-
|
12
|
+
date: 2014-12-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: commander
|
@@ -165,6 +165,20 @@ dependencies:
|
|
165
165
|
- - "~>"
|
166
166
|
- !ruby/object:Gem::Version
|
167
167
|
version: '10.1'
|
168
|
+
- !ruby/object:Gem::Dependency
|
169
|
+
name: rspec
|
170
|
+
requirement: !ruby/object:Gem::Requirement
|
171
|
+
requirements:
|
172
|
+
- - "~>"
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: '3.1'
|
175
|
+
type: :development
|
176
|
+
prerelease: false
|
177
|
+
version_requirements: !ruby/object:Gem::Requirement
|
178
|
+
requirements:
|
179
|
+
- - "~>"
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '3.1'
|
168
182
|
description: ''
|
169
183
|
email:
|
170
184
|
- piers@impossibly.org
|
@@ -182,17 +196,27 @@ files:
|
|
182
196
|
- VERSION
|
183
197
|
- bin/phase
|
184
198
|
- lib/phase.rb
|
199
|
+
- lib/phase/adapter.rb
|
200
|
+
- lib/phase/adapters/abstract.rb
|
201
|
+
- lib/phase/adapters/abstract/base.rb
|
202
|
+
- lib/phase/adapters/abstract/load_balancer.rb
|
203
|
+
- lib/phase/adapters/abstract/network.rb
|
204
|
+
- lib/phase/adapters/abstract/server.rb
|
185
205
|
- lib/phase/adapters/aws.rb
|
206
|
+
- lib/phase/adapters/aws/load_balancer.rb
|
207
|
+
- lib/phase/adapters/aws/network.rb
|
208
|
+
- lib/phase/adapters/aws/server.rb
|
209
|
+
- lib/phase/adapters/aws/subnet.rb
|
186
210
|
- lib/phase/cli.rb
|
187
211
|
- lib/phase/cli/all.rb
|
188
212
|
- lib/phase/cli/command.rb
|
189
213
|
- lib/phase/cli/env.rb
|
190
214
|
- lib/phase/cli/keys.rb
|
191
215
|
- lib/phase/cli/logs.rb
|
216
|
+
- lib/phase/cli/mixins/loggable.rb
|
192
217
|
- lib/phase/cli/mosh.rb
|
193
218
|
- lib/phase/cli/ssh.rb
|
194
219
|
- lib/phase/cli/status.rb
|
195
|
-
- lib/phase/cli/utils/loggable.rb
|
196
220
|
- lib/phase/configuration.rb
|
197
221
|
- lib/phase/dsl.rb
|
198
222
|
- lib/phase/keys/key.rb
|
@@ -201,6 +225,8 @@ files:
|
|
201
225
|
- lib/phase/ssh/coordinator.rb
|
202
226
|
- lib/phase/version.rb
|
203
227
|
- phase.gemspec
|
228
|
+
- spec/dsl_spec.rb
|
229
|
+
- spec/spec_helper.rb
|
204
230
|
homepage: https://github.com/piersadrian/phase
|
205
231
|
licenses:
|
206
232
|
- MIT
|
@@ -226,4 +252,6 @@ signing_key:
|
|
226
252
|
specification_version: 4
|
227
253
|
summary: Provides a simple API for managing cloud instances running in a multi-subnet
|
228
254
|
network.
|
229
|
-
test_files:
|
255
|
+
test_files:
|
256
|
+
- spec/dsl_spec.rb
|
257
|
+
- spec/spec_helper.rb
|