Skip to content

Commit

Permalink
Pass StorageClient & MigrationsClient directly through the constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
romantmb committed May 10, 2024
1 parent f17aa55 commit a9db868
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 73 deletions.
10 changes: 10 additions & 0 deletions src/Component.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Keboola\AppProjectMigrate\JobRunner\JobRunnerFactory;
use Keboola\Component\BaseComponent;
use Keboola\Component\UserException;
use Keboola\EncryptionApiClient\Migrations;
use Keboola\StorageApi\Client as StorageClient;
use Keboola\StorageApi\ClientException as StorageClientException;
use Keboola\StorageApi\Components;
Expand Down Expand Up @@ -51,6 +52,10 @@ protected function run(): void
);
}

if ($config->shouldMigrateSecrets() && !$config->getSourceManageToken()) {
throw new UserException('#sourceManageToken must be set.', 422);
}

Utils::checkMigrationApps($sourceProjectClient, $destProjectClient);

if (!Utils::checkIfProjectEmpty($destProjectClient, new Components($destProjectClient))) {
Expand All @@ -71,11 +76,16 @@ protected function run(): void

$sourceJobRunner = JobRunnerFactory::create($sourceProjectClient, $logger);
$destJobRunner = JobRunnerFactory::create($destProjectClient, $logger);
$migrationsClient = new Migrations($config->getSourceManageToken() ?? '', [
'url' => $sourceProjectClient->getServiceUrl('encryption'),
]);

$migrate = new Migrate(
$config,
$sourceJobRunner,
$destJobRunner,
$sourceProjectClient,
$migrationsClient,
$destProjectClient->getApiUrl(),
$destProjectClient->getTokenString(),
$logger,
Expand Down
60 changes: 12 additions & 48 deletions src/Migrate.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,11 @@

namespace Keboola\AppProjectMigrate;

use Closure;
use Keboola\AppProjectMigrate\JobRunner\JobRunner;
use Keboola\AppProjectMigrate\JobRunner\SyrupJobRunner;
use Keboola\Component\UserException;
use Keboola\EncryptionApiClient\Exception\ClientException as EncryptionClientException;
use Keboola\EncryptionApiClient\Migrations;
use Keboola\EncryptionApiClient\Migrations as MigrationsClient;
use Keboola\StorageApi\Client as StorageClient;
use Keboola\StorageApi\Components;
use Keboola\StorageApi\DevBranches;
Expand All @@ -24,6 +23,10 @@ class Migrate

private JobRunner $destJobRunner;

private StorageClient $sourceProjectStorageClient;

private MigrationsClient $migrationsClient;

private string $sourceProjectUrl;

private string $sourceProjectToken;
Expand All @@ -32,18 +35,12 @@ class Migrate

private string $destinationProjectToken;

private ?string $sourceManageApiToken;

private LoggerInterface $logger;

private bool $directDataMigration;

private bool $migrateSecrets;

private Closure $sourceClientFactory;

private Closure $migrationsClientFactory;

public const OBSOLETE_COMPONENTS = [
'orchestrator',
'gooddata-writer',
Expand All @@ -53,17 +50,20 @@ public function __construct(
Config $config,
JobRunner $sourceJobRunner,
JobRunner $destJobRunner,
StorageClient $sourceProjectStorageClient,
MigrationsClient $migrationsClient,
string $destinationProjectUrl,
string $destinationProjectToken,
LoggerInterface $logger
) {
$this->sourceJobRunner = $sourceJobRunner;
$this->destJobRunner = $destJobRunner;
$this->sourceProjectStorageClient = $sourceProjectStorageClient;
$this->migrationsClient = $migrationsClient;
$this->sourceProjectUrl = $config->getSourceProjectUrl();
$this->sourceProjectToken = $config->getSourceProjectToken();
$this->destinationProjectUrl = $destinationProjectUrl;
$this->destinationProjectToken = $destinationProjectToken;
$this->sourceManageApiToken = $config->getSourceManageToken();
$this->directDataMigration = $config->directDataMigration();
$this->migrateSecrets = $config->shouldMigrateSecrets();
$this->logger = $logger;
Expand Down Expand Up @@ -100,16 +100,6 @@ public function run(): void
}
}

public function setSourceClientFactory(callable $factory): void
{
$this->sourceClientFactory = Closure::fromCallable($factory);
}

public function setMigrationsClientFactory(callable $factory): void
{
$this->migrationsClientFactory = Closure::fromCallable($factory);
}

private function generateBackupCredentials(): array
{
$this->logger->info('Creating backup credentials');
Expand Down Expand Up @@ -162,22 +152,17 @@ private function migrateSecrets(): void
{
$this->logger->info('Migrating secrets in configurations', ['secrets']);

$sourceClient = $this->createSourceClient();

$sourceDevBranches = new DevBranches($sourceClient);
$sourceDevBranches = new DevBranches($this->sourceProjectStorageClient);
$sourceBranches = $sourceDevBranches->listBranches();
$defaultSourceBranch = current(array_filter($sourceBranches, fn($b) => $b['isDefault'] === true));

$sourceComponentsApi = new Components($sourceClient);
$sourceComponentsApi = new Components($this->sourceProjectStorageClient);
$components = $sourceComponentsApi->listComponents();
if (!$components) {
$this->logger->info('There are no components to migrate.', ['secrets']);
return;
}

$encryptionApiUrl = $sourceClient->getServiceUrl('encryption');
$migrations = $this->createMigrationsClient($encryptionApiUrl);

foreach ($components as $component) {
if (in_array($component['id'], self::OBSOLETE_COMPONENTS, true)) {
$this->logger->info(
Expand All @@ -188,7 +173,7 @@ private function migrateSecrets(): void
}

foreach ($component['configurations'] as $config) {
$response = $migrations
$response = $this->migrationsClient
->migrateConfiguration(
$this->sourceProjectToken,
Utils::getStackFromProjectUrl($this->destinationProjectUrl),
Expand All @@ -203,27 +188,6 @@ private function migrateSecrets(): void
}
}

private function createSourceClient(): StorageClient
{
if (isset($this->sourceClientFactory)) {
return (fn(): StorageClient => ($this->sourceClientFactory)())();
}
return new StorageClient(['token' => $this->sourceProjectToken, 'url' => $this->sourceProjectUrl ]);
}

private function createMigrationsClient(string $encryptionApiUrl): Migrations
{
if (isset($this->migrationsClientFactory)) {
return (fn(): Migrations => ($this->migrationsClientFactory)($encryptionApiUrl))();
}
if (!$this->sourceManageApiToken) {
throw new UserException('#sourceManageToken must be set', 422);
}
return new Migrations($this->sourceManageApiToken, [
'url' => $encryptionApiUrl,
]);
}

private function migrateDataOfTablesDirectly(): void
{
$this->logger->info('Migrate data of tables directly.');
Expand Down
61 changes: 36 additions & 25 deletions tests/phpunit/MigrateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,17 +133,6 @@ public function testMigrateSuccess(
$logsHandler = new TestHandler();
$logger = new Logger('tests', [$logsHandler]);

/** @var JobRunner $sourceJobRunnerMock */
/** @var JobRunner $destJobRunnerMock */
$migrate = new Migrate(
$config,
$sourceJobRunnerMock,
$destJobRunnerMock,
'https://dest-stack/',
'dest-token',
$logger,
);

$sourceClientMock = $this->createMock(StorageClient::class);
$sourceClientMock
->method('apiGet')
Expand Down Expand Up @@ -211,8 +200,18 @@ public function testMigrateSuccess(
$migrationsClientMock->expects(self::never())->method('migrateConfiguration');
}

$migrate->setSourceClientFactory(fn() => $sourceClientMock);
$migrate->setMigrationsClientFactory(fn() => $migrationsClientMock);
/** @var JobRunner $sourceJobRunnerMock */
/** @var JobRunner $destJobRunnerMock */
$migrate = new Migrate(
$config,
$sourceJobRunnerMock,
$destJobRunnerMock,
$sourceClientMock,
$migrationsClientMock,
'https://dest-stack/',
'dest-token',
$logger,
);

$migrate->run();

Expand Down Expand Up @@ -249,6 +248,8 @@ public function testShouldFailOnSnapshotError(): void
{
$sourceJobRunnerMock = $this->createMock(SyrupJobRunner::class);
$destJobRunnerMock = $this->createMock(SyrupJobRunner::class);
$sourceClientMock = $this->createMock(StorageClient::class);
$migrationsClientMock = $this->createMock(Migrations::class);

// generate credentials
$this->mockAddMethodGenerateS3ReadCredentials($sourceJobRunnerMock);
Expand Down Expand Up @@ -286,6 +287,8 @@ public function testShouldFailOnSnapshotError(): void
$config,
$sourceJobRunnerMock,
$destJobRunnerMock,
$sourceClientMock,
$migrationsClientMock,
'xxx-b',
'yyy-b',
new NullLogger(),
Expand All @@ -295,20 +298,22 @@ public function testShouldFailOnSnapshotError(): void

public function testShouldFailOnRestoreError(): void
{
$sourceClientMock = $this->createMock(SyrupJobRunner::class);
$destClientMock = $this->createMock(SyrupJobRunner::class);
$sourceJobRunnerMock = $this->createMock(SyrupJobRunner::class);
$destJobRunnerMock = $this->createMock(SyrupJobRunner::class);
$sourceClientMock = $this->createMock(StorageClient::class);
$migrationsClientMock = $this->createMock(Migrations::class);

$this->mockAddMethodGenerateS3ReadCredentials($sourceClientMock);
$this->mockAddMethodGenerateS3ReadCredentials($sourceJobRunnerMock);
$this->mockAddMethodBackupProject(
$sourceClientMock,
$sourceJobRunnerMock,
[
'id' => '222',
'status' => 'success',
],
false
);

$destClientMock
$destJobRunnerMock
->method('runJob')
->willReturn([
'id' => '222',
Expand All @@ -335,8 +340,10 @@ public function testShouldFailOnRestoreError(): void

$migrate = new Migrate(
$config,
$sourceJobRunnerMock,
$destJobRunnerMock,
$sourceClientMock,
$destClientMock,
$migrationsClientMock,
'xxx-b',
'yyy-b',
new NullLogger(),
Expand All @@ -346,20 +353,22 @@ public function testShouldFailOnRestoreError(): void

public function testCatchSyrupClientException(): void
{
$sourceClientMock = $this->createMock(SyrupJobRunner::class);
$destinationClientMock = $this->createMock(SyrupJobRunner::class);
$sourceJobRunnerMock = $this->createMock(SyrupJobRunner::class);
$destJobRunnerMock = $this->createMock(SyrupJobRunner::class);
$sourceClientMock = $this->createMock(StorageClient::class);
$migrationsClientMock = $this->createMock(Migrations::class);

$this->mockAddMethodGenerateS3ReadCredentials($sourceClientMock);
$this->mockAddMethodGenerateS3ReadCredentials($sourceJobRunnerMock);
$this->mockAddMethodBackupProject(
$sourceClientMock,
$sourceJobRunnerMock,
[
'id' => '222',
'status' => 'success',
],
false
);

$destinationClientMock
$destJobRunnerMock
->method('runJob')
->willThrowException(
new ClientException('Test ClientException', 401)
Expand All @@ -380,8 +389,10 @@ public function testCatchSyrupClientException(): void

$migrate = new Migrate(
$config,
$sourceJobRunnerMock,
$destJobRunnerMock,
$sourceClientMock,
$destinationClientMock,
$migrationsClientMock,
'xxx-b',
'yyy-b',
new NullLogger(),
Expand Down

0 comments on commit a9db868

Please sign in to comment.