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
|
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
from testinfra.modules.base import InstanceModule
def parse_puppet_resource(data: str) -> dict[str, dict[str, str]]:
"""Parse data returned by 'puppet resource'
$ puppet resource user
user { 'root':
ensure => 'present',
comment => 'root',
gid => '0',
home => '/root',
shell => '/usr/bin/zsh',
uid => '0',
}
user { 'sshd':
ensure => 'present',
gid => '65534',
home => '/var/run/sshd',
shell => '/usr/sbin/nologin',
uid => '106',
}
[...]
"""
state: dict[str, dict[str, str]] = {}
current = None
for line in data.splitlines():
if not current:
current = line.split("'")[1]
state[current] = {}
elif current and line == "}":
current = None
elif current:
key, value = line.split(" => ")
key = key.strip()
value = value.split("'")[1]
state[current][key] = value
return state
class PuppetResource(InstanceModule):
"""Get puppet resources
Run ``puppet resource --types`` to get a list of available types.
>>> host.puppet_resource("user", "www-data")
{
'www-data': {
'ensure': 'present',
'comment': 'www-data',
'gid': '33',
'home': '/var/www',
'shell': '/usr/sbin/nologin',
'uid': '33',
},
}
"""
def __call__(self, resource_type, name=None):
cmd = "puppet resource %s"
args = [resource_type]
if name is not None:
cmd += " %s"
args.append(name)
# TODO(phil): Since puppet 4.0.0 puppet resource has a --to_yaml option
return parse_puppet_resource(self.check_output(cmd, *args))
def __repr__(self):
return "<PuppetResource>"
class Facter(InstanceModule):
"""Get facts with `facter <https://puppetlabs.com/facter>`_
>>> host.facter()
{
"operatingsystem": "Debian",
"kernel": "linux",
[...]
}
>>> host.facter("kernelversion", "is_virtual")
{
"kernelversion": "3.16.0",
"is_virtual": "false"
}
"""
def __call__(self, *facts):
cmd = "facter --json --puppet " + " ".join(facts)
return json.loads(self.check_output(cmd))
def __repr__(self):
return "<facter>"
|