phase 0.0.2 → 0.0.4
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.
- 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
|