daktari 0.0.330__tar.gz → 0.0.332__tar.gz
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.
- {daktari-0.0.330/daktari.egg-info → daktari-0.0.332}/PKG-INFO +2 -2
- {daktari-0.0.330 → daktari-0.0.332}/README.md +1 -1
- daktari-0.0.332/daktari/__init__.py +1 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/git.py +2 -1
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/misc.py +11 -7
- daktari-0.0.332/daktari/checks/test_misc.py +53 -0
- daktari-0.0.332/daktari/test_git.py +55 -0
- {daktari-0.0.330 → daktari-0.0.332/daktari.egg-info}/PKG-INFO +2 -2
- {daktari-0.0.330 → daktari-0.0.332}/daktari.egg-info/SOURCES.txt +1 -0
- {daktari-0.0.330 → daktari-0.0.332}/pyproject.toml +1 -1
- daktari-0.0.330/daktari/__init__.py +0 -1
- daktari-0.0.330/daktari/checks/test_misc.py +0 -18
- {daktari-0.0.330 → daktari-0.0.332}/LICENSE.txt +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/MANIFEST.in +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/__main__.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/asdf.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/check.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/check_runner.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/check_sorter.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/check_utils.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/__init__.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/android.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/aws.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/certs.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/conan.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/direnv.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/docker.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/etc_hosts.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/files.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/flutter.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/google.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/intellij_idea.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/java.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/kubernetes.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/mobile.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/nodejs.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/npmrc.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/onepassword.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/pnpm.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/python.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/ssh.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/terraform.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/test_certs.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/test_intellij_idea.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/test_java.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/test_mobile.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/test_npmrc.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/test_onepassword.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/test_pnpm.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/test_ssh.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/test_yarn.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/xml.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/checks/yarn.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/collection_utils.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/command_utils.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/config.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/file_utils.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/options.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/os.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/resource_utils.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/resources/__init__.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/resources/daktari-local-template.yaml +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/resources/mock_cert.pem +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/result_printer.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/test_asdf.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/test_check.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/test_check_factory.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/test_check_runner.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/test_check_sorter.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/test_check_utils.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/test_collection_utils.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/test_config.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/test_result_printer.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/test_version_utils.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari/version_utils.py +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari.egg-info/dependency_links.txt +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari.egg-info/entry_points.txt +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari.egg-info/requires.txt +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/daktari.egg-info/top_level.txt +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/requirements.txt +0 -0
- {daktari-0.0.330 → daktari-0.0.332}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: daktari
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.332
|
|
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
|
|
@@ -45,7 +45,7 @@ In the root of the project repository, create a `.daktari.py` configuration file
|
|
|
45
45
|
```python
|
|
46
46
|
from daktari.checks.git import *
|
|
47
47
|
|
|
48
|
-
version = "0.0.
|
|
48
|
+
version = "0.0.332"
|
|
49
49
|
title = "My Project"
|
|
50
50
|
|
|
51
51
|
checks = [
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.0.332"
|
|
@@ -133,7 +133,8 @@ class PreCommitGitHooksInstalled(Check):
|
|
|
133
133
|
}
|
|
134
134
|
|
|
135
135
|
def check(self) -> CheckResult:
|
|
136
|
-
|
|
136
|
+
hook_path = get_stdout("git rev-parse --git-path hooks/pre-commit")
|
|
137
|
+
git_hooks_installed = hook_path is not None and file_contains_text(hook_path, "pre-commit.com")
|
|
137
138
|
return self.verify(git_hooks_installed, "pre-commit Git hooks are <not/> installed")
|
|
138
139
|
|
|
139
140
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from os.path import expanduser
|
|
3
|
-
from typing import Dict, Optional
|
|
3
|
+
from typing import Dict, Optional, Set
|
|
4
4
|
|
|
5
5
|
from python_hosts import Hosts
|
|
6
6
|
|
|
@@ -189,9 +189,10 @@ class Md5SumInstalled(Check):
|
|
|
189
189
|
class HostAliasesConfigured(Check):
|
|
190
190
|
name = "hostAliases.configured"
|
|
191
191
|
|
|
192
|
-
def __init__(self, required_aliases: Dict[str, str]):
|
|
192
|
+
def __init__(self, required_aliases: Dict[str, str], hosts_path: Optional[str] = None):
|
|
193
193
|
self.required_aliases = required_aliases
|
|
194
|
-
hosts_path =
|
|
194
|
+
self.hosts_path = hosts_path
|
|
195
|
+
hosts_path = hosts_path or Hosts.determine_hosts_path()
|
|
195
196
|
|
|
196
197
|
aliases_by_addr: Dict[str, list[str]] = {}
|
|
197
198
|
|
|
@@ -209,15 +210,18 @@ class HostAliasesConfigured(Check):
|
|
|
209
210
|
self.suggestions = {OS.GENERIC: suggestion_text}
|
|
210
211
|
|
|
211
212
|
def check(self) -> CheckResult:
|
|
212
|
-
hosts = Hosts()
|
|
213
|
+
hosts = Hosts(path=self.hosts_path)
|
|
213
214
|
entries = [e for e in hosts.entries if e.entry_type in ("ipv4", "ipv6")]
|
|
214
|
-
|
|
215
|
+
# A hostname can legitimately map to several addresses (e.g. dual-stack
|
|
216
|
+
# localhost -> both 127.0.0.1 and ::1), so collect all addresses per name
|
|
217
|
+
# rather than letting the last entry in file order win.
|
|
218
|
+
entries_dict: Dict[str, Set[str]] = {}
|
|
215
219
|
for entry in entries:
|
|
216
220
|
for name in entry.names:
|
|
217
|
-
entries_dict
|
|
221
|
+
entries_dict.setdefault(name, set()).add(entry.address)
|
|
218
222
|
logging.debug(f"Hosts file entries: {entries_dict}")
|
|
219
223
|
for name, address in self.required_aliases.items():
|
|
220
|
-
if entries_dict.get(name)
|
|
224
|
+
if address not in entries_dict.get(name, set()):
|
|
221
225
|
return self.failed(f"{hosts.path} alias {name} -> {address} not present")
|
|
222
226
|
|
|
223
227
|
return self.passed(f"{hosts.path} aliases present")
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import tempfile
|
|
3
|
+
import unittest
|
|
4
|
+
|
|
5
|
+
from daktari.check import CheckStatus
|
|
6
|
+
from daktari.checks.misc import HostAliasesConfigured
|
|
7
|
+
|
|
8
|
+
# Stock macOS /etc/hosts maps "localhost" to both 127.0.0.1 and ::1, with the
|
|
9
|
+
# ::1 line appearing last. The check must treat the IPv4 alias as satisfied
|
|
10
|
+
# regardless of the order the two lines appear in (see HostAliasesConfigured).
|
|
11
|
+
DUAL_STACK_IPV6_LAST = "127.0.0.1 localhost\n255.255.255.255 broadcasthost\n::1 localhost\n"
|
|
12
|
+
DUAL_STACK_IPV4_LAST = "::1 localhost\n255.255.255.255 broadcasthost\n127.0.0.1 localhost\n"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class TestHostAliasesConfigured(unittest.TestCase):
|
|
16
|
+
def _hosts_fixture(self, content):
|
|
17
|
+
f = tempfile.NamedTemporaryFile("w", suffix=".hosts", delete=False)
|
|
18
|
+
f.write(content)
|
|
19
|
+
f.close()
|
|
20
|
+
self.addCleanup(os.unlink, f.name)
|
|
21
|
+
return f.name
|
|
22
|
+
|
|
23
|
+
def test_checking_hosts_does_not_blow_up_on_success(self):
|
|
24
|
+
result = HostAliasesConfigured({}).check()
|
|
25
|
+
self.assertEqual(result.status, CheckStatus.PASS)
|
|
26
|
+
|
|
27
|
+
def test_checking_hosts_does_not_blow_up_on_failure(self):
|
|
28
|
+
result = HostAliasesConfigured({"host": "no.such.entry.surely"}).check()
|
|
29
|
+
self.assertEqual(result.status, CheckStatus.FAIL)
|
|
30
|
+
|
|
31
|
+
def test_dual_stack_alias_passes_with_ipv6_entry_last(self):
|
|
32
|
+
path = self._hosts_fixture(DUAL_STACK_IPV6_LAST)
|
|
33
|
+
result = HostAliasesConfigured({"localhost": "127.0.0.1"}, hosts_path=path).check()
|
|
34
|
+
self.assertEqual(result.status, CheckStatus.PASS)
|
|
35
|
+
|
|
36
|
+
def test_dual_stack_alias_passes_with_ipv4_entry_last(self):
|
|
37
|
+
path = self._hosts_fixture(DUAL_STACK_IPV4_LAST)
|
|
38
|
+
result = HostAliasesConfigured({"localhost": "127.0.0.1"}, hosts_path=path).check()
|
|
39
|
+
self.assertEqual(result.status, CheckStatus.PASS)
|
|
40
|
+
|
|
41
|
+
def test_dual_stack_ipv6_alias_also_satisfied(self):
|
|
42
|
+
path = self._hosts_fixture(DUAL_STACK_IPV6_LAST)
|
|
43
|
+
result = HostAliasesConfigured({"localhost": "::1"}, hosts_path=path).check()
|
|
44
|
+
self.assertEqual(result.status, CheckStatus.PASS)
|
|
45
|
+
|
|
46
|
+
def test_missing_alias_still_fails(self):
|
|
47
|
+
path = self._hosts_fixture(DUAL_STACK_IPV6_LAST)
|
|
48
|
+
result = HostAliasesConfigured({"localhost": "10.0.0.1"}, hosts_path=path).check()
|
|
49
|
+
self.assertEqual(result.status, CheckStatus.FAIL)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
if __name__ == "__main__":
|
|
53
|
+
unittest.main()
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import unittest
|
|
2
|
+
from unittest.mock import patch
|
|
3
|
+
|
|
4
|
+
from daktari.check import CheckStatus
|
|
5
|
+
from daktari.checks.git import PreCommitGitHooksInstalled
|
|
6
|
+
|
|
7
|
+
# The path git resolves the pre-commit hook to. In a worktree this is *not*
|
|
8
|
+
# ".git/hooks/pre-commit" (there ".git" is a file, not a directory), and when
|
|
9
|
+
# core.hooksPath is set it points outside the per-worktree gitdir entirely.
|
|
10
|
+
RESOLVED_HOOK_PATH = "/main/.git/hooks/pre-commit"
|
|
11
|
+
LITERAL_HOOK_PATH = ".git/hooks/pre-commit"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def fake_hook_contents(path: str, text: str) -> bool:
|
|
15
|
+
"""Model a worktree: only the git-resolved hook path exists and is installed.
|
|
16
|
+
|
|
17
|
+
The literal ".git/hooks/pre-commit" path is absent (in a worktree ".git" is a
|
|
18
|
+
file), so reading it directly always misses.
|
|
19
|
+
"""
|
|
20
|
+
return path == RESOLVED_HOOK_PATH and text == "pre-commit.com"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class TestPreCommitGitHooksInstalled(unittest.TestCase):
|
|
24
|
+
@patch("daktari.checks.git.file_contains_text", side_effect=fake_hook_contents)
|
|
25
|
+
@patch("daktari.checks.git.get_stdout", return_value=RESOLVED_HOOK_PATH)
|
|
26
|
+
def test_passes_in_worktree_when_hook_resolves_via_git(self, mock_get_stdout, mock_contains):
|
|
27
|
+
result = PreCommitGitHooksInstalled().check()
|
|
28
|
+
self.assertEqual(
|
|
29
|
+
result.status,
|
|
30
|
+
CheckStatus.PASS,
|
|
31
|
+
"Hooks are installed (resolved via git), so the check should pass even in a worktree",
|
|
32
|
+
)
|
|
33
|
+
mock_get_stdout.assert_called_once_with("git rev-parse --git-path hooks/pre-commit")
|
|
34
|
+
|
|
35
|
+
@patch("daktari.checks.git.file_contains_text", side_effect=fake_hook_contents)
|
|
36
|
+
@patch("daktari.checks.git.get_stdout", return_value=RESOLVED_HOOK_PATH)
|
|
37
|
+
def test_resolved_path_is_checked_not_literal(self, mock_get_stdout, mock_contains):
|
|
38
|
+
PreCommitGitHooksInstalled().check()
|
|
39
|
+
mock_contains.assert_called_once_with(RESOLVED_HOOK_PATH, "pre-commit.com")
|
|
40
|
+
|
|
41
|
+
@patch("daktari.checks.git.file_contains_text", return_value=False)
|
|
42
|
+
@patch("daktari.checks.git.get_stdout", return_value=RESOLVED_HOOK_PATH)
|
|
43
|
+
def test_fails_when_hook_not_installed(self, mock_get_stdout, mock_contains):
|
|
44
|
+
result = PreCommitGitHooksInstalled().check()
|
|
45
|
+
self.assertEqual(result.status, CheckStatus.FAIL)
|
|
46
|
+
|
|
47
|
+
@patch("daktari.checks.git.file_contains_text", return_value=False)
|
|
48
|
+
@patch("daktari.checks.git.get_stdout", return_value=None)
|
|
49
|
+
def test_fails_gracefully_when_git_cannot_resolve_path(self, mock_get_stdout, mock_contains):
|
|
50
|
+
result = PreCommitGitHooksInstalled().check()
|
|
51
|
+
self.assertEqual(result.status, CheckStatus.FAIL)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
if __name__ == "__main__":
|
|
55
|
+
unittest.main()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: daktari
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.332
|
|
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
|
|
@@ -45,7 +45,7 @@ In the root of the project repository, create a `.daktari.py` configuration file
|
|
|
45
45
|
```python
|
|
46
46
|
from daktari.checks.git import *
|
|
47
47
|
|
|
48
|
-
version = "0.0.
|
|
48
|
+
version = "0.0.332"
|
|
49
49
|
title = "My Project"
|
|
50
50
|
|
|
51
51
|
checks = [
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.0.330"
|
|
@@ -1,18 +0,0 @@
|
|
|
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()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|