Completed
Branch master (6576e0)
by Timur
02:16
created

ForgeServers::handle()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 17
rs 9.2
c 0
b 0
f 0
cc 4
eloc 12
nc 4
nop 1
1
<?php
2
3
namespace Laravel\Forge\Laravel\Commands;
4
5
use Laravel\Forge\Forge;
6
use Illuminate\Support\Str;
7
use Illuminate\Console\Command;
8
use GuzzleHttp\Exception\RequestException;
9
use Laravel\Forge\Servers\Providers\Provider;
10
11
class ForgeServers extends Command
12
{
13
    /**
14
     * The name and signature of the console command.
15
     *
16
     * @var string
17
     */
18
    protected $signature = 'forge:servers';
19
20
    /**
21
     * The console command description.
22
     *
23
     * @var string
24
     */
25
    protected $description = 'Manage Forge Servers';
26
27
    /**
28
     * Execute the console command.
29
     *
30
     * @return mixed
31
     */
32
    public function handle(Forge $forge)
33
    {
34
        $action = $this->choice('What do you want to do?', [
35
            'list' => 'List Servers',
36
            'create' => 'Create New Server',
37
            'delete' => 'Delete Server',
38
        ]);
39
40
        switch ($action) {
41
            case 'list':
42
                return $this->handleListAction($forge);
43
            case 'create':
44
                return $this->handleCreateAction($forge);
45
            case 'delete':
46
                return $this->handleDeleteAction($forge);
47
        }
48
    }
49
50
    /**
51
     * Asks user to choose a server.
52
     *
53
     * @param \Laravel\Forge\Forge $forge
54
     * @param string               $message = 'Choose Server'
55
     *
56
     * @return \Laravel\Forge\Server
57
     */
58
    protected function chooseServer(Forge $forge, string $message = 'Choose Server')
59
    {
60
        $choices = [];
61
62
        foreach ($forge as $server) {
63
            $choices[$server->name()] = $server->id();
64
        }
65
66
        $serverName = $this->choice($message, $choices);
67
68
        return $forge[$serverName];
69
    }
70
71
    /**
72
     * "List Servers" handler.
73
     *
74
     * @param \Laravel\Forge\Forge $forge
75
     *
76
     * @return mixed
77
     */
78
    protected function handleListAction(Forge $forge)
79
    {
80
        $headers = ['ID', 'Name', 'Size', 'Region', 'Ready?', 'PHP Version'];
81
        $rows = [];
82
83
        foreach ($forge as $server) {
84
            $rows[] = [
85
                $server->id(),
86
                $server->name(),
87
                $server->size(),
88
                $server->region(),
89
                $server->isReady() ? 'Yes' : 'No',
90
                $server->phpVersion(),
91
            ];
92
        }
93
94
        $this->info('Here are your servers:');
95
        $this->table($headers, $rows);
96
    }
97
98
    /**
99
     * "Create New Server" handler.
100
     *
101
     * @param \Laravel\Forge\Forge $forge
102
     *
103
     * @return mixed
104
     */
105
    protected function handleCreateAction(Forge $forge)
106
    {
107
        $provider = $this->choice('Choose provider', [
108
            'ocean2' => 'DigitalOcean',
109
            'linode' => 'Linode',
110
            'aws' => 'AWS',
111
            'custom' => 'Custom VPS',
112
        ]);
113
114
        $name = $this->ask('Choose name for your new server');
115
116
        switch ($provider) {
117
            case 'ocean2':
118
                return $this->createServer($forge->create()->droplet($name));
119
            case 'linode':
120
                return $this->createServer($forge->create()->linode($name));
121
            case 'aws':
122
                return $this->createServer($forge->create()->aws($name));
123
            case 'custom':
124
                return $this->createServer($forge->create()->custom($name));
125
        }
126
    }
127
128
    /**
129
     * Create server at specific provider.
130
     *
131
     * @param \Laravel\Forge\Servers\Providers\Provider $provider
132
     *
133
     * @return mixed
134
     */
135
    protected function createServer(Provider $provider)
136
    {
137
        if ($provider->provider() !== 'custom') {
138
            $size = $this->choice('Choose server size', array_keys($provider->sizes()));
139
            $provider->withMemoryOf($size);
140
141
            $regions = $provider->regions();
142
143
            $region = $this->choice('Choose server region', $regions);
144
145
            if ($provider->provider() === 'linode') {
146
                $flippedRegions = array_flip($regions);
147
                $region = $flippedRegions[$region];
148
            }
149
150
            $provider->at($region);
151
        }
152
153
        $phpVersion = $this->choice('Choose PHP version', $provider->phpVersions());
154
        $provider->runningPhp($phpVersion);
155
156
        $databaseName = 'forge';
157
158
        if ($this->confirm('Do you want to set new database name?')) {
159
            $databaseName = $this->ask('Choose database name');
160
        } else {
161
            $this->comment('OK, using default database name ("forge").');
162
        }
163
164
        if ($this->confirm('Do you want to install MariaDb instead of MySQL?')) {
165
            $provider->withMariaDb($databaseName);
166
            $this->comment('OK, MariaDb server will be installed');
167
        } else {
168
            $provider->withMysql($databaseName);
169
            $this->comment('OK, MySQL server will be installed.');
170
        }
171
172
        if ($this->confirm('Do you want to provision this server as load balancer?', false)) {
173
            $provider->asLoadBalancer();
174
            $this->comment('OK, server will be provisioned as load balancer.');
175
        }
176
177
        if ($provider->provider() === 'custom') {
178
            $publicIp = $this->ask('Please, provide public IP address for this VPS');
179
            $privateIp = $this->ask('Please, provide private IP address for this VPS');
180
181
            $provision->usingPublicIp($publicIp)->usingPrivateIp($privateIp);
182
        }
183
184
        $hasCredentials = $provider->hasPayload('credential_id');
185
        $credentialMessage = 'Seems that you\'re using predefined credential. Do you want to change credential for this server?';
186
        $updateCredential = $hasCredentials === false || $this->confirm($credentialMessage, false);
187
188
        if ($updateCredential) {
189
            $credentialId = $this->ask('Enter credential ID');
190
            $provider->usingCredential($credentialId);
191
        } else {
192
            $this->comment('OK, default credential will be used.');
193
        }
194
195
        try {
196
            $server = $provider->save();
197
        } catch (RequestException $e) {
198
            $response = $e->getResponse();
199
200
            $this->error('Request ended with error.');
201
            $this->error('HTTP Status Code: '.$response->getStatusCode());
202
203
            return $this->error((string) $response->getBody());
204
        }
205
206
        $this->info('Great! Your new server "'.$server->name().'" was created!');
207
        $this->info('Please allow up to 10-15 minutes to finish server provision.');
208
    }
209
210
    /**
211
     * "Delete Server" handler.
212
     *
213
     * @param \Laravel\Forge\Forge $forge
214
     *
215
     * @return mixed
216
     */
217
    protected function handleDeleteAction(Forge $forge)
218
    {
219
        $server = $this->chooseServer($forge);
220
221
        $this->error('THIS IS DESTRUCTIVE OPERATION! YOUR SERVER WILL BE DELETED AND THIS ACTION IS UNDONE!');
222
        $this->error('You\'re going to delete '.Str::upper($server->name()).' server.');
223
224
        if (!$this->confirm('Are you totally sure you want to delete this server?', false)) {
225
            return $this->info('Ok, your server left untoched.');
226
        }
227
228
        $this->error('We require one more confirmation that you\'re totally sure about deleting '.$server->name().' server.');
229
        $confirmation = $this->ask('Enter server name to continue');
230
231
        if ($server->name() !== $confirmation) {
232
            return $this->error('You\'ve entered wrong name, operation aborted.');
233
        }
234
235
        $this->info('Ok, server '.$server->name().' will be deleted now.');
236
237
        $server->delete();
238
239
        $this->info('Server '.$server->name().' was sucessfully deleted.');
240
    }
241
}
242