-
Notifications
You must be signed in to change notification settings - Fork 44
/
Copy pathec2din.ngs
executable file
·125 lines (100 loc) · 4.06 KB
/
ec2din.ngs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/usr/bin/env ngs
# Running example: ./demo/ec2din.ngs
# Running example: NGS_table_Instances='["InstanceId", "PublicIpAddress", "PrivateIpAddress", "State", "KeyName", "SecurityGroups"]' ./demo/ec2din.ngs
ArgvMatcher('positionals', 'filters') do
doc filters - Show only instances matching the given filters. Possible filter forms are:
doc filters - vpc-xxxyyyzz - for specific vpc
doc filters - i-xxxyyyzz - for specific instance id
doc filters - 1.2.3.4 - for instance having given IP
doc filters - kkk=vvv - for instances having given tag value
F main(filters:Arr, allreg:Bool=false, j:Bool=false, c:Str=null, out_lines:Int=5, out_columns:Int=20, err_lines:Int=5, err_columns:Int=20) {
c = Box(c).map(decode_json)
if c {
warn("ec2din.ngs: Using experimental 'c' switch. Behaviour subject to change.")
config('table_Instances', %[InstanceId tag_Name tag_proj tag_env tag_role IPs State AZ ec out err])
} else {
config('table_Instances', %[InstanceId tag_Name tag_proj tag_env tag_role IPs InstanceType State KeyName SecurityGroups AZ RestOfTags])
}
table = Table('Instances')
F limit_len(s:Str, l:Int) limit(s, l, '...')
# region to az
regions = {}
local_filters = AllOf()
filters = ['--filters'] +? collector filters.each(F(arg) {
econd {
arg == 'windows' collect("Name=platform,Values=windows")
arg == 'linux' local_filters.push('Platform' not in X)
arg.starts_with('vpc-') collect("Name=vpc-id,Values=$arg")
arg.starts_with('i-') collect("Name=instance-id,Values=$arg")
m = arg ~ /^([a-z]{2}-[a-z]+-[0-9]+)([a-z])?$/ {
# region or az
regions.dflt(m[0], {})
if m.matches.len() == 3 {
regions[m[0]][m[1]] = true
throw InvalidArgument("Availability zones filtering is not supported yet")
}
}
arg ~ /^[0-9.]+$/ {
filter_name = if IPAddr(arg).is_private() then 'private-ip-address' else 'ip-address'
collect("Name=$filter_name,Values=$arg")
}
arg ~ /^[a-z][0-9][.][0-9]*[a-z]+$/ collect("Name=instance-type,Values=$arg")
arg in AWS::INSTANCE_STATES collect("Name=instance-state-name,Values=$arg")
{kv = arg.split('='); kv.len() == 2} collect("Name=tag:${kv[0]},Values=${kv[1]}")
}
})
len(regions) > 1 throws InvalidArgument("Multiple regions are not supported yet")
instances = if allreg {
# AZ is now important so moving it to be first
config('table_Instances', ['AZ'] + config('table_Instances').without('AZ'))
AWS::regions({ ``aws ec2 describe-instances --region $A $*filters`` })
} else {
reg = Argv({'--region': regions.keys()})
``aws ec2 describe-instances $*filters $*reg``
}
instances .= sort('LaunchTime')
instances .= filter(local_filters)
c.each(F(cmd) {
instances.pmap(F(i) {
try {
argv = cmd.map(only(Pfx('i.'), F(arg) {
i[arg[2..null]]
}))
i.argv = argv
p=$(ok: $*argv)
i.ec = p.processes[-1].exit_code
i.out = try p.stdout.lines().limit(out_lines).map(limit(X, out_columns))
i.err = try p.stderr.lines().limit(err_lines).map(limit(X, err_columns))
} catch(e:KeyNotFound) {
guard e.container == i
i.err = 'No ' + e.key
}
})
})
if j {
echo(instances.encode_json())
return
}
F tag_has_column(tag_name) ["full_tag_${tag_name}", "tag_${tag_name}"].any(X in table.cols_enum)
instances % F(i) {
if ENV.get('EC2DIN_SHOW_PROFILE', 'true').decode(Bool) {
i.InstanceId = [i.InstanceId, i.get('IamInstanceProfile', {}).Box('Arn').map(basename).get('(no profile)')]
}
i.State = i.State.Name
i.SecurityGroups = i.SecurityGroups.map(F(sg) "${limit_len(sg.GroupName, 15)}(${sg.GroupId})")
i.AZ = i.Placement.AvailabilityZone
# Tags here is a Hash (after straightening by stdlib)
i.dflt('Tags', {})
i.Name = i.Tags.get('Name', '-').limit_len(20)
i.IPs = [try i.PublicIpAddress, try i.PrivateIpAddress]
i.Tags.each(F(k, v) {
i["full_tag_${k}"] = v
i["tag_${k}"] = v.limit_len(20)
})
# TODO: Move layout management to Table, don't limit_len() here
i.RestOfTags = i.Tags.rejectk(tag_has_column).map({ "${A.limit_len(10)}=${B.limit_len(15)}" })
}
table.push_all(instances)
echo(table)
log("Listed ${len(instances)} instances")
}