/
sessions.go
136 lines (112 loc) · 3.07 KB
/
sessions.go
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
126
127
128
129
130
131
132
133
134
135
136
// Copyright 2014, Bryan Matsuo. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// inspect.go [created: Thu, 20 Mar 2014]
/*
Inspect sessions
BUG sessions cannot span regions
the "sessions" command provides information about known oti sessions and their
resources. resources are identified by tag values.
oti sessions -h
locates existing sessions. sessions exists merely by having instances tagged
with their session id.
*/
package main
import (
"github.com/bmatsuo/oti/otisub"
"github.com/bmatsuo/oti/otitag"
"github.com/crowdmob/goamz/aws"
awsec2 "github.com/crowdmob/goamz/ec2"
"flag"
"fmt"
"sync"
)
var sessions = otisub.Register("sessions", func(args []string) {
fs := otisub.FlagSet(flag.ExitOnError, "sessions", "[sessionid ...]")
fs.Parse(args)
sessionids := fs.Args()
awsauth, err := Config.AwsAuth()
if err != nil {
Log.Fatalf("error reading aws credentials: %v", err)
}
wg := new(sync.WaitGroup)
for _, r := range Ec2Regions(false) {
r := r
wg.Add(1)
go func() {
SessionsMain(awsauth, r, sessionids)
wg.Done()
}()
}
wg.Wait()
})
var isAwsUsGovRegion = map[string]bool{"us-gov-west-1": true}
func Ec2Regions(usgov bool) []aws.Region {
rs := make([]aws.Region, 0, len(aws.Regions))
for k := range aws.Regions {
if isAwsUsGovRegion[k] && !usgov {
// shhh
continue
}
if aws.Regions[k].EC2Endpoint != "" {
rs = append(rs, aws.Regions[k])
}
}
return rs
}
// locate and inspect sessions, active or terminated
func SessionsMain(auth aws.Auth, region aws.Region, sessionids []string) {
ec2 := awsec2.New(auth, region)
sessions, err := LocateSessions(ec2, sessionids)
if err != nil {
Log.Fatalln("error locating instances: ", err)
}
// print session details to stdout
for _, s := range sessions {
fmt.Printf("%s\t%s\t%s\n", region.Name, s.Id, DescribeSessionInstanceStates(s))
}
}
type Session struct {
Id SessionId
Instances []awsec2.Instance
}
func LocateSessions(ec2 *awsec2.EC2, sessions []string) ([]Session, error) {
sessionIdTag := Config.Ec2Tag(otitag.SessionId)
filter := awsec2.NewFilter()
if len(sessions) > 0 {
filter.Add("tag:"+sessionIdTag, sessions...)
} else {
filter.Add("tag-key", Config.Ec2Tag(otitag.SessionId))
}
resp, err := ec2.DescribeInstances(nil, filter)
if err != nil {
return nil, err
}
simap := make(map[SessionId][]awsec2.Instance)
for _, rsvn := range resp.Reservations {
for _, inst := range rsvn.Instances {
for _, tag := range inst.Tags {
if tag.Key == sessionIdTag {
sessionId := SessionId(tag.Value)
simap[sessionId] = append(simap[sessionId], inst)
break
}
}
}
}
var ss []Session
for id, is := range simap {
ss = append(ss, Session{id, is})
}
return ss, nil
}
func DescribeSessionInstanceStates(s Session) string {
counts := make(map[string]int, 5)
for _, inst := range s.Instances {
counts[inst.State.Name]++
}
return fmt.Sprintf("%d/%d/%d/%d/%d",
counts["pending"], counts["running"],
counts["shutting-down"], counts["stopped"],
counts["terminated"])
}