-
Notifications
You must be signed in to change notification settings - Fork 1
/
find_ec2_instance_id.go
85 lines (65 loc) · 2.57 KB
/
find_ec2_instance_id.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
package aws
import (
"fmt"
"strings"
)
// FindEC2InstanceID looks up the instance ID for an EC2 instance using a given resource provider (e.g. an AWS API client) based on the specified search text. The search text can match the entire value or beginning substring for an instance's ID or name tag value, as long as the text matches exactly one EC2 instance.
func FindEC2InstanceID(searchText string, provider ResourceProvider) (string, error) {
instances, err := provider.AllEC2Instances()
if err != nil {
return "", err
}
var matchesOnID []int
var matchesOnName []int
// discover what matches exist... and an exact match on instance ID can return early.
for i, instance := range instances {
if isInstanceID(searchText) {
if strings.EqualFold(searchText, instance.ID) { // exact match -- instance ID
// no need to examine any more instances
return instance.ID, nil
}
if strings.HasPrefix(instance.ID, searchText) { // partial match -- instance ID
matchesOnID = append(matchesOnID, i)
}
}
if strings.HasPrefix(instance.NameTag, searchText) { // partial or exact match -- instance name
matchesOnName = append(matchesOnName, i)
}
}
// first priority goes to partial match on instance ID
if matchesOnID != nil {
if len(matchesOnID) == 1 {
return instances[matchesOnID[0]].ID, nil
}
if len(matchesOnID) >= 2 {
var ids []string
for _, matchIdx := range matchesOnID {
ids = append(ids, instances[matchIdx].ID)
}
matches := strings.Join(ids, ", ")
return "", fmt.Errorf("error: search text matches multiple EC2 instances' IDs (matches for search text '%s': %s)", searchText, matches)
}
}
// next, we hope for a match against name by only one instance (partial or exact)
if matchesOnName != nil {
if len(matchesOnName) == 1 {
return instances[matchesOnName[0]].ID, nil
}
if len(matchesOnName) >= 2 {
// prepare helpful error text
var matchedInstances []string
for _, matchIdx := range matchesOnID {
name := instances[matchIdx].NameTag
id := instances[matchIdx].ID
matchedInstances = append(matchedInstances, fmt.Sprintf("'%s' (%s)", name, id))
}
matches := strings.Join(matchedInstances, ", ")
return "", fmt.Errorf("error: search text matches multiple EC2 instances' name tags (matches for search text '%s': %s)", searchText, matches)
}
}
return "", fmt.Errorf("error: search text '%s' did not match the ID or name tag of any EC2 instances", searchText)
}
func isInstanceID(text string) bool {
const instanceIDPrefix = "i-"
return len(text) >= 3 && strings.HasPrefix(text, instanceIDPrefix)
}