daktari 0.0.254__py3-none-any.whl → 0.0.255__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of daktari might be problematic. Click here for more details.
- daktari/__init__.py +1 -1
- daktari/checks/__init__.py +0 -0
- daktari/checks/android.py +26 -0
- daktari/checks/aws.py +34 -0
- daktari/checks/certs.py +34 -0
- daktari/checks/conan.py +96 -0
- daktari/checks/direnv.py +59 -0
- daktari/checks/docker.py +50 -0
- daktari/checks/files.py +72 -0
- daktari/checks/flutter.py +46 -0
- daktari/checks/git.py +198 -0
- daktari/checks/google.py +113 -0
- daktari/checks/intellij_idea.py +248 -0
- daktari/checks/java.py +104 -0
- daktari/checks/kubernetes.py +154 -0
- daktari/checks/misc.py +302 -0
- daktari/checks/nodejs.py +92 -0
- daktari/checks/onepassword.py +105 -0
- daktari/checks/python.py +16 -0
- daktari/checks/ssh.py +33 -0
- daktari/checks/terraform.py +70 -0
- daktari/checks/test_certs.py +32 -0
- daktari/checks/test_intellij_idea.py +66 -0
- daktari/checks/test_java.py +88 -0
- daktari/checks/test_misc.py +18 -0
- daktari/checks/test_onepassword.py +31 -0
- daktari/checks/test_ssh.py +22 -0
- daktari/checks/test_yarn.py +86 -0
- daktari/checks/xml.py +33 -0
- daktari/checks/yarn.py +156 -0
- {daktari-0.0.254.dist-info → daktari-0.0.255.dist-info}/METADATA +2 -2
- daktari-0.0.255.dist-info/RECORD +64 -0
- daktari-0.0.254.dist-info/RECORD +0 -35
- {daktari-0.0.254.dist-info → daktari-0.0.255.dist-info}/LICENSE.txt +0 -0
- {daktari-0.0.254.dist-info → daktari-0.0.255.dist-info}/WHEEL +0 -0
- {daktari-0.0.254.dist-info → daktari-0.0.255.dist-info}/entry_points.txt +0 -0
- {daktari-0.0.254.dist-info → daktari-0.0.255.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
from semver import VersionInfo
|
|
4
|
+
|
|
5
|
+
from daktari.check import CheckStatus
|
|
6
|
+
from daktari.checks.intellij_idea import (
|
|
7
|
+
IntelliJProjectSdkJavaVersion,
|
|
8
|
+
get_intellij_version_from_product_info,
|
|
9
|
+
IntelliJTypescriptCompilerPathConfigured,
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TestIntellijIdea(unittest.TestCase):
|
|
14
|
+
def test_parse_product_info(self):
|
|
15
|
+
product_info_path = "checks/test_resources/intellij-product-info.json"
|
|
16
|
+
result = get_intellij_version_from_product_info(product_info_path)
|
|
17
|
+
self.assertEqual(result, VersionInfo(2023, 3, 5))
|
|
18
|
+
|
|
19
|
+
def test_project_sdk_unset(self):
|
|
20
|
+
check = IntelliJProjectSdkJavaVersion(17)
|
|
21
|
+
check.file_path = "checks/test_resources/intellij_misc_no_sdk.xml"
|
|
22
|
+
result = check.check()
|
|
23
|
+
self.assertEqual(result.status, CheckStatus.FAIL)
|
|
24
|
+
self.assertEqual(result.summary, "IntelliJ Project SDK is not a Java JDK")
|
|
25
|
+
|
|
26
|
+
def test_project_sdk_python(self):
|
|
27
|
+
check = IntelliJProjectSdkJavaVersion(17)
|
|
28
|
+
check.file_path = "checks/test_resources/intellij_misc_python_sdk.xml"
|
|
29
|
+
result = check.check()
|
|
30
|
+
self.assertEqual(result.status, CheckStatus.FAIL)
|
|
31
|
+
self.assertEqual(result.summary, "IntelliJ Project SDK is not a Java JDK: Python SDK")
|
|
32
|
+
|
|
33
|
+
def test_project_sdk_wrong_java_version(self):
|
|
34
|
+
check = IntelliJProjectSdkJavaVersion(21)
|
|
35
|
+
check.file_path = "checks/test_resources/intellij_misc_java_17.xml"
|
|
36
|
+
result = check.check()
|
|
37
|
+
self.assertEqual(result.status, CheckStatus.FAIL)
|
|
38
|
+
self.assertEqual(result.summary, "IntelliJ Project SDK is not set to Java 21: JDK_17")
|
|
39
|
+
|
|
40
|
+
def test_project_sdk_correct_java_version(self):
|
|
41
|
+
check = IntelliJProjectSdkJavaVersion(17)
|
|
42
|
+
check.file_path = "checks/test_resources/intellij_misc_java_17.xml"
|
|
43
|
+
result = check.check()
|
|
44
|
+
self.assertEqual(result.status, CheckStatus.PASS)
|
|
45
|
+
self.assertEqual(result.summary, "IntelliJ Project SDK is set to Java 17: JDK_17")
|
|
46
|
+
|
|
47
|
+
def test_project_typescript_path_unset(self):
|
|
48
|
+
check = IntelliJTypescriptCompilerPathConfigured("$PROJECT_DIR$/node_modules/typescript")
|
|
49
|
+
check.file_path = "checks/test_resources/intellij_misc_no_ts_path.xml"
|
|
50
|
+
result = check.check()
|
|
51
|
+
self.assertEqual(result.status, CheckStatus.FAIL)
|
|
52
|
+
self.assertIn("IntelliJ typescript compiler path is not set", result.summary)
|
|
53
|
+
|
|
54
|
+
def test_project_typescript_path_set_wrong(self):
|
|
55
|
+
check = IntelliJTypescriptCompilerPathConfigured("/some/project/node_modules/typescript")
|
|
56
|
+
check.file_path = "checks/test_resources/intellij_misc_custom_ts_path.xml"
|
|
57
|
+
result = check.check()
|
|
58
|
+
self.assertEqual(result.status, CheckStatus.FAIL)
|
|
59
|
+
self.assertIn("IntelliJ typescript compiler path has not been set to", result.summary)
|
|
60
|
+
|
|
61
|
+
def test_project_typescript_path_set_correctly(self):
|
|
62
|
+
check = IntelliJTypescriptCompilerPathConfigured("$PROJECT_DIR$/node_modules/typescript")
|
|
63
|
+
check.file_path = "checks/test_resources/intellij_misc_custom_ts_path.xml"
|
|
64
|
+
result = check.check()
|
|
65
|
+
self.assertEqual(result.status, CheckStatus.PASS)
|
|
66
|
+
self.assertIn("IntelliJ typescript compiler path has been set to", result.summary)
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
from semver import VersionInfo
|
|
4
|
+
|
|
5
|
+
from .java import parse_java_version_output, parse_javac_version_output
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class TestJava(unittest.TestCase):
|
|
9
|
+
def test_parse_java_non_semver_format_version(self):
|
|
10
|
+
# JRE versions prior to 9 do not use semver format
|
|
11
|
+
version_output = """openjdk version "1.8.0_292"
|
|
12
|
+
OpenJDK Runtime Environment (build 1.8.0_292-8u292-b10-0ubuntu1~20.04-b10)
|
|
13
|
+
OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)
|
|
14
|
+
"""
|
|
15
|
+
version = parse_java_version_output(version_output)
|
|
16
|
+
self.assertEqual(version, VersionInfo(8))
|
|
17
|
+
|
|
18
|
+
def test_parse_ubuntu_openjdk_17_version(self):
|
|
19
|
+
version_output = """openjdk version "17" 2021-09-14
|
|
20
|
+
OpenJDK Runtime Environment (build 17+35-Ubuntu-121.04)
|
|
21
|
+
OpenJDK 64-Bit Server VM (build 17+35-Ubuntu-121.04, mixed mode, sharing)
|
|
22
|
+
"""
|
|
23
|
+
version = parse_java_version_output(version_output)
|
|
24
|
+
self.assertEqual(version, VersionInfo(17, 0, 0))
|
|
25
|
+
|
|
26
|
+
def test_parse_java_semver_format_version(self):
|
|
27
|
+
version_output = """openjdk version "11.0.9" 2020-10-20
|
|
28
|
+
OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.9+11)
|
|
29
|
+
OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.9+11, mixed mode)
|
|
30
|
+
"""
|
|
31
|
+
version = parse_java_version_output(version_output)
|
|
32
|
+
self.assertEqual(version, VersionInfo(11, 0, 9))
|
|
33
|
+
|
|
34
|
+
def test_parse_java_unknown_format_version(self):
|
|
35
|
+
version_output = 'openjdk version "a.b.c"'
|
|
36
|
+
version = parse_java_version_output(version_output)
|
|
37
|
+
self.assertEqual(version, None)
|
|
38
|
+
|
|
39
|
+
def test_parse_java_unknown_format_output(self):
|
|
40
|
+
version_output = """
|
|
41
|
+
|
|
42
|
+
Command 'java' not found, but can be installed with:
|
|
43
|
+
|
|
44
|
+
sudo apt install openjdk-11-jre-headless # version 11.0.11+9-0ubuntu2~20.04, or
|
|
45
|
+
sudo apt install default-jre # version 2:1.11-72
|
|
46
|
+
sudo apt install openjdk-13-jre-headless # version 13.0.7+5-0ubuntu1~20.04
|
|
47
|
+
sudo apt install openjdk-16-jre-headless # version 16.0.1+9-1~20.04
|
|
48
|
+
sudo apt install openjdk-8-jre-headless # version 8u292-b10-0ubuntu1~20.04
|
|
49
|
+
sudo apt install openjdk-14-jre-headless # version 14.0.2+12-1~20.04
|
|
50
|
+
|
|
51
|
+
"""
|
|
52
|
+
version = parse_java_version_output(version_output)
|
|
53
|
+
self.assertEqual(version, None)
|
|
54
|
+
|
|
55
|
+
def test_parse_javac_non_semver_format_version(self):
|
|
56
|
+
version_output = "javac 1.8.0_292\n"
|
|
57
|
+
version = parse_javac_version_output(version_output)
|
|
58
|
+
self.assertEqual(version, VersionInfo(8, 0, 0))
|
|
59
|
+
|
|
60
|
+
def test_parse_javac_semver_format_version(self):
|
|
61
|
+
version_output = "javac 11.0.9\n"
|
|
62
|
+
version = parse_javac_version_output(version_output)
|
|
63
|
+
self.assertEqual(version, VersionInfo(11, 0, 9))
|
|
64
|
+
|
|
65
|
+
def test_parse_javac_unknown_format_version(self):
|
|
66
|
+
version_output = "javac a.b.c\n"
|
|
67
|
+
version = parse_javac_version_output(version_output)
|
|
68
|
+
self.assertEqual(version, None)
|
|
69
|
+
|
|
70
|
+
def test_parse_javac_unknown_format_output(self):
|
|
71
|
+
version_output = """
|
|
72
|
+
Command 'javac' not found, but can be installed with:
|
|
73
|
+
|
|
74
|
+
sudo apt install openjdk-11-jdk-headless # version 11.0.11+9-0ubuntu2~20.04, or
|
|
75
|
+
sudo apt install default-jdk # version 2:1.11-72
|
|
76
|
+
sudo apt install openjdk-13-jdk-headless # version 13.0.7+5-0ubuntu1~20.04
|
|
77
|
+
sudo apt install openjdk-16-jdk-headless # version 16.0.1+9-1~20.04
|
|
78
|
+
sudo apt install openjdk-8-jdk-headless # version 8u292-b10-0ubuntu1~20.04
|
|
79
|
+
sudo apt install ecj # version 3.16.0-1
|
|
80
|
+
sudo apt install openjdk-14-jdk-headless # version 14.0.2+12-1~20.04
|
|
81
|
+
|
|
82
|
+
"""
|
|
83
|
+
version = parse_javac_version_output(version_output)
|
|
84
|
+
self.assertEqual(version, None)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
if __name__ == "__main__":
|
|
88
|
+
unittest.main()
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
from daktari.check import CheckStatus
|
|
4
|
+
from daktari.checks.misc import HostAliasesConfigured
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class TestHostAliasesConfigured(unittest.TestCase):
|
|
8
|
+
def test_checking_hosts_does_not_blow_up_on_success(self):
|
|
9
|
+
result = HostAliasesConfigured({}).check()
|
|
10
|
+
self.assertEqual(result.status, CheckStatus.PASS)
|
|
11
|
+
|
|
12
|
+
def test_checking_hosts_does_not_blow_up_on_failure(self):
|
|
13
|
+
result = HostAliasesConfigured({"host": "no.such.entry.surely"}).check()
|
|
14
|
+
self.assertEqual(result.status, CheckStatus.FAIL)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
if __name__ == "__main__":
|
|
18
|
+
unittest.main()
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
from daktari.checks.onepassword import account_exists, contains_account
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TestOnePassword(unittest.TestCase):
|
|
7
|
+
|
|
8
|
+
def test_account_exists(self):
|
|
9
|
+
self.assertTrue(account_exists("checks/test_resources/op_config_with_account.json", "account-name"))
|
|
10
|
+
self.assertFalse(
|
|
11
|
+
account_exists("checks/test_resources/op_config_with_account.json", "non-existent-account-name")
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
def test_contains_account(self):
|
|
15
|
+
account_url = "test.1password.com"
|
|
16
|
+
|
|
17
|
+
correct_output = """
|
|
18
|
+
URL EMAIL USER ID
|
|
19
|
+
test.1password.com test.email@domain.com test-user-id
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
incorrect_output = """
|
|
23
|
+
URL EMAIL USER ID
|
|
24
|
+
my.1password.com test.email@domain.com test-user-id
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
empty_output = ""
|
|
28
|
+
|
|
29
|
+
self.assertTrue(contains_account(correct_output, account_url))
|
|
30
|
+
self.assertFalse(contains_account(incorrect_output, account_url))
|
|
31
|
+
self.assertFalse(contains_account(empty_output, account_url))
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
|
|
3
|
+
from daktari.checks.ssh import is_ssh_configured_to_use_macos_keychain
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class TestSSH(unittest.TestCase):
|
|
7
|
+
def test_ssh_configured_correctly(self):
|
|
8
|
+
self.assertTrue(is_ssh_configured_to_use_macos_keychain("checks/test_resources/good_ssh_config"))
|
|
9
|
+
|
|
10
|
+
def test_ssh_not_configured(self):
|
|
11
|
+
self.assertFalse(is_ssh_configured_to_use_macos_keychain("checks/test_resources/bad_ssh_config"))
|
|
12
|
+
|
|
13
|
+
def test_ssh_no_config_file(self):
|
|
14
|
+
self.assertFalse(is_ssh_configured_to_use_macos_keychain("/some/file/path/that/does/not/exist"))
|
|
15
|
+
|
|
16
|
+
def test_ssh_half_configured_file(self):
|
|
17
|
+
self.assertFalse(is_ssh_configured_to_use_macos_keychain("checks/test_resources/half_configured_ssh_config"))
|
|
18
|
+
|
|
19
|
+
def test_ssh_incorrectly_configured_file(self):
|
|
20
|
+
self.assertFalse(
|
|
21
|
+
is_ssh_configured_to_use_macos_keychain("checks/test_resources/incorrectly_configured_ssh_config")
|
|
22
|
+
)
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from unittest import mock
|
|
3
|
+
import responses
|
|
4
|
+
|
|
5
|
+
from daktari.check import CheckStatus
|
|
6
|
+
from daktari.checks.yarn import YarnNpmScope, match_scope, yarnrc_contains_scope, YarnNpmGithubTokenValid
|
|
7
|
+
|
|
8
|
+
TEST_SCOPE_NAME = "scope"
|
|
9
|
+
TEST_REGISTRY_SERVER = "https://registry-server.glean.co"
|
|
10
|
+
TEST_REGISTRY_SERVER_2 = "https://registry-server.sonocent.com"
|
|
11
|
+
TEST_PUBLISH_REGISTRY = "https://publish-registry.glean.co"
|
|
12
|
+
TEST_PUBLISH_REGISTRY_2 = "https://publish-registry.sonocent.com"
|
|
13
|
+
TEST_AUTH_TOKEN = "ABCD1234"
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class TestYarn(unittest.TestCase):
|
|
17
|
+
def test_matches_scope_publish_registry(self):
|
|
18
|
+
template_scope = YarnNpmScope(TEST_SCOPE_NAME, TEST_PUBLISH_REGISTRY)
|
|
19
|
+
matching_yaml = {"npmPublishRegistry": TEST_PUBLISH_REGISTRY}
|
|
20
|
+
non_matching_yaml_1 = {"npmPublishRegistry": TEST_PUBLISH_REGISTRY_2}
|
|
21
|
+
non_matching_yaml_2 = {}
|
|
22
|
+
|
|
23
|
+
self.assertTrue(match_scope(template_scope, matching_yaml))
|
|
24
|
+
self.assertFalse(match_scope(template_scope, non_matching_yaml_1))
|
|
25
|
+
self.assertFalse(match_scope(template_scope, non_matching_yaml_2))
|
|
26
|
+
|
|
27
|
+
def test_matches_scope_registry_server(self):
|
|
28
|
+
template_scope = YarnNpmScope("scope", npmRegistryServer=TEST_REGISTRY_SERVER)
|
|
29
|
+
matching_yaml = {"npmRegistryServer": TEST_REGISTRY_SERVER}
|
|
30
|
+
non_matching_yaml_1 = {"npmRegistryServer": TEST_REGISTRY_SERVER_2}
|
|
31
|
+
non_matching_yaml_2 = {}
|
|
32
|
+
|
|
33
|
+
self.assertTrue(match_scope(template_scope, matching_yaml))
|
|
34
|
+
self.assertFalse(match_scope(template_scope, non_matching_yaml_1))
|
|
35
|
+
self.assertFalse(match_scope(template_scope, non_matching_yaml_2))
|
|
36
|
+
|
|
37
|
+
def test_matches_scope_with_auth_token_required(self):
|
|
38
|
+
template_scope = YarnNpmScope("scope", requireNpmAuthToken=True)
|
|
39
|
+
matching_yaml = {"npmAuthToken": "ABCD1234"}
|
|
40
|
+
non_matching_empty_yaml = {}
|
|
41
|
+
non_matching_default_token_yaml = {"npmAuthToken": "UPDATE WITH GITHUB ACCESS TOKEN"}
|
|
42
|
+
|
|
43
|
+
# Auth token provided
|
|
44
|
+
self.assertTrue(match_scope(template_scope, matching_yaml))
|
|
45
|
+
# No auth token given
|
|
46
|
+
self.assertFalse(match_scope(template_scope, non_matching_empty_yaml))
|
|
47
|
+
# Scope is not updated from suggested yarnrc
|
|
48
|
+
self.assertFalse(match_scope(template_scope, non_matching_default_token_yaml))
|
|
49
|
+
|
|
50
|
+
def test_finds_scope_in_yarnrc(self):
|
|
51
|
+
yarnrc = {
|
|
52
|
+
"npmScopes": {
|
|
53
|
+
"glean": {"npmRegistryServer": TEST_REGISTRY_SERVER, "npmPublishRegistry": TEST_PUBLISH_REGISTRY},
|
|
54
|
+
"sonocent": {"npmRegistryServer": TEST_REGISTRY_SERVER_2, "npmAuth": "TOKEN"},
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
existing_scope_1 = YarnNpmScope("glean", npmPublishRegistry=TEST_PUBLISH_REGISTRY)
|
|
58
|
+
existing_scope_2 = YarnNpmScope("sonocent", npmRegistryServer=TEST_REGISTRY_SERVER_2)
|
|
59
|
+
# Incorrect scope configuration:
|
|
60
|
+
nonexistent_scope_1 = YarnNpmScope("glean", npmRegistryServer="http://localhost")
|
|
61
|
+
# Auth token required, none supplied:
|
|
62
|
+
nonexistent_scope_2 = YarnNpmScope("glean", npmRegistryServer=TEST_REGISTRY_SERVER, requireNpmAuthToken=True)
|
|
63
|
+
# Wrong name
|
|
64
|
+
nonexistent_scope_3 = YarnNpmScope("walter")
|
|
65
|
+
|
|
66
|
+
self.assertTrue(yarnrc_contains_scope(yarnrc, existing_scope_1))
|
|
67
|
+
self.assertTrue(yarnrc_contains_scope(yarnrc, existing_scope_2))
|
|
68
|
+
self.assertFalse(yarnrc_contains_scope(yarnrc, nonexistent_scope_1))
|
|
69
|
+
self.assertFalse(yarnrc_contains_scope(yarnrc, nonexistent_scope_2))
|
|
70
|
+
self.assertFalse(yarnrc_contains_scope(yarnrc, nonexistent_scope_3))
|
|
71
|
+
|
|
72
|
+
@responses.activate
|
|
73
|
+
@mock.patch("daktari.checks.yarn.get_yarnrc_token_for_scope")
|
|
74
|
+
def test_returns_expected_result_based_on_http_status(self, mock_get_yarnrc_token_for_scope):
|
|
75
|
+
mock_get_yarnrc_token_for_scope.return_value = "mock-token"
|
|
76
|
+
responses.add(method="GET", url="https://api.github.com/orgs/mock-org/packages?package_type=npm", status=401)
|
|
77
|
+
result = YarnNpmGithubTokenValid("mock-org", "mock-token").check()
|
|
78
|
+
self.assertEqual(result.status, CheckStatus.FAIL)
|
|
79
|
+
|
|
80
|
+
responses.add(method="GET", url="https://api.github.com/orgs/mock-org/packages?package_type=npm", status=200)
|
|
81
|
+
result = YarnNpmGithubTokenValid("mock-org", "mock-token").check()
|
|
82
|
+
self.assertEqual(result.status, CheckStatus.PASS)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
if __name__ == "__main__":
|
|
86
|
+
unittest.main()
|
daktari/checks/xml.py
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Optional
|
|
3
|
+
from xml.etree.ElementTree import Element, ElementTree, ParseError
|
|
4
|
+
|
|
5
|
+
from daktari.check import Check, CheckResult
|
|
6
|
+
from daktari.file_utils import file_exists
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class XmlFileXPathCheck(Check):
|
|
10
|
+
file_path = ""
|
|
11
|
+
xpath_query = "./"
|
|
12
|
+
pass_fail_message = ""
|
|
13
|
+
|
|
14
|
+
def validate_query_result(self, result: Optional[Element]) -> bool:
|
|
15
|
+
return result is not None
|
|
16
|
+
|
|
17
|
+
def perform_query(self) -> bool:
|
|
18
|
+
if not file_exists(self.file_path):
|
|
19
|
+
logging.debug(f"File {self.file_path} does not exist")
|
|
20
|
+
return False
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
doc = ElementTree(file=self.file_path)
|
|
24
|
+
except ParseError:
|
|
25
|
+
logging.debug(f"Error parsing {self.file_path}", exc_info=True)
|
|
26
|
+
return False
|
|
27
|
+
|
|
28
|
+
query_result = doc.find(self.xpath_query)
|
|
29
|
+
return self.validate_query_result(query_result)
|
|
30
|
+
|
|
31
|
+
def check(self) -> CheckResult:
|
|
32
|
+
success = self.perform_query()
|
|
33
|
+
return self.verify(success, self.pass_fail_message)
|
daktari/checks/yarn.py
ADDED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import os
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any, Dict, Optional
|
|
5
|
+
|
|
6
|
+
import yaml
|
|
7
|
+
from yaml.error import YAMLError
|
|
8
|
+
|
|
9
|
+
from daktari.check import Check, CheckResult
|
|
10
|
+
from daktari.file_utils import file_exists
|
|
11
|
+
from daktari.os import OS
|
|
12
|
+
import requests
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class YarnInstalled(Check):
|
|
16
|
+
name = "yarn.installed"
|
|
17
|
+
|
|
18
|
+
suggestions = {
|
|
19
|
+
OS.OS_X: "<cmd>brew install yarn</cmd>",
|
|
20
|
+
OS.GENERIC: "<cmd>npm install -g yarn</cmd>",
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
def check(self) -> CheckResult:
|
|
24
|
+
return self.verify_install("yarn")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class YarnNpmScope:
|
|
29
|
+
name: str
|
|
30
|
+
npmPublishRegistry: Optional[str] = None
|
|
31
|
+
npmRegistryServer: Optional[str] = None
|
|
32
|
+
npmAlwaysAuth: Optional[bool] = None
|
|
33
|
+
requireNpmAuthToken: bool = False
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def get_yarnrc_path() -> str:
|
|
37
|
+
return os.path.expanduser("~/.yarnrc.yml")
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_yarnrc_suggestion(scope: YarnNpmScope) -> str:
|
|
41
|
+
scope_yaml: Dict[str, Any] = {}
|
|
42
|
+
if scope.npmRegistryServer is not None:
|
|
43
|
+
scope_yaml["npmRegistryServer"] = scope.npmRegistryServer
|
|
44
|
+
if scope.npmPublishRegistry is not None:
|
|
45
|
+
scope_yaml["npmPublishRegistry"] = scope.npmPublishRegistry
|
|
46
|
+
if scope.requireNpmAuthToken:
|
|
47
|
+
scope_yaml["npmAuthToken"] = "UPDATE WITH GITHUB ACCESS TOKEN"
|
|
48
|
+
if scope.npmAlwaysAuth is not None:
|
|
49
|
+
scope_yaml["npmAlwaysAuth"] = scope.npmAlwaysAuth
|
|
50
|
+
yarnrc_yaml = {"npmScopes": {scope.name: scope_yaml}}
|
|
51
|
+
return yaml.dump(yarnrc_yaml)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def match_scope(template: YarnNpmScope, scope: Dict[str, Any]) -> bool:
|
|
55
|
+
if template.npmPublishRegistry is not None and template.npmPublishRegistry != scope.get("npmPublishRegistry", None):
|
|
56
|
+
return False
|
|
57
|
+
if template.npmRegistryServer is not None and template.npmRegistryServer != scope.get("npmRegistryServer", None):
|
|
58
|
+
return False
|
|
59
|
+
if template.npmAlwaysAuth is not None and template.npmAlwaysAuth != scope.get("npmAlwaysAuth", None):
|
|
60
|
+
return False
|
|
61
|
+
if template.requireNpmAuthToken and scope.get("npmAuthToken") is None:
|
|
62
|
+
return False
|
|
63
|
+
if template.requireNpmAuthToken and scope.get("npmAuthToken", "").strip() == "UPDATE WITH GITHUB ACCESS TOKEN":
|
|
64
|
+
return False
|
|
65
|
+
return True
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def yarnrc_contains_scope(yarnrc: Dict[str, Any], scope: YarnNpmScope) -> bool:
|
|
69
|
+
yarnrc_scopes = yarnrc.get("npmScopes", {})
|
|
70
|
+
yarnrc_scope = yarnrc_scopes.get(scope.name)
|
|
71
|
+
if yarnrc_scope is None:
|
|
72
|
+
return False
|
|
73
|
+
|
|
74
|
+
return match_scope(scope, yarnrc_scope)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class YarnNpmScopeConfigured(Check):
|
|
78
|
+
name = "yarn.npmScopeConfigured"
|
|
79
|
+
|
|
80
|
+
def __init__(self, scope: YarnNpmScope, tokenInstructions: Optional[str] = None):
|
|
81
|
+
self.scope = scope
|
|
82
|
+
self.yarnrc_suggestion = get_yarnrc_suggestion(scope)
|
|
83
|
+
tokenInstructionString = f"\n\n{tokenInstructions}" if tokenInstructions else ""
|
|
84
|
+
self.suggestions = {
|
|
85
|
+
OS.GENERIC: f"""Add the lines below to ~/.yarnrc.yml:
|
|
86
|
+
|
|
87
|
+
{self.yarnrc_suggestion}{tokenInstructionString}"""
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
def check(self) -> CheckResult:
|
|
91
|
+
try:
|
|
92
|
+
yarnrc = get_yarnrc_contents()
|
|
93
|
+
except Exception as e:
|
|
94
|
+
return self.failed(str(e))
|
|
95
|
+
|
|
96
|
+
if not yarnrc_contains_scope(yarnrc, self.scope):
|
|
97
|
+
return self.failed(f"Scope {self.scope.name} not configured in yarnrc")
|
|
98
|
+
|
|
99
|
+
return self.passed(f"Scope {self.scope.name} configured in yarnrc")
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class YarnNpmGithubTokenValid(Check):
|
|
103
|
+
name = "yarn.npmGithubTokenValid"
|
|
104
|
+
depends_on = [YarnNpmScopeConfigured]
|
|
105
|
+
|
|
106
|
+
def __init__(self, github_org: str, scope_name: str):
|
|
107
|
+
self.scope_name = scope_name
|
|
108
|
+
self.github_organisation = github_org
|
|
109
|
+
self.suggestions = {
|
|
110
|
+
OS.GENERIC: "Please check the token was copied correctly from GitHub."
|
|
111
|
+
" Ensure the token hasn't expired, or has been revoked."
|
|
112
|
+
" Also, ensure it has the correct permissions to read packages."
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
def check(self) -> CheckResult:
|
|
116
|
+
try:
|
|
117
|
+
github_token = get_yarnrc_token_for_scope(self.scope_name)
|
|
118
|
+
except Exception as e:
|
|
119
|
+
return self.failed(str(e))
|
|
120
|
+
headers = {
|
|
121
|
+
"Authorization": f"Bearer {github_token}",
|
|
122
|
+
"Accept": "application/vnd.github+json",
|
|
123
|
+
"X-GitHub-Api-Version": "2022-11-28",
|
|
124
|
+
}
|
|
125
|
+
logging.debug(f"Checking the validity of Yarn token {github_token} with the Github API")
|
|
126
|
+
response = requests.get(
|
|
127
|
+
f"https://api.github.com/orgs/{self.github_organisation}/packages?package_type=npm", headers=headers
|
|
128
|
+
)
|
|
129
|
+
if response.status_code == 200:
|
|
130
|
+
logging.debug(f"API call returned: {response.text}")
|
|
131
|
+
return self.passed("Github Yarn token is valid")
|
|
132
|
+
else:
|
|
133
|
+
return self.failed(f"Github Yarn token is not valid: {response.text}")
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def get_yarnrc_contents() -> dict:
|
|
137
|
+
yarnrc_path = get_yarnrc_path()
|
|
138
|
+
if not file_exists(yarnrc_path):
|
|
139
|
+
raise Exception(f"{yarnrc_path} does not exist")
|
|
140
|
+
|
|
141
|
+
try:
|
|
142
|
+
with open(yarnrc_path, "rb") as yarnrc_file:
|
|
143
|
+
return yaml.safe_load(yarnrc_file)
|
|
144
|
+
except YAMLError:
|
|
145
|
+
logging.error(f"Exception reading {yarnrc_path}", exc_info=True)
|
|
146
|
+
raise Exception("Failed to parse yarnrc")
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def get_yarnrc_token_for_scope(scope_name: str) -> Optional[str]:
|
|
150
|
+
yarnrc = get_yarnrc_contents()
|
|
151
|
+
yarnrc_scopes = yarnrc.get("npmScopes", {})
|
|
152
|
+
yarnrc_scope = yarnrc_scopes.get(scope_name)
|
|
153
|
+
if yarnrc_scope is None:
|
|
154
|
+
raise Exception(f"Scope {scope_name} not configured in yarnrc")
|
|
155
|
+
|
|
156
|
+
return yarnrc_scope.get("npmAuthToken", None)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: daktari
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.255
|
|
4
4
|
Summary: Assist in setting up and maintaining developer environments
|
|
5
5
|
Author-email: Matt Russell <matthew.russell@sonocent.com>
|
|
6
6
|
License: Copyright 2021 Sonocent Ltd
|
|
@@ -46,7 +46,7 @@ In the root of the project repository, create a `.daktari.py` configuration file
|
|
|
46
46
|
```python
|
|
47
47
|
from daktari.checks.git import *
|
|
48
48
|
|
|
49
|
-
version = "0.0.
|
|
49
|
+
version = "0.0.255"
|
|
50
50
|
title = "My Project"
|
|
51
51
|
|
|
52
52
|
checks = [
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
daktari/__init__.py,sha256=V7O2FCcoMFxE9dW-Xs3YFzYkFI_GJvr0aTdd-xUROWc,24
|
|
2
|
+
daktari/__main__.py,sha256=iYwgtZZE2HD9Eh9Io6OliGQwCNZJSde_66jI6kF8xJU,1463
|
|
3
|
+
daktari/asdf.py,sha256=fALVL6UTz1AYxuabw9MZeAES7J_CvImutUDD1Y2yWwM,509
|
|
4
|
+
daktari/check.py,sha256=WzIiCrrdH7gCbElNwYbYkjhpmaOs_nUWfvkTBkfZlgs,4133
|
|
5
|
+
daktari/check_runner.py,sha256=PwJkERyEYTKdHKtZEjN-kSt6nQxjDKaLadCRmUagW4I,2634
|
|
6
|
+
daktari/check_sorter.py,sha256=r6tgPDEnSjq_GVFJFEIpnBvN2azmfZ1oYY4YgbGQ028,1005
|
|
7
|
+
daktari/check_utils.py,sha256=rrmYWdekusXT4A2Tecbry_eV9DNt7bN9L5R0IJSPm5k,1027
|
|
8
|
+
daktari/collection_utils.py,sha256=JOCcaSkXFPbj2ROszTS-FGv1s35HgHv0MCWgaHio4XE,165
|
|
9
|
+
daktari/command_utils.py,sha256=3s3A3urin40eK40q9bzVnWGsSuU27FZbRkoDotlVKFk,2355
|
|
10
|
+
daktari/config.py,sha256=75l_jhq7tcCIdl78RMcUlUu1fiG8cqKtwC3yV_H5FVE,6719
|
|
11
|
+
daktari/file_utils.py,sha256=R2WA7XCtSx68cjdlJtBd6iIr1MEmR3fQDVTgSNvoBx4,1251
|
|
12
|
+
daktari/options.py,sha256=DTTCqn3BdfncWkkAFyag239fxgyxIo3IkM0R9bZhXgQ,1440
|
|
13
|
+
daktari/os.py,sha256=usoya1LQThE68aXUfbgq67hJlHmtbEZtXpi7oRfnXXY,767
|
|
14
|
+
daktari/resource_utils.py,sha256=LibGDZYOni6iVQq6OjF0cvFZrP5QmAmHoNKe4G_3BRc,331
|
|
15
|
+
daktari/result_printer.py,sha256=rTKxMFVI8Bi9FKIQ8YPFNPkZ08vtBugxv3a8_iJEpag,3492
|
|
16
|
+
daktari/test_asdf.py,sha256=xSTdf8GD2V-6byBfiaAa5qy201rZxgW8pMVyph-BIVY,946
|
|
17
|
+
daktari/test_check.py,sha256=8DC_MDABa0swRbAww98NB1vXVt5cykoGZyNS4r6IFa4,3866
|
|
18
|
+
daktari/test_check_factory.py,sha256=rGxX-rHHedotCrzi4xLrEgDl9XDdq3yCOSo_qxLEiOY,884
|
|
19
|
+
daktari/test_check_runner.py,sha256=dGMt1ksVGRHxuyoaMyfhvkXel6ZCakCCVJHF-QKQBfY,4071
|
|
20
|
+
daktari/test_check_sorter.py,sha256=6lroiF0fofh0UlLnuoLa9l7Opa1aT2WZEd7XATCHYKE,2631
|
|
21
|
+
daktari/test_check_utils.py,sha256=WLNDzmVQQSABTnS3zAFdWaZ0Z0nKAdlTnd66aiAtrX8,2268
|
|
22
|
+
daktari/test_collection_utils.py,sha256=AtPJnvFLwfiWHKdmrzwcku92vwCVDTvdP2XPBLkQAfE,347
|
|
23
|
+
daktari/test_config.py,sha256=SYLJa4emkW1C2ThLUWd1l_mq8VRZ8semmRnc5TjImCg,7538
|
|
24
|
+
daktari/test_result_printer.py,sha256=1BpR4eApbajaFwChcoUIOM6FdKM53kGzuWVr1w18pSk,1003
|
|
25
|
+
daktari/test_version_utils.py,sha256=cqudpmYKvqNkgBB9L5qLaxpVM7nD-XYuBMQXY3VohmA,1193
|
|
26
|
+
daktari/version_utils.py,sha256=gAE-hfVbdG4fyvT2qBQFYzzz2CFMTA2p_6AUYsgg8a4,1086
|
|
27
|
+
daktari/checks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
|
+
daktari/checks/android.py,sha256=Mad4m2wFw0P6FzW0xaDrir8BR5Wj27n-e5ducKE62Jc,1092
|
|
29
|
+
daktari/checks/aws.py,sha256=hbeFAazhY1cmSpKJuJn2-iMs86zdpK6EOmOQGzz0B0U,1332
|
|
30
|
+
daktari/checks/certs.py,sha256=_Q_1tNEwDoO-q-vPx2wOmGYqN-s4osK4gSRpKU5TFbU,1262
|
|
31
|
+
daktari/checks/conan.py,sha256=_IWjb5wkbxh-dR6DnEaMpmgzIOkuLWnfMos8sRDmLek,4061
|
|
32
|
+
daktari/checks/direnv.py,sha256=4J2GjbCX-2r7vxuRrNayGa2aq0WcNO07VFtgUvYU0Rc,2271
|
|
33
|
+
daktari/checks/docker.py,sha256=8bmasFOvcCdVn95JHuI4uLqZoT43A06lNscFUfbEKjM,1560
|
|
34
|
+
daktari/checks/files.py,sha256=Rth-b1XuZw-AjG3Uwg1ZTc6ItBhQ-U6ZP6VzrOzdRhU,2386
|
|
35
|
+
daktari/checks/flutter.py,sha256=1TI19pIiLVrAuJvoPMXzgX1yOVq6Q5K0TwHNSAUdR_g,1536
|
|
36
|
+
daktari/checks/git.py,sha256=yII22HkvhjGM4bpr3wiLvPxi1pSBPiQcxdTyjqPXji4,6508
|
|
37
|
+
daktari/checks/google.py,sha256=pVbMVWe_mcZ5v-Y6COMwjpMIRopSqzVvgwAQVA4x_Tc,4643
|
|
38
|
+
daktari/checks/intellij_idea.py,sha256=qm7g_sa-3B639iW1BLE-2lr2Zloy9tMLzFk2Uwcn-Tg,9808
|
|
39
|
+
daktari/checks/java.py,sha256=vS4gfuLwLxuTLizvybRx2yYXnNLMTsSfmoYHp91rono,3542
|
|
40
|
+
daktari/checks/kubernetes.py,sha256=BJjxAZzZ3y3t7oHBruUy8OxP41JaX0cxlLvTnFz-F8s,5886
|
|
41
|
+
daktari/checks/misc.py,sha256=8-xvFvMCoZTaZIVCw5QWKtFT-wSkUSUXGBak02IB6yY,10489
|
|
42
|
+
daktari/checks/nodejs.py,sha256=KOCLNQqZqaCalxcIajoDQDom1Zi4_noV4mV_-YZv_4E,2873
|
|
43
|
+
daktari/checks/onepassword.py,sha256=C2HWNlypBDTUx4K4IrrEVIkMqivKzX97oE0rENP1xK4,4155
|
|
44
|
+
daktari/checks/python.py,sha256=v6xuRwtFCjzTYMN3qRLu76Xm7Bn8NO7wVpI3d8dOBSc,658
|
|
45
|
+
daktari/checks/ssh.py,sha256=NqFhO03u523yQaffCeemcRtnYowx6LDuufayzF1t5eQ,1285
|
|
46
|
+
daktari/checks/terraform.py,sha256=fvA7VRRJftkISqcnEjbc9dUovfXEe0eXrQl2MvsnfSM,2476
|
|
47
|
+
daktari/checks/test_certs.py,sha256=LmwjzNBEJauGSFYYLGevJ5H3FRkaO0piezUm3P-hrbM,1693
|
|
48
|
+
daktari/checks/test_intellij_idea.py,sha256=dJ7Nu0eVyv1cpo8h5wUJ6w1rmsbGg3yxslaQKHT3So4,3207
|
|
49
|
+
daktari/checks/test_java.py,sha256=f-JFGI-J-pBD1WgY8a88BO7XeJhvD87QSZK0kDnflls,3613
|
|
50
|
+
daktari/checks/test_misc.py,sha256=tTvaPaZORjNf1dV8wPUKXDI3-JksyfdOsnZXFs7SLLE,587
|
|
51
|
+
daktari/checks/test_onepassword.py,sha256=HLeNjkZd85ty1U4Ut3OSjWVa5msC1Fp1OF0IIWD69u4,1115
|
|
52
|
+
daktari/checks/test_ssh.py,sha256=XJECzM9BNODSxfkK71P9TyavlBagzgkCfKWdhlOD7zU,930
|
|
53
|
+
daktari/checks/test_yarn.py,sha256=9z6NenjJGlWjl5fFQSPVrfiInbvVTxnVhQ-jZkupi6o,4337
|
|
54
|
+
daktari/checks/xml.py,sha256=BqOAI2QRLYE7QL7lFnk_fdxbLnt6ow5c7rmnLiDbNPo,1019
|
|
55
|
+
daktari/checks/yarn.py,sha256=T8b_oOoZ4l96delmPgPfgtaTkiUS129hoWlGIBcU7Io,5534
|
|
56
|
+
daktari/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
57
|
+
daktari/resources/daktari-local-template.yaml,sha256=ik7KzMcG1r90nxDOk7t5G7P-BSxQIl2PocGUVe14c44,503
|
|
58
|
+
daktari/resources/mock_cert.pem,sha256=AIc9dZOVIuxm7KFLunP5WSA1-LDWLOwpfu48B9xQ_Wg,82
|
|
59
|
+
daktari-0.0.255.dist-info/LICENSE.txt,sha256=sMo18UdnQ7rY1SYg9gmop08ubzEQOGO1URYXu1Hxdx0,1051
|
|
60
|
+
daktari-0.0.255.dist-info/METADATA,sha256=ZqIUmIB_6hwHVmpFmDlcVlCQcw6tkJLppSsv3swlZU8,4612
|
|
61
|
+
daktari-0.0.255.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
|
62
|
+
daktari-0.0.255.dist-info/entry_points.txt,sha256=mfQXkwKyloAzf7sv78icBo1PtRwf9hCP_816F6REf-I,50
|
|
63
|
+
daktari-0.0.255.dist-info/top_level.txt,sha256=LW6kawKAAyxUbGqpAbdedKRUyVy2DBzEZOalp0qDdF8,8
|
|
64
|
+
daktari-0.0.255.dist-info/RECORD,,
|
daktari-0.0.254.dist-info/RECORD
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
daktari/__init__.py,sha256=a871puGudVEgAlfgYgd9bLziU_VQH-T2wDmeGFBU0JM,24
|
|
2
|
-
daktari/__main__.py,sha256=iYwgtZZE2HD9Eh9Io6OliGQwCNZJSde_66jI6kF8xJU,1463
|
|
3
|
-
daktari/asdf.py,sha256=fALVL6UTz1AYxuabw9MZeAES7J_CvImutUDD1Y2yWwM,509
|
|
4
|
-
daktari/check.py,sha256=WzIiCrrdH7gCbElNwYbYkjhpmaOs_nUWfvkTBkfZlgs,4133
|
|
5
|
-
daktari/check_runner.py,sha256=PwJkERyEYTKdHKtZEjN-kSt6nQxjDKaLadCRmUagW4I,2634
|
|
6
|
-
daktari/check_sorter.py,sha256=r6tgPDEnSjq_GVFJFEIpnBvN2azmfZ1oYY4YgbGQ028,1005
|
|
7
|
-
daktari/check_utils.py,sha256=rrmYWdekusXT4A2Tecbry_eV9DNt7bN9L5R0IJSPm5k,1027
|
|
8
|
-
daktari/collection_utils.py,sha256=JOCcaSkXFPbj2ROszTS-FGv1s35HgHv0MCWgaHio4XE,165
|
|
9
|
-
daktari/command_utils.py,sha256=3s3A3urin40eK40q9bzVnWGsSuU27FZbRkoDotlVKFk,2355
|
|
10
|
-
daktari/config.py,sha256=75l_jhq7tcCIdl78RMcUlUu1fiG8cqKtwC3yV_H5FVE,6719
|
|
11
|
-
daktari/file_utils.py,sha256=R2WA7XCtSx68cjdlJtBd6iIr1MEmR3fQDVTgSNvoBx4,1251
|
|
12
|
-
daktari/options.py,sha256=DTTCqn3BdfncWkkAFyag239fxgyxIo3IkM0R9bZhXgQ,1440
|
|
13
|
-
daktari/os.py,sha256=usoya1LQThE68aXUfbgq67hJlHmtbEZtXpi7oRfnXXY,767
|
|
14
|
-
daktari/resource_utils.py,sha256=LibGDZYOni6iVQq6OjF0cvFZrP5QmAmHoNKe4G_3BRc,331
|
|
15
|
-
daktari/result_printer.py,sha256=rTKxMFVI8Bi9FKIQ8YPFNPkZ08vtBugxv3a8_iJEpag,3492
|
|
16
|
-
daktari/test_asdf.py,sha256=xSTdf8GD2V-6byBfiaAa5qy201rZxgW8pMVyph-BIVY,946
|
|
17
|
-
daktari/test_check.py,sha256=8DC_MDABa0swRbAww98NB1vXVt5cykoGZyNS4r6IFa4,3866
|
|
18
|
-
daktari/test_check_factory.py,sha256=rGxX-rHHedotCrzi4xLrEgDl9XDdq3yCOSo_qxLEiOY,884
|
|
19
|
-
daktari/test_check_runner.py,sha256=dGMt1ksVGRHxuyoaMyfhvkXel6ZCakCCVJHF-QKQBfY,4071
|
|
20
|
-
daktari/test_check_sorter.py,sha256=6lroiF0fofh0UlLnuoLa9l7Opa1aT2WZEd7XATCHYKE,2631
|
|
21
|
-
daktari/test_check_utils.py,sha256=WLNDzmVQQSABTnS3zAFdWaZ0Z0nKAdlTnd66aiAtrX8,2268
|
|
22
|
-
daktari/test_collection_utils.py,sha256=AtPJnvFLwfiWHKdmrzwcku92vwCVDTvdP2XPBLkQAfE,347
|
|
23
|
-
daktari/test_config.py,sha256=SYLJa4emkW1C2ThLUWd1l_mq8VRZ8semmRnc5TjImCg,7538
|
|
24
|
-
daktari/test_result_printer.py,sha256=1BpR4eApbajaFwChcoUIOM6FdKM53kGzuWVr1w18pSk,1003
|
|
25
|
-
daktari/test_version_utils.py,sha256=cqudpmYKvqNkgBB9L5qLaxpVM7nD-XYuBMQXY3VohmA,1193
|
|
26
|
-
daktari/version_utils.py,sha256=gAE-hfVbdG4fyvT2qBQFYzzz2CFMTA2p_6AUYsgg8a4,1086
|
|
27
|
-
daktari/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
|
-
daktari/resources/daktari-local-template.yaml,sha256=ik7KzMcG1r90nxDOk7t5G7P-BSxQIl2PocGUVe14c44,503
|
|
29
|
-
daktari/resources/mock_cert.pem,sha256=AIc9dZOVIuxm7KFLunP5WSA1-LDWLOwpfu48B9xQ_Wg,82
|
|
30
|
-
daktari-0.0.254.dist-info/LICENSE.txt,sha256=sMo18UdnQ7rY1SYg9gmop08ubzEQOGO1URYXu1Hxdx0,1051
|
|
31
|
-
daktari-0.0.254.dist-info/METADATA,sha256=aPU9jBKDKk90KvtHyEnG-tpA4BPgl3960ZXnmwNYygQ,4612
|
|
32
|
-
daktari-0.0.254.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
|
33
|
-
daktari-0.0.254.dist-info/entry_points.txt,sha256=mfQXkwKyloAzf7sv78icBo1PtRwf9hCP_816F6REf-I,50
|
|
34
|
-
daktari-0.0.254.dist-info/top_level.txt,sha256=LW6kawKAAyxUbGqpAbdedKRUyVy2DBzEZOalp0qDdF8,8
|
|
35
|
-
daktari-0.0.254.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|