zaws 0.0.1
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.
- data/.gitignore +35 -0
- data/.travis.yml +20 -0
- data/Gemfile +5 -0
- data/Gemfile.lock +78 -0
- data/LICENSE +204 -0
- data/README.md +17 -0
- data/Rakefile +26 -0
- data/bin/zaws +20 -0
- data/feature/compute/assoc_security_group.feature +55 -0
- data/feature/compute/compute.feature +138 -0
- data/feature/compute/secondary_ip.feature +107 -0
- data/feature/compute/view.feature +23 -0
- data/feature/compute/view_images.feature +24 -0
- data/feature/elasticip/elasticip.feature +138 -0
- data/feature/elasticip/view.feature +18 -0
- data/feature/hosted_zone/view.feature +17 -0
- data/feature/hosted_zone/view_record.feature +29 -0
- data/feature/load_balancer/instance_registration.feature +120 -0
- data/feature/load_balancer/listener.feature +86 -0
- data/feature/load_balancer/load_balancer.feature +101 -0
- data/feature/load_balancer/view.feature +18 -0
- data/feature/route_table/assoc_subnet.feature +128 -0
- data/feature/route_table/route_propagation.feature +93 -0
- data/feature/route_table/route_table.feature +91 -0
- data/feature/route_table/route_to_gateway.feature +69 -0
- data/feature/route_table/route_to_instance.feature +115 -0
- data/feature/route_table/view.feature +25 -0
- data/feature/security_group/ingress.feature +184 -0
- data/feature/security_group/security_group.feature +107 -0
- data/feature/security_group/view.feature +23 -0
- data/feature/subnet/subnet.feature +92 -0
- data/feature/subnet/view.feature +24 -0
- data/feature/support/env.rb +14 -0
- data/feature/version.feature +6 -0
- data/lib/zaws/aws.rb +26 -0
- data/lib/zaws/command/compute.rb +100 -0
- data/lib/zaws/command/elasticip.rb +47 -0
- data/lib/zaws/command/hosted_zone.rb +26 -0
- data/lib/zaws/command/load_balancer.rb +113 -0
- data/lib/zaws/command/route_table.rb +134 -0
- data/lib/zaws/command/security_group.rb +69 -0
- data/lib/zaws/command/subnet.rb +65 -0
- data/lib/zaws/ec2/compute.rb +247 -0
- data/lib/zaws/ec2/elasticip.rb +85 -0
- data/lib/zaws/ec2/route_table.rb +202 -0
- data/lib/zaws/ec2/security_group.rb +116 -0
- data/lib/zaws/ec2/subnet.rb +108 -0
- data/lib/zaws/ec2.rb +40 -0
- data/lib/zaws/elb/load_balancer.rb +157 -0
- data/lib/zaws/elb.rb +20 -0
- data/lib/zaws/helper/file.rb +23 -0
- data/lib/zaws/helper/option.rb +24 -0
- data/lib/zaws/helper/output.rb +46 -0
- data/lib/zaws/helper/shell.rb +25 -0
- data/lib/zaws/route53/hosted_zone.rb +36 -0
- data/lib/zaws/route53.rb +20 -0
- data/lib/zaws/version.rb +3 -0
- data/lib/zaws.rb +57 -0
- data/spec/spec_helper.rb +4 -0
- data/spec/zaws/ec2/compute/add_volume_spec.rb +39 -0
- data/spec/zaws/ec2/compute/block_device_mapping_spec.rb +31 -0
- data/spec/zaws/ec2/compute/instance_id_by_external_id_spec.rb +23 -0
- data/spec/zaws/ec2/compute/instance_ping_spec.rb +34 -0
- data/spec/zaws/ec2/compute/instance_running_spec.rb +47 -0
- data/spec/zaws/ec2/compute/network_interface_json_spec.rb +57 -0
- data/spec/zaws/ec2/compute/nosdcheck_spec.rb +17 -0
- data/spec/zaws/ec2/compute/tag_instance_spec.rb +21 -0
- data/spec/zaws/ec2/security_group/id_by_name_spec.rb +32 -0
- data/spec/zaws/ec2/subnet/available_spec.rb +22 -0
- data/spec/zaws/ec2/subnet/declare_spec.rb +31 -0
- data/spec/zaws/ec2/subnet/exists_spec.rb +33 -0
- data/spec/zaws/ec2/subnet/id_array_by_cidrblock_array_spec.rb +48 -0
- data/spec/zaws/ec2/subnet/id_by_cidrblock_spec.rb +35 -0
- data/spec/zaws/ec2/subnet/id_by_ip_spec.rb +42 -0
- data/spec/zaws/ec2/subnet/view_spec.rb +34 -0
- data/spec/zaws/elb/load_balancer/calculated_listener_spec.rb +18 -0
- data/spec/zaws/helper/option/absent_spec.rb +14 -0
- data/spec/zaws/helper/option/exclusive_spec.rb +14 -0
- data/spec/zaws/helper/option/exists_spec.rb +18 -0
- data/spec/zaws/helper/option/minimum_spec.rb +14 -0
- data/spec/zaws/helper/output/binary_nagios_check_spec.rb +19 -0
- data/spec/zaws/helper/output/colorize_spec.rb +30 -0
- data/spec/zaws/helper/output/opt_exclusive_spec.rb +14 -0
- data/spec/zaws/helper/output/opt_minimum_spec.rb +15 -0
- data/spec/zaws/helper/output/opt_required_spec.rb +12 -0
- data/spec/zaws/helper/shell/cli_spec.rb +33 -0
- data/spec/zaws/helper/shell/if_then_spec.rb +24 -0
- data/zaws.gemspec +34 -0
- metadata +350 -0
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'netaddr'
|
3
|
+
require 'timeout'
|
4
|
+
|
5
|
+
module ZAWS
|
6
|
+
module EC2Services
|
7
|
+
class Subnet
|
8
|
+
|
9
|
+
def initialize(shellout,aws)
|
10
|
+
@shellout=shellout
|
11
|
+
@aws=aws
|
12
|
+
end
|
13
|
+
|
14
|
+
def view(region,view,textout=nil,verbose=nil,vpcid=nil,cidrblock=nil)
|
15
|
+
comline="aws --output #{view} --region #{region} ec2 describe-subnets"
|
16
|
+
if vpcid || cidrblock
|
17
|
+
comline = comline + " --filter"
|
18
|
+
end
|
19
|
+
comline = comline + " 'Name=vpc-id,Values=#{vpcid}'" if vpcid
|
20
|
+
comline = comline + " 'Name=cidr,Values=#{cidrblock}'" if cidrblock
|
21
|
+
subnets=@shellout.cli(comline,verbose)
|
22
|
+
textout.puts(subnets) if textout
|
23
|
+
return subnets
|
24
|
+
end
|
25
|
+
|
26
|
+
def id_by_ip(region,textout=nil,verbose=nil,vpcid,ip)
|
27
|
+
subnets=JSON.parse(view(region,'json',nil,verbose,vpcid))
|
28
|
+
subnet_id=nil
|
29
|
+
subnets["Subnets"].each { |x| subnet_id = x["SubnetId"] if (NetAddr::CIDR.create(x["CidrBlock"])).contains?(ip) }
|
30
|
+
textout.puts subnet_id if textout
|
31
|
+
return subnet_id
|
32
|
+
end
|
33
|
+
|
34
|
+
def id_by_cidrblock(region,textout=nil,verbose=nil,vpcid,cidrblock)
|
35
|
+
subnets=JSON.parse(view(region,'json',nil,verbose,vpcid,cidrblock))
|
36
|
+
subnet_id= subnets["Subnets"].count == 1 ? subnets["Subnets"][0]["SubnetId"] : nil
|
37
|
+
textout.puts subnet_id if textout
|
38
|
+
return subnet_id
|
39
|
+
end
|
40
|
+
|
41
|
+
def id_array_by_cidrblock_array(region,textout=nil,verbose=nil,vpcid,cidrblock_array)
|
42
|
+
return cidrblock_array.map {|x| id_by_cidrblock(region,nil,verbose,vpcid,x)}
|
43
|
+
end
|
44
|
+
|
45
|
+
def exists(region,textout=nil,verbose=nil,vpcid,cidrblock)
|
46
|
+
val = id_by_cidrblock(region,nil,verbose,vpcid,cidrblock) ? true : false
|
47
|
+
textout.puts val.to_s if textout
|
48
|
+
return val
|
49
|
+
end
|
50
|
+
|
51
|
+
def declare(region,vpcid,cidrblock,availabilityzone,statetimeout,textout=nil,verbose=nil,nagios=false,ufile=nil)
|
52
|
+
if ufile
|
53
|
+
ZAWS::Helper::File.prepend("zaws subnet delete --region #{region} --cidrblock #{cidrblock} --vpcid #{vpcid} $XTRA_OPTS",'#Delete subnet',ufile)
|
54
|
+
end
|
55
|
+
if not exists(region,nil,verbose,vpcid,cidrblock)
|
56
|
+
if nagios
|
57
|
+
textout.puts "CRITICAL: Subnet Does Not Exist."
|
58
|
+
return 2
|
59
|
+
end
|
60
|
+
comline="aws --output json --region #{region} ec2 create-subnet --vpc-id #{vpcid} --cidr-block #{cidrblock} --availability-zone #{availabilityzone}"
|
61
|
+
subnet=@shellout.cli(comline,verbose)
|
62
|
+
begin
|
63
|
+
Timeout.timeout(statetimeout) do
|
64
|
+
until available(subnet,verbose)
|
65
|
+
sleep(1)
|
66
|
+
subnet=view(region,'json',nil,verbose,vpcid,cidrblock)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
textout.puts "Subnet created."
|
70
|
+
rescue Timeout::Error
|
71
|
+
throw 'Timeout before Subnet made available.'
|
72
|
+
end
|
73
|
+
else
|
74
|
+
if nagios
|
75
|
+
textout.puts "OK: Subnet Exists."
|
76
|
+
return 0
|
77
|
+
end
|
78
|
+
textout.puts "No action needed. Subnet exists already."
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def available(subnet,verbose)
|
83
|
+
#based on the structure of the return from create-subnet and describe-subnet determine if subnet is available
|
84
|
+
subnet_hash=JSON.parse(subnet)
|
85
|
+
if subnet_hash["Subnet"]
|
86
|
+
return (subnet_hash["Subnet"]["State"] == "available")
|
87
|
+
end
|
88
|
+
if subnet_hash["Subnets"] and subnet_hash["Subnets"].count == 1
|
89
|
+
return (subnet_hash["Subnets"][0]["State"] == "available")
|
90
|
+
end
|
91
|
+
return false
|
92
|
+
end
|
93
|
+
|
94
|
+
def delete(region,textout=nil,verbose=nil,vpcid,cidrblock)
|
95
|
+
subnetid=id_by_cidrblock(region,nil,verbose,vpcid,cidrblock)
|
96
|
+
if subnetid
|
97
|
+
comline="aws --region #{region} ec2 delete-subnet --subnet-id #{subnetid}"
|
98
|
+
val=JSON.parse(@shellout.cli(comline,verbose))
|
99
|
+
textout.puts "Subnet deleted." if val["return"] == "true"
|
100
|
+
else
|
101
|
+
textout.puts "Subnet does not exist. Skipping deletion."
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
data/lib/zaws/ec2.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'netaddr'
|
3
|
+
require 'timeout'
|
4
|
+
|
5
|
+
module ZAWS
|
6
|
+
class EC2
|
7
|
+
|
8
|
+
def initialize(shellout,aws)
|
9
|
+
@shellout=shellout
|
10
|
+
@aws=aws
|
11
|
+
end
|
12
|
+
|
13
|
+
def subnet
|
14
|
+
@_subnet ||= (ZAWS::EC2Services::Subnet.new(@shellout,@aws))
|
15
|
+
return @_subnet
|
16
|
+
end
|
17
|
+
|
18
|
+
def security_group
|
19
|
+
@_security_group ||= (ZAWS::EC2Services::SecurityGroup.new(@shellout,@aws))
|
20
|
+
return @_security_group
|
21
|
+
end
|
22
|
+
|
23
|
+
def route_table
|
24
|
+
@_route_table ||= (ZAWS::EC2Services::RouteTable.new(@shellout,@aws))
|
25
|
+
return @_route_table
|
26
|
+
end
|
27
|
+
|
28
|
+
def compute
|
29
|
+
@_compute ||= (ZAWS::EC2Services::Compute.new(@shellout,@aws))
|
30
|
+
return @_compute
|
31
|
+
end
|
32
|
+
|
33
|
+
def elasticip
|
34
|
+
@_elasticip ||= (ZAWS::EC2Services::Elasticip.new(@shellout,@aws))
|
35
|
+
return @_elasticip
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'netaddr'
|
3
|
+
require 'timeout'
|
4
|
+
|
5
|
+
module ZAWS
|
6
|
+
module ELBServices
|
7
|
+
class LoadBalancer
|
8
|
+
|
9
|
+
def initialize(shellout,aws)
|
10
|
+
@shellout=shellout
|
11
|
+
@aws=aws
|
12
|
+
end
|
13
|
+
|
14
|
+
def view(region,view,textout=nil,verbose=nil)
|
15
|
+
comline="aws --output #{view} --region #{region} elb describe-load-balancers"
|
16
|
+
lbs=@shellout.cli(comline,verbose)
|
17
|
+
textout.puts(lbs) if textout
|
18
|
+
return lbs
|
19
|
+
end
|
20
|
+
|
21
|
+
def exists(region,lbname,textout=nil,verbose=nil)
|
22
|
+
lbs=JSON.parse(view(region,'json',nil,verbose))
|
23
|
+
val = lbs["LoadBalancerDescriptions"].any? { |x| x["LoadBalancerName"]=="#{lbname}" }
|
24
|
+
instances = val ? (lbs["LoadBalancerDescriptions"].select { |x| x["LoadBalancerName"]=="#{lbname}" })[0]["Instances"] : nil
|
25
|
+
ldescriptions = val ? (lbs["LoadBalancerDescriptions"].select { |x| x["LoadBalancerName"]=="#{lbname}" })[0]["ListenerDescriptions"] : nil
|
26
|
+
textout.puts(val) if textout
|
27
|
+
return val,instances,ldescriptions
|
28
|
+
end
|
29
|
+
|
30
|
+
def calculated_listener(lbprotocol,lbport,inprotocol,inport,sslcert=nil)
|
31
|
+
listeners = []
|
32
|
+
single_listener = {}
|
33
|
+
single_listener["Protocol"]="#{lbprotocol}"
|
34
|
+
single_listener["LoadBalancerPort"]=lbport.to_i
|
35
|
+
single_listener["InstanceProtocol"]="#{inprotocol}"
|
36
|
+
single_listener["InstancePort"]=inport.to_i
|
37
|
+
single_listener["SSLCertificateId"]="#{sslcert}" if sslcert
|
38
|
+
listeners << single_listener
|
39
|
+
return listeners.to_json
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_in_subnet(region,lbname,lbprotocol,lbport,inprotocol,inport,securitygroup,cidrblocks,vpcid,nagios=false,textout=nil,verbose=nil,ufile=nil)
|
43
|
+
if ufile
|
44
|
+
ZAWS::Helper::File.prepend("zaws load_balancer delete #{lbname} --region #{region} $XTRA_OPTS",'#Delete load balancer',ufile)
|
45
|
+
end
|
46
|
+
lbexists,instances,ldescriptions=exists(region,lbname,nil,verbose)
|
47
|
+
return ZAWS::Helper::Output.binary_nagios_check(lbexists,"OK: Load Balancer Exists.","CRITICAL: Load Balancer does not exist.",textout) if nagios
|
48
|
+
if not lbexists
|
49
|
+
comline="aws --region #{region} elb create-load-balancer"
|
50
|
+
comline+=" --load-balancer-name #{lbname}"
|
51
|
+
comline+=" --listeners '#{calculated_listener(lbprotocol,lbport,inprotocol,inport)}'"
|
52
|
+
comline+=" --subnets #{@aws.ec2.subnet.id_array_by_cidrblock_array(region,nil,nil,vpcid,cidrblocks).join(" ")}"
|
53
|
+
sgroup_exists,sgroupid = @aws.ec2.security_group.exists(region,nil,nil,vpcid,securitygroup)
|
54
|
+
comline+=" --security-groups #{sgroupid}"
|
55
|
+
newlb=JSON.parse(@shellout.cli(comline,verbose))
|
56
|
+
textout.puts "Load balancer created." if newlb["DNSName"]
|
57
|
+
else
|
58
|
+
textout.puts "Load balancer already exists. Skipping creation."
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def delete(region,lbname,textout=nil,verbose=nil)
|
63
|
+
lbexists,instances,ldescriptions=exists(region,lbname,nil,verbose)
|
64
|
+
if lbexists
|
65
|
+
comline="aws --region #{region} elb delete-load-balancer"
|
66
|
+
comline+=" --load-balancer-name #{lbname}"
|
67
|
+
deletelb=JSON.parse(@shellout.cli(comline,verbose))
|
68
|
+
textout.puts "Load balancer deleted." if deletelb["return"] == "true"
|
69
|
+
else
|
70
|
+
textout.puts "Load balancer does not exist. Skipping deletion."
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def exists_instance(region,lbname,instance_external_id,vpcid,textout=nil,verbose=nil)
|
75
|
+
lbexists,instances,ldescriptions=exists(region,lbname,nil,verbose)
|
76
|
+
instance_exists,instance_id = @aws.ec2.compute.exists(region,nil,verbose,vpcid,instance_external_id)
|
77
|
+
val = (lbexists and instance_exists and (instances.any? { |x| x["InstanceId"]==instance_id }))
|
78
|
+
textout.puts(val) if textout
|
79
|
+
return val, instance_id
|
80
|
+
end
|
81
|
+
|
82
|
+
def register_instance(region,lbname,instance_external_id,vpcid,nagios=false,textout=nil,verbose=nil,ufile=nil)
|
83
|
+
if ufile
|
84
|
+
ZAWS::Helper::File.prepend("zaws load_balancer deregister_instance #{lbname} #{instance_external_id} --region #{region} --vpcid my_vpc_id $XTRA_OPTS",'#Deregister instance',ufile)
|
85
|
+
end
|
86
|
+
instance_registered,instance_id = exists_instance(region,lbname,instance_external_id,vpcid,nil,verbose)
|
87
|
+
return ZAWS::Helper::Output.binary_nagios_check(instance_registered,"OK: Instance registerd.","CRITICAL: Instance not registered.",textout) if nagios
|
88
|
+
if not instance_registered
|
89
|
+
comline="aws --region #{region} elb register-instances-with-load-balancer"
|
90
|
+
comline+=" --load-balancer-name #{lbname}"
|
91
|
+
comline+=" --instances #{instance_id}"
|
92
|
+
newinstance=JSON.parse(@shellout.cli(comline,verbose))
|
93
|
+
verbose.puts "DEBUG: newinstance=#{newinstance} TODO: need to know if it is returning a json object with a return key." if verbose
|
94
|
+
textout.puts "New instance registered." if newinstance["return"] == "true"
|
95
|
+
else
|
96
|
+
textout.puts "Instance already registered. Skipping registration."
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def deregister_instance(region,lbname,instance_external_id,vpcid,textout=nil,verbose=nil)
|
101
|
+
instance_registered,instance_id = exists_instance(region,lbname,instance_external_id,vpcid,nil,verbose)
|
102
|
+
if instance_registered
|
103
|
+
comline="aws --region #{region} elb deregister-instances-with-load-balancer"
|
104
|
+
comline+=" --load-balancer-name #{lbname}"
|
105
|
+
comline+=" --instances #{instance_id}"
|
106
|
+
newinstance=JSON.parse(@shellout.cli(comline,verbose))
|
107
|
+
verbose.puts "DEBUG: newinstance=#{newinstance} TODO: need to know if it is returning a json object with a return key." if verbose
|
108
|
+
textout.puts "Instance deregistered." if newinstance["return"] == "true"
|
109
|
+
else
|
110
|
+
textout.puts "Instance not registered. Skipping deregistration."
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def exists_listener(region,lbname,lbprotocol,lbport,inprotocol,inport,textout=nil,verbose=nil)
|
115
|
+
lbexists,instances,ldescriptions=exists(region,lbname,nil,verbose)
|
116
|
+
verbose.puts ldescriptions if verbose
|
117
|
+
val = (lbexists and (ldescriptions.any? { |x| x["Listener"]["LoadBalancerPort"]==(lbport.to_i) && x["Listener"]["Protocol"]==lbprotocol && x["Listener"]["InstancePort"]==(inport.to_i) && x["Listener"]["InstanceProtocol"]==inprotocol }))
|
118
|
+
textout.puts(val) if textout
|
119
|
+
return val
|
120
|
+
end
|
121
|
+
|
122
|
+
def declare_listener(region,lbname,lbprotocol,lbport,inprotocol,inport,nagios=false,textout=nil,verbose=nil,ufile=nil)
|
123
|
+
if ufile
|
124
|
+
ZAWS::Helper::File.prepend("zaws load_balancer delete_listener #{lbname} #{lbprotocol} #{lbport} #{inprotocol} #{inport} --region #{region} $XTRA_OPTS",'#Delete listener',ufile)
|
125
|
+
end
|
126
|
+
lexists=exists_listener(region,lbname,lbprotocol,lbport,inprotocol,inport,nil,verbose)
|
127
|
+
return ZAWS::Helper::Output.binary_nagios_check(lexists,"OK: Listerner exists.","CRITICAL: Listener does not exist.",textout) if nagios
|
128
|
+
if not lexists
|
129
|
+
comline="aws --region #{region} elb create-load-balancer-listeners"
|
130
|
+
comline+=" --load-balancer-name #{lbname}"
|
131
|
+
comline+=" --listeners '#{calculated_listener(lbprotocol,lbport,inprotocol,inport)}'"
|
132
|
+
newlistener=JSON.parse(@shellout.cli(comline,verbose))
|
133
|
+
verbose.puts "DEBUG: newinstance=#{newlistener} TODO: need to know if it is returning a json object with a return key." if verbose
|
134
|
+
textout.puts "Listener created." if newlistener["return"] == "true"
|
135
|
+
else
|
136
|
+
textout.puts "Listerner exists. Skipping creation."
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def delete_listener(region,lbname,lbprotocol,lbport,inprotocol,inport,textout=nil,verbose=nil)
|
141
|
+
lexists=exists_listener(region,lbname,lbprotocol,lbport,inprotocol,inport,nil,verbose)
|
142
|
+
if lexists
|
143
|
+
comline="aws --region #{region} elb delete-load-balancer-listeners"
|
144
|
+
comline+=" --load-balancer-name #{lbname}"
|
145
|
+
comline+=" --load-balancer-ports '#{lbport}'"
|
146
|
+
dellistener=JSON.parse(@shellout.cli(comline,verbose))
|
147
|
+
verbose.puts "DEBUG: newinstance=#{dellistener} TODO: need to know if it is returning a json object with a return key." if verbose
|
148
|
+
textout.puts "Listerner deleted." if dellistener["return"] == "true"
|
149
|
+
else
|
150
|
+
textout.puts "Listener does not exist. Skipping deletion."
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
data/lib/zaws/elb.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'netaddr'
|
3
|
+
require 'timeout'
|
4
|
+
|
5
|
+
module ZAWS
|
6
|
+
class ELB
|
7
|
+
|
8
|
+
def initialize(shellout,aws)
|
9
|
+
@shellout=shellout
|
10
|
+
@aws=aws
|
11
|
+
end
|
12
|
+
|
13
|
+
def load_balancer
|
14
|
+
@_load_balancer ||= (ZAWS::ELBServices::LoadBalancer.new(@shellout,@aws))
|
15
|
+
return @_load_balancer
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ZAWS
|
2
|
+
module Helper
|
3
|
+
class File
|
4
|
+
|
5
|
+
# This prepend function not currently unit tested,
|
6
|
+
# see "thor/spec/actions/file_manipulation_spec"
|
7
|
+
# for ideas on how to accomplish this.
|
8
|
+
def self.prepend(command,description,filepath)
|
9
|
+
new_file=filepath + ".new"
|
10
|
+
IO::File.open(new_file, 'w') do |fo|
|
11
|
+
fo.puts description
|
12
|
+
fo.puts command
|
13
|
+
IO::File.foreach(filepath) do |li|
|
14
|
+
fo.puts li
|
15
|
+
end
|
16
|
+
end
|
17
|
+
IO::File.rename(new_file, filepath)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
|
2
|
+
module ZAWS
|
3
|
+
module Helper
|
4
|
+
class Option
|
5
|
+
|
6
|
+
def self.exists?(optarr,opt_hash)
|
7
|
+
optarr.all? { |opt| opt_hash[opt] }
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.absent(optarr,opt_hash)
|
11
|
+
optarr.inject([]) { |missing,opt| opt_hash[opt] ? missing : missing << opt }
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.exclusive?(optarr,opt_hash)
|
15
|
+
(optarr.inject(0) { |total,opt| opt_hash[opt] ? total + 1 : total }) <= 1
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.minimum?(min,optarr,opt_hash)
|
19
|
+
(optarr.inject(0) { |total,opt| opt_hash[opt] ? total + 1 : total }) >= min
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
|
2
|
+
module AWS_consts
|
3
|
+
# Color codes http://kpumuk.info/ruby-on-rails/colorizing-console-ruby-script-output/
|
4
|
+
COLOR_RED=31
|
5
|
+
COLOR_GREEN=32
|
6
|
+
COLOR_YELLOW=33
|
7
|
+
COLOR_DEFAULT=39
|
8
|
+
COLOR_BLUE=34
|
9
|
+
COLOR_CYAN=36
|
10
|
+
end
|
11
|
+
|
12
|
+
module ZAWS
|
13
|
+
module Helper
|
14
|
+
class Output
|
15
|
+
|
16
|
+
def self.colorize(text, color_code)
|
17
|
+
"\e[#{color_code}m#{text}\e[0m"
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.opt_required(output,opt_arr)
|
21
|
+
opt_arr.each { |opt| output.puts(" --#{opt} required!") }
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.opt_exclusive(output,opt_arr)
|
25
|
+
output.puts(" These options cannot be combined:")
|
26
|
+
opt_arr.each { |opt| output.puts(" --#{opt}") }
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.opt_minimum(output,min,opt_arr)
|
30
|
+
output.puts(" At mininum, #{min} of the following is required:")
|
31
|
+
opt_arr.each { |opt| output.puts(" --#{opt}") }
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.binary_nagios_check(ok_condition,ok_msg,critical_msg,textout=nil)
|
35
|
+
if ok_condition
|
36
|
+
textout.puts ok_msg if textout
|
37
|
+
return 0
|
38
|
+
else
|
39
|
+
textout.puts critical_msg if textout
|
40
|
+
return 2
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'mixlib/shellout'
|
2
|
+
|
3
|
+
module ZAWS
|
4
|
+
module Helper
|
5
|
+
class Shell
|
6
|
+
|
7
|
+
def cli(command,output=nil)
|
8
|
+
output.puts ZAWS::Helper::Output.colorize(command,AWS_consts::COLOR_BLUE) if output
|
9
|
+
list = Mixlib::ShellOut.new(command)
|
10
|
+
list.run_command
|
11
|
+
list.error!
|
12
|
+
return list.stdout
|
13
|
+
end
|
14
|
+
|
15
|
+
def if_then(condition,command,output=nil)
|
16
|
+
if not condition
|
17
|
+
output.puts ZAWS::Helper::Output.colorize(command,AWS_consts::COLOR_BLUE) if output
|
18
|
+
return nil
|
19
|
+
end
|
20
|
+
return cli(command,output)
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'netaddr'
|
3
|
+
require 'timeout'
|
4
|
+
|
5
|
+
module ZAWS
|
6
|
+
module Route53Services
|
7
|
+
class HostedZone
|
8
|
+
|
9
|
+
def initialize(shellout,aws)
|
10
|
+
@shellout=shellout
|
11
|
+
@aws=aws
|
12
|
+
end
|
13
|
+
|
14
|
+
def view(viewtype,textout=nil,verbose=nil)
|
15
|
+
comline="aws --output #{viewtype} route53 list-hosted-zones"
|
16
|
+
zones=@shellout.cli(comline,verbose)
|
17
|
+
textout.puts(zones) if textout
|
18
|
+
return zones
|
19
|
+
end
|
20
|
+
|
21
|
+
def view_records(viewtype,textout=nil,verbose=nil,zonename)
|
22
|
+
zones=JSON.parse(view('json',nil,verbose))
|
23
|
+
zone_id=nil
|
24
|
+
zones["HostedZones"].each { |x| zone_id = ("#{x["Name"]}"=="#{zonename}") ? x["Id"] : nil }
|
25
|
+
if zone_id
|
26
|
+
comline="aws --output #{viewtype} route53 list-resource-record-sets --hosted-zone-id #{zone_id}"
|
27
|
+
records=@shellout.cli(comline,verbose)
|
28
|
+
textout.puts(records) if textout
|
29
|
+
return records
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
data/lib/zaws/route53.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'netaddr'
|
3
|
+
require 'timeout'
|
4
|
+
|
5
|
+
module ZAWS
|
6
|
+
class Route53
|
7
|
+
|
8
|
+
def initialize(shellout,aws)
|
9
|
+
@shellout=shellout
|
10
|
+
@aws=aws
|
11
|
+
end
|
12
|
+
|
13
|
+
def hosted_zone
|
14
|
+
@_hosted_zone ||= (ZAWS::Route53Services::HostedZone.new(@shellout,@aws))
|
15
|
+
return @_hosted_zone
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
data/lib/zaws/version.rb
ADDED
data/lib/zaws.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require "zaws/version"
|
2
|
+
require "zaws/helper/option"
|
3
|
+
require "zaws/helper/output"
|
4
|
+
require "zaws/helper/shell"
|
5
|
+
require "zaws/helper/file"
|
6
|
+
require "zaws/command/subnet"
|
7
|
+
require "zaws/command/security_group"
|
8
|
+
require "zaws/command/route_table"
|
9
|
+
require "zaws/command/compute"
|
10
|
+
require "zaws/command/elasticip"
|
11
|
+
require "zaws/command/load_balancer"
|
12
|
+
require "zaws/command/hosted_zone"
|
13
|
+
require "zaws/aws"
|
14
|
+
require "zaws/ec2"
|
15
|
+
require "zaws/elb"
|
16
|
+
require "zaws/route53"
|
17
|
+
require "zaws/ec2/subnet"
|
18
|
+
require "zaws/ec2/security_group"
|
19
|
+
require "zaws/ec2/route_table"
|
20
|
+
require "zaws/ec2/compute"
|
21
|
+
require "zaws/ec2/elasticip"
|
22
|
+
require "zaws/elb/load_balancer"
|
23
|
+
require "zaws/route53/hosted_zone"
|
24
|
+
require "thor"
|
25
|
+
|
26
|
+
module ZAWS
|
27
|
+
class ZAWSCLI < Thor
|
28
|
+
|
29
|
+
desc "subnet","ec2 subnet(s)"
|
30
|
+
subcommand "subnet",ZAWS::Command::Subnet
|
31
|
+
|
32
|
+
desc "security_group","ec2 security group(s)"
|
33
|
+
subcommand "security_group",ZAWS::Command::Security_Group
|
34
|
+
|
35
|
+
desc "route_table","ec2 route table(s)"
|
36
|
+
subcommand "route_table",ZAWS::Command::Route_Table
|
37
|
+
|
38
|
+
desc "compute","ec2 compute instance(s)"
|
39
|
+
subcommand "compute",ZAWS::Command::Compute
|
40
|
+
|
41
|
+
desc "elasticip","ec2 elasticip(s)"
|
42
|
+
subcommand "elasticip",ZAWS::Command::Elasticip
|
43
|
+
|
44
|
+
desc "load_balancer","elb load balancer(s)"
|
45
|
+
subcommand "load_balancer",ZAWS::Command::Load_Balancer
|
46
|
+
|
47
|
+
desc "hosted_zone","elb hosted_zone(s)"
|
48
|
+
subcommand "hosted_zone",ZAWS::Command::Hosted_Zone
|
49
|
+
|
50
|
+
desc "version","Get the version of the Zynx AWS Automation Tool."
|
51
|
+
def version
|
52
|
+
puts "zaws version #{ZAWS::VERSION}"
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ZAWS::EC2Services::Compute do
|
4
|
+
|
5
|
+
it "add volume to instance" do
|
6
|
+
|
7
|
+
volumes = <<-eos
|
8
|
+
{ "VolumeId": "vol-1234abcd" }
|
9
|
+
eos
|
10
|
+
|
11
|
+
attachvolume = <<-eos
|
12
|
+
{
|
13
|
+
"AttachTime": "YYYY-MM-DDTHH:MM:SS.000Z",
|
14
|
+
"InstanceId": "id-X",
|
15
|
+
"VolumeId": "vol-1234abcd",
|
16
|
+
"State": "attaching",
|
17
|
+
"Device": "/dev/sda" }
|
18
|
+
eos
|
19
|
+
|
20
|
+
tag_created = <<-eos
|
21
|
+
{ "return":"true" }
|
22
|
+
eos
|
23
|
+
|
24
|
+
textout=double('outout')
|
25
|
+
shellout=double('ZAWS::Helper::Shell')
|
26
|
+
expect(shellout).to receive(:cli).with("aws --output json --region us-west-1 ec2 create-volume --availability-zone us-west-1a --size 70",nil).and_return(volumes)
|
27
|
+
expect(shellout).to receive(:cli).with("aws --output json --region us-west-1 ec2 create-tags --resources vol-1234abcd --tags Key=externalid,Value=extername",nil).and_return(tag_created)
|
28
|
+
expect(shellout).to receive(:cli).with("aws --output json --region us-west-1 ec2 create-tags --resources vol-1234abcd --tags Key=Name,Value=extername",nil).and_return(tag_created)
|
29
|
+
expect(shellout).to receive(:cli).with('ping -q -c 2 0.0.0.0',nil).and_return(true)
|
30
|
+
expect(shellout).to receive(:cli).with("aws --output json ec2 attach-volume --region us-west-1 --volume-id vol-1234abcd --instance-id id-X --device /dev/sda",nil).and_return(attachvolume)
|
31
|
+
aws=ZAWS::AWS.new(shellout)
|
32
|
+
bdm = aws.ec2.compute.add_volume('us-west-1','id-X','extername','0.0.0.0','/dev/sda','us-west-1a',70,nil)
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ZAWS::EC2Services::Compute do
|
4
|
+
|
5
|
+
it "provides a block device mapping overriding the root size" do
|
6
|
+
|
7
|
+
images = <<-eos
|
8
|
+
{ "Images": [
|
9
|
+
{ "RootDeviceName": "/dev/sda1",
|
10
|
+
"BlockDeviceMappings": [
|
11
|
+
{ "DeviceName": "/dev/sda1",
|
12
|
+
"Ebs": {
|
13
|
+
"DeleteOnTermination": true,
|
14
|
+
"SnapshotId": "snap-XXX",
|
15
|
+
"VolumeSize": 7,
|
16
|
+
"VolumeType": "standard" } } ] } ] }
|
17
|
+
eos
|
18
|
+
|
19
|
+
textout=double('outout')
|
20
|
+
shellout=double('ZAWS::Helper::Shell')
|
21
|
+
expect(shellout).to receive(:cli).with("aws --output json --region us-west-1 ec2 describe-images --owner me --image-ids X",nil).and_return(images)
|
22
|
+
aws=ZAWS::AWS.new(shellout)
|
23
|
+
bdm = aws.ec2.compute.block_device_mapping('us-west-1','me',nil,70,'X')
|
24
|
+
expect(bdm).to eq('[{"DeviceName":"/dev/sda1","Ebs":{"DeleteOnTermination":true,"SnapshotId":"snap-XXX","VolumeSize":70,"VolumeType":"standard"}}]')
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ZAWS::EC2Services::Compute do
|
4
|
+
|
5
|
+
it "provides an instance id when you give it a external id" do
|
6
|
+
|
7
|
+
compute_instances = <<-eos
|
8
|
+
{ "Reservations": [
|
9
|
+
{ "Instances" : [ {"InstanceId": "i-XXXXXXX","Tags": [ { "Value": "my_instance","Key": "externalid" } ] } ] }
|
10
|
+
] }
|
11
|
+
eos
|
12
|
+
|
13
|
+
textout=double('outout')
|
14
|
+
shellout=double('ZAWS::Helper::Shell')
|
15
|
+
expect(shellout).to receive(:cli).with("aws --output json --region us-west-1 ec2 describe-instances --filter 'Name=vpc-id,Values=my_vpc_id' 'Name=tag:externalid,Values=my_instance'",nil).and_return(compute_instances)
|
16
|
+
aws=ZAWS::AWS.new(shellout)
|
17
|
+
instanceid = aws.ec2.compute.instance_id_by_external_id('us-west-1','my_instance','my_vpc_id',nil,nil)
|
18
|
+
expect(instanceid).to eq("i-XXXXXXX")
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
|