Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions app/Commands/Concerns/InteractsWithCloudflare.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace App\Commands\Concerns;

use App\Integrations\Cloudflare\CloudflareConnector;
use Saloon\Http\Response;

trait InteractsWithCloudflare
{
Expand Down Expand Up @@ -145,4 +146,45 @@ protected function resolveZoneIdForHostname(CloudflareConnector $connector, stri

return null;
}

/**
* Resolve a zone ID or domain name to a zone ID.
*/
protected function resolveZoneId(CloudflareConnector $connector, string $zone): ?string
{
if (preg_match('/^[a-f0-9]{32}$/', $zone) === 1) {
return $zone;
}

$response = $connector->zones()->list($zone);

if ($response->successful()) {
$zones = $response->json('result', []);

return $zones[0]['id'] ?? null;
}

return null;
}

protected function truncate(string $value, int $length): string
{
return strlen($value) > $length
? substr($value, 0, $length - 3).'...'
: $value;
}

/**
* Prefer Cloudflare errors.0.message when present.
*/
protected function formatApiError(Response $response): string
{
$message = $response->json('errors.0.message');

if (is_string($message) && $message !== '') {
return $message;
}

return $response->body();
}
}
29 changes: 6 additions & 23 deletions app/Commands/DnsCreateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use App\Commands\Concerns\InteractsWithCloudflare;
use App\Commands\Concerns\OutputsJson;
use App\Integrations\Cloudflare\CloudflareConnector;
use LaravelZero\Framework\Commands\Command;

class DnsCreateCommand extends Command
Expand All @@ -32,17 +31,13 @@ public function handle(): int
return self::FAILURE;
}

$zone = $this->argument('zone');

if (! preg_match('/^[a-f0-9]{32}$/', $zone)) {
$zoneId = $this->resolveZoneId($connector, $zone);
if (! $zoneId) {
return $this->jsonFail("Zone not found: {$zone}");
}
$zone = $zoneId;
$zone = (string) $this->argument('zone');
$zoneId = $this->resolveZoneId($connector, $zone);
if (! $zoneId) {
return $this->jsonFail("Zone not found: {$zone}");
}

$response = $connector->dns($zone)->create(
$response = $connector->dns($zoneId)->create(
$this->argument('type'),
$this->argument('name'),
$this->argument('content'),
Expand All @@ -51,7 +46,7 @@ public function handle(): int
);

if (! $response->successful()) {
return $this->jsonFail('Failed to create DNS record: '.$response->body());
return $this->jsonFail('Failed to create DNS record: '.$this->formatApiError($response));
}

$record = $response->json('result');
Expand All @@ -71,16 +66,4 @@ public function handle(): int

return self::SUCCESS;
}

protected function resolveZoneId(CloudflareConnector $connector, string $name): ?string
{
$response = $connector->zones()->list($name);
if ($response->successful()) {
$zones = $response->json('result', []);

return $zones[0]['id'] ?? null;
}

return null;
}
}
61 changes: 17 additions & 44 deletions app/Commands/DnsDeleteCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@

namespace App\Commands;

use App\Integrations\Cloudflare\CloudflareConnector;
use App\Commands\Concerns\InteractsWithCloudflare;
use App\Commands\Concerns\OutputsJson;
use LaravelZero\Framework\Commands\Command;

class DnsDeleteCommand extends Command
{
use InteractsWithCloudflare;
use OutputsJson;

protected $signature = 'dns:delete
{zone : Zone ID or domain name}
{id : DNS record ID to delete}
Expand All @@ -20,71 +24,40 @@ class DnsDeleteCommand extends Command
public function handle(): int
{
$connector = $this->getConnector();
if ($connector === null) {
return self::FAILURE;
}

$zone = (string) $this->argument('zone');
$recordId = (string) $this->argument('id');

// If zone looks like a domain, resolve it to ID
if (! preg_match('/^[a-f0-9]{32}$/', $zone)) {
$zoneId = $this->resolveZoneId($connector, $zone);
if (! $zoneId) {
$this->error("Zone not found: {$zone}");

return self::FAILURE;
}
$zone = $zoneId;
$zoneId = $this->resolveZoneId($connector, $zone);
if (! $zoneId) {
return $this->jsonFail("Zone not found: {$zone}");
}

if (! $this->option('force')) {
if (! $this->option('force') && ! $this->wantsJson()) {
if (! $this->confirm("Delete DNS record {$recordId}?")) {
$this->info('Cancelled.');

return self::SUCCESS;
}
}

$response = $connector->dns($zone)->delete($recordId);
$response = $connector->dns($zoneId)->delete($recordId);

if (! $response->successful()) {
$this->error('Failed to delete DNS record: '.$response->body());

return self::FAILURE;
return $this->jsonFail('Failed to delete DNS record: '.$this->formatApiError($response));
}

$result = $response->json('result');

if ($this->option('json')) {
$this->line(json_encode($result ?? ['id' => $recordId], JSON_PRETTY_PRINT));

return self::SUCCESS;
if ($this->wantsJson()) {
return $this->jsonSuccess($result ?? ['id' => $recordId]);
}

$this->info('DNS record deleted successfully.');

return self::SUCCESS;
}

protected function resolveZoneId(CloudflareConnector $connector, string $name): ?string
{
$response = $connector->zones()->list($name);
if ($response->successful()) {
$zones = $response->json('result', []);

return $zones[0]['id'] ?? null;
}

return null;
}

protected function getConnector(): CloudflareConnector
{
$token = env('CLOUDFLARE_API_TOKEN');
$accountId = env('CLOUDFLARE_ACCOUNT_ID');

if (! $token) {
$this->error('CLOUDFLARE_API_TOKEN not set');
exit(1);
}

return new CloudflareConnector($token, $accountId);
}
}
36 changes: 6 additions & 30 deletions app/Commands/DnsListCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

use App\Commands\Concerns\InteractsWithCloudflare;
use App\Commands\Concerns\OutputsJson;
use App\Integrations\Cloudflare\CloudflareConnector;
use LaravelZero\Framework\Commands\Command;

class DnsListCommand extends Command
Expand All @@ -29,23 +28,19 @@ public function handle(): int
return self::FAILURE;
}

$zone = $this->argument('zone');

if (! preg_match('/^[a-f0-9]{32}$/', $zone)) {
$zoneId = $this->resolveZoneId($connector, $zone);
if (! $zoneId) {
return $this->jsonFail("Zone not found: {$zone}");
}
$zone = $zoneId;
$zone = (string) $this->argument('zone');
$zoneId = $this->resolveZoneId($connector, $zone);
if (! $zoneId) {
return $this->jsonFail("Zone not found: {$zone}");
}

$response = $connector->dns($zone)->list(
$response = $connector->dns($zoneId)->list(
$this->option('type'),
$this->option('name')
);

if (! $response->successful()) {
return $this->jsonFail('Failed to list DNS records: '.$response->body());
return $this->jsonFail('Failed to list DNS records: '.$this->formatApiError($response));
}

$records = $response->json('result', []);
Expand Down Expand Up @@ -73,23 +68,4 @@ public function handle(): int

return self::SUCCESS;
}

protected function resolveZoneId(CloudflareConnector $connector, string $name): ?string
{
$response = $connector->zones()->list($name);
if ($response->successful()) {
$zones = $response->json('result', []);

return $zones[0]['id'] ?? null;
}

return null;
}

protected function truncate(string $value, int $length): string
{
return strlen($value) > $length
? substr($value, 0, $length - 3).'...'
: $value;
}
}
60 changes: 16 additions & 44 deletions app/Commands/DnsUpdateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@

namespace App\Commands;

use App\Integrations\Cloudflare\CloudflareConnector;
use App\Commands\Concerns\InteractsWithCloudflare;
use App\Commands\Concerns\OutputsJson;
use LaravelZero\Framework\Commands\Command;

class DnsUpdateCommand extends Command
{
use InteractsWithCloudflare;
use OutputsJson;

protected $signature = 'dns:update
{zone : Zone ID or domain name}
{id : DNS record ID to update}
Expand All @@ -24,20 +28,17 @@ class DnsUpdateCommand extends Command
public function handle(): int
{
$connector = $this->getConnector();
$zone = (string) $this->argument('zone');

// If zone looks like a domain, resolve it to ID
if (! preg_match('/^[a-f0-9]{32}$/', $zone)) {
$zoneId = $this->resolveZoneId($connector, $zone);
if (! $zoneId) {
$this->error("Zone not found: {$zone}");
if ($connector === null) {
return self::FAILURE;
}

return self::FAILURE;
}
$zone = $zoneId;
$zone = (string) $this->argument('zone');
$zoneId = $this->resolveZoneId($connector, $zone);
if (! $zoneId) {
return $this->jsonFail("Zone not found: {$zone}");
}

$response = $connector->dns($zone)->update(
$response = $connector->dns($zoneId)->update(
(string) $this->argument('id'),
(string) $this->argument('type'),
(string) $this->argument('name'),
Expand All @@ -47,17 +48,13 @@ public function handle(): int
);

if (! $response->successful()) {
$this->error('Failed to update DNS record: '.$response->body());

return self::FAILURE;
return $this->jsonFail('Failed to update DNS record: '.$this->formatApiError($response));
}

$record = $response->json('result');

if ($this->option('json')) {
$this->line(json_encode($record, JSON_PRETTY_PRINT));

return self::SUCCESS;
if ($this->wantsJson()) {
return $this->jsonSuccess($record);
}

$this->info('DNS record updated successfully!');
Expand All @@ -72,29 +69,4 @@ public function handle(): int

return self::SUCCESS;
}

protected function resolveZoneId(CloudflareConnector $connector, string $name): ?string
{
$response = $connector->zones()->list($name);
if ($response->successful()) {
$zones = $response->json('result', []);

return $zones[0]['id'] ?? null;
}

return null;
}

protected function getConnector(): CloudflareConnector
{
$token = env('CLOUDFLARE_API_TOKEN');
$accountId = env('CLOUDFLARE_ACCOUNT_ID');

if (! $token) {
$this->error('CLOUDFLARE_API_TOKEN not set');
exit(1);
}

return new CloudflareConnector($token, $accountId);
}
}
2 changes: 1 addition & 1 deletion app/Commands/TunnelCreateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public function handle(): int
$response = $connector->tunnels()->create($name);

if (! $response->successful()) {
return $this->jsonFail('Failed to create tunnel: '.$response->body());
return $this->jsonFail('Failed to create tunnel: '.$this->formatApiError($response));
}

$tunnel = $response->json('result') ?? [];
Expand Down
2 changes: 1 addition & 1 deletion app/Commands/TunnelDeleteCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public function handle(): int
$response = $connector->tunnels()->delete($tunnelId);

if (! $response->successful()) {
return $this->jsonFail('Failed to delete tunnel: '.$response->body());
return $this->jsonFail('Failed to delete tunnel: '.$this->formatApiError($response));
}

if ($this->wantsJson()) {
Expand Down
2 changes: 1 addition & 1 deletion app/Commands/TunnelExposeCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function handle(): int
$response = $connector->tunnels()->create($name);

if (! $response->successful()) {
return $this->jsonFail('Failed to create tunnel: '.$response->body());
return $this->jsonFail('Failed to create tunnel: '.$this->formatApiError($response));
}

$tunnel = $response->json('result') ?? [];
Expand Down
Loading
Loading