Skip to content

Commit a0dd530

Browse files
authored
Merge pull request #5 from magento-commerce/MC-38424
MC-38424: Support for Remote Storage
2 parents 75a4a56 + a98f42f commit a0dd530

File tree

12 files changed

+726
-60
lines changed

12 files changed

+726
-60
lines changed

config/schema.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,23 @@ variables:
668668
- MC-31387
669669
- MDVA-4567
670670
- MC-45634
671+
REMOTE_STORAGE:
672+
description: Configures remote storage credentials.
673+
magento_version: '>=2.4.2'
674+
type: array
675+
stages:
676+
- deploy
677+
default:
678+
deploy: []
679+
examples:
680+
- stage:
681+
deploy:
682+
REMOTE_STORAGE:
683+
adater: aws_s3
684+
prefix: test-prefix
685+
config:
686+
region: us-east-1
687+
bucket: test-bucket
671688

672689
# Environment variables
673690
ENV_RELATIONSHIPS:

dist/error-codes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ Warning errors indicate a problem with the Magento Commerce Cloud project config
150150
| 2025 | install-update:split-db | Slave connection not set. | |
151151
| 2026 | pre-deploy:restore-writable-dirs | Failed to restore some data generated during the build phase to the mounted directories | Check the `cloud.log` for more information. |
152152
| 2027 | validate-config:mage-mode-variable | Mode value for MAGE_MODE environment variable not supported | Remove the MAGE_MODE environment variable, or change its value to "production". Magento Cloud supports "production" mode only. |
153+
| 2028 | remote-storage | Remote storage could not be enabled. | Verify remote storage credentials |
153154

154155
### Post-deploy stage
155156

scenario/deploy.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@
126126
</argument>
127127
</arguments>
128128
</step>
129+
<step name="remote-storage" type="Magento\MagentoCloud\Step\Deploy\RemoteStorage" priority="1250"/>
129130
<step name="disable-maintenance-mode" type="Magento\MagentoCloud\Step\DisableMaintenanceMode" priority="1300"/>
130131
<onFail>
131132
<action name="create-deploy-failed-flag" type="Magento\MagentoCloud\OnFail\Action\CreateDeployFailedFlag" priority="100"/>

src/App/Error.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ class Error
132132
public const WARN_SLAVE_CONNECTION_NOT_SET = 2025;
133133
public const WARN_COPY_MOUNTED_DIRS_FAILED = 2026;
134134
public const WARN_NOT_SUPPORTED_MAGE_MODE = 2027;
135+
public const WARN_REMOTE_STORAGE_CANNOT_BE_ENABLED = 2028;
135136

136137
/**
137138
* Post-deploy

src/Config/RemoteStorage.php

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\MagentoCloud\Config;
9+
10+
use Magento\MagentoCloud\Config\Stage\DeployInterface;
11+
12+
/**
13+
* Config for remote storage.
14+
*/
15+
class RemoteStorage
16+
{
17+
/**
18+
* @var DeployInterface
19+
*/
20+
private $deployConfig;
21+
22+
/**
23+
* @param DeployInterface $deployConfig
24+
*/
25+
public function __construct(DeployInterface $deployConfig)
26+
{
27+
$this->deployConfig = $deployConfig;
28+
}
29+
30+
/**
31+
* @return string
32+
*/
33+
public function getDriver(): string
34+
{
35+
return (string)($this->deployConfig->get(DeployInterface::VAR_REMOTE_STORAGE)['driver'] ?? '');
36+
}
37+
38+
/**
39+
* @return string
40+
*/
41+
public function getPrefix(): string
42+
{
43+
return (string)($this->deployConfig->get(DeployInterface::VAR_REMOTE_STORAGE)['prefix'] ?? '');
44+
}
45+
46+
/**
47+
* @return string[]
48+
*/
49+
public function getConfig(): array
50+
{
51+
return (array)($this->deployConfig->get(DeployInterface::VAR_REMOTE_STORAGE)['config'] ?? []);
52+
}
53+
}

src/Config/Stage/DeployInterface.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ interface DeployInterface extends StageConfigInterface
2929
public const VAR_CLEAN_STATIC_FILES = 'CLEAN_STATIC_FILES';
3030
public const VAR_UPDATE_URLS = 'UPDATE_URLS';
3131
public const VAR_FORCE_UPDATE_URLS = 'FORCE_UPDATE_URLS';
32+
public const VAR_REMOTE_STORAGE = 'REMOTE_STORAGE';
3233

3334
/**
3435
* The variable responsible to set lock provider for Magento 2.2.5 and higher.

src/Step/Deploy/InstallUpdate/Install/Setup/InstallCommandFactory.php

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Magento\MagentoCloud\Service\ServiceException;
2222
use Magento\MagentoCloud\Util\UrlManager;
2323
use Magento\MagentoCloud\Util\PasswordGenerator;
24+
use Magento\MagentoCloud\Config\RemoteStorage;
2425

2526
/**
2627
* Generates command for magento installation
@@ -78,6 +79,11 @@ class InstallCommandFactory
7879
*/
7980
private $elasticSearch;
8081

82+
/**
83+
* @var RemoteStorage
84+
*/
85+
private $remoteStorage;
86+
8187
/**
8288
* @param UrlManager $urlManager
8389
* @param AdminDataInterface $adminData
@@ -88,6 +94,9 @@ class InstallCommandFactory
8894
* @param DbConfig $dbConfig
8995
* @param MagentoVersion $magentoVersion
9096
* @param ElasticSearch $elasticSearch
97+
* @param RemoteStorage $remoteStorage
98+
*
99+
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
91100
*/
92101
public function __construct(
93102
UrlManager $urlManager,
@@ -98,7 +107,8 @@ public function __construct(
98107
ElasticSuite $elasticSuite,
99108
DbConfig $dbConfig,
100109
MagentoVersion $magentoVersion,
101-
ElasticSearch $elasticSearch
110+
ElasticSearch $elasticSearch,
111+
RemoteStorage $remoteStorage
102112
) {
103113
$this->urlManager = $urlManager;
104114
$this->adminData = $adminData;
@@ -109,6 +119,7 @@ public function __construct(
109119
$this->dbConfig = $dbConfig;
110120
$this->magentoVersion = $magentoVersion;
111121
$this->elasticSearch = $elasticSearch;
122+
$this->remoteStorage = $remoteStorage;
112123
}
113124

114125
/**
@@ -127,7 +138,8 @@ public function create(): string
127138
$options = array_replace(
128139
$this->getBaseOptions(),
129140
$this->getAdminOptions(),
130-
$this->getEsOptions()
141+
$this->getEsOptions(),
142+
$this->getRemoteStorageOptions()
131143
);
132144
} catch (GenericException $exception) {
133145
throw new ConfigException($exception->getMessage(), $exception->getCode(), $exception);
@@ -237,6 +249,39 @@ private function getEsOptions(): array
237249
return $options;
238250
}
239251

252+
/**
253+
* Provides install options for remote storage.
254+
*
255+
* @return array
256+
* @throws UndefinedPackageException
257+
* @throws ConfigException
258+
*/
259+
private function getRemoteStorageOptions(): array
260+
{
261+
$options = [];
262+
263+
if ($this->magentoVersion->isGreaterOrEqual('2.4.2') && $this->remoteStorage->getDriver()) {
264+
$config = $this->remoteStorage->getConfig();
265+
266+
$options['--remote-storage-driver'] = $this->remoteStorage->getDriver();
267+
$options['--remote-storage-prefix'] = $this->remoteStorage->getPrefix();
268+
269+
if (empty($config['bucket']) || empty($config['region'])) {
270+
throw new ConfigException('Bucket and region are required configurations');
271+
}
272+
273+
$options['--remote-storage-bucket'] = $config['bucket'];
274+
$options['--remote-storage-region'] = $config['region'];
275+
276+
if (isset($config['key'], $config['secret'])) {
277+
$options['--remote-storage-key'] = $config['key'];
278+
$options['--remote-storage-secret'] = $config['secret'];
279+
}
280+
}
281+
282+
return $options;
283+
}
284+
240285
/**
241286
* Returns instance of ConnectionInterface
242287
*

src/Step/Deploy/RemoteStorage.php

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\MagentoCloud\Step\Deploy;
9+
10+
use Magento\MagentoCloud\App\Error;
11+
use Magento\MagentoCloud\Package\MagentoVersion;
12+
use Magento\MagentoCloud\Package\UndefinedPackageException;
13+
use Magento\MagentoCloud\Shell\MagentoShell;
14+
use Magento\MagentoCloud\Shell\ShellException;
15+
use Magento\MagentoCloud\Step\StepException;
16+
use Magento\MagentoCloud\Step\StepInterface;
17+
use Magento\MagentoCloud\Config\RemoteStorage as RemoteStorageConfig;
18+
use Psr\Log\LoggerInterface;
19+
20+
/**
21+
* Enable or disable remote storage during deployment.
22+
*/
23+
class RemoteStorage implements StepInterface
24+
{
25+
/**
26+
* @var RemoteStorageConfig
27+
*/
28+
private $config;
29+
30+
/**
31+
* @var MagentoShell
32+
*/
33+
private $magentoShell;
34+
35+
/**
36+
* @var MagentoVersion
37+
*/
38+
private $magentoVersion;
39+
40+
/**
41+
* @var LoggerInterface
42+
*/
43+
private $logger;
44+
45+
/**
46+
* @param RemoteStorageConfig $config
47+
* @param MagentoShell $magentoShell
48+
* @param MagentoVersion $magentoVersion
49+
* @param LoggerInterface $logger
50+
*/
51+
public function __construct(
52+
RemoteStorageConfig $config,
53+
MagentoShell $magentoShell,
54+
MagentoVersion $magentoVersion,
55+
LoggerInterface $logger
56+
) {
57+
$this->config = $config;
58+
$this->magentoShell = $magentoShell;
59+
$this->magentoVersion = $magentoVersion;
60+
$this->logger = $logger;
61+
}
62+
63+
/**
64+
* Enables or disables remote storage.
65+
*
66+
* @throws StepException
67+
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
68+
* @SuppressWarnings(PHPMD.NPathComplexity)
69+
*/
70+
public function execute(): void
71+
{
72+
try {
73+
if (!$this->magentoVersion->isGreaterOrEqual('2.4.2')) {
74+
return;
75+
}
76+
} catch (UndefinedPackageException $exception) {
77+
throw new StepException($exception->getMessage(), $exception->getCode(), $exception);
78+
}
79+
80+
if ($driver = $this->config->getDriver()) {
81+
$this->updateConfig($driver);
82+
} else {
83+
$this->magentoShell->execute('setup:config:set --remote-storage-driver=file -n');
84+
}
85+
}
86+
87+
/**
88+
* Update configuration.
89+
*
90+
* @param string $driver
91+
* @throws StepException
92+
*/
93+
private function updateConfig(string $driver): void
94+
{
95+
$config = $this->config->getConfig();
96+
97+
if (empty($config['bucket']) || empty($config['region'])) {
98+
throw new StepException('Bucket and region are required configurations');
99+
}
100+
101+
$options = [
102+
'--remote-storage-driver=' . $driver,
103+
'--remote-storage-bucket=' . $config['bucket'],
104+
'--remote-storage-region=' . $config['region']
105+
];
106+
107+
if ($prefix = $this->config->getPrefix()) {
108+
$options[] = '--remote-storage-prefix=' . $prefix;
109+
}
110+
111+
if (isset($config['key'], $config['secret'])) {
112+
$options[] = '--remote-storage-key=' . $config['key'];
113+
$options[] = '--remote-storage-secret=' . $config['secret'];
114+
}
115+
116+
try {
117+
$this->magentoShell->execute(sprintf(
118+
'setup:config:set %s -n',
119+
implode(' ', $options)
120+
));
121+
} catch (ShellException $exception) {
122+
$this->logger->critical(
123+
$exception->getMessage(),
124+
['errorCode' => Error::WARN_REMOTE_STORAGE_CANNOT_BE_ENABLED]
125+
);
126+
127+
throw new StepException(
128+
$exception->getMessage(),
129+
Error::WARN_REMOTE_STORAGE_CANNOT_BE_ENABLED,
130+
$exception
131+
);
132+
}
133+
134+
$this->logger->info(sprintf(
135+
'Remote storage with driver "%s" was enabled',
136+
$driver
137+
));
138+
}
139+
}

0 commit comments

Comments
 (0)