-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FMF metadata support to colin #141
Closed
Closed
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
1c38b7f
add fmf metadata support to colin
jscotka aa8c891
try to use another, more explicit way
jscotka a5f4dee
improve rulesets handling
jscotka c363e84
changed to Null from None, should be tranformed to pyton None
jscotka aba58db
reverted typo back
jscotka f6728d2
add filter possibilities via envvar values, possible to select some r…
jscotka 0e58bcf
missing important part, what raises exception in case, it fails
jscotka 9b6cbc1
consolidate logging
jscotka e1dcf4c
add support for pure fmf classes, without any python file, not compat…
jscotka 68a98f6
move readinf CHECK envvar to get_check_path, to be compatible with colin
jscotka 71f2043
fix instruction checks when *_count is 0
TomasTomecek 962b845
enable all tests by default
TomasTomecek 3229fe5
tests: more verbose logs
TomasTomecek b295827
travis: require sudo b/c of sudo apt-...
TomasTomecek a503103
fix checks location
jscotka File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
language: python | ||
sudo: false | ||
sudo: required | ||
notifications: | ||
email: false | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
test: "best_practices.py" | ||
|
||
/cmd_or_entrypoint: | ||
class: "CmdOrEntrypointCheck" | ||
message: "Cmd or Entrypoint has to be specified" | ||
description: "An ENTRYPOINT allows you to configure a container that will run as an executable. The main purpose of a CMD is to provide defaults for an executing container." | ||
reference_url: "https://fedoraproject.org/wiki/Container:Guidelines#CMD.2FENTRYPOINT_2" | ||
tags: ["cmd", "entrypoint"] | ||
|
||
/help_file_or_readme: | ||
class: "HelpFileOrReadmeCheck" | ||
message: "The 'helpfile' has to be provided." | ||
description: "Just like traditional packages, containers need some 'man page' information about how they are to be used, configured, and integrated into a larger stack." | ||
reference_url: "https://fedoraproject.org/wiki/Container:Guidelines#Help_File" | ||
files: ['/help.1', '/README.md'] | ||
tags: ['filesystem', 'helpfile', 'man'] | ||
all_must_be_present: False | ||
|
||
/no_root: | ||
class: "NoRootCheck" | ||
message: "Service should not run as root by default." | ||
description: "It can be insecure to run service as root." | ||
reference_url: "?????" | ||
tags: ["root", "user"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
description: "Generic desription for dockerfile test if not specific description given" | ||
test: "dockerfile.py" | ||
|
||
/from_tag_not_latest: | ||
class: "FromTagNotLatestCheck" | ||
message: "In FROM, tag has to be specified and not 'latest'." | ||
description: "Using the 'latest' tag may cause unpredictable builds.It is recommended that a specific tag is used in the FROM." | ||
reference_url: "https://fedoraproject.org/wiki/Container:Guidelines#FROM" | ||
tags: ["from", "dockerfile", "baseimage", "latest"] | ||
|
||
/maintainer_deprecated: | ||
class: "MaintainerDeprecatedCheck" | ||
message: "Dockerfile instruction `MAINTAINER` is deprecated." | ||
description: "Replace with label 'maintainer'." | ||
reference_url: "https://docs.docker.com/engine/reference/builder/#maintainer-deprecated" | ||
tags: ["maintainer", "dockerfile", "deprecated"] | ||
instruction: "MAINTAINER" | ||
max_count: 0 | ||
|
||
/test_maintainer_pure: | ||
class: "InstructionCountAbstractCheck" | ||
message: "Dockerfile instruction `MAINTAINER` is deprecated." | ||
description: "TEST: Replace with label 'maintainer'." | ||
reference_url: "https://docs.docker.com/engine/reference/builder/#maintainer-deprecated" | ||
tags: ["maintainer", "dockerfile", "deprecated"] | ||
instruction: "MAINTAINER" | ||
max_count: 0 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
test: labels.py | ||
|
||
/maintainer_label: | ||
class: "MaintainerLabelCheck" | ||
message: "Label 'maintainer' has to be specified." | ||
description: "The name and email of the maintainer (usually the submitter)." | ||
reference_url: "https://fedoraproject.org/wiki/Container:Guidelines#LABELS" | ||
tags: ["maintainer", "label"] | ||
labels: ["maintainer"] | ||
required: True | ||
value_regex: Null |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
""" | ||
Module handling FMF stored metadata for classes | ||
""" | ||
|
||
import os | ||
import copy | ||
import re | ||
import logging | ||
|
||
from fmf import Tree | ||
from .abstract_check import AbstractCheck | ||
from ..ruleset.ruleset import get_checks_path | ||
|
||
|
||
logger = logging.getLogger(__name__) | ||
|
||
|
||
class ExtendedTree(Tree): | ||
""" | ||
FMF Extension. Allows to use references via @ to another items -> usefull for rulesets | ||
""" | ||
|
||
def __remove_append_items(self, whole=False): | ||
""" | ||
internal method, delete all append items (ends with +) | ||
:param whole: pass thru 'whole' param to climb | ||
:return: None | ||
""" | ||
for node in self.climb(whole=whole): | ||
for key in sorted(node.data.keys()): | ||
if key.endswith('+'): | ||
del node.data[key] | ||
|
||
def references(self, patterntree, whole=False): | ||
""" | ||
resolve references in names like /a/b/c/[email protected] or /a/b/c/@y | ||
it uses simple references schema, do not use references to another references | ||
avoid usind / in reference because actual solution creates also this tree items | ||
it is bug or feature, who knows :-) | ||
:param whole: pass thru 'whole' param to climb | ||
:param patterntree: original tree with testcases to contain parent nodes | ||
:return: None | ||
""" | ||
reference_nodes = self.prune(whole=whole, names=["@"]) | ||
for node in reference_nodes: | ||
node.data = node.original_data | ||
ref_item_name = node.name.rsplit("@", 1)[1] | ||
# match item what does not contain @ before name, otherwise it | ||
# match same item | ||
reference_node = patterntree.search("[^@]%s" % ref_item_name) | ||
logger.debug("MERGING: %s @ %s", node.name, reference_node.name) | ||
if not reference_node: | ||
raise ValueError("Unable to find reference for node: %s via name search: %s" % | ||
(node.name, ref_item_name)) | ||
node.merge(parent=reference_node) | ||
|
||
self.__remove_append_items(whole=whole) | ||
|
||
def search(self, name): | ||
""" Search node with given name based on reqexp""" | ||
for node in self.climb(): | ||
if re.search(name, node.name): | ||
return node | ||
return None | ||
|
||
|
||
class FMFCaseLoader(object): | ||
""" | ||
search and load FMF metadata | ||
""" | ||
|
||
def __init__(self, name_id, path=None): | ||
""" | ||
Case loader metatada init, it try to gather metadata form FMF based on name identifier | ||
:param name_id: | ||
:param path: | ||
""" | ||
self.metadata = self.__receive_fmf_metadata( | ||
path or get_checks_path(), name=name_id) | ||
self.name = self.get_name() | ||
|
||
def __receive_fmf_metadata(self, fmfpath, name=None, object_list=False): | ||
""" | ||
internal method, search name in metadata in fmfpath | ||
|
||
:param fmfpath: path to filesystem | ||
:param name: str - name as pattern to search (substring) | ||
:param object_list: bool, if true, return whole list of found items | ||
:return: Tree Object or list | ||
""" | ||
output = {} | ||
fmf_tree = ExtendedTree(fmfpath) | ||
logger.debug("get FMF metadata for test (path:%s name=%s)", fmfpath, name) | ||
items = [x for x in fmf_tree.climb( | ||
) if name in x.name and "@" not in x.name] | ||
if object_list: | ||
return items | ||
if len(items) == 1: | ||
output = items[0] | ||
elif len(items) > 1: | ||
raise Exception("There is more FMF test metadata for item by name:{}({}) {}".format( | ||
name, len(items), [x.name for x in items])) | ||
elif not items: | ||
raise Exception("Unable to get FMF metadata for: {}".format(name)) | ||
return output | ||
|
||
def get_name(self, full=False): | ||
""" | ||
return FMF Name of item | ||
:param full: if True return full path identifier | ||
:return: str - name identifier | ||
""" | ||
out = self.metadata.name | ||
if not full: | ||
out = self.metadata.name.rsplit("/", 1)[-1] | ||
return out | ||
|
||
|
||
class FMFAbstractCheck(AbstractCheck): | ||
""" | ||
Abstract class for checks and loading metadata from FMF format | ||
""" | ||
metadata = None | ||
name = None | ||
|
||
@classmethod | ||
def get_metadata(cls, name, path=None): | ||
""" | ||
Very important method what returns tuple for object initialization | ||
COLIN tool expects to have class attribute: name | ||
to be able to find cases | ||
:param name: str, identifier of name in FMF | ||
:param path: where to look for metadata | ||
:return: tuple, name, FMF metadata Tree | ||
""" | ||
item = FMFCaseLoader(name_id=name, path=path) | ||
return item.name, item.metadata | ||
|
||
def __init__(self): | ||
""" | ||
wraps parameters to COLIN format | ||
""" | ||
kwargs = copy.deepcopy(self.metadata.data) | ||
if "class" in kwargs: | ||
del kwargs["class"] | ||
if "test" in kwargs: | ||
del kwargs["test"] | ||
super(FMFAbstractCheck, self).__init__(**kwargs) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder whether there is a nicer way of doing this. Calling functions on class' attributes outside of methods seems sketchy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, I had also troubles with this, but actually there is probably not better way how to do it without bigger changes in colin. Because current colin implementation does static inspection of classes, to find checks based on class attribute
name
. If you have some idea I'll be happy to change it to better way