|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* This file is part of the Gerrie package. |
|
4
|
|
|
* |
|
5
|
|
|
* (c) Andreas Grunwald <[email protected]> |
|
6
|
|
|
* |
|
7
|
|
|
* For the full copyright and license information, please view the LICENSE |
|
8
|
|
|
* file that was distributed with this source code. |
|
9
|
|
|
*/ |
|
10
|
|
|
|
|
11
|
|
|
namespace Gerrie\Command; |
|
12
|
|
|
|
|
13
|
|
|
use Gerrie\Check\APIConnectionCheck; |
|
14
|
|
|
use Gerrie\Check\ConfigurationValidationCheck; |
|
15
|
|
|
use Gerrie\Check\CurlExtensionCheck; |
|
16
|
|
|
use Gerrie\Check\ConfigFileCheck; |
|
17
|
|
|
use Gerrie\Check\PDOMySqlExtensionCheck; |
|
18
|
|
|
use Gerrie\Check\SSHCheck; |
|
19
|
|
|
use Gerrie\Check\CheckInterface; |
|
20
|
|
|
use Gerrie\Check\DatabaseConnectionCheck; |
|
21
|
|
|
use Gerrie\Component\Configuration\ConfigurationFactory; |
|
22
|
|
|
use Gerrie\Component\Console\InputExtendedInterface; |
|
23
|
|
|
use Gerrie\Component\Database\Database; |
|
24
|
|
|
use Gerrie\API\DataService\DataServiceFactory; |
|
25
|
|
|
use Symfony\Component\Console\Input\InputInterface; |
|
26
|
|
|
use Symfony\Component\Console\Output\OutputInterface; |
|
27
|
|
|
|
|
28
|
|
|
/** |
|
29
|
|
|
* TODO Add -v / -vv / -vvv to output error messages in second line |
|
30
|
|
|
* TODO Add link to documentation if the "Oh dear" / fail message will be output |
|
31
|
|
|
* |
|
32
|
|
|
*/ |
|
33
|
|
|
|
|
34
|
|
|
class CheckCommand extends GerrieBaseCommand |
|
35
|
|
|
{ |
|
36
|
|
|
/** |
|
37
|
|
|
* OK sign from unicode table |
|
38
|
|
|
* |
|
39
|
|
|
* @link http://apps.timwhitlock.info/emoji/tables/unicode |
|
40
|
|
|
* @var string |
|
41
|
|
|
*/ |
|
42
|
|
|
const EMOJI_OK = "\xE2\x9C\x85"; |
|
43
|
|
|
|
|
44
|
|
|
/** |
|
45
|
|
|
* Failure sign from unicode table |
|
46
|
|
|
* |
|
47
|
|
|
* @link http://apps.timwhitlock.info/emoji/tables/unicode |
|
48
|
|
|
* @var string |
|
49
|
|
|
*/ |
|
50
|
|
|
const EMOJI_FAILURE = "\xE2\x9D\x8C"; |
|
51
|
|
|
|
|
52
|
|
|
/** |
|
53
|
|
|
* Question mark sign from unicode table |
|
54
|
|
|
* |
|
55
|
|
|
* @link http://apps.timwhitlock.info/emoji/tables/unicode |
|
56
|
|
|
* @var string |
|
57
|
|
|
*/ |
|
58
|
|
|
const EMOJI_OPTIONAL = "\xE2\x9D\x93"; |
|
59
|
|
|
|
|
60
|
|
|
/** |
|
61
|
|
|
* Stores the overall result of all checks. |
|
62
|
|
|
* |
|
63
|
|
|
* @var bool |
|
64
|
|
|
*/ |
|
65
|
|
|
private $overallResult = true; |
|
66
|
|
|
|
|
67
|
|
|
protected function configure() |
|
68
|
|
|
{ |
|
69
|
|
|
$this |
|
70
|
|
|
->setName('gerrie:check') |
|
71
|
|
|
->setDescription('Checks if the setup is working'); |
|
72
|
|
|
$this->addConfigFileOption(); |
|
73
|
|
|
$this->addDatabaseOptions(); |
|
74
|
|
|
$this->addSSHKeyOption(); |
|
75
|
|
|
$this->addInstancesArgument(); |
|
76
|
|
|
} |
|
77
|
|
|
|
|
78
|
|
|
protected function execute(InputInterface $input, OutputInterface $output) |
|
79
|
|
|
{ |
|
80
|
|
|
/** @var InputExtendedInterface $input */ |
|
81
|
|
|
|
|
82
|
|
|
/** |
|
83
|
|
|
* Welcome message |
|
84
|
|
|
*/ |
|
85
|
|
|
// Run gerrie:create-database-Command |
|
86
|
|
|
$output->writeln('<info>Gerrie will check if the current setup will work as expected.</info>'); |
|
87
|
|
|
$output->writeln('<info>Lets start!</info>'); |
|
88
|
|
|
|
|
89
|
|
|
/** |
|
90
|
|
|
* Start checking |
|
91
|
|
|
*/ |
|
92
|
|
|
$output->writeln(''); |
|
93
|
|
|
$output->writeln('<comment>System:</comment>'); |
|
94
|
|
|
|
|
95
|
|
|
// Check if curl is installed |
|
96
|
|
|
$curlCheck = new CurlExtensionCheck(); |
|
97
|
|
|
$this->checkProperty($output, $curlCheck); |
|
98
|
|
|
|
|
99
|
|
|
// Check if PDO and MySQL are installed |
|
100
|
|
|
$pdoCheck = new PDOMySqlExtensionCheck(); |
|
101
|
|
|
$this->checkProperty($output, $pdoCheck); |
|
102
|
|
|
|
|
103
|
|
|
// Check if SSH is installed |
|
104
|
|
|
$sshCheck = new SSHCheck(); |
|
105
|
|
|
$this->checkProperty($output, $sshCheck); |
|
106
|
|
|
|
|
107
|
|
|
$output->writeln(''); |
|
108
|
|
|
$output->writeln('<comment>Configuration:</comment>'); |
|
109
|
|
|
|
|
110
|
|
|
// Check if the config file exists |
|
111
|
|
|
$configFileCheck = new ConfigFileCheck($input->getOption('config-file')); |
|
112
|
|
|
$this->checkProperty($output, $configFileCheck); |
|
113
|
|
|
|
|
114
|
|
|
// Check if the config file is valid |
|
115
|
|
|
$configFile = $input->getOption('config-file'); |
|
116
|
|
|
$configuration = ConfigurationFactory::getConfigurationByConfigFileAndCommandOptionsAndArguments($configFile, $input); |
|
|
|
|
|
|
117
|
|
|
|
|
118
|
|
|
$configurationValidationCheck = new ConfigurationValidationCheck($configuration); |
|
119
|
|
|
$this->checkProperty($output, $configurationValidationCheck); |
|
120
|
|
|
|
|
121
|
|
|
$output->writeln(''); |
|
122
|
|
|
$output->writeln('<comment>Connection:</comment>'); |
|
123
|
|
|
|
|
124
|
|
|
// Check database connection |
|
125
|
|
|
$databaseConfig = $configuration->getConfigurationValue('Database'); |
|
126
|
|
|
$database = new Database($databaseConfig, false); |
|
127
|
|
|
|
|
128
|
|
|
$databaseConnectionCheck = new DatabaseConnectionCheck($database); |
|
129
|
|
|
$this->checkProperty($output, $databaseConnectionCheck); |
|
130
|
|
|
|
|
131
|
|
|
// TODO Refactor this. This is copy / paste from CrawlCommand |
|
132
|
|
|
$gerritSystems = $configuration->getConfigurationValue('Gerrit'); |
|
133
|
|
|
$defaultSSHKeyFile = $configuration->getConfigurationValue('SSH.KeyFile'); |
|
134
|
|
|
|
|
135
|
|
|
foreach ($gerritSystems as $name => $gerrieProject) { |
|
136
|
|
|
|
|
137
|
|
|
foreach ($gerrieProject as $gerritInstance) { |
|
138
|
|
|
// Get instance url |
|
139
|
|
|
// If the instance is a string, we only got a url path like scheme://user@url:port/ |
|
140
|
|
|
if (is_string($gerritInstance)) { |
|
141
|
|
|
$instanceConfig = [ |
|
142
|
|
|
'Instance' => $gerritInstance, |
|
143
|
|
|
'KeyFile' => $defaultSSHKeyFile |
|
144
|
|
|
]; |
|
145
|
|
|
|
|
146
|
|
|
// If the instance is an array, we get a key => value structure with an Instance key |
|
147
|
|
|
} elseif (is_array($gerritInstance) && isset($gerritInstance['Instance'])) { |
|
148
|
|
|
$instanceConfig = [ |
|
149
|
|
|
'Instance' => $gerritInstance['Instance'], |
|
150
|
|
|
'KeyFile' => $defaultSSHKeyFile |
|
151
|
|
|
]; |
|
152
|
|
|
|
|
153
|
|
|
if (array_key_exists('KeyFile', $gerritInstance) === true) { |
|
154
|
|
|
$instanceConfig['KeyFile'] = $gerritInstance['KeyFile']; |
|
155
|
|
|
} |
|
156
|
|
|
} else { |
|
157
|
|
|
throw new \RuntimeException('No Gerrit instance config given', 1415451921); |
|
158
|
|
|
} |
|
159
|
|
|
|
|
160
|
|
|
$dataService = DataServiceFactory::getDataService($instanceConfig); |
|
161
|
|
|
|
|
162
|
|
|
// Check the API (SSH / HTTP) connection |
|
163
|
|
|
// TODO Authentification |
|
164
|
|
|
$apiConnectionCheck = new APIConnectionCheck($dataService); |
|
165
|
|
|
$this->checkProperty($output, $apiConnectionCheck); |
|
166
|
|
|
} |
|
167
|
|
|
} |
|
168
|
|
|
|
|
169
|
|
|
/** |
|
170
|
|
|
* Message end result |
|
171
|
|
|
*/ |
|
172
|
|
|
if ($this->overallResult === false) { |
|
173
|
|
|
$this->outputFixMessage($output); |
|
174
|
|
|
} else { |
|
175
|
|
|
$this->outputEverythingIsFineAndIWantABeerMessage($output); |
|
176
|
|
|
} |
|
177
|
|
|
} |
|
178
|
|
|
|
|
179
|
|
|
/** |
|
180
|
|
|
* Checks a single property |
|
181
|
|
|
* |
|
182
|
|
|
* @param OutputInterface $output |
|
183
|
|
|
* @param CheckInterface $property |
|
184
|
|
|
* @return bool |
|
185
|
|
|
*/ |
|
186
|
|
|
protected function checkProperty(OutputInterface $output, CheckInterface $property) |
|
187
|
|
|
{ |
|
188
|
|
|
$result = $property->check(); |
|
189
|
|
|
|
|
190
|
|
|
if ($result === false) { |
|
191
|
|
|
$outputLevel = 'error'; |
|
192
|
|
|
$sign = self::EMOJI_FAILURE; |
|
193
|
|
|
|
|
194
|
|
|
if ($property->isOptional() === true) { |
|
195
|
|
|
$outputLevel = 'comment'; |
|
196
|
|
|
$sign = self::EMOJI_OPTIONAL; |
|
197
|
|
|
} |
|
198
|
|
|
|
|
199
|
|
|
$message = $property->getFailureMessage(); |
|
200
|
|
|
|
|
201
|
|
|
// The default value from overallResult is true. |
|
202
|
|
|
// So it is enough to set it to false once. |
|
203
|
|
|
$this->overallResult = false; |
|
204
|
|
|
|
|
205
|
|
|
} elseif ($result === true) { |
|
206
|
|
|
$outputLevel = 'info'; |
|
207
|
|
|
$sign = self::EMOJI_OK; |
|
208
|
|
|
$message = $property->getSuccessMessage(); |
|
209
|
|
|
} |
|
210
|
|
|
|
|
211
|
|
|
$outputMessage = " <info>%s</info> <%s>%s</%s>"; |
|
212
|
|
|
$outputMessage = sprintf($outputMessage, $sign, $outputLevel, $message, $outputLevel); |
|
|
|
|
|
|
213
|
|
|
$output->writeln($outputMessage); |
|
214
|
|
|
|
|
215
|
|
|
return $result; |
|
216
|
|
|
} |
|
217
|
|
|
|
|
218
|
|
|
/** |
|
219
|
|
|
* If minimum one check fails (optional or not does not matter), this message will be outputted. |
|
220
|
|
|
* |
|
221
|
|
|
* @param OutputInterface $output |
|
222
|
|
|
* @return void |
|
223
|
|
|
*/ |
|
224
|
|
|
protected function outputFixMessage(OutputInterface $output) |
|
225
|
|
|
{ |
|
226
|
|
|
$output->writeln(''); |
|
227
|
|
|
$output->writeln("<error> Oh dear \xF0\x9F\x98\xA2 </error>"); |
|
228
|
|
|
$output->writeln(''); |
|
229
|
|
|
$output->writeln("<info>Sadly, not all checks went well</info>"); |
|
230
|
|
|
$output->writeln('<info>But this is no reason to give up!</info>'); |
|
231
|
|
|
$output->writeln('<info>Remember: This check was to verifiy if Gerrie is working to avoid unnecessary problems.</info>'); |
|
232
|
|
|
$output->writeln("<info>So get up, grab a \xE2\x98\x95 and try to fix the failing checks.</info>"); |
|
233
|
|
|
$output->writeln(''); |
|
234
|
|
|
$output->writeln('<info>If you don`t know how to solve this "problem(s)":</info>'); |
|
235
|
|
|
$output->writeln('<info> * have a look at the documentation</info>'); |
|
236
|
|
|
$output->writeln('<info> * or open an issue on GitHub</info>'); |
|
237
|
|
|
$output->writeln(''); |
|
238
|
|
|
$output->writeln('<info>Do not be afraid. You can execute this check whenever you want.</info>'); |
|
239
|
|
|
$output->writeln('<info>It is for free and breaks nothing :)</info>'); |
|
240
|
|
|
$output->writeln("<info>So keep \xF0\x9F\x8E\xB8 and cu next time \xF0\x9F\x91\x8B</info>"); |
|
241
|
|
|
$output->writeln(''); |
|
242
|
|
|
} |
|
243
|
|
|
|
|
244
|
|
|
/** |
|
245
|
|
|
* If everything is fine and all checks went good, this message will be outputted. |
|
246
|
|
|
* |
|
247
|
|
|
* @param OutputInterface $output |
|
248
|
|
|
* @return void |
|
249
|
|
|
*/ |
|
250
|
|
|
protected function outputEverythingIsFineAndIWantABeerMessage(OutputInterface $output) |
|
251
|
|
|
{ |
|
252
|
|
|
$output->writeln(''); |
|
253
|
|
|
$output->writeln("<info>Wow! Everything works fine. Gratulations \xF0\x9F\x8E\x81</info>"); |
|
254
|
|
|
$output->writeln(''); |
|
255
|
|
|
$output->writeln('<info>Now you are ready to use Gerrie with the full featureset. Awesome!</info>'); |
|
256
|
|
|
|
|
257
|
|
|
$message = "<info>Grab a \xF0\x9F\x8D\xBA (better \xF0\x9F\x8D\xBB ) or a \xF0\x9F\x8D\xB7 "; |
|
258
|
|
|
$message .= "and start crawling your Gerrit instances.</info>"; |
|
259
|
|
|
$output->writeln($message); |
|
260
|
|
|
$output->writeln("<info>Have fun \xF0\x9F\x98\x83</info>"); |
|
261
|
|
|
$output->writeln(''); |
|
262
|
|
|
} |
|
263
|
|
|
} |
This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.
Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.