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.