1
|
|
|
<?php |
2
|
|
|
|
3
|
|
|
namespace Spatie\ServerMonitor\Commands; |
4
|
|
|
|
5
|
|
|
use File; |
6
|
|
|
use Illuminate\Database\Eloquent\Collection; |
7
|
|
|
use Spatie\ServerMonitor\Models\Host; |
8
|
|
|
use Spatie\ServerMonitor\Models\Check; |
9
|
|
|
|
10
|
|
|
class SyncFile extends BaseCommand |
11
|
|
|
{ |
12
|
|
|
protected $signature = 'server-monitor:sync-file |
13
|
|
|
{--force-export : Overwrite existing entries in hosts file with database entries} |
14
|
|
|
{--delete-missing : Delete hosts from the database that are not in the hosts file}'; |
15
|
|
|
|
16
|
|
|
protected $description = 'Syncs hosts in file with the database'; |
17
|
|
|
|
18
|
|
|
protected $path; |
19
|
|
|
|
20
|
|
|
protected $filename = 'hosts.json'; |
21
|
|
|
|
22
|
|
|
public function handle() |
23
|
|
|
{ |
24
|
|
|
$this->prepareStorageDirectory(); |
25
|
|
|
|
26
|
|
|
if($this->option('force-export') || ! File::exists($this->getFilepath())) { |
27
|
|
|
$this->exportAll(); |
28
|
|
|
|
29
|
|
|
return; |
30
|
|
|
} |
31
|
|
|
|
32
|
|
|
$hostsInFile = collect(json_decode(File::get($this->getFilepath()), true)); |
33
|
|
|
|
34
|
|
|
$this->updateOrCreateHosts($hostsInFile); |
35
|
|
|
|
36
|
|
|
$this->deleteMissingHosts($hostsInFile); |
37
|
|
|
|
38
|
|
|
$this->writeToFile(Host::all()); |
|
|
|
|
39
|
|
|
} |
40
|
|
|
|
41
|
|
|
protected function getFilepath(): string |
42
|
|
|
{ |
43
|
|
|
return $this->path.DIRECTORY_SEPARATOR.$this->filename; |
44
|
|
|
} |
45
|
|
|
|
46
|
|
|
protected function writeToFile(Collection $hosts) |
47
|
|
|
{ |
48
|
|
|
$json = $hosts |
49
|
|
|
->map(function (Host $host) { |
50
|
|
|
$checks = $host->checks->pluck('type'); |
|
|
|
|
51
|
|
|
$host = collect($host)->only('name', 'ssh_user', 'ip', 'port')->toArray(); |
52
|
|
|
$host['checks'] = $checks; |
53
|
|
|
|
54
|
|
|
return $host; |
55
|
|
|
}) |
56
|
|
|
->toJson(); |
57
|
|
|
|
58
|
|
|
File::put($this->getFilepath(), $json); |
59
|
|
|
} |
60
|
|
|
|
61
|
|
|
protected function prepareStorageDirectory() |
62
|
|
|
{ |
63
|
|
|
$this->path = storage_path('server-monitor'); |
64
|
|
|
|
65
|
|
|
if (!File::exists($this->path)) { |
66
|
|
|
File::makeDirectory($this->path); |
67
|
|
|
} |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
protected function exportAll() |
71
|
|
|
{ |
72
|
|
|
$this->writeToFile(Host::all()); |
|
|
|
|
73
|
|
|
|
74
|
|
|
$this->info('Exported all hosts from database to ' . $this->getFilepath()); |
75
|
|
|
|
76
|
|
|
return; |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
/** |
80
|
|
|
* @param $hostsInFile |
81
|
|
|
*/ |
82
|
|
|
protected function deleteMissingHosts($hostsInFile) |
83
|
|
|
{ |
84
|
|
|
if ($this->option('delete-missing')) { |
85
|
|
|
Host::all()->each(function (Host $host) use ($hostsInFile) { |
86
|
|
|
if (!$hostsInFile->contains('name', $host->name)) { |
|
|
|
|
87
|
|
|
$this->comment("Deleted host '{$host->name}' from database (was not found in hosts file)"); |
|
|
|
|
88
|
|
|
$host->delete(); |
89
|
|
|
} |
90
|
|
|
}); |
91
|
|
|
} |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* @param $hostsInFile |
96
|
|
|
*/ |
97
|
|
|
protected function updateOrCreateHosts($hostsInFile) |
98
|
|
|
{ |
99
|
|
|
$hostsInFile->each(function ($host) { |
100
|
|
|
$host = collect($host); |
101
|
|
|
|
102
|
|
|
$hostModel = Host::firstOrNew(['name' => $host['name']]); |
103
|
|
|
|
104
|
|
|
$hostModel |
105
|
|
|
->fill($host->except('checks')->toArray()) |
106
|
|
|
->save(); |
107
|
|
|
|
108
|
|
|
// Delete checks that were deleted from the file |
109
|
|
|
$hostModel->checks->each(function (Check $check) use ($host) { |
110
|
|
|
if (!in_array($check->type, $host['checks'])) { |
|
|
|
|
111
|
|
|
$this->comment("Deleted '{$check->type}' from host '{$host['name']}' (not found in hosts file)"); |
|
|
|
|
112
|
|
|
$check->delete(); |
113
|
|
|
} |
114
|
|
|
}); |
115
|
|
|
|
116
|
|
|
// Add checks that do not exist in db |
117
|
|
|
foreach ($host['checks'] as $check) { |
118
|
|
|
if ($hostModel->checks->where('type', $check)->count() === 0) { |
119
|
|
|
$hostModel->checks()->create(['type' => $check]); |
120
|
|
|
} |
121
|
|
|
} |
122
|
|
|
}); |
123
|
|
|
|
124
|
|
|
$this->info("Synced {$hostsInFile->count()} host(s) to database"); |
125
|
|
|
} |
126
|
|
|
} |
127
|
|
|
|
This check looks at variables that are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.