Skip to content

Commit

Permalink
Add action group sanity test.
Browse files Browse the repository at this point in the history
  • Loading branch information
felixfontein committed Jan 24, 2024
1 parent cc32e0e commit b496acc
Show file tree
Hide file tree
Showing 3 changed files with 149 additions and 0 deletions.
11 changes: 11 additions & 0 deletions tests/sanity/extra/action-group.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"include_symlinks": true,
"prefixes": [
"meta/runtime.yml",
"plugins/modules/"
],
"output": "path-message",
"requirements": [
"pyyaml"
]
}
3 changes: 3 additions & 0 deletions tests/sanity/extra/action-group.json.license
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
SPDX-License-Identifier: GPL-3.0-or-later
SPDX-FileCopyrightText: Ansible Project
135 changes: 135 additions & 0 deletions tests/sanity/extra/action-group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#!/usr/bin/env python
# Copyright (c) 2024, Felix Fontein <felix@fontein.de>
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
# SPDX-License-Identifier: GPL-3.0-or-later
"""Make sure all modules that should show up in the action group."""
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

import os
import glob
import sys
import yaml


def format_license_list(licenses):
if not licenses:
return '(empty)'
return ', '.join(['"%s"' % license for license in licenses])


def find_licenses(filename, relax=False):
spdx_license_identifiers = []
other_license_identifiers = []
has_copyright = False
try:
with open(filename, 'r', encoding='utf-8') as f:
for line in f:
line = line.rstrip()
if 'Copyright ' in line:
has_copyright = True
if 'Copyright: ' in line:
print('%s: found copyright line with "Copyright:". Please remove the colon.' % (filename, ))
if 'SPDX-FileCopyrightText: ' in line:
has_copyright = True
idx = line.find('SPDX-License-Identifier: ')
if idx >= 0:
lic_id = line[idx + len('SPDX-License-Identifier: '):]
spdx_license_identifiers.extend(lic_id.split(' OR '))
if 'GNU General Public License' in line:
if 'v3.0+' in line:
other_license_identifiers.append('GPL-3.0-or-later')
if 'version 3 or later' in line:
other_license_identifiers.append('GPL-3.0-or-later')
if 'Simplified BSD License' in line:
other_license_identifiers.append('BSD-2-Clause')
if 'Apache License 2.0' in line:
other_license_identifiers.append('Apache-2.0')
if 'PSF License' in line or 'Python-2.0' in line:
other_license_identifiers.append('PSF-2.0')
if 'MIT License' in line:
other_license_identifiers.append('MIT')
except Exception as exc:
print('%s: error while processing file: %s' % (filename, exc))
if len(set(spdx_license_identifiers)) < len(spdx_license_identifiers):
print('%s: found identical SPDX-License-Identifier values' % (filename, ))
if other_license_identifiers and set(other_license_identifiers) != set(spdx_license_identifiers):
print('%s: SPDX-License-Identifier yielded the license list %s, while manual guessing yielded the license list %s' % (
filename, format_license_list(spdx_license_identifiers), format_license_list(other_license_identifiers)))
if not has_copyright and not relax:
print('%s: found no copyright notice' % (filename, ))
return sorted(spdx_license_identifiers)


def main():
"""Main entry point."""

# Load redirects
meta_runtime = 'meta/runtime.yml'
try:
with open(meta_runtime, 'rb') as f:
data = yaml.safe_load(f)
action_group = data['action_groups']['docker']
except Exception as exc:
print('%s: cannot load action group: %s' % (meta_runtime, exc))
return

exclusions = ['current_container_facts']
modules_directory = 'plugins/modules/'
modules_suffix = '.py'

for file in os.listdir(modules_directory):
if not file.endswith(modules_suffix):
continue
module_name = file[:-len(modules_suffix)]

should_be_in_action_group = module_name not in exclusions

if should_be_in_action_group:
if module_name not in action_group:
print('%s: module %s is not part of docker action group' % (meta_runtime, module_name))
else:
action_group.remove(module_name)

path = os.path.join(modules_directory, file)
documentation = []
in_docs = False
with open(path, 'r', encoding='utf-8') as f:
for line in f:
if line.startswith('DOCUMENTATION ='):
in_docs = True
elif line.startswith(("'''", '"""')) and in_docs:
in_docs = False
elif in_docs:
documentation.append(line)
if in_docs:
print('%s: cannot find DOCUMENTATION end' % (path))
if not documentation:
print('%s: cannot find DOCUMENTATION' % (path))
continue

try:
docs = yaml.safe_load('\n'.join(documentation))
if not isinstance(docs, dict):
raise Exception('is not a top-level dictionary')
except Exception as exc:
print('%s: cannot load DOCUMENTATION as YAML: %s' % (path, exc))
continue

docs_fragments = docs.get('extends_documentation_fragment') or []
is_in_action_group = 'community.docker.attributes.actiongroup_docker' in docs_fragments

if should_be_in_action_group != is_in_action_group:
if should_be_in_action_group:
print('%s: module does not document itself as part of action group, but it should' % (path))
else:
print('%s: module documents itself as part of action group, but it should not be' % (path))



for module_name in action_group:
print('%s: module %s mentioned in docker action group does not exist' % (meta_runtime, module_name))


if __name__ == '__main__':
main()

0 comments on commit b496acc

Please sign in to comment.