-
-
Notifications
You must be signed in to change notification settings - Fork 31
/
augeas.rb
148 lines (119 loc) · 3.86 KB
/
augeas.rb
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
# frozen_string_literal: true
# Alternative Augeas-based providers for Puppet
#
# Copyright (c) 2015-2020 Raphaël Pinson
# Licensed under the Apache License, Version 2.0
raise('Missing augeasproviders_core dependency') if Puppet::Type.type(:augeasprovider).nil?
Puppet::Type.type(:sshd_config_match).provide(:augeas, parent: Puppet::Type.type(:augeasprovider).provider(:default)) do
desc 'Uses Augeas API to update an sshd_config Match group'
default_file { '/etc/ssh/sshd_config' }
lens { 'Sshd.lns' }
confine feature: :augeas
def self.static_path(resource)
path = "$target/Match[count(Condition/*)=#{resource[:condition].keys.size}]"
resource[:condition].each do |c, v|
path += "[Condition/#{c}='#{v}']"
end
path
end
def self.path(resource)
path = '$target/*'
path += "[label()=~regexp('match', 'i') and *[label()=~regexp('condition', 'i') and count(*)=#{resource[:condition].keys.size}]"
resource[:condition].each do |c, v|
path += "[*[label()=~regexp('#{c}', 'i')]='#{v}']"
end
path += ']'
end
resource_path do |resource|
path(resource)
end
def self.instances
augopen do |aug, _path|
resources = []
search_path = "$target/*[label()=~regexp('match', 'i')]/*[label()=~regexp('condition', 'i')]"
aug.match(search_path.to_s).each do |hpath|
conditions = []
aug.match("#{hpath}/*").each do |cpath|
c = path_label(aug, cpath)
next if c.start_with?('#')
conditions << "#{c} #{aug.get(cpath)}"
end
condition = conditions.join(' ')
resources << new(ensure: :present,
name: "#{condition} in #{target}",
condition: condition)
end
resources
end
end
POS_ALIASES = {
'first match' => 'Match[1]',
'last match' => 'Match[last()]',
}.freeze
def self.position_path(position)
if POS_ALIASES.include? position[:match]
POS_ALIASES[position[:match]]
else
match_a = position[:match].split
path(condition: Hash[*match_a])
end
end
def self.in_position?(aug, resource)
position = resource[:position]
return unless position
path = if position[:before]
"$resource[following-sibling::#{position_path(position)}]"
else
"$resource[preceding-sibling::#{position_path(position)}]"
end
!aug.match(path).empty?
end
def in_position?
augopen do |aug|
self.class.in_position?(aug, resource)
end
end
def self.position!(aug, resource)
position = resource[:position]
path = position_path(position)
aug.insert(path, 'Match', position[:before])
aug.mv('$resource', '$target/Match[count(*)=0]')
end
def position!
augopen! do |aug|
self.class.position!(aug, resource)
self.comment = resource[:comment]
end
end
def create
augopen! do |aug|
path = self.class.static_path(resource)
aug.defnode('resource', path, nil)
resource[:condition].each do |c, v|
aug.set("$resource/Condition/#{c}", v)
end
aug.clear('$resource/Settings')
self.class.position!(aug, resource) \
if !self.class.in_position?(aug, resource) && resource[:position]
# At least one entry is mandatory (in the lens at least)
self.comment = resource[:comment]
end
end
def comment
augopen do |aug|
comment = aug.get('$resource/Settings/#comment[1]')
comment&.sub!(%r{^#{resource[:name]}:\s*}i, '')
comment || ''
end
end
def comment=(_value)
augopen! do |aug|
cmtnode = '$resource/Settings/#comment[1]'
if aug.match(cmtnode).empty? && aug.match('$resource/Settings/*').any?
# Insert before first entry
aug.insert('$resource/Settings/*[1]', '#comment', true)
end
aug.set(cmtnode, "#{resource[:name]}: #{resource[:comment]}")
end
end
end