-
Notifications
You must be signed in to change notification settings - Fork 12
/
aini.go
172 lines (151 loc) · 4.2 KB
/
aini.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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
package aini
import (
"bufio"
"bytes"
"io"
"os"
"path"
"sort"
"strings"
)
// InventoryData contains parsed inventory representation
// Note: Groups and Hosts fields contain all the groups and hosts, not only top-level
type InventoryData struct {
Groups map[string]*Group
Hosts map[string]*Host
}
// Group represents ansible group
type Group struct {
Name string
Vars map[string]string
Hosts map[string]*Host
Children map[string]*Group
Parents map[string]*Group
DirectParents map[string]*Group
// Vars set in inventory
InventoryVars map[string]string
// Vars set in group_vars
FileVars map[string]string
// Projection of all parent inventory variables
AllInventoryVars map[string]string
// Projection of all parent group_vars variables
AllFileVars map[string]string
}
// Host represents ansible host
type Host struct {
Name string
Port int
Vars map[string]string
Groups map[string]*Group
DirectGroups map[string]*Group
// Vars set in inventory
InventoryVars map[string]string
// Vars set in host_vars
FileVars map[string]string
}
// ParseFile parses Inventory represented as a file
func ParseFile(f string) (*InventoryData, error) {
bs, err := os.ReadFile(f)
if err != nil {
return &InventoryData{}, err
}
return Parse(bytes.NewReader(bs))
}
// ParseString parses Inventory represented as a string
func ParseString(input string) (*InventoryData, error) {
return Parse(strings.NewReader(input))
}
// Parse using some Reader
func Parse(r io.Reader) (*InventoryData, error) {
input := bufio.NewReader(r)
inventory := &InventoryData{}
err := inventory.parse(input)
if err != nil {
return inventory, err
}
inventory.Reconcile()
return inventory, nil
}
// Match looks for hosts that match the pattern
// Deprecated: Use `MatchHosts`, which does proper error handling
func (inventory *InventoryData) Match(pattern string) []*Host {
matchedHosts := make([]*Host, 0)
for _, host := range inventory.Hosts {
if m, err := path.Match(pattern, host.Name); err == nil && m {
matchedHosts = append(matchedHosts, host)
}
}
return matchedHosts
}
// GroupMapListValues transforms map of Groups into Group list in lexical order
func GroupMapListValues(mymap map[string]*Group) []*Group {
values := make([]*Group, len(mymap))
i := 0
for _, v := range mymap {
values[i] = v
i++
}
sort.Slice(values, func(i, j int) bool {
return values[i].Name < values[j].Name
})
return values
}
// HostMapListValues transforms map of Hosts into Host list in lexical order
func HostMapListValues(mymap map[string]*Host) []*Host {
values := make([]*Host, len(mymap))
i := 0
for _, v := range mymap {
values[i] = v
i++
}
sort.Slice(values, func(i, j int) bool {
return values[i].Name < values[j].Name
})
return values
}
// HostsToLower transforms all host names to lowercase
func (inventory *InventoryData) HostsToLower() {
inventory.Hosts = hostMapToLower(inventory.Hosts, false)
for _, group := range inventory.Groups {
group.Hosts = hostMapToLower(group.Hosts, true)
}
}
func hostMapToLower(hosts map[string]*Host, keysOnly bool) map[string]*Host {
newHosts := make(map[string]*Host, len(hosts))
for hostname, host := range hosts {
hostname = strings.ToLower(hostname)
if !keysOnly {
host.Name = hostname
}
newHosts[hostname] = host
}
return newHosts
}
// GroupsToLower transforms all group names to lowercase
func (inventory *InventoryData) GroupsToLower() {
inventory.Groups = groupMapToLower(inventory.Groups, false)
for _, host := range inventory.Hosts {
host.DirectGroups = groupMapToLower(host.DirectGroups, true)
host.Groups = groupMapToLower(host.Groups, true)
}
}
func (group Group) String() string {
return group.Name
}
func (host Host) String() string {
return host.Name
}
func groupMapToLower(groups map[string]*Group, keysOnly bool) map[string]*Group {
newGroups := make(map[string]*Group, len(groups))
for groupname, group := range groups {
groupname = strings.ToLower(groupname)
if !keysOnly {
group.Name = groupname
group.DirectParents = groupMapToLower(group.DirectParents, true)
group.Parents = groupMapToLower(group.Parents, true)
group.Children = groupMapToLower(group.Children, true)
}
newGroups[groupname] = group
}
return newGroups
}