Skip to content

Commit

Permalink
Merge pull request #54 from keboola/roman-pst-2400-handle-encryptiona…
Browse files Browse the repository at this point in the history
…pi-errors

PST-2400: Handle encryption-api errors during secrets migration
  • Loading branch information
romantmb authored Jan 21, 2025
2 parents 0134e97 + 5ba0131 commit 886c1e6
Show file tree
Hide file tree
Showing 2 changed files with 171 additions and 9 deletions.
34 changes: 25 additions & 9 deletions src/Migrate.php
Original file line number Diff line number Diff line change
Expand Up @@ -215,16 +215,32 @@ private function migrateSecrets(): void
),
['secrets'],
);
$response = $this->migrationsClient
->migrateConfiguration(
$this->sourceProjectToken,
Utils::getStackFromProjectUrl($this->destinationProjectUrl),
$this->destinationProjectToken,
$component['id'],
$config['id'],
(string) $defaultSourceBranch['id'],
$this->dryRun

try {
$response = $this->migrationsClient
->migrateConfiguration(
$this->sourceProjectToken,
Utils::getStackFromProjectUrl($this->destinationProjectUrl),
$this->destinationProjectToken,
$component['id'],
$config['id'],
(string) $defaultSourceBranch['id'],
$this->dryRun
);
} catch (EncryptionClientException $e) {
$this->logger->error(
sprintf(
'Migrating configuration "%s" of component "%s" failed: %s',
$config['id'],
$component['id'],
$e->getMessage()
),
[
'exception' => $e,
],
);
continue;
}

if (in_array($component['id'], self::SNOWFLAKE_WRITER_COMPONENT_IDS, true)) {
$this->preserveProperSnowflakeWorkspace(
Expand Down
146 changes: 146 additions & 0 deletions tests/phpunit/MigrateTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Keboola\AppProjectMigrate\JobRunner\SyrupJobRunner;
use Keboola\AppProjectMigrate\Migrate;
use Keboola\Component\UserException;
use Keboola\EncryptionApiClient\Exception\ClientException as EncryptionClientException;
use Keboola\EncryptionApiClient\Migrations;
use Keboola\StorageApi\Client as StorageClient;
use Keboola\Syrup\ClientException;
Expand Down Expand Up @@ -597,6 +598,151 @@ public function testMigrateSnowflakeWritersWithSharedWorkspacesSuccess(): void
);
}

public function testMigrateShouldHandleEncryptionApiErrorResponse(): void
{
$sourceJobRunnerMock = $this->createMock(QueueV2JobRunner::class);
$destJobRunnerMock = $this->createMock(QueueV2JobRunner::class);

// generate credentials
$this->mockAddMethodGenerateAbsReadCredentials($sourceJobRunnerMock);
$this->mockAddMethodBackupProject(
$sourceJobRunnerMock,
[
'id' => '222',
'status' => 'success',
],
true
);

$destJobRunnerMock->method('runJob')
->willReturn([
'id' => '222',
'status' => 'success',
]);

$config = new Config(
[
'parameters' => [
'sourceKbcUrl' => 'https://connection.keboola.com',
'#sourceKbcToken' => 'xyz',
'migrateSecrets' => true,
'#sourceManageToken' => 'manage-token',
],
],
new ConfigDefinition()
);

$logsHandler = new TestHandler();
$logger = new Logger('tests', [$logsHandler]);

$sourceClientMock = $this->createMock(StorageClient::class);
$sourceClientMock
->method('apiGet')
->willReturnMap([
[
'dev-branches/', null, [],
[
[
'id' => '123',
'name' => 'default',
'isDefault' => true,
],
],
],
[
'components?include=', null, [],
[
[
'id' => 'some-component',
'configurations' => [
[
'id' => '101',
],
[
'id' => '666',
],
[
'id' => '103',
],
],
],
],
],
])
;
$sourceClientMock
->method('getServiceUrl')
->with('encryption')
->willReturn('https://encryption.keboola.com')
;

$destClientMock = $this->createMock(StorageClient::class);

$encryptionApiException = new EncryptionClientException('Something went wrong');

$migrationsClientMock = $this->createMock(Migrations::class);
$migrationsClientMock
->expects(self::exactly(3))
->method('migrateConfiguration')
->willReturnCallback(function (...$args) use ($encryptionApiException) {
[, $destinationStack, , , $configId] = $args;
if ($configId === '666') {
throw $encryptionApiException;
}
return [
'message' => "Configuration with ID '$configId' successfully " .
"migrated to stack '$destinationStack'.",
'data' => [],
];
});

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

$migrate->run();

self::assertTrue(
$logsHandler->hasInfo('Migrating configurations with secrets'),
);

self::assertTrue(
$logsHandler->hasInfo('Migrating configuration "101" of component "some-component"'),
);
self::assertTrue(
$logsHandler->hasInfo('Configuration with ID \'101\' successfully migrated to stack \'dest-stack\'.'),
);

self::assertTrue(
$logsHandler->hasInfo('Migrating configuration "666" of component "some-component"'),
);
self::assertTrue(
$logsHandler->hasError([
'message' => 'Migrating configuration "666" of component "some-component" failed: Something went wrong',
'context' => [
'exception' => $encryptionApiException,
],
]),
);

self::assertTrue(
$logsHandler->hasInfo('Migrating configuration "103" of component "some-component"'),
);
self::assertTrue(
$logsHandler->hasInfo('Configuration with ID \'103\' successfully migrated to stack \'dest-stack\'.'),
);
}

public function testShouldFailOnSnapshotError(): void
{
$sourceJobRunnerMock = $this->createMock(SyrupJobRunner::class);
Expand Down

0 comments on commit 886c1e6

Please sign in to comment.