File: aini.go

package info (click to toggle)
golang-github-relex-aini 1.6.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 204 kB
  • sloc: makefile: 15
file content (172 lines) | stat: -rw-r--r-- 4,296 bytes parent folder | download
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
}