├── .gitignore ├── README.md ├── blacksmith ├── composer.json ├── doc └── servers.md ├── phpunit.xml └── src └── Mpociot └── Blacksmith ├── Blacksmith.php ├── Browser.php ├── Driver └── BlacksmithDriver.php └── Models ├── Circle.php ├── Database.php ├── DatabaseUser.php ├── ForgeModel.php ├── Recipe.php ├── SSHKey.php ├── ScheduledJob.php ├── Server.php ├── Site.php └── User.php /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | composer.lock 3 | .php_cs.cache 4 | /vendor/ 5 | .idea 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Blacksmith - The unofficial Laravel Forge PHP API 2 | 3 | Laravel Forge is **awesome**, right? 4 | Yes it is - but there's one thing it's missing - a proper API. 5 | 6 | That's why this library exists - Blacksmith is an unofficial [Laravel Forge API](http://forge.laravel.com) to automate common tasks. 7 | 8 | The API is still improving and I will keep adding features, as I need them. 9 | 10 | ## Getting Started 11 | 12 | ```php 13 | use Mpociot\Blacksmith\Blacksmith; 14 | 15 | $blacksmith = new Blacksmith($email, $password); 16 | 17 | ``` 18 | 19 | ## Available methods 20 | 21 | 22 | ### Get all active servers 23 | 24 | Returns a Collection of `Server` objects. 25 | 26 | ```php 27 | $activeServers = $blacksmith->getActiveServers(); 28 | ``` 29 | 30 | ### Get all sites for all servers 31 | 32 | Returns a Collection of `Site` objects. 33 | 34 | ```php 35 | $sites = $blacksmith->getSites(); 36 | ``` 37 | 38 | ### Get a server by its ID 39 | 40 | Returns a single `Server` object. 41 | 42 | ```php 43 | $server = $blacksmith->getServer(1); 44 | ``` 45 | 46 | ### Add a server to Forge 47 | 48 | Returns a single `Server` object with a provision url. 49 | 50 | The following example will create a Load Balancer with a custom provider 51 | ```php 52 | $server = $blacksmith->addServer([ 53 | 'backups' => false, 54 | 'database' => 'forge', 55 | 'hhvm' => false, 56 | 'ip_address' => '94.212.124.121', 57 | 'maria' => false, 58 | 'name' => 'harmonious-lagoon', 59 | 'nodeBalancer' => true, 60 | 'old_php' => false, 61 | 'php_version' => 'php70', 62 | 'private_ip_address' => '10.0.0.2', 63 | 'provider' => 'custom', 64 | 'size' => '2', 65 | 'timezone' => 'Europe/Berlin', 66 | ]); 67 | ``` 68 | 69 | ### Get a site by its ID 70 | 71 | Returns a single `Site` object. 72 | 73 | ```php 74 | $site = $blacksmith->getSite(1); 75 | ``` 76 | 77 | ### Get all circles 78 | 79 | Returns a Collection of `Circle` objects of the user. 80 | 81 | ```php 82 | $circles = $blacksmith->getCircles(); 83 | ``` 84 | 85 | ### Get a circle by its ID 86 | 87 | Returns a single `Circle` object. 88 | 89 | ```php 90 | $circle = $blacksmith->getCircle(1); 91 | ``` 92 | 93 | ### Add a new circle 94 | 95 | Returns a single `Circle` object. 96 | 97 | ```php 98 | $circle = $blacksmith->addCircle('Name of Circle'); 99 | ``` 100 | 101 | ### Get all recipes 102 | 103 | Returns a Collection of `Recipe` objects. 104 | 105 | ```php 106 | $recipes = $blacksmith->getRecipes(); 107 | ``` 108 | 109 | ### Get a recipe by its ID 110 | 111 | Returns a single `Recipe` object. 112 | 113 | ```php 114 | $recipe = $blacksmith->getRecipe(1); 115 | ``` 116 | 117 | ### Add a new recipe 118 | 119 | Returns a single `Recipe` object. 120 | 121 | ```php 122 | $recipe = $blacksmith->addRecipe('RecipeName', 'root', 'Recipe contents'); 123 | ``` 124 | 125 | ## Server methods 126 | 127 | ### Get Sites 128 | 129 | Returns a Collection of `Site` objects for the server. 130 | 131 | ```php 132 | $sites = $server->getSites(); 133 | ``` 134 | 135 | ### Add a new site 136 | 137 | Returns a the newly created `Site` object or throws an exception if errors occur. 138 | 139 | ```php 140 | $newSite = $server->addSite($site_name, $project_type = 'php', $directory = '/public', $wildcards = false); 141 | ``` 142 | 143 | ### Add a new SSH key 144 | 145 | Add a SSH key to a server 146 | 147 | ```php 148 | $server->addSSHKey('Name SSH key', 'Contents of SSH key'); 149 | ``` 150 | 151 | ### Remove a SSH key from a server 152 | 153 | ```php 154 | $server->removeSSHKey(1); 155 | ``` 156 | 157 | ### Update Metadata 158 | 159 | Update the metadata of the current site, and return an updated `Server` object or throws an exception if errors occur. 160 | 161 | ```php 162 | $server = $server->updateMetadata($server_name, $ip_address, $private_ip_address, $size); 163 | ``` 164 | 165 | ### Get Schedules Jobs 166 | 167 | Returns a Collection of `ScheduledJob` objects for the server. 168 | 169 | ```php 170 | $jobs = $server->getScheduledJobs(); 171 | ``` 172 | 173 | ### Add a new scheduled job 174 | 175 | Returns a the newly created `ScheduledJob` object or throws an exception if errors occur. 176 | 177 | ```php 178 | $newJob = $server->addScheduledJob($command, $user = 'forge', $frequency = 'minutely'); 179 | ``` 180 | 181 | ### toArray 182 | 183 | Returns an array containing all available server information. 184 | 185 | ```php 186 | $data = $server->toArray(); 187 | ``` 188 | 189 | 190 | ## Site methods 191 | 192 | ### Get Environment 193 | 194 | Returns the configured .env file 195 | 196 | ```php 197 | $env_content = $site->getEnvironment(); 198 | ``` 199 | 200 | ### Install an application 201 | 202 | Install and deploy an application to the site. 203 | 204 | ```php 205 | $site->installApp($repository, $provider = 'github', $branch = 'master', $composer = true, $migrate = false); 206 | ``` 207 | 208 | ### Deploy an application 209 | 210 | Deploys an application on this site. 211 | 212 | ```php 213 | $site->deploy(); 214 | ``` 215 | 216 | ### Get last deployment log 217 | 218 | Returns the last deployment log for this site. 219 | 220 | ```php 221 | $site->deployLog(); 222 | ``` 223 | 224 | ### toArray 225 | 226 | Returns an array containing all available site information. 227 | 228 | ```php 229 | $data = $site->toArray(); 230 | ``` 231 | 232 | ## Circle methods 233 | 234 | ### Invite a member by email 235 | 236 | Returns a fresh `Circle` object or throws an exception if errors occur. 237 | 238 | ```php 239 | $circle = $circle->inviteMember('email@company.com'); 240 | ``` 241 | 242 | ### Set all circle members 243 | 244 | If you want to delete a member you update a circle with all member id's. 245 | It return a fresh `Circle` object. 246 | 247 | ```php 248 | $circle = $circle->setMembers([1,2]); 249 | ``` 250 | 251 | ### Set all circle servers 252 | 253 | If you want to add or delete a server from the circle you update a circle with all server id's. 254 | It return a fresh `Circle` object. 255 | 256 | ```php 257 | $circle = $circle->setServers([1,2]); 258 | ``` 259 | 260 | ## Recipe methods 261 | 262 | ### Update a Recipe 263 | 264 | ```php 265 | $recipe = $recipe->update($name, $user, $script); 266 | ``` 267 | 268 | ## License 269 | 270 | Blacksmith is free software distributed under the terms of the MIT license. 271 | -------------------------------------------------------------------------------- /blacksmith: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | '', 'password' => ''])); 26 | } 27 | $config = json_decode(file_get_contents(BLACKSMITH_HOME_PATH.'/config.json')); 28 | 29 | $blacksmith = new Blacksmith($config->email, $config->password); 30 | 31 | $app->command('login email password', function ($email, $password, OutputInterface $output) use ($configFile) { 32 | file_put_contents($configFile, json_encode([ 33 | 'email' => $email, 34 | 'password' => $password 35 | ])); 36 | 37 | $output->write('Email and Password successfully set.'); 38 | }); 39 | 40 | 41 | $app->command( 42 | 'servers:list [--format=]', 43 | function ($format, OutputInterface $output) use ($blacksmith) { 44 | $servers = $blacksmith->getActiveServers(); 45 | 46 | if($format === 'json') { 47 | $output->writeln(json_encode($servers->toArray(), JSON_PRETTY_PRINT)); 48 | exit; 49 | } 50 | 51 | $table = new Table($output); 52 | $table->setHeaders(['ID', 'Name', 'Provider', 'IP Address', 'PHP Version', 'Status', 'Connection']); 53 | $servers->each(function ($server) use ($table, $blacksmith) { 54 | $server = $blacksmith->getServer($server->id); 55 | $table->addRow([$server->id, $server->name, $server->provider, $server->ip_address, $server->php_version, $server->displayable_provision, $server->connection_status]); 56 | }); 57 | $table->render(); 58 | } 59 | ); 60 | 61 | $app->command( 62 | 'servers:get serverId [--format=]', 63 | function ($serverId, $format, OutputInterface $output) use ($blacksmith) { 64 | 65 | $server = $blacksmith->getServer($serverId); 66 | 67 | if($format === 'json') { 68 | $output->writeln(json_encode($server->toArray(), JSON_PRETTY_PRINT)); 69 | return; 70 | } 71 | 72 | $table = new Table($output); 73 | $table->setHeaders([ 74 | 'ID', 75 | 'Name', 76 | 'Provider', 77 | 'IP Address', 78 | 'PHP Version', 79 | 'Status', 80 | 'Connection' 81 | ]); 82 | $table->addRow([ 83 | $server->id, 84 | $server->name, 85 | $server->provider, 86 | $server->ip_address, 87 | $server->php_version, 88 | $server->displayable_provision, 89 | $server->connection_status 90 | ]); 91 | $table->render(); 92 | } 93 | ); 94 | 95 | $app->command( 96 | 'sites:list [--format=]', 97 | function ($format, OutputInterface $output) use ($blacksmith) { 98 | 99 | $sites = $blacksmith->getSites(); 100 | 101 | if($format === 'json') { 102 | $output->writeln(json_encode($sites->toArray(), JSON_PRETTY_PRINT)); 103 | return; 104 | 105 | } 106 | 107 | $table = new Table($output); 108 | $table->setHeaders([ 109 | 'ID', 110 | 'Name', 111 | 'Server Name', 112 | 'Server ID' 113 | ]); 114 | $sites->each(function ($site) use ($table, $blacksmith) { 115 | $table->addRow([ 116 | $site->id, 117 | $site->name, 118 | $site->server_name, 119 | $site->server_id 120 | ]); 121 | }); 122 | $table->render(); 123 | } 124 | ); 125 | 126 | $app->command( 127 | 'sites:get siteId [--format=]', 128 | function ($siteId, $format, OutputInterface $output) use ($blacksmith) { 129 | 130 | $site = $blacksmith->getSite($siteId); 131 | 132 | if($format === 'json') { 133 | $output->writeln(json_encode($site->toArray(), JSON_PRETTY_PRINT)); 134 | return; 135 | } 136 | 137 | $table = new Table($output); 138 | $table->setHeaders([ 139 | 'ID', 140 | 'Name', 141 | 'Directory', 142 | 'Wildcards', 143 | 'Status', 144 | 'Repository', 145 | 'Server ID', 146 | 'Server Name' 147 | ]); 148 | $table->addRow([ 149 | $site->id, 150 | $site->name, 151 | $site->directory, 152 | $site->widlcards, 153 | $site->status, 154 | $site->repository, 155 | $site->server['id'], 156 | $site->server['name'], 157 | ]); 158 | $table->render(); 159 | } 160 | ); 161 | 162 | $app->command( 163 | 'server:sites:list serverId [--format]', 164 | function ($serverId, $format, OutputInterface $output) use ($blacksmith) { 165 | 166 | $server = $blacksmith->getServer($serverId); 167 | $sites = $server->getSites(); 168 | 169 | if($format === 'json') { 170 | $output->writeln(json_encode($sites->toArray(), JSON_PRETTY_PRINT)); 171 | exit; 172 | } 173 | 174 | $table = new Table($output); 175 | $table->setHeaders([ 176 | 'ID', 177 | 'Name', 178 | 'Directory', 179 | 'Wildcards', 180 | 'Status', 181 | 'Repository', 182 | 'Server ID', 183 | 'Server Name' 184 | ]); 185 | 186 | $sites->each(function ($site) use ($table, $blacksmith, $server) { 187 | $table->addRow([ 188 | $site->id, 189 | $site->name, 190 | $site->directory, 191 | $site->wildcards, 192 | $site->status, 193 | $site->repository, 194 | $server->id, 195 | $server->name, 196 | ]); 197 | }); 198 | 199 | $table->render(); 200 | } 201 | ); 202 | 203 | $app->command( 204 | 'server:sites:get serverId siteId [--format=]', 205 | function($serverId, $siteId, $format, OutputInterface $output) use ($blacksmith) { 206 | $server = $blacksmith->getServer($serverId); 207 | $site = $server->getSite($siteId); 208 | 209 | if($format === 'json') { 210 | $output->writeln(json_encode($site->toArray(), JSON_PRETTY_PRINT)); 211 | return; 212 | } 213 | 214 | $table = new Table($output); 215 | $table->setHeaders([ 216 | 'ID', 217 | 'Name', 218 | 'Directory', 219 | 'Wildcards', 220 | 'Status', 221 | 'Repository', 222 | 'Server ID', 223 | 'Server Name' 224 | ]); 225 | 226 | $table->addRow([ 227 | $site->id, 228 | $site->name, 229 | $site->directory, 230 | $site->wildcards, 231 | $site->status, 232 | $site->repository, 233 | $server->id, 234 | $server->name, 235 | ]); 236 | 237 | $table->render(); 238 | } 239 | ); 240 | 241 | 242 | $app->command( 243 | 'server:sites:add serverId siteName [--projectType=] [--directory=] [--wildcards=] [--format=]', 244 | function($serverId, $siteName, $projectType = 'php', $directory = '/public', $wildcards = false, $format, OutputInterface $output) use ($blacksmith) { 245 | $server = $blacksmith->getServer($serverId); 246 | $site = $server->addSite($siteName, $projectType, $directory, $wildcards); 247 | 248 | if($format === 'json') { 249 | $output->writeln(json_encode($site->toArray(), JSON_PRETTY_PRINT)); 250 | exit; 251 | } 252 | 253 | $table = new Table($output); 254 | $table->setHeaders([ 255 | 'ID', 256 | 'Name', 257 | 'Directory', 258 | 'Wildcards', 259 | 'Status', 260 | 'Repository', 261 | 'Server ID', 262 | 'Server Name' 263 | ]); 264 | 265 | $table->addRow([ 266 | $site->id, 267 | $site->name, 268 | $site->directory, 269 | $site->wildcards, 270 | $site->status, 271 | $site->repository, 272 | $server->id, 273 | $server->name, 274 | ]); 275 | 276 | $table->render(); 277 | 278 | } 279 | ); 280 | 281 | $app->command( 282 | 'server:sites:remove serverId siteId [--format=]', 283 | function($serverId, $siteId, $format, OutputInterface $output) use ($blacksmith) { 284 | $server = $blacksmith->getServer($serverId); 285 | $response = $server->removeSite($siteId); 286 | if($format === 'json') { 287 | $output->writeln(json_encode($response->toArray(), JSON_PRETTY_PRINT)); 288 | return; 289 | } 290 | } 291 | ); 292 | 293 | $app->command( 294 | 'server:databases:list serverId [--format=]', 295 | function ($serverId, $format, OutputInterface $output) use ($blacksmith) { 296 | 297 | $server = $blacksmith->getServer($serverId); 298 | $databases = $server->getDatabases(); 299 | 300 | if($format === 'json') { 301 | $output->writeln(json_encode($databases->toArray(), JSON_PRETTY_PRINT)); 302 | return; 303 | } 304 | 305 | $table = new Table($output); 306 | $table->setHeaders([ 307 | 'ID', 308 | 'Name', 309 | 'Status', 310 | 'Server ID', 311 | 'Server Name' 312 | ]); 313 | 314 | $databases->each(function ($database) use ($table, $blacksmith, $server) { 315 | $table->addRow([ 316 | $database->id, 317 | $database->name, 318 | $database->status, 319 | $server->id, 320 | $server->name, 321 | ]); 322 | }); 323 | 324 | $table->render(); 325 | } 326 | ); 327 | 328 | 329 | $app->command( 330 | 'server:databases:get serverId databaseId [--format=]', 331 | function($serverId, $databaseId, $format, OutputInterface $output) use ($blacksmith) { 332 | $server = $blacksmith->getServer($serverId); 333 | $database = $server->getDatabase($databaseId); 334 | if($format === 'json') { 335 | $output->writeln(json_encode($database->toArray(), JSON_PRETTY_PRINT)); 336 | return; 337 | } 338 | 339 | $table = new Table($output); 340 | $table->setHeaders([ 341 | 'ID', 342 | 'Name', 343 | 'Status', 344 | 'Server ID', 345 | 'Server Name' 346 | ]); 347 | 348 | $table->addRow([ 349 | $database->id, 350 | $database->name, 351 | $database->status, 352 | $server->id, 353 | $server->name, 354 | ]); 355 | 356 | $table->render(); 357 | } 358 | ); 359 | 360 | $app->command( 361 | 'server:databases:add serverId databaseName [--username=] [--password=] [--format=]', 362 | function($serverId, $databaseName, $username = '', $password = '', $format, OutputInterface $output) use ($blacksmith) { 363 | $server = $blacksmith->getServer($serverId); 364 | $database = $server->addDatabase($databaseName, $username, $password); 365 | if($format === 'json') { 366 | $output->writeln(json_encode($database->toArray(), JSON_PRETTY_PRINT)); 367 | return; 368 | } 369 | 370 | $table = new Table($output); 371 | $table->setHeaders([ 372 | 'ID', 373 | 'Name', 374 | 'Status', 375 | 'Server ID', 376 | 'Server Name' 377 | ]); 378 | 379 | $table->addRow([ 380 | $database->id, 381 | $database->name, 382 | $database->status, 383 | $server->id, 384 | $server->name, 385 | ]); 386 | 387 | $table->render(); 388 | } 389 | ); 390 | 391 | $app->command( 392 | 'server:databases:remove serverId databaseId [--format=]', 393 | function($serverId, $databaseId, $format, OutputInterface $output) use ($blacksmith) { 394 | $server = $blacksmith->getServer($serverId); 395 | $response = $server->removeDatabase($databaseId); 396 | if($format === 'json') { 397 | $output->writeln(json_encode($response->toArray(), JSON_PRETTY_PRINT)); 398 | return; 399 | } 400 | } 401 | ); 402 | 403 | 404 | $app->command( 405 | 'server:database_users:list serverId [--format=]', 406 | function ($serverId, $format, OutputInterface $output) use ($blacksmith) { 407 | 408 | $server = $blacksmith->getServer($serverId); 409 | $databaseUsers = $server->getDatabaseUsers(); 410 | 411 | if($format === 'json') { 412 | echo (json_encode($databaseUsers->toArray(), JSON_PRETTY_PRINT)); 413 | return; 414 | } 415 | 416 | $table = new Table($output); 417 | $table->setHeaders([ 418 | 'ID', 419 | 'Name', 420 | 'Status', 421 | 'Server ID', 422 | 'Server Name', 423 | 'Databases', 424 | ]); 425 | 426 | $databaseUsers->each(function ($databaseUser) use ($table, $blacksmith, $server) { 427 | $databases = $databaseUser->getDatabases(); 428 | $databaseNames = $databases->transform(function($database){ 429 | return $database->name; 430 | }); 431 | $table->addRow([ 432 | $databaseUser->id, 433 | $databaseUser->name, 434 | $databaseUser->status, 435 | $server->id, 436 | $server->name, 437 | implode("\n", $databaseNames->toArray()), 438 | ]); 439 | }); 440 | 441 | $table->render(); 442 | } 443 | ); 444 | 445 | $app->command( 446 | 'server:database_users:get serverId databaseUserId [--format=]', 447 | function($serverId, $databaseUserId, $format, OutputInterface $output) use ($blacksmith) { 448 | $server = $blacksmith->getServer($serverId); 449 | $databaseUser = $server->getDatabaseUser($databaseUserId); 450 | 451 | if($format === 'json') { 452 | echo (json_encode($databaseUser->toArray(), JSON_PRETTY_PRINT)); 453 | return; 454 | } 455 | 456 | $table = new Table($output); 457 | $table->setHeaders([ 458 | 'ID', 459 | 'Name', 460 | 'Status', 461 | 'Server ID', 462 | 'Server Name', 463 | 'Databases', 464 | ]); 465 | 466 | $databases = $databaseUser->getDatabases(); 467 | $databaseNames = $databases->transform(function($database){ 468 | return $database->name; 469 | }); 470 | $table->addRow([ 471 | $databaseUser->id, 472 | $databaseUser->name, 473 | $databaseUser->status, 474 | $server->id, 475 | $server->name, 476 | implode("\n", $databaseNames->toArray()), 477 | ]); 478 | 479 | $table->render(); 480 | } 481 | ); 482 | 483 | $app->command( 484 | 'server:database_users:add serverId username password [--canAccess=]* [--format=]', 485 | function($serverId, $username, $password, $canAccess = array(), $format, OutputInterface $output) use ($blacksmith) { 486 | $server = $blacksmith->getServer($serverId); 487 | $databaseUser = $server->addDatabaseUser($username, $password, $canAccess); 488 | 489 | if($format === 'json') { 490 | echo (json_encode($databaseUser->toArray(), JSON_PRETTY_PRINT)); 491 | return; 492 | } 493 | 494 | $table = new Table($output); 495 | $table->setHeaders([ 496 | 'ID', 497 | 'Name', 498 | 'Status', 499 | 'Server ID', 500 | 'Server Name' 501 | ]); 502 | 503 | $databases = $databaseUser->getDatabases(); 504 | $table->addRow([ 505 | $databaseUser->id, 506 | $databaseUser->name, 507 | $databaseUser->status, 508 | $server->id, 509 | $server->name 510 | ]); 511 | 512 | $table->render(); 513 | }); 514 | 515 | $app->command( 516 | 'server:database_users:remove serverId databaseUserId [--format=]', 517 | function($serverId, $databaseUserId, $format, OutputInterface $output) use ($blacksmith) { 518 | $server = $blacksmith->getServer($serverId); 519 | $response = $server->removeDatabaseUser($databaseUserId); 520 | if($format === 'json') { 521 | $output->writeln(json_encode($response->toArray(), JSON_PRETTY_PRINT)); 522 | return; 523 | } 524 | } 525 | ); 526 | 527 | $app->command( 528 | 'server:database_users:update serverId username [--canAccess=]* [--format=]', 529 | function($serverId, $username, $canAccess = array(), $format, OutputInterface $output) use ($blacksmith) { 530 | $server = $blacksmith->getServer($serverId); 531 | $databaseUser = $server->updateDatabaseUser($username, $canAccess); 532 | 533 | if($format === 'json') { 534 | echo (json_encode($databaseUser->toArray(), JSON_PRETTY_PRINT)); 535 | return; 536 | } 537 | 538 | $table = new Table($output); 539 | $table->setHeaders([ 540 | 'ID', 541 | 'Name', 542 | 'Status', 543 | 'Server ID', 544 | 'Server Name' 545 | ]); 546 | 547 | $table->addRow([ 548 | $databaseUser->id, 549 | $databaseUser->name, 550 | $databaseUser->status, 551 | $server->id, 552 | $server->name 553 | ]); 554 | 555 | $table->render(); 556 | }); 557 | 558 | 559 | $app->command( 560 | 'server:ssh_keys:list serverId [--format=]', 561 | function ($serverId, $format, OutputInterface $output) use ($blacksmith) { 562 | 563 | $server = $blacksmith->getServer($serverId); 564 | $sshKeys = $server->getSSHKeys(); 565 | 566 | if($format === 'json') { 567 | $output->writeln(json_encode($sshKeys->toArray(), JSON_PRETTY_PRINT)); 568 | return; 569 | } 570 | 571 | $table = new Table($output); 572 | $table->setHeaders([ 573 | 'ID', 574 | 'Name', 575 | 'Status', 576 | 'Server ID', 577 | 'Server Name' 578 | ]); 579 | 580 | $sshKeys->each(function ($sshKey) use ($table, $blacksmith, $server) { 581 | $table->addRow([ 582 | $sshKey->id, 583 | $sshKey->name, 584 | $sshKey->status, 585 | $server->id, 586 | $server->name 587 | ]); 588 | }); 589 | 590 | $table->render(); 591 | } 592 | ); 593 | 594 | $app->command( 595 | 'server:ssh_keys:add serverId name key [--format=]', 596 | function($serverId, $name, $key, $format, OutputInterface $output) use ($blacksmith) { 597 | $server = $blacksmith->getServer($serverId); 598 | $sshKey = $server->addSSHKey($name, $key); 599 | 600 | if($format === 'json') { 601 | echo (json_encode($sshKey->toArray(), JSON_PRETTY_PRINT)); 602 | return; 603 | } 604 | 605 | $table = new Table($output); 606 | $table->setHeaders([ 607 | 'ID', 608 | 'Name', 609 | 'Status', 610 | 'Server ID', 611 | 'Server Name' 612 | ]); 613 | 614 | $table->addRow([ 615 | $sshKey->id, 616 | $sshKey->name, 617 | $sshKey->status, 618 | $server->id, 619 | $server->name 620 | ]); 621 | 622 | $table->render(); 623 | }); 624 | 625 | $app->command( 626 | 'server:ssh_keys:remove serverId sshKeyId [--format=]', 627 | function($serverId, $sshKeyId, $format, OutputInterface $output) use ($blacksmith) { 628 | $server = $blacksmith->getServer($serverId); 629 | $response = $server->removeSSHKey($sshKeyId); 630 | if($format === 'json') { 631 | $output->writeln(json_encode($response->toArray(), JSON_PRETTY_PRINT)); 632 | return; 633 | } 634 | } 635 | ); 636 | 637 | $app->command( 638 | 'server:scheduled_jobs:list serverId [--format=]', 639 | function ($serverId, $format, OutputInterface $output) use ($blacksmith) { 640 | 641 | $server = $blacksmith->getServer($serverId); 642 | $scheduledJobs = $server->getScheduledJobs(); 643 | 644 | if($format === 'json') { 645 | $output->writeln(json_encode($scheduledJobs->toArray(), JSON_PRETTY_PRINT)); 646 | return; 647 | } 648 | 649 | $table = new Table($output); 650 | $table->setHeaders([ 651 | 'ID', 652 | 'Command', 653 | 'User', 654 | 'Frequency', 655 | 'Cron', 656 | 'Status', 657 | 'Server ID', 658 | 'Server Name' 659 | ]); 660 | 661 | $scheduledJobs->each(function ($scheduledJob) use ($table, $blacksmith, $server) { 662 | $table->addRow([ 663 | $scheduledJob->id, 664 | $scheduledJob->command, 665 | $scheduledJob->user, 666 | $scheduledJob->frequency, 667 | $scheduledJob->cron, 668 | $scheduledJob->status, 669 | $server->id, 670 | $server->name 671 | ]); 672 | }); 673 | 674 | $table->render(); 675 | } 676 | ); 677 | 678 | $app->command( 679 | 'server:scheduled_jobs:add serverId script user frequency [--format=]', 680 | function($serverId, $script, $user, $frequency, $format, OutputInterface $output) use ($blacksmith) { 681 | $server = $blacksmith->getServer($serverId); 682 | $scheduledJob = $server->addScheduledJob($script, $user, $frequency); 683 | 684 | if($format === 'json') { 685 | echo (json_encode($scheduledJob->toArray(), JSON_PRETTY_PRINT)); 686 | return; 687 | } 688 | 689 | $table = new Table($output); 690 | $table->setHeaders([ 691 | 'ID', 692 | 'Command', 693 | 'User', 694 | 'Frequency', 695 | 'Cron', 696 | 'Status', 697 | 'Server ID', 698 | 'Server Name' 699 | ]); 700 | 701 | $table->addRow([ 702 | $scheduledJob->id, 703 | $scheduledJob->command, 704 | $scheduledJob->user, 705 | $scheduledJob->frequency, 706 | $scheduledJob->cron, 707 | $scheduledJob->status, 708 | $server->id, 709 | $server->name 710 | ]); 711 | 712 | $table->render(); 713 | } 714 | ); 715 | 716 | $app->command( 717 | 'server:scheduled_jobs:remove serverId scheduledJobId [--format=]', 718 | function($serverId, $scheduledJobId, $format, OutputInterface $output) use ($blacksmith) { 719 | $server = $blacksmith->getServer($serverId); 720 | $response = $server->removeScheduledJob($scheduledJobId); 721 | if($format === 'json') { 722 | $output->writeln(json_encode($response, JSON_PRETTY_PRINT)); 723 | return; 724 | } 725 | } 726 | ); 727 | 728 | $app->command( 729 | 'server:max_file_upload_size:update serverId megabytes [--format=]', 730 | function($serverId, $megabytes, $format, OutputInterface $output) use ($blacksmith) { 731 | $server = $blacksmith->getServer($serverId); 732 | $response = $server->updateMaxFileUploadSize($megabytes); 733 | if($format === 'json') { 734 | $output->writeln(json_encode($response, JSON_PRETTY_PRINT)); 735 | return; 736 | } 737 | } 738 | ); 739 | 740 | $app->command( 741 | 'server:meta:update serverId serverName ipAddress size [--privateIpAddress=] [--format=]', 742 | function($serverId, $serverName, $ipAddress, $privateIpAddress = '', $size, $format, OutputInterface $output) use ($blacksmith) { 743 | $server = $blacksmith->getServer($serverId); 744 | $response = $server->updateMetadata($serverName, $ipAddress, $privateIpAddress, $size); 745 | if($format === 'json') { 746 | $output->writeln(json_encode($response, JSON_PRETTY_PRINT)); 747 | return; 748 | } 749 | } 750 | ); 751 | 752 | $app->command( 753 | 'site:environment:get siteId [--format=]', 754 | function ($siteId, $format, OutputInterface $output) use ($blacksmith) { 755 | $site = $blacksmith->getSite($siteId); 756 | $response = $site->getEnvironment(); 757 | if($format === 'json') { 758 | $output->write(json_encode($response, JSON_PRETTY_PRINT)); 759 | return; 760 | } 761 | } 762 | ); 763 | 764 | $app->command( 765 | 'site:environment:update siteId data [--format=]', 766 | function ($siteId, $data, $format, OutputInterface $output) use ($blacksmith) { 767 | $site = $blacksmith->getSite($siteId); 768 | $response = $site->updateEnvironment($data); 769 | if($format === 'json') { 770 | $output->writeln(json_encode($response, JSON_PRETTY_PRINT)); 771 | return; 772 | } 773 | } 774 | ); 775 | 776 | $app->command( 777 | 'site:nginx_config:get siteId [--format=]', 778 | function ($siteId, $format, OutputInterface $output) use ($blacksmith) { 779 | $site = $blacksmith->getSite($siteId); 780 | $response = $site->getNginxConfig(); 781 | if($format === 'json') { 782 | $output->writeln(json_encode($response, JSON_PRETTY_PRINT)); 783 | return; 784 | } 785 | } 786 | ); 787 | 788 | $app->command( 789 | 'site:nginx_config:update siteId data [--format=]', 790 | function ($siteId, $data, $format, OutputInterface $output) use ($blacksmith) { 791 | $site = $blacksmith->getSite($siteId); 792 | $response = $site->updateNginxConfig($data); 793 | if($format === 'json') { 794 | $output->writeln(json_encode($response, JSON_PRETTY_PRINT)); 795 | return; 796 | } 797 | } 798 | ); 799 | 800 | $app->command( 801 | 'site:web_directory:update siteId directory [--format=]', 802 | function ($siteId, $directory, $format, OutputInterface $output) use ($blacksmith) { 803 | $site = $blacksmith->getSite($siteId); 804 | $response = $site->updateWebDirectory($directory); 805 | if($format === 'json') { 806 | $output->writeln(json_encode($response, JSON_PRETTY_PRINT)); 807 | return; 808 | } 809 | } 810 | ); 811 | 812 | $app->command('site:deploy siteId', function ($siteId, OutputInterface $output) use ($blacksmith) { 813 | $site = $blacksmith->getSite($siteId); 814 | $site->deploy(); 815 | $output->writeln('Deployed '.$site->name.' successfully!'); 816 | }); 817 | 818 | $app->command('site:deploy:log siteId', function ($siteId, OutputInterface $output) use ($blacksmith) { 819 | $site = $blacksmith->getSite($siteId); 820 | 821 | $output->writeln('Last deployment log for: '.$site->name.''); 822 | $output->write($site->deployLog()); 823 | }); 824 | 825 | /** 826 | * Run the application. 827 | */ 828 | $app->run(); 829 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mpociot/blacksmith", 3 | "license": "MIT", 4 | "description": "The unofficial Laravel Forge API", 5 | "keywords": [ 6 | "API", 7 | "Forge", 8 | "Laravel" 9 | ], 10 | "homepage": "http://github.com/mpociot/blacksmith", 11 | "authors": [ 12 | { 13 | "name": "Marcel Pociot", 14 | "email": "m.pociot@gmail.com" 15 | } 16 | ], 17 | "require": { 18 | "php": ">=5.5.0", 19 | "tightenco/collect": "~5.0", 20 | "behat/mink-goutte-driver": "^1.2", 21 | "behat/mink": "^1.7", 22 | "mnapoli/silly": "^1.5" 23 | }, 24 | "require-dev": { 25 | "phpunit/phpunit": "~5.0", 26 | "mockery/mockery": "^0.9.5" 27 | }, 28 | "autoload": { 29 | "psr-0": { 30 | "Mpociot\\Blacksmith": "src/" 31 | } 32 | }, 33 | "bin": [ 34 | "blacksmith" 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /doc/servers.md: -------------------------------------------------------------------------------- 1 | # Servers 2 | 3 | ## Get all active servers 4 | 5 | Returns a Collection of `Server` objects. 6 | 7 | ```php 8 | $activeServers = $blacksmith->getActiveServers(); 9 | ``` 10 | 11 | ## Get all servers 12 | 13 | Returns a Collection of `Server` objects. 14 | 15 | ```php 16 | $servers = $blacksmith->getServers(); 17 | ``` 18 | 19 | ## Get a server by its ID 20 | 21 | Returns a single `Server` object. 22 | 23 | ```php 24 | $server = $blacksmith->getServer(1); 25 | ``` 26 | 27 | ## Add a server to Forge 28 | 29 | ### Globals options to set 30 | 31 | PHP version options 32 | - 'php71' - Install PHP 7.1 on the server 33 | - 'php70' - Install PHP 7.0 on the server 34 | - 'php56' - Install PHP 5.6 on the server 35 | 36 | Database option 37 | Set the 'maria' key on the configuration with one of the following 38 | - true - Server will install and use MariaDB 10.1 39 | - false - Server will install and use MySQL 5.7 40 | 41 | ### Add a server with DigitalOcean 2.0 provider 42 | 43 | If you want weekly backups on DigitalOcean for this server set the 'backups' key to **true**. 44 | 45 | ```php 46 | $server = $blacksmith->addServer([ 47 | 'backups' => false 48 | 'credential' => _CREDENTIAL_ID_ 49 | 'database' => 'forge' 50 | 'hhvm' => false 51 | 'maria' => true 52 | 'name' => 'solitary-fern' 53 | 'nodeBalancer' => false 54 | 'old_php' => false 55 | 'php_version' => 'php70' 56 | 'provider' => 'ocean2' 57 | 'region' => 'ams3' 58 | 'size' => '1GB' 59 | 'timezone' => 'Europe/Berlin' 60 | ]); 61 | ``` 62 | 63 | Replace _CREDENTIAL_ID_ with your DigitalOcean2.0 provider credential ID. 64 | 65 | Possible size options: 66 | - '512MB' => 512MB RAM, 1 CPU, 20GB SSD, 1TB Transfer 67 | - '1GB' => 1GB RAM, 1 CPU, 30GB SSD, 2TB Transfer 68 | - '2GB' => 2GB RAM, 2 CPU, 40GB SSD, 3TB Transfer 69 | - '4GB' => 4GB RAM, 2 CPU, 60GB SSD, 4TB Transfer 70 | - '8GB' => 8GB RAM, 4 CPU, 80GB SSD, 5TB Transfer 71 | - '16GB' => 16GB RAM, 8 CPU, 160GB SSD, 6TB Transfer 72 | - 'm-16GB' => 16GB RAM, 2 CPU, 30GB SSD, 6TB Transfer 73 | - '32GB' => 32GB RAM, 12 CPU, 320GB SSD, 7TB Transfer 74 | - 'm-32GB' => 32GB RAM, 4 CPU, 90GB SSD, 7TB Transfer 75 | - '64GB' => 64GB RAM, 20 CPU, 640GB SSD, 9TB Transfer 76 | - 'm-64GB' => 64GB RAM, 8 CPU, 200GB SSD, 8TB Transfer 77 | 78 | Possible region options: 79 | - 'ams2' => Amsterdam 2 80 | - 'ams3' => Amsterdam 3 81 | - 'blr1' => Bangalore 82 | - 'lon1' => London 83 | - 'fra1' => Frankfurt 84 | - 'nyc1' => New York 1 85 | - 'nyc2' => New York 2 86 | - 'nyc3' => New York 3 87 | - 'sfo1' => San Francisco 1 88 | - 'sfo2' => San Francisco 2 89 | - 'sgp1' => Singapore 90 | - 'tor1' => Toronto 91 | 92 | ### Add a server with Linode provider 93 | 94 | ```php 95 | $server = $blacksmith->addServer([ 96 | 'backups' => false 97 | 'credential' => _CREDENTIAL_ID_ 98 | 'database' => 'forge' 99 | 'hhvm' => false 100 | 'maria' => true 101 | 'name' => 'moonlight-fern' 102 | 'nodeBalancer' => false 103 | 'old_php' => false 104 | 'php_version' => 'php70' 105 | 'provider' => 'linode' 106 | 'region' => 7 107 | 'size' => '2GB' 108 | 'timezone' => 'Europe/Berlin' 109 | ]); 110 | ``` 111 | 112 | Replace _CREDENTIAL_ID_ with your Linode provider credential ID. 113 | 114 | Possible size options: 115 | - '2GB' => 2GB RAM - 1 CPU Cores - 24GB SSD - $0.015 / Hour - $10 / Month 116 | - '4GB' => 4GB RAM - 2 CPU Cores - 48GB SSD - $0.03 / Hour - $20 / Month 117 | - '8GB' => 8GB RAM - 4 CPU Cores - 96GB SSD - $0.06 / Hour - $40 / Month 118 | - '12GB' => 12GB RAM - 6 CPU Cores - 192GB SSD - $0.12 / Hour - $80 / Month 119 | - '24GB' => 24GB RAM - 8 CPU Cores - 384GB SSD - $0.24 / Hour - $160 / Month 120 | - '48GB' => 48GB RAM - 12 CPU Cores - 768GB SSD - $0.48 / Hour - $320 / Month 121 | - '64GB' => 64GB RAM - 16 CPU Cores - 1152GB SSD - $0.72 / Hour - $480 / Month 122 | - '80GB' => 80GB RAM - 20 CPU Cores - 1536GB SSD - $0.96 / Hour - $640 / Month 123 | - '120GB' => 120GB RAM - 20 CPU Cores - 1920GB SSD - $1.44 / Hour - $960 / Month 124 | 125 | Possible region options: 126 | - 4 => Atlanta 127 | - 2 => Dallas 128 | - 10 => Frankfurt 129 | - 3 => Fremont 130 | - 7 => London 131 | - 6 => Newark 132 | - 9 => Singapore 133 | - 8 => Tokyo 134 | 135 | ### Add a server with Amazon provider 136 | 137 | ```php 138 | $server = $blacksmith->addServer([ 139 | 'backups' => false 140 | 'credential' => _CREDENTIAL_ID_ 141 | 'database' => 'forge' 142 | 'hhvm' => false 143 | 'maria' => true 144 | 'name' => 'howling-moon' 145 | 'nodeBalancer' => false 146 | 'old_php' => false 147 | 'php_version' => 'php70' 148 | 'provider' => 'aws' 149 | 'region' => 7 150 | 'size' => '2GB' 151 | 'timezone' => 'Europe/Berlin' 152 | ]); 153 | ``` 154 | 155 | Replace _CREDENTIAL_ID_ with your Amazon provider credential ID. 156 | 157 | Possible size options: 158 | - '1GB' => 1 GiB RAM - 1 vCPU - $0.013 / Hour - $10 / Month 159 | - '2GB' => 2 GiB RAM - 1 vCPU - $0.026 / Hour - $20 / Month 160 | - '4GB' => 4 GiB RAM - 2 vCPUs - $0.052 / Hour - $40 / Month 161 | - '8GB' => 8 GiB RAM - 2 vCPUs - $0.104 / Hour - $80 / Month 162 | - '16GB' => 16 GiB RAM - 4 vCPUs - $0.239 / Hour - $175 / Month 163 | - '32GB' => 32 GiB RAM - 8 vCPUs - $0.479 / Hour - $350 / Month 164 | - '64GB' => 64 GiB RAM - 16 vCPUs - $0.958 / Hour - $700 / Month 165 | 166 | Possible region options: 167 | - 'us-west-1' => California 168 | - 'eu-west-1' => Ireland 169 | - 'eu-central-1' => Frankfurt 170 | - 'us-west-2' => Oregon 171 | - 'sa-east-1' => Sao Paulo 172 | - 'ap-northeast-2' => Seoul 173 | - 'ap-southeast-1' => Singapore 174 | - 'ap-southeast-2' => Sydney 175 | - 'ap-northeast-1' => Tokyo 176 | - 'us-east-1' => Virginia 177 | 178 | ### Add a custom server example 179 | 180 | The following example will create a server with a custom provider. 181 | Returns a single `Server` object with a provision url. 182 | 183 | Fields to override: 184 | - ip_address 185 | - name 186 | - size 187 | - private_ip_address 188 | 189 | ```php 190 | $server = $blacksmith->addServer([ 191 | 'backups' => false, 192 | 'database' => 'forge', 193 | 'hhvm' => false, 194 | 'ip_address' => '123.212.124.121', 195 | 'maria' => false, 196 | 'name' => 'sparkling-lake', 197 | 'nodeBalancer' => false, 198 | 'old_php' => false, 199 | 'php_version' => 'php70', 200 | 'private_ip_address' => '', 201 | 'provider' => 'custom', 202 | 'size' => '2', 203 | 'timezone' => 'Europe/Berlin', 204 | ]); 205 | ``` 206 | 207 | ### Add a custom LoadBalancer example 208 | 209 | The following example will create a Load Balancer with a custom provider. 210 | Returns a single `Server` object with a provision url. 211 | 212 | Fields to override: 213 | - ip_address 214 | - name 215 | - size 216 | - private_ip_address 217 | 218 | ```php 219 | $server = $blacksmith->addServer([ 220 | 'backups' => false, 221 | 'database' => 'forge', 222 | 'hhvm' => false, 223 | 'ip_address' => '123.212.124.121', 224 | 'maria' => false, 225 | 'name' => 'harmonious-lagoon', 226 | 'nodeBalancer' => true, 227 | 'old_php' => false, 228 | 'php_version' => 'php70', 229 | 'private_ip_address' => '10.0.0.2', 230 | 'provider' => 'custom', 231 | 'size' => '2', 232 | 'timezone' => 'Europe/Berlin', 233 | ]); 234 | ``` 235 | 236 | Notice the difference on the custom servers. The only change is nodeBalancer is set to true instead of false when a nodeBalancer is needed. 237 | 238 | ## Remove a server by its ID 239 | 240 | Remove a server from Forge. Don't try this at home, you have been warned.. 241 | 242 | ```php 243 | $server = $blacksmith->deleteServer(1); 244 | ``` 245 | -------------------------------------------------------------------------------- /phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | tests/ 16 | 17 | 18 | 19 | 20 | src/Mpociot/ 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/Mpociot/Blacksmith/Blacksmith.php: -------------------------------------------------------------------------------- 1 | browser = new Browser($email, $password); 30 | } 31 | 32 | /** 33 | * @return Collection A list of servers from /api/servers/active 34 | */ 35 | public function getActiveServers() 36 | { 37 | return $this->browser->getContent('https://forge.laravel.com/api/servers/active')->transform(function ($data) { 38 | return new Server($data, $this->browser); 39 | }); 40 | } 41 | 42 | /** 43 | * Get all available servers 44 | * 45 | * @return Collection A collection of servers from /api/servers 46 | */ 47 | public function getServers() 48 | { 49 | return $this->browser->getContent('https://forge.laravel.com/api/servers')->transform(function ($data) { 50 | return new Server($data, $this->browser); 51 | }); 52 | } 53 | 54 | /** 55 | * Get a single server by its ID or name 56 | * 57 | * @param $id 58 | * @return Server A single server from /api/servers/:serverId 59 | * @throws Exception 60 | */ 61 | public function getServer($id) 62 | { 63 | if(!is_numeric($id)) { 64 | $servers = $this->getServers(); 65 | $server = $servers->filter(function($server) use ($id){ return $server->name == $id; })->first(); 66 | if($server) { 67 | $id = $server->id; 68 | } 69 | } 70 | 71 | $serverData = $this->browser->getContent('https://forge.laravel.com/api/servers/'.$id)->toArray(); 72 | 73 | if(!$serverData) { 74 | throw new Exception(sprintf('Server "%s" could not be found', $id)); 75 | } 76 | 77 | return new Server($serverData, $this->browser); 78 | } 79 | 80 | /** 81 | * Add new server to Forge with given configuration 82 | * 83 | * @param array $server_configuration 84 | * @return Server 85 | * @throws Exception 86 | */ 87 | public function addServer($server_configuration) 88 | { 89 | $result = $this->browser->postContent('https://forge.laravel.com/servers', $server_configuration); 90 | 91 | if ($this->browser->getSession()->getStatusCode() === 500) { 92 | throw new Exception('Error: '.print_r($result, true)); 93 | } 94 | 95 | // Add the provision URL 96 | $result['provision_url'] = 'wget -O forge.sh https://forge.laravel.com/servers/'.$result['id'].'/vps?forge_token='.$this->getUser()->forge_token.'; bash forge.sh'; 97 | 98 | return new Server($result, $this->browser); 99 | } 100 | 101 | /** 102 | * Delete a server by its ID or name 103 | * 104 | * @param $id 105 | */ 106 | public function deleteServer($id) 107 | { 108 | if(!is_numeric($id)) { 109 | $server = $this->getServer($id); 110 | $id = $server->id; 111 | } 112 | 113 | $this->browser->deleteContent('https://forge.laravel.com/servers/'.$id); 114 | } 115 | 116 | /** 117 | * Get sites 118 | * 119 | * @return Collection of sites from /api/servers/sites/list 120 | */ 121 | public function getSites(){ 122 | $sites = $this->browser->getContent('https://forge.laravel.com/api/servers/sites/list')->transform(function ($data) { 123 | return new Site($data, $this->browser); 124 | }); 125 | return $sites; 126 | } 127 | 128 | /** 129 | * Get a single site by its ID or name 130 | * 131 | * @param $id 132 | * @return Site A single site from /api/servers/:serverId/sites/:siteId 133 | * @throws Exception 134 | */ 135 | public function getSite($id) 136 | { 137 | $sites = $this->getSites(); 138 | $criteria = !is_numeric($id) ? 'name' : 'id'; 139 | $site = $sites->filter(function($site) use ($criteria, $id){ 140 | return $site->{$criteria} == $id; 141 | })->first(); 142 | 143 | $siteData = $this->browser->getContent('https://forge.laravel.com/api/servers/'.$site->server_id.'/sites/'.$site->id)->toArray(); 144 | 145 | if(!$siteData) { 146 | throw new Exception(sprintf('Site "%s" could not be found', $id)); 147 | } 148 | 149 | return new Site($siteData, $this->browser); 150 | } 151 | 152 | /** 153 | * Get all circles 154 | * 155 | * @return Collection 156 | */ 157 | public function getCircles() 158 | { 159 | return $this->browser->getContent('https://forge.laravel.com/api/circles')->transform(function ($data) { 160 | return new Circle($data, $this->browser); 161 | }); 162 | } 163 | 164 | /** 165 | * Get a single circle by its ID 166 | * 167 | * @param $id 168 | * @return mixed 169 | * @throws Exception 170 | */ 171 | public function getCircle($id) 172 | { 173 | $circles = $this->getCircles(); 174 | $criteria = is_numeric($id) ? 'id': 'name'; 175 | $circle = $circles->filter(function($circle) use ($criteria, $id){ 176 | return $circle->$criteria = $id; 177 | })->first(); 178 | 179 | if(!$circle) { 180 | throw new Exception(sprintf('Circle "%s" could not be found', $id)); 181 | } 182 | 183 | return $circle; 184 | } 185 | 186 | /** 187 | * Add a new Circle 188 | * 189 | * @param string $name 190 | * @return Circle 191 | */ 192 | public function addCircle($name) 193 | { 194 | $result = $this->browser->postContent('https://forge.laravel.com/circles', ['name' => $name]); 195 | return new Circle($result, $this->browser); 196 | } 197 | 198 | /** 199 | * Delete a Circle 200 | * 201 | * @param int $id 202 | * @return mixed 203 | */ 204 | public function deleteCircle($id) 205 | { 206 | $circle = $this->getCircle($id); 207 | return $this->browser->deleteContent('https://forge.laravel.com/circles/'.$circle->id); 208 | } 209 | 210 | /** 211 | * Get all recipes 212 | * 213 | * @return Collection 214 | */ 215 | public function getRecipes() 216 | { 217 | return $this->browser->getContent('https://forge.laravel.com/api/recipes')->transform(function ($data) { 218 | return new Recipe($data, $this->browser); 219 | }); 220 | } 221 | 222 | /** 223 | * Get a single recipe by its ID or name 224 | * 225 | * @param int $id 226 | * @return Recipe 227 | */ 228 | public function getRecipe($id) 229 | { 230 | $recipes = $this->getRecipes(); 231 | $criteria = is_numeric($id) ? 'id': 'name'; 232 | 233 | $recipe = $recipes->filter(function($recipe) use ($criteria, $id){ 234 | return $recipe->$criteria = $id; 235 | })->first(); 236 | 237 | return $recipe; 238 | } 239 | 240 | /** 241 | * Add a new Recipe 242 | * 243 | * @param string $name 244 | * @return Recipe 245 | */ 246 | public function addRecipe($name, $user, $script) 247 | { 248 | $result = $this->browser->postContent('https://forge.laravel.com/recipes', [ 249 | 'name' => $name, 250 | 'user' => $user, 251 | 'script' => $script, 252 | ]); 253 | return new Recipe($result, $this->browser); 254 | } 255 | 256 | /** 257 | * Delete a Recipe 258 | * 259 | * @param int $id 260 | * @return mixed 261 | */ 262 | public function deleteRecipe($id) 263 | { 264 | $recipe = $this->getRecipe($id); 265 | return $this->browser->deleteContent('https://forge.laravel.com/recipes/'.$recipe->id); 266 | } 267 | 268 | /** 269 | * Get the logged in User 270 | * 271 | * @return User 272 | */ 273 | public function getUser() 274 | { 275 | $user = $this->browser->getContent('https://forge.laravel.com/api/user')->toArray(); 276 | return new User($user, $this->browser); 277 | } 278 | } 279 | -------------------------------------------------------------------------------- /src/Mpociot/Blacksmith/Browser.php: -------------------------------------------------------------------------------- 1 | session = new Session(new BlacksmithDriver()); 37 | $this->session->start(); 38 | 39 | $this->email = $email; 40 | $this->password = $password; 41 | } 42 | 43 | /** 44 | * @throws Exception 45 | */ 46 | protected function login() 47 | { 48 | $this->session->visit(self::LOGIN_URL); 49 | $page = $this->session->getPage(); 50 | $page->find('css', '#email')->setValue($this->email); 51 | $page->find('css', 'input[type="password"]')->setValue($this->password); 52 | $page->find('css', 'form')->submit(); 53 | 54 | if ($this->session->getCurrentUrl() === self::LOGIN_URL) { 55 | throw new Exception('Invalid login'); 56 | } 57 | $this->logged_in = true; 58 | } 59 | 60 | /** 61 | * @param $url 62 | * @param bool $raw 63 | * @return \Illuminate\Support\Collection 64 | * @throws Exception 65 | */ 66 | public function getContent($url, $raw = false) 67 | { 68 | if ($this->logged_in === false) { 69 | $this->login(); 70 | } 71 | 72 | $this->session->visit($url); 73 | $content = $this->session->getPage()->getContent(); 74 | 75 | if ($raw) { 76 | return $content; 77 | } 78 | return collect(json_decode($content, true)); 79 | } 80 | 81 | /** 82 | * @param $url 83 | * @param $payload 84 | * @param $raw 85 | * @return mixed 86 | * @throws Exception 87 | */ 88 | public function postContent($url, $payload, $raw = false) 89 | { 90 | if ($this->logged_in === false) { 91 | $this->login(); 92 | } 93 | 94 | $this->session->getDriver()->post($url, json_encode($payload)); 95 | $content = $this->session->getPage()->getContent(); 96 | 97 | if ($raw) { 98 | return $content; 99 | } 100 | return json_decode($content, true); 101 | } 102 | 103 | /** 104 | * @param $url 105 | * @param $payload 106 | * @return mixed 107 | * @throws Exception 108 | */ 109 | public function putContent($url, $payload) 110 | { 111 | if ($this->logged_in === false) { 112 | $this->login(); 113 | } 114 | 115 | $this->session->getDriver()->put($url, json_encode($payload)); 116 | return json_decode($this->session->getPage()->getContent(), true); 117 | } 118 | 119 | /** 120 | * @param $url 121 | * @return mixed 122 | * @throws Exception 123 | */ 124 | public function deleteContent($url) 125 | { 126 | if ($this->logged_in === false) { 127 | $this->login(); 128 | } 129 | 130 | return $this->session->getDriver()->delete($url); 131 | } 132 | 133 | /** 134 | * Gets the value of session. 135 | * 136 | * @return mixed 137 | */ 138 | public function getSession() 139 | { 140 | return $this->session; 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /src/Mpociot/Blacksmith/Driver/BlacksmithDriver.php: -------------------------------------------------------------------------------- 1 | getClient()->request('POST', $this->prepareUrl($url), [], [], [ 15 | 'HTTP_ACCEPT' => 'application/json', 16 | 'HTTP_CONTENT_TYPE' => 'application/json', 17 | 'HTTP_X_XSRF_TOKEN' => $this->getClient()->getCookieJar()->get('XSRF-TOKEN')->getValue() 18 | ], $postData); 19 | } 20 | 21 | /** 22 | * Perform a PUT request 23 | */ 24 | public function put($url, $postData) 25 | { 26 | $this->getClient()->request('PUT', $this->prepareUrl($url), [], [], [ 27 | 'HTTP_ACCEPT' => 'application/json', 28 | 'HTTP_CONTENT_TYPE' => 'application/json', 29 | 'HTTP_X_XSRF_TOKEN' => $this->getClient()->getCookieJar()->get('XSRF-TOKEN')->getValue() 30 | ], $postData); 31 | } 32 | 33 | /** 34 | * Perform a PUT request 35 | */ 36 | public function delete($url) 37 | { 38 | $this->getClient()->request('DELETE', $this->prepareUrl($url), [], [], [ 39 | 'HTTP_ACCEPT' => 'application/json', 40 | 'HTTP_CONTENT_TYPE' => 'application/json', 41 | 'HTTP_X_XSRF_TOKEN' => $this->getClient()->getCookieJar()->get('XSRF-TOKEN')->getValue() 42 | ]); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/Mpociot/Blacksmith/Models/Circle.php: -------------------------------------------------------------------------------- 1 | browser->postContent('https://forge.laravel.com/circles/'.$this->id.'/invite', [ 21 | 'email' => $email, 22 | ]); 23 | 24 | if ($this->browser->getSession()->getStatusCode() === 422) { 25 | throw new Exception('Error: '.print_r($result, true)); 26 | } 27 | 28 | return new Circle($result, $this->browser); 29 | } 30 | 31 | /** 32 | * Set all members of the circle 33 | * 34 | * @param array $member_ids 35 | * @return Circle 36 | */ 37 | public function setMembers($member_ids) 38 | { 39 | $result = $this->browser->putContent('https://forge.laravel.com/circles/'.$this->id.'/members', [ 40 | 'members' => $member_ids, 41 | ]); 42 | 43 | return new Circle($result, $this->browser); 44 | } 45 | 46 | /** 47 | * Set all servers of the circle 48 | * 49 | * @param array $server_ids 50 | * @return Circle 51 | */ 52 | public function setServers($server_ids) 53 | { 54 | $result = $this->browser->putContent('https://forge.laravel.com/circles/'.$this->id.'/servers', [ 55 | 'servers' => $server_ids, 56 | ]); 57 | 58 | return new Circle($result, $this->browser); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Mpociot/Blacksmith/Models/Database.php: -------------------------------------------------------------------------------- 1 | data->get('database_users'))->transform( 21 | function ($data) { 22 | return new DatabaseUser($data, $this->browser); 23 | } 24 | ); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Mpociot/Blacksmith/Models/DatabaseUser.php: -------------------------------------------------------------------------------- 1 | data->get('databases'))->transform(function ($data) { 21 | return new Database($data, $this->browser); 22 | }); 23 | } 24 | 25 | /** 26 | * Get a single user database 27 | * 28 | * @param $identifier 29 | * @return mixed 30 | */ 31 | public function getDatabase($identifier) { 32 | $criteria = (is_numeric($identifier)) ? 'id' : 'name'; 33 | /** @var Collection $databases */ 34 | $databases = $this->getDatabases(); 35 | $database = $databases->filter(function($database) use ($criteria, $identifier){ 36 | return $database->$criteria == $identifier; 37 | }, $databases)->first(); 38 | return $database; 39 | } 40 | 41 | /** 42 | * Add a database to the user 43 | * 44 | * @param Database $database 45 | * @return array 46 | */ 47 | public function addDatabase(Database $database){ 48 | /** @var Collection $databases */ 49 | $databases = $this->getDatabases(); 50 | 51 | // Add the database and get the ids 52 | $databaseIds = $databases 53 | ->push($database) 54 | ->map(function($value){ 55 | return $value->id; 56 | }) 57 | ->toArray(); 58 | 59 | $data = [ 60 | 'databases' => $databaseIds 61 | ]; 62 | 63 | $result = $this->browser->putContent('https://forge.laravel.com/servers/'.$this->server_id.'/database-user/'.$this->id, $data); 64 | 65 | if ($this->browser->getSession()->getStatusCode() === 500) { 66 | throw new Exception('Error: '.print_r($result, true)); 67 | } 68 | 69 | $response = [ 70 | 'responseCode' => $this->browser->getSession()->getStatusCode(), 71 | 'response' => $result 72 | ]; 73 | 74 | return $response; 75 | } 76 | 77 | /** 78 | * Remove a database to the user 79 | * 80 | * @param Database $database 81 | * @return array 82 | */ 83 | public function removeDatabase(Database $database){ 84 | /** @var Collection $databases */ 85 | $databases = $this->getDatabases(); 86 | $databaseId = $database->id; 87 | 88 | // Remove the database and get the ids 89 | $databaseIds = $databases 90 | ->filter(function($value) use ($databaseId){ 91 | return $databaseId != $value->id; 92 | }) 93 | ->map(function($value){ 94 | return $value->id; 95 | }) 96 | ->toArray(); 97 | 98 | $data = [ 99 | 'databases' => $databaseIds 100 | ]; 101 | 102 | $result = $this->browser->putContent('https://forge.laravel.com/servers/'.$this->server_id.'/database-user/'.$this->id, $data); 103 | 104 | if ($this->browser->getSession()->getStatusCode() === 500) { 105 | throw new Exception('Error: '.print_r($result, true)); 106 | } 107 | 108 | $response = [ 109 | 'responseCode' => $this->browser->getSession()->getStatusCode(), 110 | 'response' => $result 111 | ]; 112 | 113 | return $response; 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/Mpociot/Blacksmith/Models/ForgeModel.php: -------------------------------------------------------------------------------- 1 | data = collect($data); 25 | $this->browser = $browser; 26 | 27 | $this->build(); 28 | } 29 | 30 | public function __get($key) 31 | { 32 | return $this->data->get($key); 33 | } 34 | 35 | protected function build() 36 | { 37 | $this->data->each(function ($value, $property) { 38 | if (property_exists($this, $property)) { 39 | $this->$property = $value; 40 | } 41 | }); 42 | } 43 | 44 | /** 45 | * @return array 46 | */ 47 | public function toArray() 48 | { 49 | return $this->data->toArray(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/Mpociot/Blacksmith/Models/Recipe.php: -------------------------------------------------------------------------------- 1 | browser->putContent('https://forge.laravel.com/recipes/'.$this->id, [ 15 | 'name' => $name, 16 | 'user' => $user, 17 | 'script' => $script, 18 | ]); 19 | 20 | if ($this->browser->getSession()->getStatusCode() === 500) { 21 | throw new Exception('Error: '.print_r($result, true)); 22 | } 23 | 24 | $this->data = $this->data->merge($result); 25 | 26 | return $this; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Mpociot/Blacksmith/Models/SSHKey.php: -------------------------------------------------------------------------------- 1 | data->get('sites'))->transform(function ($data) { 31 | return new Site($data, $this->browser); 32 | }); 33 | } 34 | 35 | /** 36 | * Refresh the server data. 37 | */ 38 | public function refresh(){ 39 | $serverData = $this->browser->getContent('https://forge.laravel.com/api/servers/'.$this->id)->toArray(); 40 | $this->data = collect($serverData); 41 | } 42 | 43 | /** 44 | * Get a site on this server 45 | * 46 | * @param $id 47 | * @return Site 48 | * @throws Exception 49 | */ 50 | public function getSite($id) { 51 | 52 | if(!is_numeric($id)) { 53 | $sites = $this->getSites(); 54 | $site = $sites->filter(function($site) use ($id){ return $site->name === $id; })->first(); 55 | if($site) { 56 | $id = $site->id; 57 | } 58 | } 59 | 60 | $siteData = $this->browser->getContent('https://forge.laravel.com/api/servers/'.$this->id.'/sites/'.$id)->toArray(); 61 | 62 | if(!$siteData) { 63 | throw new Exception(sprintf('Site "%s" could not be found', $id)); 64 | } 65 | 66 | return new Site($siteData, $this->browser); 67 | } 68 | 69 | /** 70 | * Create a new site on this server. 71 | * 72 | * @param string $siteName 73 | * @param string $projectType 74 | * @param string $directory 75 | * @param bool $wildcards 76 | * @return Site 77 | * @throws Exception 78 | */ 79 | public function addSite($siteName, $projectType = 'php', $directory = '/public', $wildcards = false) 80 | { 81 | $result = $this->browser->postContent('https://forge.laravel.com/servers/'.$this->id.'/sites', [ 82 | 'site_name' => $siteName, 83 | 'project_type' => $projectType, 84 | 'directory' => $directory, 85 | 'wildcards' => $wildcards, 86 | ]); 87 | 88 | if ($this->browser->getSession()->getStatusCode() === 500) { 89 | throw new Exception('Error: '.print_r($result, true)); 90 | } 91 | 92 | return new Site($result, $this->browser); 93 | } 94 | 95 | /** 96 | * Remove site 97 | * 98 | * @param $id 99 | * @return mixed 100 | * @throws Exception 101 | */ 102 | public function removeSite($id) 103 | { 104 | if(!is_numeric($id)) { 105 | $sites = $this->getSites(); 106 | $site = $sites->filter(function($site) use ($id){ return $site->name === $id; })->first(); 107 | if($site) { 108 | $id = $site->id; 109 | } 110 | } 111 | 112 | $this->browser->deleteContent('https://forge.laravel.com/api/servers/'.$this->id.'/sites/'.$id); 113 | $response = [ 114 | 'responseCode' => $this->browser->getSession()->getStatusCode() 115 | ]; 116 | 117 | return $response; 118 | } 119 | 120 | /** ------------------------------------------------------------------------ 121 | * Databases 122 | */ 123 | 124 | /** 125 | * Get all databases on this server. 126 | * 127 | * @return Collection 128 | */ 129 | public function getDatabases(){ 130 | return collect($this->data->get('databases'))->transform(function ($data) { 131 | return new Database($data, $this->browser); 132 | }); 133 | } 134 | 135 | /** 136 | * Get a database on this server 137 | * 138 | * @param $id 139 | * @return Database 140 | * @throws Exception 141 | */ 142 | public function getDatabase($id) { 143 | 144 | $criteria = !is_numeric($id) ? 'name' : 'id'; 145 | $databases = $this->getDatabases(); 146 | 147 | $database = $databases->filter(function($database) use ($criteria, $id){ 148 | return $database->{$criteria} == $id; 149 | })->first(); 150 | 151 | if(!$database) { 152 | throw new Exception(sprintf('Database "%s" could not be found', $id)); 153 | } 154 | 155 | return $database; 156 | } 157 | 158 | /** 159 | * Create a new database on this server. 160 | * 161 | * @param $databaseName 162 | * @param bool $username 163 | * @param bool $password 164 | * @return Database 165 | * @throws Exception 166 | */ 167 | public function addDatabase($databaseName, $username = false, $password = false) 168 | { 169 | $data = array_filter([ 170 | 'name' => $databaseName, 171 | 'user' => $username, 172 | 'password' => $password, 173 | ]); 174 | 175 | $result = $this->browser->postContent('https://forge.laravel.com/servers/'.$this->id.'/database', $data); 176 | 177 | if ($this->browser->getSession()->getStatusCode() === 500) { 178 | throw new Exception('Error: '.print_r($result, true)); 179 | } 180 | 181 | return new Database($result, $this->browser); 182 | } 183 | 184 | /** 185 | * Delete Database 186 | * 187 | * @param $id 188 | * @return mixed 189 | */ 190 | public function removeDatabase($id) 191 | { 192 | if(!is_numeric($id)) { 193 | $databases = $this->getDatabases(); 194 | $database = $databases->filter(function($database) use ($id){ return $database->name === $id; })->first(); 195 | if($database) { 196 | $id = $database->id; 197 | } 198 | } 199 | 200 | $this->browser->deleteContent('https://forge.laravel.com/servers/'.$this->id.'/database/'.$id); 201 | $response = [ 202 | 'responseCode' => $this->browser->getSession()->getStatusCode() 203 | ]; 204 | return $response; 205 | } 206 | 207 | 208 | /** ------------------------------------------------------------------------ 209 | * Database Users 210 | */ 211 | 212 | /** 213 | * Get all database users on this server. 214 | * 215 | * @return Collection 216 | */ 217 | public function getDatabaseUsers() 218 | { 219 | return collect($this->data->get('database_users'))->transform( 220 | function ($data) { 221 | return new DatabaseUser($data, $this->browser); 222 | } 223 | ); 224 | } 225 | 226 | /** 227 | * Get a database on this server 228 | * 229 | * @param $id 230 | * @return Database 231 | * @throws Exception 232 | */ 233 | public function getDatabaseUser($id) 234 | { 235 | $criteria = !is_numeric($id) ? 'name' : 'id'; 236 | $databaseUsers = $this->getDatabaseUsers(); 237 | 238 | $databaseUser = $databaseUsers->filter(function($databaseUser) use ($criteria, $id){ 239 | return $databaseUser->{$criteria} == $id; 240 | })->first(); 241 | 242 | if(!$databaseUser) { 243 | throw new Exception(sprintf('Database User "%s" could not be found', $id)); 244 | } 245 | 246 | return $databaseUser; 247 | } 248 | 249 | /** 250 | * Create a new database user on this server. 251 | * 252 | * @param bool $username 253 | * @param bool $password 254 | * @param array $canAccess 255 | * @return DatabaseUser 256 | * @throws Exception 257 | */ 258 | public function addDatabaseUser($username = false, $password = false, $canAccess = array()) 259 | { 260 | $databases = $this->getDatabases(); 261 | /** @var Collection $canAccess */ 262 | $canAccess = collect($canAccess); 263 | $canAccess = $canAccess->transform(function($databaseId) use ($databases) { 264 | $database = $this->getDatabase($databaseId); 265 | return $database->id; 266 | }); 267 | 268 | $data = [ 269 | 'name' => $username, 270 | 'password' => $password, 271 | 'databases' => $canAccess 272 | ]; 273 | 274 | $result = $this->browser->postContent('https://forge.laravel.com/servers/'.$this->id.'/database-user', $data); 275 | 276 | if ($this->browser->getSession()->getStatusCode() === 500) { 277 | throw new Exception('Error: '.print_r($result, true)); 278 | } 279 | 280 | return new DatabaseUser($result, $this->browser); 281 | } 282 | 283 | /** 284 | * Delete Database User 285 | * 286 | * @param $id 287 | * @return mixed 288 | */ 289 | public function removeDatabaseUser($id) 290 | { 291 | if(!is_numeric($id)) { 292 | $databaseUsers = $this->getDatabaseUsers(); 293 | $databaseUser = $databaseUsers->filter(function($databaseUser) use ($id){ return $databaseUser->name === $id; })->first(); 294 | if($databaseUser) { 295 | $id = $databaseUser->id; 296 | } 297 | } 298 | 299 | $this->browser->deleteContent('https://forge.laravel.com/servers/'.$this->id.'/database-user/'.$id); 300 | $response = [ 301 | 'responseCode' => $this->browser->getSession()->getStatusCode() 302 | ]; 303 | return $response; 304 | } 305 | 306 | /** 307 | * Update an existing database user on this server. 308 | * 309 | * @param bool $id 310 | * @param array $canAccess 311 | * @return DatabaseUser 312 | * @throws Exception 313 | */ 314 | public function updateDatabaseUser($id, $canAccess = array()) 315 | { 316 | $databaseUser = $this->getDatabaseUser($id); 317 | 318 | $databases = $this->getDatabases(); 319 | /** @var Collection $canAccess */ 320 | $canAccess = collect($canAccess); 321 | $canAccess = $canAccess->transform(function($databaseId) use ($databases) { 322 | $database = $this->getDatabase($databaseId); 323 | return $database->id; 324 | }); 325 | 326 | $data = [ 327 | 'databases' => $canAccess 328 | ]; 329 | 330 | $result = $this->browser->putContent('https://forge.laravel.com/servers/'.$this->id.'/database-user/'.$databaseUser->id, $data); 331 | 332 | if ($this->browser->getSession()->getStatusCode() === 500) { 333 | throw new Exception('Error: '.print_r($result, true)); 334 | } 335 | 336 | return new DatabaseUser($result, $this->browser); 337 | } 338 | 339 | /** ------------------------------------------------------------------------ 340 | * SSH Keys 341 | */ 342 | 343 | /** 344 | * Get all ssh keys on this server. 345 | * 346 | * @return Collection 347 | */ 348 | public function getSSHKeys(){ 349 | return collect($this->data->get('keys'))->transform(function ($data) { 350 | return new SSHKey($data, $this->browser); 351 | }); 352 | } 353 | 354 | /** 355 | * Add an SSH key to server. 356 | * 357 | * @param $name 358 | * @param $key 359 | * @return SSHKey 360 | * @throws Exception 361 | */ 362 | public function addSSHKey($name, $key) 363 | { 364 | $data = [ 365 | 'name' => $name, 366 | 'key' => $key, 367 | ]; 368 | $result = $this->browser->postContent('https://forge.laravel.com/servers/'.$this->id.'/key', $data); 369 | 370 | if ($this->browser->getSession()->getStatusCode() === 500) { 371 | throw new Exception('Error: '.print_r($result, true)); 372 | } 373 | 374 | return new SSHKey($result, $this->browser); 375 | } 376 | 377 | /** 378 | * Delete SSH Key from this server 379 | * 380 | * @param $id 381 | * @return mixed 382 | */ 383 | public function removeSSHKey($id) 384 | { 385 | if(!is_numeric($id)) { 386 | $sshKeys = $this->getSSHKeys(); 387 | $sshKey = $sshKeys->filter(function($sshKey) use ($id){ return $sshKey->name === $id; })->first(); 388 | if($sshKey) { 389 | $id = $sshKey->id; 390 | } 391 | } 392 | 393 | $this->browser->deleteContent('https://forge.laravel.com/servers/'.$this->id.'/key/'.$id); 394 | $response = [ 395 | 'responseCode' => $this->browser->getSession()->getStatusCode() 396 | ]; 397 | return $response; 398 | } 399 | 400 | /** ------------------------------------------------------------------------ 401 | * Scheduled Jobs 402 | */ 403 | 404 | /** 405 | * Get all scheduled jobs on this server. 406 | * 407 | * @return Collection 408 | */ 409 | public function getScheduledJobs(){ 410 | return collect($this->data->get('jobs'))->transform(function ($data) { 411 | return new ScheduledJob($data, $this->browser); 412 | }); 413 | } 414 | 415 | /** 416 | * Add an Scheduled Job to server. 417 | * 418 | * @param $command 419 | * @param $user 420 | * @param $frequency 421 | * @return ScheduledJob 422 | * @throws Exception 423 | */ 424 | public function addScheduledJob($command, $user, $frequency) 425 | { 426 | $data = [ 427 | 'command' => $command, 428 | 'user' => $user, 429 | 'frequency' => $frequency, 430 | ]; 431 | 432 | $result = $this->browser->postContent('https://forge.laravel.com/servers/'.$this->id.'/job', $data); 433 | 434 | if ($this->browser->getSession()->getStatusCode() === 500) { 435 | throw new Exception('Error: '.print_r($result, true)); 436 | } 437 | 438 | // Result is the full server object 439 | // So we pull out the last job 440 | $scheduledJobData = collect($result['jobs'])->last(); 441 | 442 | return new ScheduledJob($scheduledJobData, $this->browser); 443 | } 444 | 445 | /** 446 | * Delete Scheduled Job from this server 447 | * 448 | * @param $id 449 | * @return array 450 | * @throws Exception 451 | */ 452 | public function removeScheduledJob($id) 453 | { 454 | if(!is_numeric($id)) { 455 | $scheduledJobs = $this->getScheduledJobs(); 456 | $scheduledJob = $scheduledJobs->filter(function($scheduledJob) use ($id){ return $scheduledJob->command === $id; })->first(); 457 | if($scheduledJob) { 458 | $id = $scheduledJob->id; 459 | } 460 | } 461 | 462 | $result = $this->browser->deleteContent('https://forge.laravel.com/servers/'.$this->id.'/job/'.$id); 463 | 464 | if ($this->browser->getSession()->getStatusCode() === 500) { 465 | throw new Exception('Error: '.print_r($result, true)); 466 | } 467 | 468 | $response = [ 469 | 'responseCode' => $this->browser->getSession()->getStatusCode(), 470 | 'response' => $result 471 | ]; 472 | 473 | return $response; 474 | } 475 | 476 | /** ------------------------------------------------------------------------ 477 | * Metadata 478 | */ 479 | 480 | /** 481 | * Update the server metadata. 482 | * 483 | * @param $serverName 484 | * @param $ipAddress 485 | * @param $privateIpAddress 486 | * @param $size 487 | * @return $this 488 | * @throws Exception 489 | */ 490 | public function updateMetadata($serverName, $ipAddress, $privateIpAddress, $size) 491 | { 492 | $data = [ 493 | 'name' => $serverName, 494 | 'ip_address' => $ipAddress, 495 | 'private_ip_address' => $privateIpAddress, 496 | 'size' => $size, 497 | ]; 498 | 499 | $result = $this->browser->putContent('https://forge.laravel.com/servers/'.$this->id.'/meta', $data); 500 | 501 | if ($this->browser->getSession()->getStatusCode() === 500) { 502 | throw new Exception('Error: '.print_r($result, true)); 503 | } 504 | 505 | $response = [ 506 | 'responseCode' => $this->browser->getSession()->getStatusCode(), 507 | 'response' => $result 508 | ]; 509 | 510 | return $response; 511 | } 512 | 513 | /** 514 | * Update max file upload size 515 | * 516 | * @param $megaBytes 517 | * @return $this 518 | * @throws Exception 519 | */ 520 | public function updateMaxFileUploadSize($megaBytes) 521 | { 522 | $data = [ 523 | 'megabytes' => $megaBytes, 524 | ]; 525 | 526 | $result = $this->browser->putContent('https://forge.laravel.com/servers/'.$this->id.'/settings/php/max-upload-size', $data); 527 | 528 | if ($this->browser->getSession()->getStatusCode() === 500) { 529 | throw new Exception('Error: '.print_r($result, true)); 530 | } 531 | 532 | $response = [ 533 | 'responseCode' => $this->browser->getSession()->getStatusCode(), 534 | 'response' => $result 535 | ]; 536 | 537 | return $response; 538 | } 539 | } 540 | -------------------------------------------------------------------------------- /src/Mpociot/Blacksmith/Models/Site.php: -------------------------------------------------------------------------------- 1 | has_app_installed) { 34 | return false; 35 | } 36 | 37 | $data = [ 38 | 'repository' => $repository, 39 | 'provider' => $provider, 40 | 'branch' => $branch, 41 | 'composer' => $composer, 42 | 'migrate' => $migrate, 43 | ]; 44 | 45 | $response = $this->browser->postContent('https://forge.laravel.com/servers/'.$this->server_id.'/sites/'.$this->id.'/project', $data); 46 | 47 | return $response; 48 | } 49 | 50 | /** ------------------------------------------------------------------------ 51 | * Environment 52 | */ 53 | 54 | /** 55 | * Return the configured .env data 56 | * 57 | * @return string 58 | */ 59 | public function getEnvironment() 60 | { 61 | $result = $this->browser->getContent('https://forge.laravel.com/servers/'.$this->server_id.'/sites/'.$this->id.'/environment', true); 62 | 63 | if ($this->browser->getSession()->getStatusCode() === 500) { 64 | throw new Exception('Error: '.print_r($result, true)); 65 | } 66 | 67 | $response = [ 68 | 'responseCode' => $this->browser->getSession()->getStatusCode(), 69 | 'response' => $result 70 | ]; 71 | 72 | return $response; 73 | } 74 | 75 | /** 76 | * Update the configured .env data 77 | * 78 | * @return string 79 | */ 80 | public function updateEnvironment($env) 81 | { 82 | $data = [ 83 | 'env' => $env 84 | ]; 85 | 86 | $result = $this->browser->putContent('https://forge.laravel.com/servers/'.$this->server_id.'/sites/'.$this->id.'/environment', $data); 87 | 88 | if ($this->browser->getSession()->getStatusCode() === 500) { 89 | throw new Exception('Error: '.print_r($result, true)); 90 | } 91 | 92 | $response = [ 93 | 'responseCode' => $this->browser->getSession()->getStatusCode(), 94 | 'response' => $result 95 | ]; 96 | 97 | return $response; 98 | } 99 | 100 | /** ------------------------------------------------------------------------ 101 | * Nginx Config 102 | */ 103 | 104 | /** 105 | * Return the sites nginx config 106 | * 107 | * @return string 108 | */ 109 | public function getNginxConfig() 110 | { 111 | $result = $this->browser->getContent('https://forge.laravel.com/servers/'.$this->server_id.'/sites/'.$this->id.'/nginx/config', true); 112 | 113 | if ($this->browser->getSession()->getStatusCode() === 500) { 114 | throw new Exception('Error: '.print_r($result, true)); 115 | } 116 | 117 | $response = [ 118 | 'responseCode' => $this->browser->getSession()->getStatusCode(), 119 | 'response' => $result 120 | ]; 121 | 122 | return $response; 123 | } 124 | 125 | 126 | /** 127 | * Update the sites nginx config 128 | * 129 | * @return string 130 | */ 131 | public function updateNginxConfig($config) 132 | { 133 | $data = [ 134 | 'config' => $config 135 | ]; 136 | 137 | $result = $this->browser->putContent('https://forge.laravel.com/servers/'.$this->server_id.'/sites/'.$this->id.'/nginx/config', $data); 138 | 139 | if ($this->browser->getSession()->getStatusCode() === 500) { 140 | throw new Exception('Error: '.print_r($result, true)); 141 | } 142 | 143 | $response = [ 144 | 'responseCode' => $this->browser->getSession()->getStatusCode(), 145 | 'response' => $result 146 | ]; 147 | 148 | return $response; 149 | } 150 | 151 | /** ------------------------------------------------------------------------ 152 | * Meta 153 | */ 154 | 155 | /** 156 | * Update the site metadata. 157 | * 158 | * @param $directory 159 | * @return array 160 | */ 161 | public function updateWebDirectory($directory) 162 | { 163 | $data = [ 164 | 'directory' => $directory 165 | ]; 166 | 167 | $result = $this->browser->putContent('https://forge.laravel.com/servers/'.$this->server_id.'/sites/'.$this->id.'/directory', $data); 168 | 169 | if ($this->browser->getSession()->getStatusCode() === 500) { 170 | throw new Exception('Error: '.print_r($result, true)); 171 | } 172 | 173 | $response = [ 174 | 'responseCode' => $this->browser->getSession()->getStatusCode(), 175 | 'response' => $result 176 | ]; 177 | 178 | return $response; 179 | } 180 | 181 | /** ------------------------------------------------------------------------ 182 | * Deployments 183 | */ 184 | 185 | /** 186 | * Deploy the current installed application on this site. 187 | * 188 | * @return mixed 189 | */ 190 | public function deploy() 191 | { 192 | if ($this->has_app_installed) { 193 | return $this->browser->postContent('https://forge.laravel.com/servers/'.$this->server_id.'/sites/'.$this->id.'/deploy/now', []); 194 | } 195 | return false; 196 | } 197 | 198 | /** 199 | * Get the last deployment log on this site. 200 | * 201 | * @return mixed 202 | */ 203 | public function deployLog() 204 | { 205 | if ($this->has_app_installed) { 206 | return $this->browser->postContent('https://forge.laravel.com/servers/'.$this->server_id.'/sites/'.$this->id.'/deploy/log', [], true); 207 | } 208 | return ''; 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /src/Mpociot/Blacksmith/Models/User.php: -------------------------------------------------------------------------------- 1 |