diff -Nru click-reviewers-tools-0.26/bin/clickreviews/cr_bin_path.py click-reviewers-tools-0.27/bin/clickreviews/cr_bin_path.py --- click-reviewers-tools-0.26/bin/clickreviews/cr_bin_path.py 2015-04-20 15:40:24.000000000 +0000 +++ click-reviewers-tools-0.27/bin/clickreviews/cr_bin_path.py 2015-05-04 18:32:35.000000000 +0000 @@ -35,9 +35,8 @@ # snappy yaml currently only allows specifying: # - exec (optional) # - description (optional) - # - TODO: caps (optional) self.required_keys = [] - self.optional_keys = ['description', 'exec'] + self.optional_keys = ['description', 'exec'] + self.snappy_exe_security self.bin_paths_files = dict() self.bin_paths = dict() @@ -142,16 +141,14 @@ def _verify_optional(self, my_dict, test_str): for app in sorted(my_dict): for o in self.optional_keys: + if o in self.snappy_exe_security: + continue # checked in cr_security.py found = False t = 'info' n = '%s_optional_key_%s_%s' % (test_str, o, app) s = "OK" if o in my_dict[app]: - if o == 'stop-timeout' and \ - not isinstance(my_dict[app][o], int): - t = 'error' - s = "'%s' is not an integer" % o - elif not isinstance(my_dict[app][o], str): + if not isinstance(my_dict[app][o], str): t = 'error' s = "'%s' is not a string" % o elif my_dict[app][o] == "": diff -Nru click-reviewers-tools-0.26/bin/clickreviews/cr_common.py click-reviewers-tools-0.27/bin/clickreviews/cr_common.py --- click-reviewers-tools-0.26/bin/clickreviews/cr_common.py 2015-04-20 15:40:24.000000000 +0000 +++ click-reviewers-tools-0.27/bin/clickreviews/cr_common.py 2015-05-04 18:32:35.000000000 +0000 @@ -84,6 +84,7 @@ # optional snappy fields here (may be required by appstore) snappy_optional = ["architecture", "binaries", + "caps", "config", "frameworks", "icon", @@ -95,6 +96,10 @@ "type", "vendor", # replaces maintainer ] + snappy_exe_security = ["caps", + "security-template", + "security-override", + "security-policy"] def __init__(self, fn, review_type, peer_hooks=None, overrides=None): self.click_package = fn diff -Nru click-reviewers-tools-0.26/bin/clickreviews/cr_lint.py click-reviewers-tools-0.27/bin/clickreviews/cr_lint.py --- click-reviewers-tools-0.26/bin/clickreviews/cr_lint.py 2015-04-20 15:40:24.000000000 +0000 +++ click-reviewers-tools-0.27/bin/clickreviews/cr_lint.py 2015-05-04 18:32:35.000000000 +0000 @@ -36,6 +36,8 @@ ClickReview.__init__(self, fn, "lint", overrides=overrides) if not self.is_snap and "md5sums" not in CONTROL_FILE_NAMES: CONTROL_FILE_NAMES.append("md5sums") + elif self.is_snap: + CONTROL_FILE_NAMES.append("hashes.yaml") self.control_files = dict() self._list_control_files() # Valid values for Architecture in DEBIAN/control. Note: @@ -646,30 +648,40 @@ l = "http://askubuntu.com/questions/460512/what-framework-should-i-use-in-my-manifest-file" framework_overrides = self.overrides.get('framework', {}) frameworks = Frameworks(overrides=framework_overrides) - if self.manifest['framework'] in frameworks.AVAILABLE_FRAMEWORKS: - t = 'info' - s = 'OK' + + if not self.is_snap and ',' in self.manifest['framework']: + # click doesn't support multiple frameworks yet + t = 'error' + s = 'ERROR: multiple frameworks found in click manifest' self._add_result(t, n, s) - # If it's an available framework, we're done checking return - elif self.manifest['framework'] in frameworks.DEPRECATED_FRAMEWORKS: - t = 'warn' - s = "'%s' is deprecated. Please use a newer framework" % \ - self.manifest['framework'] - self._add_result(t, n, s, l) - return - elif self.manifest['framework'] in frameworks.OBSOLETE_FRAMEWORKS: - t = 'error' - s = "'%s' is obsolete. Please use a newer framework" % \ - self.manifest['framework'] - self._add_result(t, n, s, l) - return - else: - # None of the above checks triggered, this is an unknown framework - t = 'error' - s = "'%s' is not a supported framework" % \ - self.manifest['framework'] - self._add_result(t, n, s, l) + + for framework in self.manifest['framework'].split(','): + framework = framework.strip() + if framework in frameworks.AVAILABLE_FRAMEWORKS: + t = 'info' + s = 'OK' + self._add_result(t, n, s) + # If it's an available framework, we're done checking + return + elif framework in frameworks.DEPRECATED_FRAMEWORKS: + t = 'warn' + s = "'%s' is deprecated. Please use a newer framework" % \ + framework + self._add_result(t, n, s, l) + return + elif framework in frameworks.OBSOLETE_FRAMEWORKS: + t = 'error' + s = "'%s' is obsolete. Please use a newer framework" % \ + framework + self._add_result(t, n, s, l) + return + else: + # None of the above checks triggered, this is an unknown framework + t = 'error' + s = "'%s' is not a supported framework" % \ + framework + self._add_result(t, n, s, l) def check_click_local_extensions(self): '''Report any click local extensions''' diff -Nru click-reviewers-tools-0.26/bin/clickreviews/cr_security.py click-reviewers-tools-0.27/bin/clickreviews/cr_security.py --- click-reviewers-tools-0.26/bin/clickreviews/cr_security.py 2015-04-20 15:40:24.000000000 +0000 +++ click-reviewers-tools-0.27/bin/clickreviews/cr_security.py 2015-05-04 18:32:35.000000000 +0000 @@ -96,6 +96,8 @@ # framework policy is based on major framework version. In 13.10, there # was only 'ubuntu-sdk-13.10', but in 14.04, there will be several, # like 'ubuntu-sdk-14.04-html5', 'ubuntu-sdk-14.04-platform', etc + # TODO: in 15.10 we will be using the policy version will match the + # release framework, so we can simplify these checks self.major_framework_policy = { 'ubuntu-sdk-13.10': { 'policy_version': 1.0, @@ -106,6 +108,9 @@ 'ubuntu-sdk-14.10': { 'policy_version': 1.2, }, + 'ubuntu-sdk-15.04': { + 'policy_version': 1.3, + }, 'ubuntu-core-15.04': { 'policy_vendor': 'ubuntu-core', 'policy_version': 15.04, @@ -329,8 +334,14 @@ if 'policy_vendor' in m: # policy_vendor is optional found_major = False for name, data in self.major_framework_policy.items(): - # TODO: use libclick when it is available - if not self.manifest['framework'].startswith(name): + framework = self.manifest['framework'] + # snappy compat manifest supports comma-separated list + # for framework + if self.is_snap and ',' in framework: + # For now, we know the release framework is appended. + # TODO: fix for multiple frameworks + framework = framework.split(',')[-1] + if not framework.startswith(name): continue elif 'policy_vendor' not in data: # when not specified, default to 'ubuntu' @@ -340,10 +351,10 @@ t = 'error' s = '%s != %s (%s)' % (str(m['policy_vendor']), data['policy_vendor'], - self.manifest['framework']) + framework) if not found_major: t = 'error' - s = "Invalid framework '%s'" % self.manifest['framework'] + s = "Invalid framework '%s'" % framework self._add_result(t, n, s) def check_policy_version(self): @@ -385,18 +396,24 @@ s = "OK" found_major = False for name, data in self.major_framework_policy.items(): - # TODO: use libclick when it is available - if not self.manifest['framework'].startswith(name): + framework = self.manifest['framework'] + # snappy compat manifest supports comma-separated list + # for framework + if self.is_snap and ',' in framework: + # For now, we know the release framework is appended. + # TODO: fix for multiple frameworks + framework = framework.split(',')[-1] + if not framework.startswith(name): continue found_major = True if m['policy_version'] != data['policy_version']: t = 'error' s = '%s != %s (%s)' % (str(m['policy_version']), data['policy_version'], - self.manifest['framework']) + framework) if not found_major: t = 'error' - s = "Invalid framework '%s'" % self.manifest['framework'] + s = "Invalid framework '%s'" % framework self._add_result(t, n, s) def check_template(self): diff -Nru click-reviewers-tools-0.26/bin/clickreviews/cr_systemd.py click-reviewers-tools-0.27/bin/clickreviews/cr_systemd.py --- click-reviewers-tools-0.26/bin/clickreviews/cr_systemd.py 2015-04-20 15:40:24.000000000 +0000 +++ click-reviewers-tools-0.27/bin/clickreviews/cr_systemd.py 2015-05-04 18:32:35.000000000 +0000 @@ -19,6 +19,7 @@ from clickreviews.cr_common import ClickReview, error, open_file_read import yaml import os +import re class ClickReviewSystemd(ClickReview): @@ -41,7 +42,8 @@ # - stop-timeout # - TODO: caps self.required_keys = ['start', 'description'] - self.optional_keys = ['stop', 'poststop', 'stop-timeout'] + self.optional_keys = ['stop', 'poststop', 'stop-timeout'] + \ + self.snappy_exe_security self.systemd_files = dict() # click-show-files and tests self.systemd = dict() @@ -135,15 +137,25 @@ for app in sorted(my_dict): f = os.path.basename(self.systemd_files[app]) for o in self.optional_keys: + if o in self.snappy_exe_security: + continue # checked in cr_security.py found = False t = 'info' n = '%s_optional_key_%s_%s' % (test_str, o, f) s = "OK" if o in my_dict[app]: - if o == 'stop-timeout' and \ - not isinstance(my_dict[app][o], int): - t = 'error' - s = "'%s' is not an integer" % o + if o == 'stop-timeout': + if isinstance(my_dict[app][o], int): + found = True + elif not isinstance(my_dict[app][o], str): + t = 'error' + s = "'%s' is not a string or integer" % o + elif not re.search(r'[0-9]+[ms]?$', my_dict[app][o]): + t = 'error' + s = "'%s' is not of form NN[ms] (%s)" % \ + (my_dict[app][o], o) + else: + found = True elif not isinstance(my_dict[app][o], str): t = 'error' s = "'%s' is not a string" % o @@ -298,11 +310,27 @@ if 'stop-timeout' not in my_dict[app]: s = "OK (skip missing)" - elif not isinstance(my_dict[app]['stop-timeout'], int): + self._add_result(t, n, s) + return + + st = my_dict[app]['stop-timeout'] + + if not isinstance(st, int) and not isinstance(st, str): t = 'error' - s = 'stop-timeout is not an integer' - elif my_dict[app]['stop-timeout'] < 0 or \ - my_dict[app]['stop-timeout'] > 60: + s = 'stop-timeout is not a string or integer' + self._add_result(t, n, s) + return + + if isinstance(st, str): + if re.search(r'[0-9]+[ms]?$', st): + st = int(st.rstrip(r'[ms]')) + else: + t = 'error' + s = "'%s' is not of form NN[ms] (%s)" % (my_dict[app], st) + self._add_result(t, n, s) + return + + if st < 0 or st > 60: t = 'error' s = "stop-timeout '%d' out of range (0-60)" % \ my_dict[app]['stop-timeout'] diff -Nru click-reviewers-tools-0.26/bin/clickreviews/tests/test_cr_lint.py click-reviewers-tools-0.27/bin/clickreviews/tests/test_cr_lint.py --- click-reviewers-tools-0.26/bin/clickreviews/tests/test_cr_lint.py 2015-04-20 15:40:24.000000000 +0000 +++ click-reviewers-tools-0.27/bin/clickreviews/tests/test_cr_lint.py 2015-05-04 18:32:35.000000000 +0000 @@ -33,11 +33,13 @@ def patch_frameworks(self): def _mock_frameworks(self, overrides=None): self.FRAMEWORKS = { + 'ubuntu-core-15.04': 'available', 'ubuntu-sdk-14.10-qml-dev2': 'available', 'ubuntu-sdk-13.10': 'deprecated', 'ubuntu-sdk-14.10-qml-dev1': 'obsolete', } - self.AVAILABLE_FRAMEWORKS = ['ubuntu-sdk-14.10-qml-dev2'] + self.AVAILABLE_FRAMEWORKS = ['ubuntu-core-15.04', + 'ubuntu-sdk-14.10-qml-dev2'] self.OBSOLETE_FRAMEWORKS = ['ubuntu-sdk-14.10-qml-dev1'] self.DEPRECATED_FRAMEWORKS = ['ubuntu-sdk-13.10'] p = patch('clickreviews.frameworks.Frameworks.__init__', @@ -612,6 +614,30 @@ c.check_framework() r = c.click_report expected_counts = {'info': 1, 'warn': 0, 'error': 0} + self.check_results(r, expected_counts) + + def test_check_framework_multiple_click(self): + '''Test check_framework() - click''' + self.patch_frameworks() + self.set_test_manifest("framework", + "ubuntu-sdk-14.10-qml-dev2,ubuntu-core-15.04") + c = ClickReviewLint(self.test_name) + c.is_snap = False + c.check_framework() + r = c.click_report + expected_counts = {'info': 0, 'warn': 0, 'error': 1} + self.check_results(r, expected_counts) + + def test_check_framework_multiple_snappy(self): + '''Test check_framework() - snappy''' + self.patch_frameworks() + self.set_test_manifest("framework", + "ubuntu-sdk-14.10-qml-dev2,ubuntu-core-15.04") + c = ClickReviewLint(self.test_name) + c.is_snap = True + c.check_framework() + r = c.click_report + expected_counts = {'info': 1, 'warn': 0, 'error': 0} self.check_results(r, expected_counts) @patch('clickreviews.remote.read_cr_file') diff -Nru click-reviewers-tools-0.26/bin/clickreviews/tests/test_cr_security.py click-reviewers-tools-0.27/bin/clickreviews/tests/test_cr_security.py --- click-reviewers-tools-0.26/bin/clickreviews/tests/test_cr_security.py 2015-04-20 15:40:24.000000000 +0000 +++ click-reviewers-tools-0.27/bin/clickreviews/tests/test_cr_security.py 2015-05-04 18:32:35.000000000 +0000 @@ -146,6 +146,20 @@ expected_counts = {'info': 3, 'warn': 0, 'error': 0} self.check_results(report, expected_counts) + def test_check_policy_version_framework_match_snappy_multiple(self): + '''Test check_policy_version() - matching framework - multiple''' + self.set_test_manifest("framework", "foo,ubuntu-core-15.04") + self.set_test_security_manifest(self.default_appname, + "policy_vendor", "ubuntu-core") + self.set_test_security_manifest(self.default_appname, + "policy_version", 15.04) + c = ClickReviewSecurity(self.test_name) + c.check_policy_version() + report = c.click_report + + expected_counts = {'info': 3, 'warn': 0, 'error': 0} + self.check_results(report, expected_counts) + def test_check_policy_version_framework_unmatch(self): '''Test check_policy_version() - unmatching framework (lower)''' self.set_test_manifest("framework", "ubuntu-sdk-14.04") @@ -304,6 +318,19 @@ expected_counts = {'info': 2, 'warn': 0, 'error': 0} self.check_results(report, expected_counts) + def test_check_policy_vendor_framwork_match_snappy_multiple(self): + '''Test check_policy_vendor() - matching framework - multiple''' + self.set_test_manifest("framework", "foo,ubuntu-core-15.04") + c = ClickReviewSecurity(self.test_name) + self.set_test_security_manifest(self.default_appname, + "policy_vendor", "ubuntu-core") + self.set_test_security_manifest(self.default_appname, + "policy_version", 15.04) + c.check_policy_vendor() + report = c.click_report + expected_counts = {'info': 2, 'warn': 0, 'error': 0} + self.check_results(report, expected_counts) + def test_check_policy_vendor_framework_unmatch1(self): '''Test check_policy_vendor() - unmatching framework''' self.set_test_security_manifest(self.default_appname, diff -Nru click-reviewers-tools-0.26/bin/clickreviews/tests/test_cr_systemd.py click-reviewers-tools-0.27/bin/clickreviews/tests/test_cr_systemd.py --- click-reviewers-tools-0.26/bin/clickreviews/tests/test_cr_systemd.py 2015-04-20 15:40:24.000000000 +0000 +++ click-reviewers-tools-0.27/bin/clickreviews/tests/test_cr_systemd.py 2015-05-04 18:32:35.000000000 +0000 @@ -514,6 +514,23 @@ expected_counts = {'info': 1, 'warn': 0, 'error': 0} self.check_results(r, expected_counts) + def test_check_service_stop_timeout2(self): + '''Test check_service_stop_timeout() - with granularity''' + self.set_test_systemd(self.default_appname, + key="start", + value="bin/foo") + self.set_test_systemd(self.default_appname, + key="description", + value="something") + self.set_test_systemd(self.default_appname, + key="stop-timeout", + value="30s") + c = ClickReviewSystemd(self.test_name) + c.check_service_stop_timeout() + r = c.click_report + expected_counts = {'info': 1, 'warn': 0, 'error': 0} + self.check_results(r, expected_counts) + def test_check_service_stop_timeout_empty(self): '''Test check_service_stop_timeout() - empty''' self.set_test_systemd(self.default_appname, @@ -545,6 +562,23 @@ c = ClickReviewSystemd(self.test_name) c.check_service_stop_timeout() r = c.click_report + expected_counts = {'info': None, 'warn': 0, 'error': 1} + self.check_results(r, expected_counts) + + def test_check_service_stop_timeout_bad2(self): + '''Test check_service_stop_timeout() - bad with granularity''' + self.set_test_systemd(self.default_appname, + key="start", + value="bin/foo") + self.set_test_systemd(self.default_appname, + key="description", + value="something") + self.set_test_systemd(self.default_appname, + key="stop-timeout", + value="30a") + c = ClickReviewSystemd(self.test_name) + c.check_service_stop_timeout() + r = c.click_report expected_counts = {'info': None, 'warn': 0, 'error': 1} self.check_results(r, expected_counts) diff -Nru click-reviewers-tools-0.26/clickreviews/cr_bin_path.py click-reviewers-tools-0.27/clickreviews/cr_bin_path.py --- click-reviewers-tools-0.26/clickreviews/cr_bin_path.py 2015-04-20 15:40:24.000000000 +0000 +++ click-reviewers-tools-0.27/clickreviews/cr_bin_path.py 2015-05-04 18:32:35.000000000 +0000 @@ -35,9 +35,8 @@ # snappy yaml currently only allows specifying: # - exec (optional) # - description (optional) - # - TODO: caps (optional) self.required_keys = [] - self.optional_keys = ['description', 'exec'] + self.optional_keys = ['description', 'exec'] + self.snappy_exe_security self.bin_paths_files = dict() self.bin_paths = dict() @@ -142,16 +141,14 @@ def _verify_optional(self, my_dict, test_str): for app in sorted(my_dict): for o in self.optional_keys: + if o in self.snappy_exe_security: + continue # checked in cr_security.py found = False t = 'info' n = '%s_optional_key_%s_%s' % (test_str, o, app) s = "OK" if o in my_dict[app]: - if o == 'stop-timeout' and \ - not isinstance(my_dict[app][o], int): - t = 'error' - s = "'%s' is not an integer" % o - elif not isinstance(my_dict[app][o], str): + if not isinstance(my_dict[app][o], str): t = 'error' s = "'%s' is not a string" % o elif my_dict[app][o] == "": diff -Nru click-reviewers-tools-0.26/clickreviews/cr_common.py click-reviewers-tools-0.27/clickreviews/cr_common.py --- click-reviewers-tools-0.26/clickreviews/cr_common.py 2015-04-20 15:40:24.000000000 +0000 +++ click-reviewers-tools-0.27/clickreviews/cr_common.py 2015-05-04 18:32:35.000000000 +0000 @@ -84,6 +84,7 @@ # optional snappy fields here (may be required by appstore) snappy_optional = ["architecture", "binaries", + "caps", "config", "frameworks", "icon", @@ -95,6 +96,10 @@ "type", "vendor", # replaces maintainer ] + snappy_exe_security = ["caps", + "security-template", + "security-override", + "security-policy"] def __init__(self, fn, review_type, peer_hooks=None, overrides=None): self.click_package = fn diff -Nru click-reviewers-tools-0.26/clickreviews/cr_lint.py click-reviewers-tools-0.27/clickreviews/cr_lint.py --- click-reviewers-tools-0.26/clickreviews/cr_lint.py 2015-04-20 15:40:24.000000000 +0000 +++ click-reviewers-tools-0.27/clickreviews/cr_lint.py 2015-05-04 18:32:35.000000000 +0000 @@ -36,6 +36,8 @@ ClickReview.__init__(self, fn, "lint", overrides=overrides) if not self.is_snap and "md5sums" not in CONTROL_FILE_NAMES: CONTROL_FILE_NAMES.append("md5sums") + elif self.is_snap: + CONTROL_FILE_NAMES.append("hashes.yaml") self.control_files = dict() self._list_control_files() # Valid values for Architecture in DEBIAN/control. Note: @@ -646,30 +648,40 @@ l = "http://askubuntu.com/questions/460512/what-framework-should-i-use-in-my-manifest-file" framework_overrides = self.overrides.get('framework', {}) frameworks = Frameworks(overrides=framework_overrides) - if self.manifest['framework'] in frameworks.AVAILABLE_FRAMEWORKS: - t = 'info' - s = 'OK' + + if not self.is_snap and ',' in self.manifest['framework']: + # click doesn't support multiple frameworks yet + t = 'error' + s = 'ERROR: multiple frameworks found in click manifest' self._add_result(t, n, s) - # If it's an available framework, we're done checking return - elif self.manifest['framework'] in frameworks.DEPRECATED_FRAMEWORKS: - t = 'warn' - s = "'%s' is deprecated. Please use a newer framework" % \ - self.manifest['framework'] - self._add_result(t, n, s, l) - return - elif self.manifest['framework'] in frameworks.OBSOLETE_FRAMEWORKS: - t = 'error' - s = "'%s' is obsolete. Please use a newer framework" % \ - self.manifest['framework'] - self._add_result(t, n, s, l) - return - else: - # None of the above checks triggered, this is an unknown framework - t = 'error' - s = "'%s' is not a supported framework" % \ - self.manifest['framework'] - self._add_result(t, n, s, l) + + for framework in self.manifest['framework'].split(','): + framework = framework.strip() + if framework in frameworks.AVAILABLE_FRAMEWORKS: + t = 'info' + s = 'OK' + self._add_result(t, n, s) + # If it's an available framework, we're done checking + return + elif framework in frameworks.DEPRECATED_FRAMEWORKS: + t = 'warn' + s = "'%s' is deprecated. Please use a newer framework" % \ + framework + self._add_result(t, n, s, l) + return + elif framework in frameworks.OBSOLETE_FRAMEWORKS: + t = 'error' + s = "'%s' is obsolete. Please use a newer framework" % \ + framework + self._add_result(t, n, s, l) + return + else: + # None of the above checks triggered, this is an unknown framework + t = 'error' + s = "'%s' is not a supported framework" % \ + framework + self._add_result(t, n, s, l) def check_click_local_extensions(self): '''Report any click local extensions''' diff -Nru click-reviewers-tools-0.26/clickreviews/cr_security.py click-reviewers-tools-0.27/clickreviews/cr_security.py --- click-reviewers-tools-0.26/clickreviews/cr_security.py 2015-04-20 15:40:24.000000000 +0000 +++ click-reviewers-tools-0.27/clickreviews/cr_security.py 2015-05-04 18:32:35.000000000 +0000 @@ -96,6 +96,8 @@ # framework policy is based on major framework version. In 13.10, there # was only 'ubuntu-sdk-13.10', but in 14.04, there will be several, # like 'ubuntu-sdk-14.04-html5', 'ubuntu-sdk-14.04-platform', etc + # TODO: in 15.10 we will be using the policy version will match the + # release framework, so we can simplify these checks self.major_framework_policy = { 'ubuntu-sdk-13.10': { 'policy_version': 1.0, @@ -106,6 +108,9 @@ 'ubuntu-sdk-14.10': { 'policy_version': 1.2, }, + 'ubuntu-sdk-15.04': { + 'policy_version': 1.3, + }, 'ubuntu-core-15.04': { 'policy_vendor': 'ubuntu-core', 'policy_version': 15.04, @@ -329,8 +334,14 @@ if 'policy_vendor' in m: # policy_vendor is optional found_major = False for name, data in self.major_framework_policy.items(): - # TODO: use libclick when it is available - if not self.manifest['framework'].startswith(name): + framework = self.manifest['framework'] + # snappy compat manifest supports comma-separated list + # for framework + if self.is_snap and ',' in framework: + # For now, we know the release framework is appended. + # TODO: fix for multiple frameworks + framework = framework.split(',')[-1] + if not framework.startswith(name): continue elif 'policy_vendor' not in data: # when not specified, default to 'ubuntu' @@ -340,10 +351,10 @@ t = 'error' s = '%s != %s (%s)' % (str(m['policy_vendor']), data['policy_vendor'], - self.manifest['framework']) + framework) if not found_major: t = 'error' - s = "Invalid framework '%s'" % self.manifest['framework'] + s = "Invalid framework '%s'" % framework self._add_result(t, n, s) def check_policy_version(self): @@ -385,18 +396,24 @@ s = "OK" found_major = False for name, data in self.major_framework_policy.items(): - # TODO: use libclick when it is available - if not self.manifest['framework'].startswith(name): + framework = self.manifest['framework'] + # snappy compat manifest supports comma-separated list + # for framework + if self.is_snap and ',' in framework: + # For now, we know the release framework is appended. + # TODO: fix for multiple frameworks + framework = framework.split(',')[-1] + if not framework.startswith(name): continue found_major = True if m['policy_version'] != data['policy_version']: t = 'error' s = '%s != %s (%s)' % (str(m['policy_version']), data['policy_version'], - self.manifest['framework']) + framework) if not found_major: t = 'error' - s = "Invalid framework '%s'" % self.manifest['framework'] + s = "Invalid framework '%s'" % framework self._add_result(t, n, s) def check_template(self): diff -Nru click-reviewers-tools-0.26/clickreviews/cr_systemd.py click-reviewers-tools-0.27/clickreviews/cr_systemd.py --- click-reviewers-tools-0.26/clickreviews/cr_systemd.py 2015-04-20 15:40:24.000000000 +0000 +++ click-reviewers-tools-0.27/clickreviews/cr_systemd.py 2015-05-04 18:32:35.000000000 +0000 @@ -19,6 +19,7 @@ from clickreviews.cr_common import ClickReview, error, open_file_read import yaml import os +import re class ClickReviewSystemd(ClickReview): @@ -41,7 +42,8 @@ # - stop-timeout # - TODO: caps self.required_keys = ['start', 'description'] - self.optional_keys = ['stop', 'poststop', 'stop-timeout'] + self.optional_keys = ['stop', 'poststop', 'stop-timeout'] + \ + self.snappy_exe_security self.systemd_files = dict() # click-show-files and tests self.systemd = dict() @@ -135,15 +137,25 @@ for app in sorted(my_dict): f = os.path.basename(self.systemd_files[app]) for o in self.optional_keys: + if o in self.snappy_exe_security: + continue # checked in cr_security.py found = False t = 'info' n = '%s_optional_key_%s_%s' % (test_str, o, f) s = "OK" if o in my_dict[app]: - if o == 'stop-timeout' and \ - not isinstance(my_dict[app][o], int): - t = 'error' - s = "'%s' is not an integer" % o + if o == 'stop-timeout': + if isinstance(my_dict[app][o], int): + found = True + elif not isinstance(my_dict[app][o], str): + t = 'error' + s = "'%s' is not a string or integer" % o + elif not re.search(r'[0-9]+[ms]?$', my_dict[app][o]): + t = 'error' + s = "'%s' is not of form NN[ms] (%s)" % \ + (my_dict[app][o], o) + else: + found = True elif not isinstance(my_dict[app][o], str): t = 'error' s = "'%s' is not a string" % o @@ -298,11 +310,27 @@ if 'stop-timeout' not in my_dict[app]: s = "OK (skip missing)" - elif not isinstance(my_dict[app]['stop-timeout'], int): + self._add_result(t, n, s) + return + + st = my_dict[app]['stop-timeout'] + + if not isinstance(st, int) and not isinstance(st, str): t = 'error' - s = 'stop-timeout is not an integer' - elif my_dict[app]['stop-timeout'] < 0 or \ - my_dict[app]['stop-timeout'] > 60: + s = 'stop-timeout is not a string or integer' + self._add_result(t, n, s) + return + + if isinstance(st, str): + if re.search(r'[0-9]+[ms]?$', st): + st = int(st.rstrip(r'[ms]')) + else: + t = 'error' + s = "'%s' is not of form NN[ms] (%s)" % (my_dict[app], st) + self._add_result(t, n, s) + return + + if st < 0 or st > 60: t = 'error' s = "stop-timeout '%d' out of range (0-60)" % \ my_dict[app]['stop-timeout'] diff -Nru click-reviewers-tools-0.26/clickreviews/tests/test_cr_lint.py click-reviewers-tools-0.27/clickreviews/tests/test_cr_lint.py --- click-reviewers-tools-0.26/clickreviews/tests/test_cr_lint.py 2015-04-20 15:40:24.000000000 +0000 +++ click-reviewers-tools-0.27/clickreviews/tests/test_cr_lint.py 2015-05-04 18:32:35.000000000 +0000 @@ -33,11 +33,13 @@ def patch_frameworks(self): def _mock_frameworks(self, overrides=None): self.FRAMEWORKS = { + 'ubuntu-core-15.04': 'available', 'ubuntu-sdk-14.10-qml-dev2': 'available', 'ubuntu-sdk-13.10': 'deprecated', 'ubuntu-sdk-14.10-qml-dev1': 'obsolete', } - self.AVAILABLE_FRAMEWORKS = ['ubuntu-sdk-14.10-qml-dev2'] + self.AVAILABLE_FRAMEWORKS = ['ubuntu-core-15.04', + 'ubuntu-sdk-14.10-qml-dev2'] self.OBSOLETE_FRAMEWORKS = ['ubuntu-sdk-14.10-qml-dev1'] self.DEPRECATED_FRAMEWORKS = ['ubuntu-sdk-13.10'] p = patch('clickreviews.frameworks.Frameworks.__init__', @@ -612,6 +614,30 @@ c.check_framework() r = c.click_report expected_counts = {'info': 1, 'warn': 0, 'error': 0} + self.check_results(r, expected_counts) + + def test_check_framework_multiple_click(self): + '''Test check_framework() - click''' + self.patch_frameworks() + self.set_test_manifest("framework", + "ubuntu-sdk-14.10-qml-dev2,ubuntu-core-15.04") + c = ClickReviewLint(self.test_name) + c.is_snap = False + c.check_framework() + r = c.click_report + expected_counts = {'info': 0, 'warn': 0, 'error': 1} + self.check_results(r, expected_counts) + + def test_check_framework_multiple_snappy(self): + '''Test check_framework() - snappy''' + self.patch_frameworks() + self.set_test_manifest("framework", + "ubuntu-sdk-14.10-qml-dev2,ubuntu-core-15.04") + c = ClickReviewLint(self.test_name) + c.is_snap = True + c.check_framework() + r = c.click_report + expected_counts = {'info': 1, 'warn': 0, 'error': 0} self.check_results(r, expected_counts) @patch('clickreviews.remote.read_cr_file') diff -Nru click-reviewers-tools-0.26/clickreviews/tests/test_cr_security.py click-reviewers-tools-0.27/clickreviews/tests/test_cr_security.py --- click-reviewers-tools-0.26/clickreviews/tests/test_cr_security.py 2015-04-20 15:40:24.000000000 +0000 +++ click-reviewers-tools-0.27/clickreviews/tests/test_cr_security.py 2015-05-04 18:32:35.000000000 +0000 @@ -146,6 +146,20 @@ expected_counts = {'info': 3, 'warn': 0, 'error': 0} self.check_results(report, expected_counts) + def test_check_policy_version_framework_match_snappy_multiple(self): + '''Test check_policy_version() - matching framework - multiple''' + self.set_test_manifest("framework", "foo,ubuntu-core-15.04") + self.set_test_security_manifest(self.default_appname, + "policy_vendor", "ubuntu-core") + self.set_test_security_manifest(self.default_appname, + "policy_version", 15.04) + c = ClickReviewSecurity(self.test_name) + c.check_policy_version() + report = c.click_report + + expected_counts = {'info': 3, 'warn': 0, 'error': 0} + self.check_results(report, expected_counts) + def test_check_policy_version_framework_unmatch(self): '''Test check_policy_version() - unmatching framework (lower)''' self.set_test_manifest("framework", "ubuntu-sdk-14.04") @@ -304,6 +318,19 @@ expected_counts = {'info': 2, 'warn': 0, 'error': 0} self.check_results(report, expected_counts) + def test_check_policy_vendor_framwork_match_snappy_multiple(self): + '''Test check_policy_vendor() - matching framework - multiple''' + self.set_test_manifest("framework", "foo,ubuntu-core-15.04") + c = ClickReviewSecurity(self.test_name) + self.set_test_security_manifest(self.default_appname, + "policy_vendor", "ubuntu-core") + self.set_test_security_manifest(self.default_appname, + "policy_version", 15.04) + c.check_policy_vendor() + report = c.click_report + expected_counts = {'info': 2, 'warn': 0, 'error': 0} + self.check_results(report, expected_counts) + def test_check_policy_vendor_framework_unmatch1(self): '''Test check_policy_vendor() - unmatching framework''' self.set_test_security_manifest(self.default_appname, diff -Nru click-reviewers-tools-0.26/clickreviews/tests/test_cr_systemd.py click-reviewers-tools-0.27/clickreviews/tests/test_cr_systemd.py --- click-reviewers-tools-0.26/clickreviews/tests/test_cr_systemd.py 2015-04-20 15:40:24.000000000 +0000 +++ click-reviewers-tools-0.27/clickreviews/tests/test_cr_systemd.py 2015-05-04 18:32:35.000000000 +0000 @@ -514,6 +514,23 @@ expected_counts = {'info': 1, 'warn': 0, 'error': 0} self.check_results(r, expected_counts) + def test_check_service_stop_timeout2(self): + '''Test check_service_stop_timeout() - with granularity''' + self.set_test_systemd(self.default_appname, + key="start", + value="bin/foo") + self.set_test_systemd(self.default_appname, + key="description", + value="something") + self.set_test_systemd(self.default_appname, + key="stop-timeout", + value="30s") + c = ClickReviewSystemd(self.test_name) + c.check_service_stop_timeout() + r = c.click_report + expected_counts = {'info': 1, 'warn': 0, 'error': 0} + self.check_results(r, expected_counts) + def test_check_service_stop_timeout_empty(self): '''Test check_service_stop_timeout() - empty''' self.set_test_systemd(self.default_appname, @@ -545,6 +562,23 @@ c = ClickReviewSystemd(self.test_name) c.check_service_stop_timeout() r = c.click_report + expected_counts = {'info': None, 'warn': 0, 'error': 1} + self.check_results(r, expected_counts) + + def test_check_service_stop_timeout_bad2(self): + '''Test check_service_stop_timeout() - bad with granularity''' + self.set_test_systemd(self.default_appname, + key="start", + value="bin/foo") + self.set_test_systemd(self.default_appname, + key="description", + value="something") + self.set_test_systemd(self.default_appname, + key="stop-timeout", + value="30a") + c = ClickReviewSystemd(self.test_name) + c.check_service_stop_timeout() + r = c.click_report expected_counts = {'info': None, 'warn': 0, 'error': 1} self.check_results(r, expected_counts) diff -Nru click-reviewers-tools-0.26/data/apparmor-easyprof-ubuntu.json click-reviewers-tools-0.27/data/apparmor-easyprof-ubuntu.json --- click-reviewers-tools-0.26/data/apparmor-easyprof-ubuntu.json 2015-04-20 15:40:24.000000000 +0000 +++ click-reviewers-tools-0.27/data/apparmor-easyprof-ubuntu.json 2015-05-04 18:32:35.000000000 +0000 @@ -183,7 +183,9 @@ }, "policy_groups": { "common": [ - "networking" + "networking", + "network-service", + "network-client" ], "reserved": [] } @@ -201,7 +203,9 @@ }, "policy_groups": { "common": [ - "networking" + "networking", + "network-service", + "network-client" ], "reserved": [] } diff -Nru click-reviewers-tools-0.26/debian/bzr-builder.manifest click-reviewers-tools-0.27/debian/bzr-builder.manifest --- click-reviewers-tools-0.26/debian/bzr-builder.manifest 2015-04-20 15:40:25.000000000 +0000 +++ click-reviewers-tools-0.27/debian/bzr-builder.manifest 2015-05-04 18:32:36.000000000 +0000 @@ -1,2 +1,2 @@ -# bzr-builder format 0.3 deb-version {debupstream}-0~444 -lp:click-reviewers-tools revid:daniel.holbach@canonical.com-20150420152938-d0l0e9h4vgf92ibq +# bzr-builder format 0.3 deb-version {debupstream}-0~455 +lp:click-reviewers-tools revid:jamie@ubuntu.com-20150504182904-96faw9yek88eaec5 diff -Nru click-reviewers-tools-0.26/debian/changelog click-reviewers-tools-0.27/debian/changelog --- click-reviewers-tools-0.26/debian/changelog 2015-04-20 15:40:25.000000000 +0000 +++ click-reviewers-tools-0.27/debian/changelog 2015-05-04 18:32:36.000000000 +0000 @@ -1,14 +1,27 @@ -click-reviewers-tools (0.26-0~444~ubuntu14.04.1) trusty; urgency=low +click-reviewers-tools (0.27-0~455~ubuntu14.04.1) trusty; urgency=low * Auto build. - -- Daniel Holbach Mon, 20 Apr 2015 15:40:25 +0000 + -- Daniel Holbach Mon, 04 May 2015 18:32:36 +0000 -click-reviewers-tools (0.26) UNRELEASED; urgency=medium +click-reviewers-tools (0.27) UNRELEASED; urgency=medium - * + * cr_security.py: add ubuntu-sdk-15.04 framework and policy version + (LP: #1449368) - -- Daniel Holbach Mon, 20 Apr 2015 17:29:25 +0200 + -- Jamie Strandboge Fri, 01 May 2015 10:46:57 -0500 + +click-reviewers-tools (0.26) vivid; urgency=medium + + [ Jamie Strandboge ] + * adjust tests for new format for systemd stop-timeout + * add network-service and network-client policygroups for 15.04 policy + * require existence of hashes.yaml for snaps. More checks coming + * skip security yaml checks in bin-path and systemd checks + * cr_security.py: handle multiple frameworks in compat manifest + * cr_lint.py: handle multiple frameworks with snaps + + -- Jamie Strandboge Fri, 01 May 2015 10:22:06 -0500 click-reviewers-tools (0.25) vivid; urgency=medium