daktari 0.0.236__py3-none-any.whl → 0.0.254__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-0.0.236.dist-info → daktari-0.0.254.dist-info}/METADATA +35 -34
- daktari-0.0.254.dist-info/RECORD +35 -0
- {daktari-0.0.236.dist-info → daktari-0.0.254.dist-info}/WHEEL +1 -1
- daktari/checks/__init__.py +0 -0
- daktari/checks/android.py +0 -26
- daktari/checks/aws.py +0 -34
- daktari/checks/certs.py +0 -34
- daktari/checks/conan.py +0 -96
- daktari/checks/direnv.py +0 -59
- daktari/checks/docker.py +0 -50
- daktari/checks/files.py +0 -72
- daktari/checks/flutter.py +0 -46
- daktari/checks/git.py +0 -198
- daktari/checks/google.py +0 -113
- daktari/checks/intellij_idea.py +0 -248
- daktari/checks/java.py +0 -104
- daktari/checks/kubernetes.py +0 -154
- daktari/checks/misc.py +0 -302
- daktari/checks/nodejs.py +0 -92
- daktari/checks/onepassword.py +0 -105
- daktari/checks/python.py +0 -16
- daktari/checks/ssh.py +0 -33
- daktari/checks/terraform.py +0 -70
- daktari/checks/test_certs.py +0 -32
- daktari/checks/test_intellij_idea.py +0 -66
- daktari/checks/test_java.py +0 -88
- daktari/checks/test_misc.py +0 -18
- daktari/checks/test_onepassword.py +0 -31
- daktari/checks/test_ssh.py +0 -22
- daktari/checks/test_yarn.py +0 -86
- daktari/checks/xml.py +0 -33
- daktari/checks/yarn.py +0 -156
- daktari-0.0.236.dist-info/RECORD +0 -64
- {daktari-0.0.236.dist-info → daktari-0.0.254.dist-info}/LICENSE.txt +0 -0
- {daktari-0.0.236.dist-info → daktari-0.0.254.dist-info}/entry_points.txt +0 -0
- {daktari-0.0.236.dist-info → daktari-0.0.254.dist-info}/top_level.txt +0 -0
daktari/checks/kubernetes.py
DELETED
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import logging
|
|
3
|
-
import re
|
|
4
|
-
from typing import Optional, List
|
|
5
|
-
|
|
6
|
-
from semver import VersionInfo
|
|
7
|
-
|
|
8
|
-
from daktari.check import Check, CheckResult
|
|
9
|
-
from daktari.command_utils import get_stdout, can_run_command
|
|
10
|
-
from daktari.os import OS
|
|
11
|
-
from daktari.version_utils import try_parse_semver
|
|
12
|
-
from daktari.checks.google import GkeGcloudAuthPluginInstalled
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class KubectlInstalled(Check):
|
|
16
|
-
def __init__(self, required_version: Optional[str] = None, recommended_version: Optional[str] = None):
|
|
17
|
-
self.required_version = required_version
|
|
18
|
-
self.recommended_version = recommended_version
|
|
19
|
-
self.name = "kubectl.installed"
|
|
20
|
-
self.suggestions = {
|
|
21
|
-
OS.OS_X: "<cmd>brew install kubectl</cmd>",
|
|
22
|
-
OS.UBUNTU: "<cmd>sudo snap install kubectl --classic</cmd>",
|
|
23
|
-
OS.GENERIC: "Install kubectl: https://kubernetes.io/docs/tasks/tools/#kubectl",
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
def check(self) -> CheckResult:
|
|
27
|
-
installed_version = get_kubectl_version()
|
|
28
|
-
return self.validate_semver_expression(
|
|
29
|
-
"Kubectl", installed_version, self.required_version, self.recommended_version
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
version_pattern = re.compile("Client Version: v(.*)")
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def get_kubectl_version() -> Optional[VersionInfo]:
|
|
37
|
-
raw_version = get_stdout("kubectl version --client=true --short")
|
|
38
|
-
# Handle deprecation of --short
|
|
39
|
-
if raw_version is None:
|
|
40
|
-
raw_version = get_stdout("kubectl version --client=true")
|
|
41
|
-
|
|
42
|
-
if raw_version:
|
|
43
|
-
match = version_pattern.search(raw_version)
|
|
44
|
-
if match:
|
|
45
|
-
version = try_parse_semver(match.group(1))
|
|
46
|
-
logging.debug(f"Kubectl version: {version}")
|
|
47
|
-
return version
|
|
48
|
-
return None
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
class KubectlContextExists(Check):
|
|
52
|
-
depends_on = [GkeGcloudAuthPluginInstalled]
|
|
53
|
-
|
|
54
|
-
def __init__(self, context_name: str, provision_command: str = ""):
|
|
55
|
-
self.context_name = context_name
|
|
56
|
-
self.name = f"kubectl.contextExists.{context_name}"
|
|
57
|
-
self.suggestions = {OS.GENERIC: provision_command}
|
|
58
|
-
|
|
59
|
-
def check(self) -> CheckResult:
|
|
60
|
-
output = get_stdout("kubectl config get-contexts")
|
|
61
|
-
passed = bool(output and self.context_name in output)
|
|
62
|
-
if not passed:
|
|
63
|
-
return self.failed(f"{self.context_name} is <not/> configured for the current user")
|
|
64
|
-
|
|
65
|
-
can_connect = can_run_command(f"kubectl get ns --context {self.context_name}")
|
|
66
|
-
return self.verify(can_connect, f"Could <not/> connect to context {self.context_name}")
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
class KubectlNoExtraneousContexts(Check):
|
|
70
|
-
def __init__(self, expected_contexts: List[str]):
|
|
71
|
-
self.expected_contexts = expected_contexts
|
|
72
|
-
self.name = "kubectl.noExtraneousContexts"
|
|
73
|
-
|
|
74
|
-
def check(self) -> CheckResult:
|
|
75
|
-
output = get_stdout("kubectl config get-contexts -o name")
|
|
76
|
-
if not output:
|
|
77
|
-
return self.failed("Failed to list kubectl contexts")
|
|
78
|
-
|
|
79
|
-
contexts = output.splitlines()
|
|
80
|
-
extraneous_contexts = list(filter(lambda context: context not in self.expected_contexts, contexts))
|
|
81
|
-
if extraneous_contexts:
|
|
82
|
-
suggestion = "\n".join(
|
|
83
|
-
f"<cmd>kubectl config delete-context {context}</cmd>" for context in extraneous_contexts
|
|
84
|
-
)
|
|
85
|
-
self.suggestions = {
|
|
86
|
-
OS.GENERIC: suggestion,
|
|
87
|
-
}
|
|
88
|
-
return self.passed_with_warning(f"{len(extraneous_contexts)} extraneous kubectl context(s) found")
|
|
89
|
-
|
|
90
|
-
return self.passed("No extraneous kubectl contexts found")
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
class HelmInstalled(Check):
|
|
94
|
-
name = "helm.installed"
|
|
95
|
-
|
|
96
|
-
def __init__(self, required_version: Optional[str] = None, recommended_version: Optional[str] = None):
|
|
97
|
-
self.required_version = required_version
|
|
98
|
-
self.recommended_version = recommended_version
|
|
99
|
-
self.suggestions = {
|
|
100
|
-
OS.OS_X: "<cmd>brew install helm</cmd>",
|
|
101
|
-
OS.UBUNTU: "<cmd>sudo snap install helm --classic</cmd>",
|
|
102
|
-
OS.GENERIC: "Install Helm: https://helm.sh/docs/intro/install/",
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
def check(self) -> CheckResult:
|
|
106
|
-
installed_version = get_helm_version()
|
|
107
|
-
return self.validate_semver_expression(
|
|
108
|
-
"Helm", installed_version, self.required_version, self.recommended_version
|
|
109
|
-
)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
helm_version_pattern = re.compile("v([0-9\\.]+)")
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
def get_helm_version() -> Optional[VersionInfo]:
|
|
116
|
-
raw_version = get_stdout("helm version --short")
|
|
117
|
-
if raw_version:
|
|
118
|
-
match = helm_version_pattern.search(raw_version)
|
|
119
|
-
if match:
|
|
120
|
-
version = try_parse_semver(match.group(1))
|
|
121
|
-
logging.debug(f"Helm Version: {version}")
|
|
122
|
-
return version
|
|
123
|
-
return None
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
class HelmRepoExists(Check):
|
|
127
|
-
depends_on = [HelmInstalled]
|
|
128
|
-
|
|
129
|
-
def __init__(self, repo_name: str, repo_url: str):
|
|
130
|
-
self.repo_name = repo_name
|
|
131
|
-
self.repo_url = repo_url.strip("/")
|
|
132
|
-
self.name = f"helm.repoExists.{repo_name}"
|
|
133
|
-
self.suggestions = {
|
|
134
|
-
OS.GENERIC: f"<cmd>helm repo add {repo_name} {repo_url} --force-update</cmd>",
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
def check(self) -> CheckResult:
|
|
138
|
-
output = get_stdout("helm repo list -o json")
|
|
139
|
-
if not output:
|
|
140
|
-
return self.failed("No helm repos appear to be configured for the current user.")
|
|
141
|
-
repo_json = json.loads(output)
|
|
142
|
-
repo = next(filter(lambda repo_details: repo_details.get("name") == self.repo_name, repo_json), None)
|
|
143
|
-
if repo is None:
|
|
144
|
-
return self.failed(f"{self.repo_name} is not configured for the current user")
|
|
145
|
-
|
|
146
|
-
installed_url = repo["url"].strip("/")
|
|
147
|
-
logging.debug(f"{self.repo_name} helm repo is installed with URL {installed_url}.")
|
|
148
|
-
|
|
149
|
-
if installed_url != self.repo_url:
|
|
150
|
-
return self.failed(
|
|
151
|
-
f"{self.repo_name} is configured to use the wrong URL. Expected {self.repo_url}, got {installed_url}"
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
return self.passed(f"{self.repo_name} is configured for the current user")
|
daktari/checks/misc.py
DELETED
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
from os.path import expanduser
|
|
3
|
-
from typing import Dict, Optional
|
|
4
|
-
|
|
5
|
-
from python_hosts import Hosts
|
|
6
|
-
from tabulate import tabulate
|
|
7
|
-
|
|
8
|
-
from daktari.check import Check, CheckResult
|
|
9
|
-
from daktari.os import OS, check_env_var_exists, get_env_var_value
|
|
10
|
-
from daktari.version_utils import get_simple_cli_version
|
|
11
|
-
from daktari.command_utils import can_run_command
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class WatchmanInstalled(Check):
|
|
15
|
-
name = "watchman.installed"
|
|
16
|
-
|
|
17
|
-
suggestions = {
|
|
18
|
-
OS.OS_X: "<cmd>brew install watchman</cmd>",
|
|
19
|
-
OS.GENERIC: "Install watchman: https://facebook.github.io/watchman/docs/install.html#buildinstall",
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
def check(self) -> CheckResult:
|
|
23
|
-
return self.verify_install("watchman")
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
class MkcertInstalled(Check):
|
|
27
|
-
name = "mkcert.installed"
|
|
28
|
-
|
|
29
|
-
suggestions = {
|
|
30
|
-
OS.OS_X: """
|
|
31
|
-
Install mkcert:
|
|
32
|
-
<cmd>brew install mkcert</cmd>
|
|
33
|
-
Install the local CA in the system trust store:
|
|
34
|
-
<cmd>mkcert -install</cmd>
|
|
35
|
-
""",
|
|
36
|
-
OS.GENERIC: """
|
|
37
|
-
Install mkcert: https://mkcert.dev/#installation
|
|
38
|
-
Install the local CA in the system trust store:
|
|
39
|
-
<cmd>mkcert -install</cmd>
|
|
40
|
-
""",
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
def check(self) -> CheckResult:
|
|
44
|
-
return self.verify_install("mkcert")
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
class KtlintInstalled(Check):
|
|
48
|
-
name = "ktlint.installed"
|
|
49
|
-
|
|
50
|
-
suggestions = {
|
|
51
|
-
OS.OS_X: "<cmd>brew install ktlint</cmd>",
|
|
52
|
-
OS.GENERIC: "Install ktlint: https://github.com/pinterest/ktlint#installation",
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
def __init__(self, required_version: Optional[str] = None, recommended_version: Optional[str] = None):
|
|
56
|
-
self.required_version = required_version
|
|
57
|
-
self.recommended_version = recommended_version
|
|
58
|
-
|
|
59
|
-
def check(self) -> CheckResult:
|
|
60
|
-
installed_version = get_simple_cli_version("ktlint")
|
|
61
|
-
return self.validate_semver_expression(
|
|
62
|
-
"ktlint", installed_version, self.required_version, self.recommended_version
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
class CmakeInstalled(Check):
|
|
67
|
-
name = "cmake.installed"
|
|
68
|
-
|
|
69
|
-
suggestions = {
|
|
70
|
-
OS.OS_X: "<cmd>brew install cmake</cmd>",
|
|
71
|
-
OS.UBUNTU: "<cmd>apt-get install cmake</cmd>",
|
|
72
|
-
OS.GENERIC: "Install cmake: https://cmake.org/install/",
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
def __init__(self, required_version: Optional[str] = None, recommended_version: Optional[str] = None):
|
|
76
|
-
self.required_version = required_version
|
|
77
|
-
self.recommended_version = recommended_version
|
|
78
|
-
|
|
79
|
-
def check(self) -> CheckResult:
|
|
80
|
-
installed_version = get_simple_cli_version("cmake")
|
|
81
|
-
return self.validate_semver_expression(
|
|
82
|
-
"cmake", installed_version, self.required_version, self.recommended_version
|
|
83
|
-
)
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
class JqInstalled(Check):
|
|
87
|
-
name = "jq.installed"
|
|
88
|
-
|
|
89
|
-
suggestions = {
|
|
90
|
-
OS.OS_X: "<cmd>brew install jq</cmd>",
|
|
91
|
-
OS.UBUNTU: "<cmd>sudo apt install jq</cmd>",
|
|
92
|
-
OS.GENERIC: "Install jq: https://stedolan.github.io/jq/download/",
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
def check(self) -> CheckResult:
|
|
96
|
-
return self.verify_install("jq")
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
class FlywayInstalled(Check):
|
|
100
|
-
name = "flyway.installed"
|
|
101
|
-
|
|
102
|
-
suggestions = {
|
|
103
|
-
OS.OS_X: "<cmd>brew install flyway</cmd>",
|
|
104
|
-
OS.UBUNTU: "<cmd>snap install flyway</cmd>",
|
|
105
|
-
OS.GENERIC: "Install flyway: https://flywaydb.org/documentation/usage/commandline/#download-and-installation",
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
def check(self) -> CheckResult:
|
|
109
|
-
return self.verify_install("flyway", "-v")
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
class ShellcheckInstalled(Check):
|
|
113
|
-
name = "shellcheck.installed"
|
|
114
|
-
|
|
115
|
-
suggestions = {
|
|
116
|
-
OS.OS_X: "<cmd>brew install shellcheck</cmd>",
|
|
117
|
-
OS.UBUNTU: "<cmd>sudo apt install shellcheck</cmd>",
|
|
118
|
-
OS.GENERIC: "Install shellcheck: https://github.com/koalaman/shellcheck#user-content-installing",
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
def check(self) -> CheckResult:
|
|
122
|
-
return self.verify_install("shellcheck")
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
class MakeInstalled(Check):
|
|
126
|
-
name = "make.installed"
|
|
127
|
-
|
|
128
|
-
suggestions = {
|
|
129
|
-
OS.OS_X: "<cmd>xcode-select --install</cmd>",
|
|
130
|
-
OS.UBUNTU: "<cmd>sudo apt install make</cmd>",
|
|
131
|
-
OS.GENERIC: "Install make: https://www.gnu.org/software/make/",
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
def check(self) -> CheckResult:
|
|
135
|
-
return self.verify_install("make")
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
class GccInstalled(Check):
|
|
139
|
-
name = "gcc.installed"
|
|
140
|
-
|
|
141
|
-
suggestions = {
|
|
142
|
-
OS.OS_X: "<cmd>xcode-select --install</cmd>",
|
|
143
|
-
OS.UBUNTU: "<cmd>sudo apt install gcc</cmd>",
|
|
144
|
-
OS.GENERIC: "Install gcc: https://gcc.gnu.org/",
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
def check(self) -> CheckResult:
|
|
148
|
-
return self.verify_install("gcc")
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
class EnvVarSet(Check):
|
|
152
|
-
def __init__(self, variable_name: str, variable_value: Optional[str] = "", provision_command: str = ""):
|
|
153
|
-
self.name = f"env.variableSet.{variable_name}"
|
|
154
|
-
self.suggestions = {OS.GENERIC: provision_command}
|
|
155
|
-
self.variable_name = variable_name
|
|
156
|
-
self.variable_value = variable_value
|
|
157
|
-
|
|
158
|
-
def check(self) -> CheckResult:
|
|
159
|
-
if self.variable_value:
|
|
160
|
-
return self.verify(
|
|
161
|
-
get_env_var_value(self.variable_name) == self.variable_value,
|
|
162
|
-
f"{self.variable_name} has <not/> got the required value of {self.variable_value}",
|
|
163
|
-
)
|
|
164
|
-
else:
|
|
165
|
-
return self.verify(check_env_var_exists(self.variable_name), f"{self.variable_name} is <not/> set")
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
class ShfmtInstalled(Check):
|
|
169
|
-
name = "shfmt.installed"
|
|
170
|
-
|
|
171
|
-
suggestions = {
|
|
172
|
-
OS.OS_X: "<cmd>brew install shfmt</cmd>",
|
|
173
|
-
OS.UBUNTU: "<cmd>snap install shfmt</cmd>",
|
|
174
|
-
OS.GENERIC: "Install shfmt: https://github.com/mvdan/sh",
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
def check(self) -> CheckResult:
|
|
178
|
-
return self.verify_install("shfmt")
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
class Md5SumInstalled(Check):
|
|
182
|
-
name = "md5sum.installed"
|
|
183
|
-
|
|
184
|
-
suggestions = {OS.OS_X: "<cmd>brew install md5sha1sum</cmd>", OS.GENERIC: "Install md5sum"}
|
|
185
|
-
|
|
186
|
-
def check(self) -> CheckResult:
|
|
187
|
-
return self.verify_install("md5sum")
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
class HostAliasesConfigured(Check):
|
|
191
|
-
name = "hostAliases.configured"
|
|
192
|
-
|
|
193
|
-
def __init__(self, required_aliases: Dict[str, str]):
|
|
194
|
-
self.required_aliases = required_aliases
|
|
195
|
-
hosts_path = Hosts.determine_hosts_path()
|
|
196
|
-
entries_text = tabulate([(addr, name) for (name, addr) in self.required_aliases.items()], tablefmt="plain")
|
|
197
|
-
self.suggestions = {OS.GENERIC: f"Add the following entries to {hosts_path}:\n\n{entries_text}"}
|
|
198
|
-
|
|
199
|
-
def check(self) -> CheckResult:
|
|
200
|
-
hosts = Hosts()
|
|
201
|
-
entries = [e for e in hosts.entries if e.entry_type in ("ipv4", "ipv6")]
|
|
202
|
-
entries_dict = {}
|
|
203
|
-
for entry in entries:
|
|
204
|
-
for name in entry.names:
|
|
205
|
-
entries_dict[name] = entry.address
|
|
206
|
-
logging.debug(f"Hosts file entries: {entries_dict}")
|
|
207
|
-
for name, address in self.required_aliases.items():
|
|
208
|
-
if entries_dict.get(name) != address:
|
|
209
|
-
return self.failed(f"{hosts.path} alias {name} -> {address} not present")
|
|
210
|
-
|
|
211
|
-
return self.passed(f"{hosts.path} aliases present")
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
class DirectoryIsOnPath(Check):
|
|
215
|
-
name = "directory.on.path"
|
|
216
|
-
|
|
217
|
-
def __init__(self, directory: str):
|
|
218
|
-
self.directory = expanduser(directory) # $PATH won't auto-expand ~
|
|
219
|
-
self.suggestions = {
|
|
220
|
-
OS.GENERIC: f"""
|
|
221
|
-
Append the following line to your profile (~/.bashrc or ~/.zshrc):
|
|
222
|
-
export PATH="{self.directory}:$PATH
|
|
223
|
-
""",
|
|
224
|
-
OS.UBUNTU: f"""
|
|
225
|
-
Append the following line to your profile (~/.bashrc):
|
|
226
|
-
export PATH="{self.directory}:$PATH"
|
|
227
|
-
For first time setup, you can run this:
|
|
228
|
-
<cmd>echo 'export PATH="{self.directory}:$PATH"' >> ~/.bashrc && source ~/.bashrc</cmd>
|
|
229
|
-
""",
|
|
230
|
-
OS.OS_X: f"""
|
|
231
|
-
Append the following line to your profile (~/.zshrc):
|
|
232
|
-
export PATH="{self.directory}:$PATH"
|
|
233
|
-
For first time setup, you can run this:
|
|
234
|
-
<cmd>echo 'export PATH="{self.directory}:$PATH"' >> ~/.zshrc && source ~/.zshrc</cmd>
|
|
235
|
-
""",
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
def check(self) -> CheckResult:
|
|
239
|
-
path_value = get_env_var_value("PATH")
|
|
240
|
-
return self.verify(path_value.__contains__(self.directory), f"{self.directory} is <not/> on the $PATH")
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
class DetektInstalled(Check):
|
|
244
|
-
name = "detekt.installed"
|
|
245
|
-
|
|
246
|
-
def __init__(
|
|
247
|
-
self,
|
|
248
|
-
required_version: Optional[str] = None,
|
|
249
|
-
recommended_version: Optional[str] = None,
|
|
250
|
-
install_version: Optional[str] = None,
|
|
251
|
-
):
|
|
252
|
-
self.install_version = install_version
|
|
253
|
-
self.required_version = required_version
|
|
254
|
-
self.recommended_version = recommended_version
|
|
255
|
-
self.suggestions = {
|
|
256
|
-
OS.OS_X: self.get_install_cmd(),
|
|
257
|
-
OS.UBUNTU: self.get_install_cmd(),
|
|
258
|
-
OS.GENERIC: "Install detekt: https://detekt.dev/cli.html#install-the-cli",
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
def get_install_cmd(self) -> str:
|
|
262
|
-
version = self.install_version or "[desired version - see https://github.com/detekt/detekt/releases]"
|
|
263
|
-
url = "https://github.com/detekt/detekt/releases/download/v$DETEKT_VERSION/detekt-cli-$DETEKT_VERSION.zip"
|
|
264
|
-
return f"""
|
|
265
|
-
<cmd>DETEKT_VERSION={version}</cmd>
|
|
266
|
-
<cmd>LOCAL_BIN=~/.local/bin</cmd>
|
|
267
|
-
<cmd>TEMP_FILE=$(mktemp)</cmd>
|
|
268
|
-
<cmd>mkdir -p "$LOCAL_BIN"</cmd>
|
|
269
|
-
<cmd>curl -L {url} --output "$TEMP_FILE"</cmd>
|
|
270
|
-
<cmd>unzip -u "$TEMP_FILE" -d "$LOCAL_BIN"</cmd>
|
|
271
|
-
<cmd>rm "$TEMP_FILE"</cmd>
|
|
272
|
-
<cmd>chmod +x "$LOCAL_BIN/detekt-cli-$DETEKT_VERSION/bin/detekt-cli"</cmd>
|
|
273
|
-
<cmd>ln -f -s "$LOCAL_BIN/detekt-cli-$DETEKT_VERSION/bin/detekt-cli" "$LOCAL_BIN/detekt"</cmd>
|
|
274
|
-
"""
|
|
275
|
-
|
|
276
|
-
def check(self) -> CheckResult:
|
|
277
|
-
installed_version = get_simple_cli_version("detekt")
|
|
278
|
-
return self.validate_semver_expression(
|
|
279
|
-
"detekt", installed_version, self.required_version, self.recommended_version
|
|
280
|
-
)
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
class TaskInstalled(Check):
|
|
284
|
-
name = "task.installed"
|
|
285
|
-
suggestions = {
|
|
286
|
-
OS.OS_X: "<cmd>brew install go-task</cmd>",
|
|
287
|
-
OS.GENERIC: "Install task: https://taskfile.dev/installation/",
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
def check(self) -> CheckResult:
|
|
291
|
-
return self.verify_install("task")
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
class Rosetta2Installed(Check):
|
|
295
|
-
name = "rosetta2.installed"
|
|
296
|
-
run_on = OS.OS_X
|
|
297
|
-
suggestions = {OS.OS_X: "<cmd>softwareupdate --install-rosetta</cmd>"}
|
|
298
|
-
|
|
299
|
-
def check(self) -> CheckResult:
|
|
300
|
-
return self.verify(
|
|
301
|
-
can_run_command("arch -x86_64 true"), "Rosetta 2 is installed or not required", "Rosetta 2 is not installed"
|
|
302
|
-
)
|
daktari/checks/nodejs.py
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
from typing import List, Optional
|
|
3
|
-
|
|
4
|
-
from semver import VersionInfo
|
|
5
|
-
|
|
6
|
-
from daktari.check import Check, CheckResult
|
|
7
|
-
from daktari.command_utils import get_stdout, run_command
|
|
8
|
-
from daktari.os import OS
|
|
9
|
-
from daktari.version_utils import try_parse_semver
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
def get_nodejs_version() -> Optional[VersionInfo]:
|
|
13
|
-
version_output = get_stdout("node --version")
|
|
14
|
-
version_output = None if version_output is None else version_output.lstrip("v")
|
|
15
|
-
return try_parse_semver(version_output)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def run_nvm(nvm_args: List[str]):
|
|
19
|
-
return run_command(["sh", "-c", '. "$NVM_DIR/nvm.sh"; nvm "$@"', "--", *nvm_args])
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def can_run_nvm() -> bool:
|
|
23
|
-
try:
|
|
24
|
-
run_nvm(["--version"])
|
|
25
|
-
return True
|
|
26
|
-
except Exception:
|
|
27
|
-
logging.debug("Exception running nvm", exc_info=True)
|
|
28
|
-
return False
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def get_nvmrc_version() -> Optional[str]:
|
|
32
|
-
try:
|
|
33
|
-
with open(".nvmrc", "r") as nvmrc_file:
|
|
34
|
-
return nvmrc_file.readline().strip()
|
|
35
|
-
except IOError:
|
|
36
|
-
logging.debug("Could not read .nvmrc", exc_info=True)
|
|
37
|
-
return None
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
class NodeJsVersion(Check):
|
|
41
|
-
name = "nodejs.version"
|
|
42
|
-
|
|
43
|
-
def __init__(self, required_version: str, recommended_version: Optional[str] = None):
|
|
44
|
-
self.required_version = required_version
|
|
45
|
-
self.recommended_version = recommended_version
|
|
46
|
-
|
|
47
|
-
suggestions = {
|
|
48
|
-
OS.GENERIC: "Install node.js",
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
def check(self) -> CheckResult:
|
|
52
|
-
nodejs_version = get_nodejs_version()
|
|
53
|
-
logging.info(f"node.js version: {nodejs_version}")
|
|
54
|
-
return self.validate_semver_expression(
|
|
55
|
-
"node.js", nodejs_version, self.required_version, self.recommended_version
|
|
56
|
-
)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class NvmInstalled(Check):
|
|
60
|
-
name = "nvm.installed"
|
|
61
|
-
|
|
62
|
-
suggestions = {OS.GENERIC: "Install nvm from: https://nvm.sh"}
|
|
63
|
-
|
|
64
|
-
def check(self) -> CheckResult:
|
|
65
|
-
return self.verify(can_run_nvm(), "nvm is <not/> installed")
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
class NodeJsVersionMatchesNvmrc(Check):
|
|
69
|
-
name = "nodejs.nvmrc.version"
|
|
70
|
-
|
|
71
|
-
suggestions = {
|
|
72
|
-
OS.GENERIC: """
|
|
73
|
-
Run: <cmd>nvm install</cmd> (automatically picks up the right version from .nvmrc)
|
|
74
|
-
Run: <cmd>nvm use</cmd>
|
|
75
|
-
Run: <cmd>nvm alias default <version></cmd> to set the default node version to the newly
|
|
76
|
-
installed one
|
|
77
|
-
"""
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
def check(self) -> CheckResult:
|
|
81
|
-
nvmrc_version = get_nvmrc_version()
|
|
82
|
-
if nvmrc_version is None:
|
|
83
|
-
return self.failed("Missing or invalid .nvmrc file")
|
|
84
|
-
|
|
85
|
-
active_version = get_nodejs_version()
|
|
86
|
-
if active_version is None:
|
|
87
|
-
return self.failed(f'node.js version "{nvmrc_version}" is not installed')
|
|
88
|
-
|
|
89
|
-
if active_version != nvmrc_version:
|
|
90
|
-
return self.failed(f'the active node.js version is {active_version}, "{nvmrc_version}" is required')
|
|
91
|
-
|
|
92
|
-
return self.passed(f"node.js version is {active_version}")
|
daktari/checks/onepassword.py
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import grp
|
|
2
|
-
import json
|
|
3
|
-
import os
|
|
4
|
-
from stat import S_IMODE, S_ISGID
|
|
5
|
-
from typing import Optional
|
|
6
|
-
|
|
7
|
-
from daktari.check import Check, CheckResult
|
|
8
|
-
from daktari.os import OS
|
|
9
|
-
from daktari.command_utils import get_stdout
|
|
10
|
-
from daktari.version_utils import get_simple_cli_version
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class OnePasswordCliInstalled(Check):
|
|
14
|
-
name = "onePasswordCli.installed"
|
|
15
|
-
|
|
16
|
-
def __init__(self, required_version: Optional[str] = None, recommended_version: Optional[str] = None):
|
|
17
|
-
self.required_version = required_version
|
|
18
|
-
self.recommended_version = recommended_version
|
|
19
|
-
self.suggestions = {
|
|
20
|
-
OS.GENERIC: """
|
|
21
|
-
Install the 1Password CLI (op):
|
|
22
|
-
https://support.1password.com/command-line-getting-started/#set-up-the-command-line-tool""",
|
|
23
|
-
OS.OS_X: """
|
|
24
|
-
Use these commands to update 1pass-cli to correct version:
|
|
25
|
-
<cmd>brew tap glean-notes/homebrew-tap git@github.com:glean-notes/homebrew-tap</cmd>
|
|
26
|
-
<cmd>brew reinstall glean-notes/homebrew-tap/1password-cli</cmd>""",
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
def check(self) -> CheckResult:
|
|
30
|
-
installed_version = get_simple_cli_version("op")
|
|
31
|
-
return self.validate_semver_expression(
|
|
32
|
-
"1Password CLI", installed_version, self.required_version, self.recommended_version
|
|
33
|
-
)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
class OnePasswordAccountConfigured(Check):
|
|
37
|
-
depends_on = [OnePasswordCliInstalled]
|
|
38
|
-
name = "onePassword.accountConfigured"
|
|
39
|
-
|
|
40
|
-
def __init__(self, account_shorthand: str):
|
|
41
|
-
self.account_shorthand = account_shorthand
|
|
42
|
-
self.account_url = f"{account_shorthand}.1password.com"
|
|
43
|
-
self.suggestions = {
|
|
44
|
-
OS.GENERIC: f"""
|
|
45
|
-
Use the 1Password desktop app integration: https://developer.1password.com/docs/cli/get-started/#sign-in
|
|
46
|
-
Otherwise:
|
|
47
|
-
<cmd>op signin -f --account {self.account_url}</cmd>""",
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
def check(self) -> CheckResult:
|
|
51
|
-
output = get_stdout("op account list")
|
|
52
|
-
if output is None:
|
|
53
|
-
return self.failed("1Password CLI command failed. Make sure it's installed and configured.")
|
|
54
|
-
|
|
55
|
-
account_present = contains_account(output, self.account_url)
|
|
56
|
-
|
|
57
|
-
if account_present:
|
|
58
|
-
return self.passed(f"{self.account_shorthand} is configured with OP CLI for the current user")
|
|
59
|
-
else:
|
|
60
|
-
return self.failed(f"{self.account_shorthand} is not configured with OP CLI for the current user")
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def contains_account(op_account_list_output: str, account_url: str) -> bool:
|
|
64
|
-
return account_url in op_account_list_output
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
# If not set up, this breaks the integration between cli and desktop app (at least on Ubuntu)
|
|
68
|
-
# https://github.com/NeoHsu/asdf-1password-cli/issues/6#issuecomment-1587502411
|
|
69
|
-
class OnePasswordCliOwnedByCorrectGroup(Check):
|
|
70
|
-
depends_on = [OnePasswordCliInstalled]
|
|
71
|
-
name = "onePasswordCli.ownedByCorrectGroup"
|
|
72
|
-
run_on = OS.UBUNTU
|
|
73
|
-
|
|
74
|
-
def __init__(self):
|
|
75
|
-
self.suggestions = {
|
|
76
|
-
OS.UBUNTU: """
|
|
77
|
-
Ensure the onepassword-cli group exists:
|
|
78
|
-
<cmd>sudo groupadd -f onepassword-cli</cmd>
|
|
79
|
-
Then update the group ownership and set group id when executing:
|
|
80
|
-
<cmd>sudo chgrp onepassword-cli $(asdf which op) && sudo chmod g+s $(asdf which op)</cmd>
|
|
81
|
-
""",
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
def check(self) -> CheckResult:
|
|
85
|
-
op_path = get_stdout(["sh", "-c", "asdf which op"])
|
|
86
|
-
if op_path is None:
|
|
87
|
-
return self.failed("op not found")
|
|
88
|
-
|
|
89
|
-
op_stat = os.stat(op_path)
|
|
90
|
-
group_id = op_stat.st_gid
|
|
91
|
-
group_name = grp.getgrgid(group_id)[0]
|
|
92
|
-
|
|
93
|
-
if group_name != "onepassword-cli":
|
|
94
|
-
return self.failed(f"op group should be onepassword-cli, but was {group_name}")
|
|
95
|
-
|
|
96
|
-
if S_IMODE(op_stat.st_mode) & S_ISGID == 0:
|
|
97
|
-
return self.failed("op does not set groupid when running")
|
|
98
|
-
|
|
99
|
-
return self.passed("op has correct group and sets groupid when running")
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
def account_exists(path: str, account_shorthand: str) -> bool:
|
|
103
|
-
with open(path) as f:
|
|
104
|
-
config = json.load(f)
|
|
105
|
-
return any(account.get("shorthand") == account_shorthand for account in config.get("accounts", []))
|
daktari/checks/python.py
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
from daktari.check import Check, CheckResult
|
|
2
|
-
from daktari.os import OS
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
class PythonInstalled(Check):
|
|
6
|
-
def __init__(self, required_version: int):
|
|
7
|
-
self.required_version = required_version
|
|
8
|
-
self.name = f"python{required_version}.installed"
|
|
9
|
-
self.suggestions = {
|
|
10
|
-
OS.OS_X: f"<cmd>brew install python{required_version}</cmd>",
|
|
11
|
-
OS.UBUNTU: f"<cmd>sudo apt install python{required_version}-dev</cmd>",
|
|
12
|
-
OS.GENERIC: f"Download python {required_version}: https://www.python.org/downloads/",
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
def check(self) -> CheckResult:
|
|
16
|
-
return self.verify_install(f"python{self.required_version}")
|