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.

@@ -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.254
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.254"
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,,
@@ -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,,