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/git.py
DELETED
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
from typing import Optional
|
|
3
|
-
|
|
4
|
-
from daktari.check import Check, CheckResult
|
|
5
|
-
from daktari.command_utils import can_run_command, get_stdout
|
|
6
|
-
from daktari.file_utils import file_contains_text, is_ascii
|
|
7
|
-
from daktari.os import OS
|
|
8
|
-
from daktari.version_utils import get_simple_cli_version
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class GitInstalled(Check):
|
|
12
|
-
name = "git.installed"
|
|
13
|
-
|
|
14
|
-
suggestions = {
|
|
15
|
-
OS.OS_X: "<cmd>brew install git</cmd>",
|
|
16
|
-
OS.UBUNTU: "<cmd>sudo apt install git</cmd>",
|
|
17
|
-
OS.GENERIC: "Install Git: https://git-scm.com/downloads",
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
def check(self) -> CheckResult:
|
|
21
|
-
if can_run_command("git version"):
|
|
22
|
-
return self.passed("Git is installed")
|
|
23
|
-
else:
|
|
24
|
-
return self.failed("Could not find git on the path")
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class GitLfsInstalled(Check):
|
|
28
|
-
name = "git.lfs.installed"
|
|
29
|
-
depends_on = [GitInstalled]
|
|
30
|
-
|
|
31
|
-
suggestions = {
|
|
32
|
-
OS.OS_X: "<cmd>brew install git-lfs</cmd>",
|
|
33
|
-
OS.UBUNTU: "<cmd>sudo apt install git-lfs</cmd>",
|
|
34
|
-
OS.GENERIC: "Install Git LFS: https://github.com/git-lfs/git-lfs/wiki/Installation",
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
def check(self) -> CheckResult:
|
|
38
|
-
return self.verify(can_run_command("git lfs version"), "Git LFS is <not/> installed")
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
class GitLfsSetUpForUser(Check):
|
|
42
|
-
name = "git.lfs.setUpForUser"
|
|
43
|
-
depends_on = [GitLfsInstalled]
|
|
44
|
-
|
|
45
|
-
suggestions = {
|
|
46
|
-
OS.GENERIC: """
|
|
47
|
-
Set up Git LFS for your user account:
|
|
48
|
-
<cmd>git lfs install</cmd>
|
|
49
|
-
"""
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
def check(self) -> CheckResult:
|
|
53
|
-
output = get_stdout("git lfs env")
|
|
54
|
-
passed = bool(output and "git-lfs filter-process" in output)
|
|
55
|
-
return self.verify(passed, "Git LFS is <not/> set up for the current user")
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
class GitLfsFilesDownloaded(Check):
|
|
59
|
-
name = "git.lfs.filesDownloaded"
|
|
60
|
-
depends_on = [GitLfsSetUpForUser]
|
|
61
|
-
|
|
62
|
-
suggestions = {
|
|
63
|
-
OS.GENERIC: """
|
|
64
|
-
Download all Git LFS files and update working copy with the downloaded content:
|
|
65
|
-
<cmd>git lfs pull</cmd>
|
|
66
|
-
"""
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
def check(self) -> CheckResult:
|
|
70
|
-
output = get_stdout("git lfs ls-files") or ""
|
|
71
|
-
files_not_downloaded = [line.split()[2] for line in output.splitlines() if line.split()[1] == "-"]
|
|
72
|
-
for file in files_not_downloaded:
|
|
73
|
-
logging.info(f"Git LFS file not downloaded: {file}")
|
|
74
|
-
passed = len(files_not_downloaded) == 0
|
|
75
|
-
return self.verify(passed, "Git LFS files have <not/> been downloaded")
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
class GitCryptInstalled(Check):
|
|
79
|
-
name = "git.crypt.installed"
|
|
80
|
-
depends_on = [GitInstalled]
|
|
81
|
-
|
|
82
|
-
suggestions = {
|
|
83
|
-
OS.OS_X: "<cmd>brew install git-crypt</cmd>",
|
|
84
|
-
OS.UBUNTU: "<cmd>sudo apt install git-crypt</cmd>",
|
|
85
|
-
OS.GENERIC: "Install git-crypt: https://www.agwa.name/projects/git-crypt/",
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
def check(self) -> CheckResult:
|
|
89
|
-
return self.verify(can_run_command("git crypt version"), "git-crypt is <not/> installed")
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
class GitCryptUnlocked(Check):
|
|
93
|
-
name = "git.crypt.unlocked"
|
|
94
|
-
depends_on = [GitCryptInstalled]
|
|
95
|
-
|
|
96
|
-
def __init__(self, fileToCheck: str):
|
|
97
|
-
self.fileToCheck = fileToCheck
|
|
98
|
-
|
|
99
|
-
suggestions = {
|
|
100
|
-
OS.GENERIC: """
|
|
101
|
-
Unlock this repository with:
|
|
102
|
-
<cmd>git-crypt unlock</cmd>
|
|
103
|
-
""",
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
def check(self) -> CheckResult:
|
|
107
|
-
is_unlocked = is_ascii(self.fileToCheck)
|
|
108
|
-
return self.verify(is_unlocked, "Encrypted files have <not/> been unlocked")
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
class PreCommitInstalled(Check):
|
|
112
|
-
name = "preCommit.installed"
|
|
113
|
-
depends_on = [GitInstalled]
|
|
114
|
-
|
|
115
|
-
def __init__(self, required_version: Optional[str] = None, recommended_version: Optional[str] = None):
|
|
116
|
-
self.required_version = required_version
|
|
117
|
-
self.recommended_version = recommended_version
|
|
118
|
-
|
|
119
|
-
suggestions = {
|
|
120
|
-
OS.OS_X: "<cmd>brew install pre-commit</cmd>",
|
|
121
|
-
OS.GENERIC: "Install pre-commit: https://pre-commit.com/#installation",
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
def check(self) -> CheckResult:
|
|
125
|
-
installed_version = get_simple_cli_version("pre-commit")
|
|
126
|
-
return self.validate_semver_expression(
|
|
127
|
-
"pre-commit", installed_version, self.required_version, self.recommended_version
|
|
128
|
-
)
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
class PreCommitGitHooksInstalled(Check):
|
|
132
|
-
name = "preCommit.gitHooksInstalled"
|
|
133
|
-
depends_on = [PreCommitInstalled]
|
|
134
|
-
|
|
135
|
-
suggestions = {
|
|
136
|
-
OS.GENERIC: "<cmd>pre-commit install</cmd>",
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
def check(self) -> CheckResult:
|
|
140
|
-
git_hooks_installed = file_contains_text(".git/hooks/pre-commit", "pre-commit.com")
|
|
141
|
-
return self.verify(git_hooks_installed, "pre-commit Git hooks are <not/> installed")
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
class GpgInstalled(Check):
|
|
145
|
-
name = "gpg.installed"
|
|
146
|
-
|
|
147
|
-
suggestions = {
|
|
148
|
-
OS.OS_X: "<cmd>brew install gpg2 gnupg pinentry-mac</cmd>",
|
|
149
|
-
OS.UBUNTU: "<cmd>sudo apt install gpg</cmd>",
|
|
150
|
-
OS.GENERIC: "Install gpg: https://gnupg.org/",
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
def check(self) -> CheckResult:
|
|
154
|
-
return self.verify_install("gpg")
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
class GitCommitSigningSetUp(Check):
|
|
158
|
-
name = "git.commitSigningSetUp"
|
|
159
|
-
|
|
160
|
-
suggestions = {
|
|
161
|
-
OS.OS_X: "Follow instructions to set up commit signing: "
|
|
162
|
-
"https://gist.github.com/troyfontaine/18c9146295168ee9ca2b30c00bd1b41e#file-2-using-gpg-md",
|
|
163
|
-
OS.UBUNTU: "Follow instructions to set up commit signing: "
|
|
164
|
-
"https://brain2life.hashnode.dev/how-to-sign-your-git-commits-in-ubuntu-2004-and-why-you-need-it",
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
def check(self) -> CheckResult:
|
|
168
|
-
key = get_stdout("git config user.signingkey")
|
|
169
|
-
passed = key is not None and key != ""
|
|
170
|
-
return self.verify(passed, "user.signingkey is <not/> set")
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
class GitCommitAutoSigningEnabled(Check):
|
|
174
|
-
name = "git.commitAutoSigningEnabled"
|
|
175
|
-
depends_on = [GitCommitSigningSetUp]
|
|
176
|
-
|
|
177
|
-
suggestions = {OS.GENERIC: "<cmd>git config commit.gpgsign true</cmd>"}
|
|
178
|
-
|
|
179
|
-
def check(self) -> CheckResult:
|
|
180
|
-
setting = get_stdout("git config commit.gpgsign")
|
|
181
|
-
passed = setting == "true"
|
|
182
|
-
return self.verify(passed, "commit.gpgsign is <not/> enabled")
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
class GitCommitSigningFormat(Check):
|
|
186
|
-
name = "git.commitSigningFormat"
|
|
187
|
-
|
|
188
|
-
def __init__(self, required_format: str, suggestion: str):
|
|
189
|
-
self.required_format = required_format
|
|
190
|
-
self.suggestions = {OS.GENERIC: suggestion}
|
|
191
|
-
|
|
192
|
-
def check(self) -> CheckResult:
|
|
193
|
-
format_setting = get_stdout("git config gpg.format")
|
|
194
|
-
return self.verify(
|
|
195
|
-
format_setting == self.required_format,
|
|
196
|
-
f"gpg.format is {self.required_format}",
|
|
197
|
-
f"gpg.format is not {self.required_format}: {format_setting}",
|
|
198
|
-
)
|
daktari/checks/google.py
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import logging
|
|
3
|
-
import os.path
|
|
4
|
-
from json import JSONDecodeError
|
|
5
|
-
from typing import Optional
|
|
6
|
-
|
|
7
|
-
from daktari.check import Check, CheckResult
|
|
8
|
-
from daktari.command_utils import can_run_command
|
|
9
|
-
from daktari.file_utils import file_exists
|
|
10
|
-
from daktari.os import OS
|
|
11
|
-
from daktari.version_utils import get_simple_cli_version
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class GoogleCloudSdkInstalled(Check):
|
|
15
|
-
name = "google.cloudSdkInstalled"
|
|
16
|
-
|
|
17
|
-
suggestions = {
|
|
18
|
-
OS.OS_X: """<cmd>brew install --cask google-cloud-sdk</cmd>
|
|
19
|
-
|
|
20
|
-
Then, add the gcloud components to your PATH.
|
|
21
|
-
|
|
22
|
-
For bash users, add this to ~/.bashrc:
|
|
23
|
-
source "$(brew --prefix)/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/path.bash.inc"
|
|
24
|
-
|
|
25
|
-
For zsh users, add this to ~/.zhsrc:
|
|
26
|
-
source "$(brew --prefix)/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/path.zsh.inc\" """,
|
|
27
|
-
OS.UBUNTU: "<cmd>sudo snap install google-cloud-sdk --classic</cmd>",
|
|
28
|
-
OS.GENERIC: "Install gcloud: https://cloud.google.com/sdk/docs/quickstart",
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
def check(self) -> CheckResult:
|
|
32
|
-
return self.verify(can_run_command("gcloud --version"), "Google Cloud SDK is <not/> installed and on $PATH")
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
class CloudSqlProxyInstalled(Check):
|
|
36
|
-
name = "google.cloudSqlProxyInstalled"
|
|
37
|
-
|
|
38
|
-
def __init__(self, required_version: Optional[str] = None, recommended_version: Optional[str] = None):
|
|
39
|
-
self.required_version = required_version
|
|
40
|
-
self.recommended_version = recommended_version
|
|
41
|
-
|
|
42
|
-
suggestions = {
|
|
43
|
-
OS.GENERIC: "Install Cloud SQL Proxy: <cmd>gcloud components install cloud_sql_proxy</cmd>",
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
def check(self) -> CheckResult:
|
|
47
|
-
installed_version = get_simple_cli_version("cloud_sql_proxy")
|
|
48
|
-
return self.validate_semver_expression(
|
|
49
|
-
"cloud_sql_proxy", installed_version, self.required_version, self.recommended_version
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
class GkeGcloudAuthPluginInstalled(Check):
|
|
54
|
-
name = "google.gkeGcloudAuthPluginInstalled"
|
|
55
|
-
depends_on = [GoogleCloudSdkInstalled]
|
|
56
|
-
|
|
57
|
-
suggestions = {
|
|
58
|
-
OS.UBUNTU: "<cmd>sudo apt-get install google-cloud-sdk-gke-gcloud-auth-plugin</cmd>",
|
|
59
|
-
OS.GENERIC: "<cmd>gcloud components install gke-gcloud-auth-plugin</cmd>",
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
def check(self) -> CheckResult:
|
|
63
|
-
return self.verify(can_run_command("gke-gcloud-auth-plugin --version "), "GKE auth plugin is <not/> installed")
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
class DockerGoogleCloudAuthConfigured(Check):
|
|
67
|
-
name = "google.dockerGCloudAuthConfigured"
|
|
68
|
-
depends_on = [GoogleCloudSdkInstalled]
|
|
69
|
-
|
|
70
|
-
def __init__(self, cloud_project, region, registry):
|
|
71
|
-
self.registry = registry
|
|
72
|
-
self.suggestions = {
|
|
73
|
-
OS.GENERIC: f"""
|
|
74
|
-
Setup gcloud authentication and docker credential helper for gcloud.
|
|
75
|
-
The following commands will open your browser and ask you to login and approve.
|
|
76
|
-
Run:
|
|
77
|
-
<cmd>rm -r ~/.config/gcloud</cmd>
|
|
78
|
-
<cmd>gcloud auth login</cmd>
|
|
79
|
-
<cmd>gcloud config set project {cloud_project}</cmd>
|
|
80
|
-
<cmd>gcloud config set --quiet compute/zone {region}</cmd>
|
|
81
|
-
<cmd>gcloud auth application-default login</cmd>
|
|
82
|
-
<cmd>gcloud auth configure-docker {registry}</cmd>
|
|
83
|
-
"""
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
def check(self) -> CheckResult:
|
|
87
|
-
# Logged in with gcloud
|
|
88
|
-
google_config_path = os.path.expanduser("~/.config/gcloud/application_default_credentials.json")
|
|
89
|
-
if not file_exists(google_config_path):
|
|
90
|
-
return self.failed(f"{google_config_path} does not exist")
|
|
91
|
-
|
|
92
|
-
if not can_run_command("gcloud auth application-default print-access-token"):
|
|
93
|
-
return self.failed("Application Default Credentials are not correctly set up")
|
|
94
|
-
|
|
95
|
-
# Docker configured correctly
|
|
96
|
-
docker_config_path = os.path.expanduser("~/.docker/config.json")
|
|
97
|
-
if not file_exists(docker_config_path):
|
|
98
|
-
return self.failed(f"{docker_config_path} does not exist")
|
|
99
|
-
|
|
100
|
-
try:
|
|
101
|
-
with open(docker_config_path, "rb") as docker_config_file:
|
|
102
|
-
docker_config = json.load(docker_config_file)
|
|
103
|
-
except IOError:
|
|
104
|
-
logging.error(f"Exception reading {docker_config_path}", exc_info=True)
|
|
105
|
-
return self.failed(f"Failed to read {docker_config_path}")
|
|
106
|
-
except JSONDecodeError:
|
|
107
|
-
logging.error(f"Exception parsing {docker_config_path}", exc_info=True)
|
|
108
|
-
return self.failed(f"Failed to parse {docker_config_path}")
|
|
109
|
-
|
|
110
|
-
if docker_config.get("credHelpers", {}).get(self.registry) != "gcloud":
|
|
111
|
-
return self.failed("docker gcloud auth for {self.registry} not configured")
|
|
112
|
-
|
|
113
|
-
return self.passed("docker gcloud auth configured")
|
daktari/checks/intellij_idea.py
DELETED
|
@@ -1,248 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import logging
|
|
3
|
-
import os
|
|
4
|
-
from json.decoder import JSONDecodeError
|
|
5
|
-
from pathlib import Path
|
|
6
|
-
from typing import Optional
|
|
7
|
-
from xml.etree.ElementTree import Element
|
|
8
|
-
|
|
9
|
-
import dpath.util
|
|
10
|
-
from semver import VersionInfo
|
|
11
|
-
|
|
12
|
-
from daktari.check import Check, CheckResult
|
|
13
|
-
from daktari.checks.files import FilesExist
|
|
14
|
-
from daktari.checks.xml import XmlFileXPathCheck
|
|
15
|
-
from daktari.command_utils import get_stdout
|
|
16
|
-
from daktari.os import OS, detect_os
|
|
17
|
-
from daktari.version_utils import try_parse_semver, sanitise_version_string
|
|
18
|
-
|
|
19
|
-
BUNDLE_ID_INTELLIJ_IDEA = "com.jetbrains.intellij"
|
|
20
|
-
BUNDLE_ID_INTELLIJ_IDEA_CE = "com.jetbrains.intellij.ce"
|
|
21
|
-
|
|
22
|
-
SNAP_NAME_INTELLIJ_IDEA = "intellij-idea-ultimate"
|
|
23
|
-
SNAP_NAME_INTELLIJ_IDEA_CE = "intellij-idea-community"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def locate_intellij_idea_mac():
|
|
27
|
-
from AppKit import NSWorkspace
|
|
28
|
-
|
|
29
|
-
for bundle_id in (BUNDLE_ID_INTELLIJ_IDEA, BUNDLE_ID_INTELLIJ_IDEA_CE):
|
|
30
|
-
url = NSWorkspace.sharedWorkspace().URLForApplicationWithBundleIdentifier_(bundle_id)
|
|
31
|
-
if url is not None:
|
|
32
|
-
logging.debug(f"IntelliJ IDEA location (via NSWorkspace): {url}")
|
|
33
|
-
return url
|
|
34
|
-
|
|
35
|
-
logging.debug("Could not find IntelliJ IDEA (via NSWorkspace)")
|
|
36
|
-
return None
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def get_intellij_idea_version_mac() -> Optional[VersionInfo]:
|
|
40
|
-
intellij_url = locate_intellij_idea_mac()
|
|
41
|
-
if intellij_url is None:
|
|
42
|
-
return None
|
|
43
|
-
else:
|
|
44
|
-
from Foundation import NSBundle
|
|
45
|
-
|
|
46
|
-
version_str = NSBundle.bundleWithURL_(intellij_url).objectForInfoDictionaryKey_("CFBundleShortVersionString")
|
|
47
|
-
|
|
48
|
-
version_str = sanitise_version_string(version_str)
|
|
49
|
-
version = try_parse_semver(version_str)
|
|
50
|
-
|
|
51
|
-
logging.debug(f"IntelliJ IDEA version (via NSBundle): {version} ({version_str})")
|
|
52
|
-
return version
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
def get_intellij_idea_version_snap() -> Optional[VersionInfo]:
|
|
56
|
-
if not Path("/run/snapd.socket").is_socket():
|
|
57
|
-
logging.debug("/run/snapd.socket does not exist, not querying snapd")
|
|
58
|
-
return None
|
|
59
|
-
|
|
60
|
-
from requests_unixsocket import Session
|
|
61
|
-
|
|
62
|
-
session = Session()
|
|
63
|
-
snaps_req = session.get(
|
|
64
|
-
f"http+unix://%2Frun%2Fsnapd.socket/v2/snaps?snaps={SNAP_NAME_INTELLIJ_IDEA},{SNAP_NAME_INTELLIJ_IDEA_CE}"
|
|
65
|
-
)
|
|
66
|
-
snaps_info = snaps_req.json()
|
|
67
|
-
logging.debug(f"response from snapd: {snaps_info}")
|
|
68
|
-
version_str = dpath.util.get(snaps_info, "/result/0/version", default=None)
|
|
69
|
-
logging.debug(f"raw snapd version: {version_str}")
|
|
70
|
-
if not isinstance(version_str, str):
|
|
71
|
-
return None
|
|
72
|
-
version_str = sanitise_version_string(version_str)
|
|
73
|
-
|
|
74
|
-
version = try_parse_semver(version_str)
|
|
75
|
-
logging.debug(f"IntelliJ IDEA version (via snapd): {version}")
|
|
76
|
-
return version
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def get_intellij_idea_version_tarball() -> Optional[VersionInfo]:
|
|
80
|
-
idea_bin_path = get_stdout(["sh", "-c", "which idea.sh"])
|
|
81
|
-
if idea_bin_path is None:
|
|
82
|
-
return None
|
|
83
|
-
|
|
84
|
-
product_info_path = os.path.join(os.path.dirname(idea_bin_path), "..", "product-info.json")
|
|
85
|
-
return get_intellij_version_from_product_info(product_info_path)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def get_intellij_idea_toolbox_version() -> Optional[VersionInfo]:
|
|
89
|
-
idea_bin_path = get_stdout(["sh", "-c", "which idea"])
|
|
90
|
-
if idea_bin_path is None:
|
|
91
|
-
return None
|
|
92
|
-
|
|
93
|
-
apps_dir = os.path.join(os.path.dirname(idea_bin_path), "..", "apps")
|
|
94
|
-
toolbox_apps = os.listdir(apps_dir)
|
|
95
|
-
logging.debug(f"Toolbox apps found: {toolbox_apps}", exc_info=True)
|
|
96
|
-
intellij_installs = [app for app in toolbox_apps if "intellij-idea" in app]
|
|
97
|
-
if len(intellij_installs) == 0:
|
|
98
|
-
logging.debug("No IntelliJ IDEA installs found")
|
|
99
|
-
return None
|
|
100
|
-
|
|
101
|
-
product_info_path = os.path.join(apps_dir, intellij_installs[0], "product-info.json")
|
|
102
|
-
return get_intellij_version_from_product_info(product_info_path)
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
def get_intellij_version_from_product_info(product_info_path: str) -> Optional[VersionInfo]:
|
|
106
|
-
try:
|
|
107
|
-
with open(product_info_path, "rb") as product_info_file:
|
|
108
|
-
product_info = json.load(product_info_file)
|
|
109
|
-
except IOError:
|
|
110
|
-
logging.debug("Failed to read IntelliJ IDEA product-info.json", exc_info=True)
|
|
111
|
-
return None
|
|
112
|
-
except JSONDecodeError:
|
|
113
|
-
logging.debug("Failed to parse IntelliJ IDEA product-info.json", exc_info=True)
|
|
114
|
-
return None
|
|
115
|
-
|
|
116
|
-
version_str = product_info.get("version", None)
|
|
117
|
-
version = try_parse_semver(version_str)
|
|
118
|
-
logging.debug(f"IntelliJ IDEA version (via product-info.json): {version}")
|
|
119
|
-
return version
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
def get_intellij_idea_version() -> Optional[VersionInfo]:
|
|
123
|
-
os = detect_os()
|
|
124
|
-
if os == OS.OS_X:
|
|
125
|
-
return get_intellij_idea_version_mac()
|
|
126
|
-
elif os == OS.UBUNTU:
|
|
127
|
-
return (
|
|
128
|
-
get_intellij_idea_version_snap()
|
|
129
|
-
or get_intellij_idea_version_tarball()
|
|
130
|
-
or get_intellij_idea_toolbox_version()
|
|
131
|
-
)
|
|
132
|
-
else:
|
|
133
|
-
return get_intellij_idea_version_tarball() or get_intellij_idea_toolbox_version()
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
class IntelliJIdeaInstalled(Check):
|
|
137
|
-
name = "intellij.installed"
|
|
138
|
-
|
|
139
|
-
suggestions = {OS.GENERIC: "Install IntelliJ Ultimate: https://www.jetbrains.com/idea/download/"}
|
|
140
|
-
|
|
141
|
-
def __init__(self, required_version: Optional[str] = None, recommended_version: Optional[str] = None):
|
|
142
|
-
self.required_version = required_version
|
|
143
|
-
self.recommended_version = recommended_version
|
|
144
|
-
|
|
145
|
-
def check(self) -> CheckResult:
|
|
146
|
-
intellij_version = get_intellij_idea_version()
|
|
147
|
-
return self.validate_semver_expression(
|
|
148
|
-
"IntelliJ IDEA", intellij_version, self.required_version, self.recommended_version
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
class IntelliJProjectImported(FilesExist):
|
|
153
|
-
name = "intellij.projectImported"
|
|
154
|
-
file_paths = [".idea/workspace.xml"]
|
|
155
|
-
pass_fail_message = "Project <not/> imported into IntelliJ"
|
|
156
|
-
depends_on = [IntelliJIdeaInstalled]
|
|
157
|
-
suggestions = {
|
|
158
|
-
OS.GENERIC: """
|
|
159
|
-
From the IntelliJ start screen, click 'Open or Import' and choose the repository root directory
|
|
160
|
-
"""
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
class IntelliJNodePackageManagerConfigured(XmlFileXPathCheck):
|
|
165
|
-
name = "intellij.nodePackageManagerConfigured"
|
|
166
|
-
file_path = ".idea/workspace.xml"
|
|
167
|
-
xpath_query = "./component[@name='PropertiesComponent']"
|
|
168
|
-
depends_on = [IntelliJProjectImported]
|
|
169
|
-
|
|
170
|
-
def __init__(self, package_manager_path: str):
|
|
171
|
-
self.package_manager_path = package_manager_path
|
|
172
|
-
self.pass_fail_message = f"IntelliJ package manager has <not/> been set to {package_manager_path}"
|
|
173
|
-
|
|
174
|
-
self.suggestions = {
|
|
175
|
-
OS.GENERIC: f"""
|
|
176
|
-
Follow the steps to configure {self.package_manager_path} as your package manager:
|
|
177
|
-
https://www.jetbrains.com/help/idea/installing-and-removing-external-software-using-node-package-manager.html#ws_npm_yarn_configure_package_manager
|
|
178
|
-
"""
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
def validate_query_result(self, result):
|
|
182
|
-
key_json = None if result is None else json.loads(result.text)
|
|
183
|
-
logging.debug(f"Raw properties json: {key_json}")
|
|
184
|
-
current_package_manager = str(key_json["keyToString"]["nodejs_package_manager_path"])
|
|
185
|
-
logging.debug(f"IntelliJ node package manager set to: {current_package_manager}")
|
|
186
|
-
return current_package_manager.__contains__(self.package_manager_path)
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
class IntelliJTypescriptCompilerPathConfigured(XmlFileXPathCheck):
|
|
190
|
-
name = "intellij.typescriptCompilerPathConfigured"
|
|
191
|
-
file_path = ".idea/compiler.xml"
|
|
192
|
-
xpath_query = "./component[@name='TypeScriptCompiler']/option[@name='typeScriptServiceDirectory']"
|
|
193
|
-
depends_on = [IntelliJProjectImported]
|
|
194
|
-
|
|
195
|
-
def __init__(self, typescript_compiler_path: str):
|
|
196
|
-
self.typescript_compiler_path = typescript_compiler_path
|
|
197
|
-
resolved_path = typescript_compiler_path.replace("$PROJECT_DIR$", os.getcwd())
|
|
198
|
-
self.pass_fail_message = f"IntelliJ typescript compiler path has <not/> been set to {resolved_path}"
|
|
199
|
-
|
|
200
|
-
self.suggestions = {
|
|
201
|
-
OS.GENERIC: f"""
|
|
202
|
-
Follow the steps to set {resolved_path} as your typescript compiler path:
|
|
203
|
-
https://www.jetbrains.com/help/idea/typescript-support.html#ws_ts_use_ts_service_checkbox
|
|
204
|
-
"""
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
def validate_query_result(self, result):
|
|
208
|
-
if result is None:
|
|
209
|
-
self.pass_fail_message = "IntelliJ typescript compiler path is <not/> set"
|
|
210
|
-
return False
|
|
211
|
-
current_typescript_compiler_path = result.get("value")
|
|
212
|
-
logging.debug(f"IntelliJ typescript compiler set to: {current_typescript_compiler_path}")
|
|
213
|
-
return current_typescript_compiler_path == self.typescript_compiler_path
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
class IntelliJProjectSdkJavaVersion(XmlFileXPathCheck):
|
|
217
|
-
name = "intellij.jdkVersionConfigured"
|
|
218
|
-
file_path = ".idea/misc.xml"
|
|
219
|
-
xpath_query = "./component[@name='ProjectRootManager']"
|
|
220
|
-
depends_on = [IntelliJProjectImported]
|
|
221
|
-
|
|
222
|
-
def __init__(self, jdk_version: int):
|
|
223
|
-
self.jdk_version = jdk_version
|
|
224
|
-
|
|
225
|
-
self.suggestions = {
|
|
226
|
-
OS.GENERIC: f"""
|
|
227
|
-
Follow the steps to configure JDK {jdk_version}:
|
|
228
|
-
https://www.jetbrains.com/help/idea/sdk.html#change-project-sdk
|
|
229
|
-
"""
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
def validate_query_result(self, result: Optional[Element]):
|
|
233
|
-
if result is None:
|
|
234
|
-
self.pass_fail_message = "IntelliJ Project SDK is not set"
|
|
235
|
-
return False
|
|
236
|
-
|
|
237
|
-
try:
|
|
238
|
-
jdk_type = result.attrib["project-jdk-type"]
|
|
239
|
-
if jdk_type != "JavaSDK":
|
|
240
|
-
self.pass_fail_message = f"IntelliJ Project SDK is not a Java JDK: {jdk_type}"
|
|
241
|
-
return False
|
|
242
|
-
except KeyError:
|
|
243
|
-
self.pass_fail_message = "IntelliJ Project SDK is not a Java JDK"
|
|
244
|
-
return False
|
|
245
|
-
|
|
246
|
-
language_level = result.attrib["languageLevel"]
|
|
247
|
-
self.pass_fail_message = f"IntelliJ Project SDK is <not/> set to Java {self.jdk_version}: {language_level}"
|
|
248
|
-
return language_level == f"JDK_{self.jdk_version}"
|
daktari/checks/java.py
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
import re
|
|
3
|
-
from typing import Optional
|
|
4
|
-
|
|
5
|
-
from semver import VersionInfo
|
|
6
|
-
|
|
7
|
-
from daktari.check import Check, CheckResult
|
|
8
|
-
from daktari.command_utils import get_stderr, run_command
|
|
9
|
-
from daktari.os import OS
|
|
10
|
-
|
|
11
|
-
java_version_pattern = re.compile('^.*version "(.*?)".*$', re.MULTILINE)
|
|
12
|
-
javac_version_pattern = re.compile("^javac (.*)$", re.MULTILINE)
|
|
13
|
-
|
|
14
|
-
one_dot_pattern = re.compile("1\\.([0-9]+)")
|
|
15
|
-
other_pattern = re.compile("([0-9]+)")
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def get_java_version() -> Optional[VersionInfo]:
|
|
19
|
-
version_output = get_stderr("java -version")
|
|
20
|
-
return parse_java_version_output(version_output)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def get_jdk_version() -> Optional[VersionInfo]:
|
|
24
|
-
try:
|
|
25
|
-
version_output = run_command("javac -version")
|
|
26
|
-
except Exception:
|
|
27
|
-
return None
|
|
28
|
-
|
|
29
|
-
return parse_javac_version_output(version_output.stdout + version_output.stderr)
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
def parse_java_version_output(version_output: Optional[str]) -> Optional[VersionInfo]:
|
|
33
|
-
if version_output:
|
|
34
|
-
match = java_version_pattern.search(version_output)
|
|
35
|
-
if match:
|
|
36
|
-
version_string = match.group(1)
|
|
37
|
-
logging.debug(f"Java version string: {version_string}")
|
|
38
|
-
return parse_java_version_string(version_string)
|
|
39
|
-
return None
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def parse_javac_version_output(version_output: Optional[str]) -> Optional[VersionInfo]:
|
|
43
|
-
if version_output:
|
|
44
|
-
match = javac_version_pattern.search(version_output)
|
|
45
|
-
if match:
|
|
46
|
-
version_string = match.group(1)
|
|
47
|
-
logging.debug(f"JDK version string: {version_string}")
|
|
48
|
-
return parse_java_version_string(version_string)
|
|
49
|
-
return None
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
def parse_java_version_string(version_string: str) -> Optional[VersionInfo]:
|
|
53
|
-
try:
|
|
54
|
-
return VersionInfo.parse(version_string)
|
|
55
|
-
except ValueError:
|
|
56
|
-
return parse_alternative_java_version_numbers(version_string)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
def parse_alternative_java_version_numbers(version_string: str) -> Optional[VersionInfo]:
|
|
60
|
-
one_dot_match = one_dot_pattern.search(version_string)
|
|
61
|
-
if one_dot_match:
|
|
62
|
-
return VersionInfo(int(one_dot_match.group(1)))
|
|
63
|
-
other_pattern_match = other_pattern.search(version_string)
|
|
64
|
-
if other_pattern_match:
|
|
65
|
-
return VersionInfo(int(other_pattern_match.group(1)))
|
|
66
|
-
return None
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
class JavaVersion(Check):
|
|
70
|
-
name = "java.version"
|
|
71
|
-
|
|
72
|
-
def __init__(
|
|
73
|
-
self,
|
|
74
|
-
required_version: Optional[str] = None,
|
|
75
|
-
recommended_version: Optional[str] = None,
|
|
76
|
-
java_instructions: Optional[str] = None,
|
|
77
|
-
):
|
|
78
|
-
self.required_version = required_version
|
|
79
|
-
self.recommended_version = recommended_version
|
|
80
|
-
|
|
81
|
-
java_instructions = f"\n\n{java_instructions}" if java_instructions else ""
|
|
82
|
-
self.suggestions = {OS.GENERIC: f"""Install Java{java_instructions}"""}
|
|
83
|
-
|
|
84
|
-
def check(self) -> CheckResult:
|
|
85
|
-
java_version = get_java_version()
|
|
86
|
-
logging.info(f"Java version: {java_version}")
|
|
87
|
-
return self.validate_semver_expression("Java", java_version, self.required_version, self.recommended_version)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
class JdkVersion(Check):
|
|
91
|
-
name = "jdk.version"
|
|
92
|
-
|
|
93
|
-
def __init__(self, required_version: str, recommended_version: Optional[str] = None):
|
|
94
|
-
self.required_version = required_version
|
|
95
|
-
self.recommended_version = recommended_version
|
|
96
|
-
|
|
97
|
-
suggestions = {
|
|
98
|
-
OS.GENERIC: "Install Java JDK",
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
def check(self) -> CheckResult:
|
|
102
|
-
jdk_version = get_jdk_version()
|
|
103
|
-
logging.info(f"JDK version: {jdk_version}")
|
|
104
|
-
return self.validate_semver_expression("JDK", jdk_version, self.required_version, self.recommended_version)
|