@scandipwa/magento-scripts 2.0.0-alpha.2 → 2.0.0-alpha.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/exec.js +71 -0
- package/index.js +1 -1
- package/lib/commands/cli.js +14 -1
- package/lib/commands/execute.js +2 -57
- package/lib/commands/start.js +24 -3
- package/lib/commands/status.js +9 -1
- package/lib/config/config.js +20 -2
- package/lib/config/docker.js +86 -53
- package/lib/config/get-project-configuration.js +5 -0
- package/lib/config/index.js +10 -3
- package/lib/config/php/versions/php-7.2.js +1 -0
- package/lib/config/php/versions/php-7.3.js +1 -0
- package/lib/config/php/versions/php-7.4.js +1 -0
- package/lib/config/php/versions/php-8.1.js +1 -0
- package/lib/config/php-config.js +4 -3
- package/lib/config/port-config.js +3 -1
- package/lib/config/services/composer/versions/composer-1.js +13 -0
- package/lib/config/services/composer/versions/composer-2.js +8 -0
- package/lib/config/services/composer/versions/index.js +4 -0
- package/lib/config/services/maildev/index.js +7 -0
- package/lib/config/services/nginx/versions/index.js +3 -0
- package/lib/config/services/nginx/versions/nginx-1.18.js +11 -0
- package/lib/config/{ssl-terminator → services/ssl-terminator}/index.js +3 -0
- package/lib/config/templates/magentorc.template +6 -5
- package/lib/config/templates/php-debug.template.ini +31 -0
- package/lib/config/templates/php-fpm.template.conf +1 -2
- package/lib/config/templates/php.template.ini +5 -201
- package/lib/config/templates/ssl-terminator.template.conf +10 -3
- package/lib/config/templates/varnish.template.vcl +20 -13
- package/lib/config/varnish/varnish-6-0.js +4 -0
- package/lib/config/varnish/varnish-6-6.js +4 -0
- package/lib/config/varnish/varnish-7-0.js +4 -0
- package/lib/config/versions/magento-2.2.10.js +41 -0
- package/lib/config/versions/magento-2.3.0.js +8 -10
- package/lib/config/versions/magento-2.3.1.js +8 -10
- package/lib/config/versions/magento-2.3.2-p1.js +8 -10
- package/lib/config/versions/magento-2.3.2-p2.js +8 -10
- package/lib/config/versions/magento-2.3.2.js +8 -10
- package/lib/config/versions/magento-2.3.3-p1.js +8 -10
- package/lib/config/versions/magento-2.3.3.js +8 -10
- package/lib/config/versions/magento-2.3.4-p1.js +8 -10
- package/lib/config/versions/magento-2.3.4-p2.js +8 -10
- package/lib/config/versions/magento-2.3.4.js +8 -10
- package/lib/config/versions/magento-2.3.5-p1.js +8 -10
- package/lib/config/versions/magento-2.3.5-p2.js +8 -10
- package/lib/config/versions/magento-2.3.5.js +8 -10
- package/lib/config/versions/magento-2.3.6-p1.js +8 -10
- package/lib/config/versions/magento-2.3.6.js +8 -10
- package/lib/config/versions/magento-2.3.7-p1.js +8 -10
- package/lib/config/versions/magento-2.3.7-p2.js +8 -10
- package/lib/config/versions/magento-2.3.7-p3.js +8 -10
- package/lib/config/versions/magento-2.3.7-p4.js +42 -0
- package/lib/config/versions/magento-2.3.7.js +8 -10
- package/lib/config/versions/magento-2.4.0-p1.js +8 -10
- package/lib/config/versions/magento-2.4.0.js +8 -10
- package/lib/config/versions/magento-2.4.1-p1.js +8 -10
- package/lib/config/versions/magento-2.4.1.js +8 -10
- package/lib/config/versions/magento-2.4.2-p1.js +8 -10
- package/lib/config/versions/magento-2.4.2-p2.js +8 -10
- package/lib/config/versions/magento-2.4.2.js +8 -10
- package/lib/config/versions/magento-2.4.3-p1.js +8 -10
- package/lib/config/versions/magento-2.4.3-p2.js +8 -10
- package/lib/config/versions/magento-2.4.3-p3.js +44 -0
- package/lib/config/versions/magento-2.4.3.js +8 -10
- package/lib/config/versions/magento-2.4.4-p1.js +44 -0
- package/lib/config/versions/magento-2.4.4.js +8 -10
- package/lib/config/versions/magento-2.4.5.js +44 -0
- package/lib/tasks/cli/create-bashrc-config.js +1 -1
- package/lib/tasks/composer/local-auth-json.js +1 -1
- package/lib/tasks/database/connect-to-database.js +6 -3
- package/lib/tasks/database/create-magento-database.js +5 -2
- package/lib/tasks/database/create-magento-user.js +50 -0
- package/lib/tasks/database/default-magento-database.js +3 -0
- package/lib/tasks/database/default-magento-user.js +7 -0
- package/lib/tasks/database/import-dump-to-database.js +3 -2
- package/lib/tasks/docker/api.d.ts +25 -1
- package/lib/tasks/docker/api.js +31 -1
- package/lib/tasks/docker/containers/container-api.d.ts +21 -0
- package/lib/tasks/docker/containers/container-api.js +82 -17
- package/lib/tasks/docker/containers/tasks.js +44 -13
- package/lib/tasks/docker/convert-composer-home-to-composer-cache-volume.js +52 -0
- package/lib/tasks/docker/convert-mysql-to-mariadb.js +2 -2
- package/lib/tasks/docker/image/image-api.d.ts +44 -0
- package/lib/tasks/docker/image/image-api.js +30 -2
- package/lib/tasks/docker/index.js +6 -1
- package/lib/tasks/docker/project-image-builder.js +36 -13
- package/lib/tasks/docker/system/index.js +5 -0
- package/lib/tasks/docker/system/system-api.d.ts +71 -0
- package/lib/tasks/docker/system/system-api.js +29 -0
- package/lib/tasks/docker/volume/index.js +2 -1
- package/lib/tasks/docker/volume/tasks.js +67 -9
- package/lib/tasks/docker/volume/volume-api.d.ts +40 -0
- package/lib/tasks/docker/volume/volume-api.js +54 -1
- package/lib/tasks/execute.js +100 -0
- package/lib/tasks/file-system/create-nginx-config.js +3 -5
- package/lib/tasks/file-system/create-php-config.js +2 -23
- package/lib/tasks/file-system/create-php-debug-config.js +45 -0
- package/lib/tasks/file-system/create-php-fpm-config.js +2 -4
- package/lib/tasks/file-system/create-phpstorm-config/exclude-folder-config.js +13 -3
- package/lib/tasks/file-system/create-phpstorm-config/workspace-config/php-workspace-project-configuration-config.js +1 -1
- package/lib/tasks/file-system/create-ssl-terminator-config.js +4 -7
- package/lib/tasks/file-system/create-varnish-config.js +4 -7
- package/lib/tasks/file-system/index.js +2 -0
- package/lib/tasks/magento/enable-magento-composer-plugins.js +85 -30
- package/lib/tasks/magento/install-magento-project.js +3 -2
- package/lib/tasks/magento/setup-magento/configure-elasticsearch.js +2 -4
- package/lib/tasks/magento/setup-magento/flush-redis-config.js +3 -6
- package/lib/tasks/magento/setup-magento/index.js +2 -0
- package/lib/tasks/magento/setup-magento/install-magento.js +8 -10
- package/lib/tasks/magento/setup-magento/set-base-url.js +1 -1
- package/lib/tasks/magento/setup-magento/set-mail-config.js +26 -0
- package/lib/tasks/magento/setup-magento/varnish-config.js +4 -9
- package/lib/tasks/magento/setup-magento/waiting-for-varnish.js +17 -16
- package/lib/tasks/php/php-container.js +7 -3
- package/lib/tasks/php/update-env-php.js +3 -4
- package/lib/tasks/{prefix → project-config}/index.js +6 -6
- package/lib/tasks/requirements/composer-credentials.js +7 -3
- package/lib/tasks/requirements/docker/context.js +88 -0
- package/lib/tasks/requirements/docker/index.js +114 -20
- package/lib/tasks/requirements/docker/install.js +21 -7
- package/lib/tasks/requirements/docker/permissions.js +2 -11
- package/lib/tasks/requirements/docker/running-status.js +94 -24
- package/lib/tasks/requirements/docker/version.js +1 -0
- package/lib/tasks/requirements/index.js +0 -2
- package/lib/tasks/requirements/php-version.js +4 -2
- package/lib/tasks/start.js +27 -8
- package/lib/tasks/status/index.js +29 -20
- package/lib/tasks/stop.js +2 -0
- package/lib/tasks/theme/retrieve-theme-data.js +11 -1
- package/lib/util/config-file-validator.js +15 -2
- package/lib/util/execute-in-container.js +62 -0
- package/lib/util/instance-metadata.js +14 -2
- package/lib/util/systemctl.js +62 -13
- package/package.json +4 -3
- package/typings/context.d.ts +11 -0
- package/typings/index.d.ts +42 -1
- package/lib/tasks/execute/index.js +0 -26
- package/lib/tasks/requirements/dependency/arch.js +0 -50
- package/lib/tasks/requirements/dependency/centos.js +0 -36
- package/lib/tasks/requirements/dependency/fedora.js +0 -36
- package/lib/tasks/requirements/dependency/index.js +0 -33
- package/lib/tasks/requirements/dependency/mac.js +0 -124
- package/lib/tasks/requirements/dependency/ubuntu.js +0 -83
- package/yarn-error.log +0 -9660
|
@@ -6,9 +6,9 @@ const containerApi = require('./container-api');
|
|
|
6
6
|
const { imageApi } = require('../image');
|
|
7
7
|
const { execAsyncSpawn } = require('../../../util/exec-async-command');
|
|
8
8
|
|
|
9
|
-
const
|
|
10
|
-
await
|
|
11
|
-
await
|
|
9
|
+
const stopAndRemoveContainers = async (containers) => {
|
|
10
|
+
await containerApi.stop(containers);
|
|
11
|
+
await containerApi.rm(containers);
|
|
12
12
|
};
|
|
13
13
|
|
|
14
14
|
const pull = async (image) => execAsyncSpawn(`docker pull ${image}`);
|
|
@@ -26,8 +26,39 @@ const remoteImageReducer = (acc, val) => {
|
|
|
26
26
|
*/
|
|
27
27
|
const pullImages = () => ({
|
|
28
28
|
title: 'Pulling container images',
|
|
29
|
-
task: async ({ config: { docker } }, task) => {
|
|
29
|
+
task: async ({ config: { docker }, pullImages }, task) => {
|
|
30
30
|
const containers = Object.values(docker.getContainers());
|
|
31
|
+
|
|
32
|
+
if (pullImages) {
|
|
33
|
+
return task.newListr(
|
|
34
|
+
containers
|
|
35
|
+
.reduce(remoteImageReducer, [])
|
|
36
|
+
.map((image) => {
|
|
37
|
+
const [repo, tag = 'latest'] = image.split(':');
|
|
38
|
+
|
|
39
|
+
return { repo, tag };
|
|
40
|
+
})
|
|
41
|
+
.reduce(
|
|
42
|
+
(acc, val) => acc.concat(
|
|
43
|
+
acc.some(
|
|
44
|
+
(c) => c.repo === val.repo
|
|
45
|
+
&& c.tag === val.tag
|
|
46
|
+
)
|
|
47
|
+
? []
|
|
48
|
+
: val
|
|
49
|
+
),
|
|
50
|
+
[]
|
|
51
|
+
)
|
|
52
|
+
.map(({ repo, tag }) => ({
|
|
53
|
+
title: `Pulling ${ logger.style.file(`${repo}:${tag}`) } image`,
|
|
54
|
+
task: () => pull(`${repo}:${tag}`)
|
|
55
|
+
})), {
|
|
56
|
+
concurrent: true,
|
|
57
|
+
exitOnError: true
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
31
62
|
const imagesFilter = containers
|
|
32
63
|
.reduce(remoteImageReducer, [])
|
|
33
64
|
.map((image) => `reference='${image}'`);
|
|
@@ -85,10 +116,10 @@ const pullImages = () => ({
|
|
|
85
116
|
const startContainers = () => ({
|
|
86
117
|
title: 'Starting containers',
|
|
87
118
|
task: async ({ ports, config: { docker }, debug }, task) => {
|
|
88
|
-
const containerList =
|
|
119
|
+
const containerList = await containerApi.ls({ formatToJSON: true, all: true });
|
|
89
120
|
|
|
90
121
|
const missingContainers = Object.values(docker.getContainers(ports)).filter(
|
|
91
|
-
({ name }) => !containerList.
|
|
122
|
+
({ name }) => !containerList.some((c) => c.Names === name)
|
|
92
123
|
);
|
|
93
124
|
|
|
94
125
|
if (missingContainers.length === 0) {
|
|
@@ -129,22 +160,22 @@ const startContainers = () => ({
|
|
|
129
160
|
const stopContainers = () => ({
|
|
130
161
|
title: 'Stopping Docker containers',
|
|
131
162
|
task: async ({ config: { baseConfig: { prefix } } }, task) => {
|
|
132
|
-
const containerList =
|
|
163
|
+
const containerList = await containerApi.ls({ formatToJSON: true, all: true });
|
|
133
164
|
|
|
134
|
-
const runningContainers = containerList.filter((containerName) => containerName.startsWith(prefix));
|
|
165
|
+
const runningContainers = containerList.filter((containerName) => containerName.Names.startsWith(prefix));
|
|
135
166
|
|
|
136
167
|
if (runningContainers.length === 0) {
|
|
137
168
|
task.skip();
|
|
138
169
|
return;
|
|
139
170
|
}
|
|
140
171
|
|
|
141
|
-
await
|
|
172
|
+
await stopAndRemoveContainers(runningContainers.map(({ Names }) => Names));
|
|
142
173
|
}
|
|
143
174
|
});
|
|
144
175
|
|
|
145
176
|
const getContainerStatus = async (containerName) => {
|
|
146
177
|
try {
|
|
147
|
-
return JSON.parse(await execAsyncSpawn(`docker inspect --format='{{json .
|
|
178
|
+
return JSON.parse(await execAsyncSpawn(`docker inspect --format='{{json .}}' ${containerName}`));
|
|
148
179
|
} catch {
|
|
149
180
|
return null;
|
|
150
181
|
}
|
|
@@ -167,11 +198,11 @@ const checkContainersAreRunning = () => ({
|
|
|
167
198
|
}))
|
|
168
199
|
);
|
|
169
200
|
|
|
170
|
-
if (containersWithStatus.some((c) => c.status.Status !== 'running')) {
|
|
201
|
+
if (containersWithStatus.some((c) => c.status.State.Status !== 'running')) {
|
|
171
202
|
if (tries === 2) {
|
|
172
|
-
throw new KnownError(`${containersWithStatus.filter((c) => c.status.Status !== 'running').map((c) => c._).join(', ')} containers are not running! Please check container logs for more details!`);
|
|
203
|
+
throw new KnownError(`${containersWithStatus.filter((c) => c.status.State.Status !== 'running').map((c) => c._).join(', ')} containers are not running! Please check container logs for more details!`);
|
|
173
204
|
} else {
|
|
174
|
-
task.output = `${containersWithStatus.filter((c) => c.status.Status !== 'running').map((c) => c._).join(', ')} are not running, waiting if something will change...`;
|
|
205
|
+
task.output = `${containersWithStatus.filter((c) => c.status.State.Status !== 'running').map((c) => c._).join(', ')} are not running, waiting if something will change...`;
|
|
175
206
|
await sleep(2000);
|
|
176
207
|
tries++;
|
|
177
208
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const { containerApi } = require('./containers');
|
|
2
|
+
const volumeApi = require('./volume/volume-api');
|
|
3
|
+
|
|
4
|
+
const composeHomeDataVolumeName = 'composer_home-data';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
|
|
8
|
+
*/
|
|
9
|
+
const convertComposerHomeToComposerCacheVolume = () => ({
|
|
10
|
+
skip: async () => {
|
|
11
|
+
const volumeList = await volumeApi.ls({
|
|
12
|
+
formatToJSON: true,
|
|
13
|
+
filter: `name=${ composeHomeDataVolumeName }`
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
return volumeList.length === 0;
|
|
17
|
+
},
|
|
18
|
+
task: async (ctx, task) => {
|
|
19
|
+
if (ctx.platform === 'linux' && !ctx.isDockerDesktop) {
|
|
20
|
+
await volumeApi.rm({ volumes: [composeHomeDataVolumeName] });
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const { composer_cache } = ctx.config.docker.volumes;
|
|
25
|
+
task.title = `Migrating from ${ composer_cache.name } volume to ${ composeHomeDataVolumeName }...`;
|
|
26
|
+
await containerApi.run({
|
|
27
|
+
rm: true,
|
|
28
|
+
detach: false,
|
|
29
|
+
mountVolumes: [
|
|
30
|
+
`${ composeHomeDataVolumeName }:/from:ro`,
|
|
31
|
+
`${ composer_cache.name }:/to`
|
|
32
|
+
],
|
|
33
|
+
image: 'alpine',
|
|
34
|
+
command: 'ash -c "cd /from/cache; cp -av . /to"'
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const runningContainers = await volumeApi.inspect({ volume: composeHomeDataVolumeName, formatToJSON: true });
|
|
38
|
+
|
|
39
|
+
if (runningContainers.Containers && Object.entries(runningContainers.Containers).length > 0) {
|
|
40
|
+
await Promise.all(Object.values(runningContainers.Containers).map(async (c) => {
|
|
41
|
+
await containerApi.stop([c.Name]);
|
|
42
|
+
await containerApi.rm([c.Name]);
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
await volumeApi.rm({ volumes: [composeHomeDataVolumeName] });
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
module.exports = {
|
|
51
|
+
convertComposerHomeToComposerCacheVolume
|
|
52
|
+
};
|
|
@@ -5,7 +5,6 @@ const { volumeApi, createVolumes } = require('./volume');
|
|
|
5
5
|
const { execAsyncSpawn } = require('../../util/exec-async-command');
|
|
6
6
|
const { containerApi, stopContainers, pullImages } = require('./containers');
|
|
7
7
|
const { importDumpToDatabase, connectToDatabase } = require('../database');
|
|
8
|
-
const { setPrefix } = require('../prefix');
|
|
9
8
|
const getProjectConfiguration = require('../../config/get-project-configuration');
|
|
10
9
|
const { getAvailablePorts, getCachedPorts } = require('../../config/get-port-config');
|
|
11
10
|
const { saveConfiguration } = require('../../config/save-config');
|
|
@@ -21,6 +20,7 @@ const KnownError = require('../../errors/known-error');
|
|
|
21
20
|
const { createCacheFolder } = require('../cache');
|
|
22
21
|
const { getSystemConfigTask } = require('../../config/system-config');
|
|
23
22
|
const sleep = require('../../util/sleep');
|
|
23
|
+
const { setProjectConfigTask } = require('../project-config');
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
26
|
* @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
|
|
@@ -203,7 +203,7 @@ Please wait, this will take some time and do not restart the MySQL container unt
|
|
|
203
203
|
getSystemConfigTask(),
|
|
204
204
|
getCachedPorts(),
|
|
205
205
|
stopContainers(),
|
|
206
|
-
|
|
206
|
+
setProjectConfigTask(),
|
|
207
207
|
getProjectConfiguration(),
|
|
208
208
|
// get fresh ports
|
|
209
209
|
getAvailablePorts(),
|
|
@@ -32,3 +32,47 @@ export function ls(
|
|
|
32
32
|
options?: ImagesLsOptions<true>,
|
|
33
33
|
execOptions?: ExecAsyncSpawnOptions<false>
|
|
34
34
|
): Promise<ImagesLsResult[]>
|
|
35
|
+
|
|
36
|
+
export interface ImagesInspectOptions<T extends boolean = false> {
|
|
37
|
+
image: string
|
|
38
|
+
format?: string
|
|
39
|
+
formatToJSON?: T
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface ImagesInspectResult {
|
|
43
|
+
Id: string
|
|
44
|
+
RepoTags: string[]
|
|
45
|
+
RepoDigests: string[]
|
|
46
|
+
Parent: string
|
|
47
|
+
Comment: string
|
|
48
|
+
Created: string
|
|
49
|
+
Container: string
|
|
50
|
+
ContainerConfig: unknown
|
|
51
|
+
DockerVersion: string
|
|
52
|
+
Author: string
|
|
53
|
+
Config: {
|
|
54
|
+
Env: string[],
|
|
55
|
+
Cmd: string[]
|
|
56
|
+
WorkingDir: string
|
|
57
|
+
Entrypoint: string[]
|
|
58
|
+
StopSignal: string
|
|
59
|
+
}
|
|
60
|
+
Architecture: string
|
|
61
|
+
Os: string
|
|
62
|
+
Size: number
|
|
63
|
+
VirtualSize: number
|
|
64
|
+
GraphDriver: unknown
|
|
65
|
+
RootFs: unknown
|
|
66
|
+
Metadata: Record<string, unknown>
|
|
67
|
+
CreatedTime: number
|
|
68
|
+
Container: Record<string, unknown>
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function inspect(
|
|
72
|
+
options?: ImagesInspectOptions,
|
|
73
|
+
execOptions?: ExecAsyncSpawnOptions<false>
|
|
74
|
+
): Promise<string>
|
|
75
|
+
export function inspect(
|
|
76
|
+
options?: ImagesInspectOptions<true>,
|
|
77
|
+
execOptions?: ExecAsyncSpawnOptions<false>
|
|
78
|
+
): Promise<ImagesInspectResult>
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const { execAsyncSpawn } = require('../../../util/exec-async-command');
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
4
|
* @param {import('./image-api').ImagesLsOptions} options
|
|
6
5
|
* @param {import('../../../util/exec-async-command').ExecAsyncSpawnOptions} execOptions
|
|
7
6
|
*/
|
|
@@ -44,6 +43,35 @@ const ls = async (options, execOptions = {}) => {
|
|
|
44
43
|
return execAsyncSpawn(`docker image ls ${args}`, execOptions);
|
|
45
44
|
};
|
|
46
45
|
|
|
46
|
+
/**
|
|
47
|
+
* @param {import('./image-api').ImagesInspectOptions} options
|
|
48
|
+
* @param {import('../../../util/exec-async-command').ExecAsyncSpawnOptions} execOptions
|
|
49
|
+
*/
|
|
50
|
+
const inspect = async (options, execOptions = {}) => {
|
|
51
|
+
const {
|
|
52
|
+
image,
|
|
53
|
+
format,
|
|
54
|
+
formatToJSON = false
|
|
55
|
+
} = options;
|
|
56
|
+
|
|
57
|
+
const formatArg = !formatToJSON && format
|
|
58
|
+
? `--format=${format}`
|
|
59
|
+
: formatToJSON && '--format=\'{{json .}}\'';
|
|
60
|
+
|
|
61
|
+
const args = [
|
|
62
|
+
formatArg,
|
|
63
|
+
image
|
|
64
|
+
].filter(Boolean).join(' ');
|
|
65
|
+
|
|
66
|
+
if (formatToJSON) {
|
|
67
|
+
const result = await execAsyncSpawn(`docker image inspect ${args}`, execOptions);
|
|
68
|
+
return JSON.parse(result);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return execAsyncSpawn(`docker image inspect ${args}`, execOptions);
|
|
72
|
+
};
|
|
73
|
+
|
|
47
74
|
module.exports = {
|
|
48
|
-
ls
|
|
75
|
+
ls,
|
|
76
|
+
inspect
|
|
49
77
|
};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
const containers = require('./containers');
|
|
2
2
|
const network = require('./network');
|
|
3
|
+
const volume = require('./volume');
|
|
4
|
+
const dockerApi = require('./api');
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
|
|
@@ -19,13 +21,16 @@ const startServices = () => ({
|
|
|
19
21
|
* @type {() => import('listr2').ListrTask<import('../../../typings/context').ListrContext>}
|
|
20
22
|
*/
|
|
21
23
|
const stopServices = () => ({
|
|
24
|
+
title: 'Stopping Docker services',
|
|
22
25
|
task: (ctx, task) => task.newListr([
|
|
23
26
|
containers.stopContainers(),
|
|
27
|
+
volume.removeLocalVolumes(),
|
|
24
28
|
network.tasks.removeNetwork()
|
|
25
29
|
])
|
|
26
30
|
});
|
|
27
31
|
|
|
28
32
|
module.exports = {
|
|
29
33
|
startServices,
|
|
30
|
-
stopServices
|
|
34
|
+
stopServices,
|
|
35
|
+
dockerApi
|
|
31
36
|
};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const os = require('os');
|
|
1
3
|
const { DockerFileBuilder } = require('../../util/dockerfile-builder');
|
|
2
|
-
const semver = require('semver');
|
|
3
4
|
const { execAsyncSpawn } = require('../../util/exec-async-command');
|
|
4
5
|
const KnownError = require('../../errors/known-error');
|
|
5
6
|
const { runContainerImage } = require('../../util/run-container-image');
|
|
7
|
+
const { imageApi } = require('./image');
|
|
6
8
|
|
|
7
9
|
/**
|
|
8
10
|
* Get enabled extensions list with versions
|
|
@@ -27,13 +29,13 @@ const getEnabledExtensionsFromImage = async (imageWithTag) => {
|
|
|
27
29
|
.reduce((acc, [name, version]) => ({ ...acc, [name]: version }), {});
|
|
28
30
|
};
|
|
29
31
|
|
|
30
|
-
const addExtensionToBuilder = (builder, ctx) => ([extensionName, extensionInstructions]) => {
|
|
32
|
+
const addExtensionToBuilder = (builder, ctx) => async ([extensionName, extensionInstructions]) => {
|
|
31
33
|
const { command, ...extensionInstructionsWithoutCommand } = extensionInstructions;
|
|
32
34
|
let runCommand = '';
|
|
33
35
|
if (typeof command === 'string') {
|
|
34
36
|
runCommand += ` ${command}`;
|
|
35
|
-
} else if (typeof command === 'function') {
|
|
36
|
-
runCommand += ` ${command({ ...extensionInstructionsWithoutCommand, ctx })}`;
|
|
37
|
+
} else if (typeof command === 'function' || command instanceof Promise) {
|
|
38
|
+
runCommand += ` ${await Promise.resolve(command({ ...extensionInstructionsWithoutCommand, ctx }))}`;
|
|
37
39
|
} else {
|
|
38
40
|
runCommand += ` docker-php-ext-install ${extensionInstructionsWithoutCommand.name}`;
|
|
39
41
|
}
|
|
@@ -49,6 +51,7 @@ const addExtensionToBuilder = (builder, ctx) => ([extensionName, extensionInstru
|
|
|
49
51
|
const buildDockerFileInstructions = async (ctx, { image, tag }) => {
|
|
50
52
|
const { composer } = ctx.config.overridenConfiguration.configuration;
|
|
51
53
|
const existingPHPExtensions = await getEnabledExtensionsFromImage(`${image}:${tag}`);
|
|
54
|
+
const imageDetails = await imageApi.inspect({ image: `${image}:${tag}`, formatToJSON: true });
|
|
52
55
|
|
|
53
56
|
const missingExtensions = Object.entries(
|
|
54
57
|
ctx.config.overridenConfiguration.configuration.php.extensions
|
|
@@ -68,10 +71,6 @@ const buildDockerFileInstructions = async (ctx, { image, tag }) => {
|
|
|
68
71
|
.comment('project image')
|
|
69
72
|
.from({ image, tag });
|
|
70
73
|
|
|
71
|
-
// install bash in image
|
|
72
|
-
dockerFileInstructions
|
|
73
|
-
.run('apk add --no-cache bash');
|
|
74
|
-
|
|
75
74
|
if (missingExtensions.length > 0) {
|
|
76
75
|
const allDependencies = missingExtensions.map(
|
|
77
76
|
([_extensionName, extensionInstructions]) => (extensionInstructions.dependencies || [])
|
|
@@ -79,7 +78,9 @@ const buildDockerFileInstructions = async (ctx, { image, tag }) => {
|
|
|
79
78
|
.reduce((acc, val) => acc.concat(val.filter((ex) => !acc.includes(ex))), []);
|
|
80
79
|
|
|
81
80
|
dockerFileInstructions.run(`apk add --no-cache ${allDependencies.join(' ')}`);
|
|
82
|
-
|
|
81
|
+
for (const missingExtensionInstructions of missingExtensions) {
|
|
82
|
+
await addExtensionToBuilder(dockerFileInstructions, ctx)(missingExtensionInstructions);
|
|
83
|
+
}
|
|
83
84
|
}
|
|
84
85
|
|
|
85
86
|
const composerVersion = /^\d$/.test(composer.version)
|
|
@@ -92,17 +93,39 @@ const buildDockerFileInstructions = async (ctx, { image, tag }) => {
|
|
|
92
93
|
.comment('make composer executable')
|
|
93
94
|
.run('chmod +x ./composer')
|
|
94
95
|
.comment('move composer to bin directory')
|
|
95
|
-
.run('mv composer /usr/local/bin/composer')
|
|
96
|
+
.run('mv composer /usr/local/bin/composer')
|
|
97
|
+
.run('mkdir -p /composer/home/cache')
|
|
98
|
+
.env({
|
|
99
|
+
COMPOSER_HOME: '/composer/home',
|
|
100
|
+
COMPOSER_CACHE_DIR: '/composer/home/cache'
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (composer.plugins && Object.values(composer.plugins).length > 0) {
|
|
104
|
+
for (const [pluginName, pluginOptions] of Object.entries(composer.plugins)) {
|
|
105
|
+
if (pluginOptions.enabled) {
|
|
106
|
+
dockerFileInstructions
|
|
107
|
+
.comment(`install ${pluginName} composer global package`)
|
|
108
|
+
// eslint-disable-next-line max-len
|
|
109
|
+
.run(`composer global require ${pluginName}${ pluginOptions.options ? ` ${pluginOptions.options}` : '' }${ pluginOptions.options ? ` ${pluginOptions.options}` : ''}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
96
113
|
|
|
97
|
-
if (
|
|
114
|
+
if (!ctx.isDockerDesktop) {
|
|
98
115
|
dockerFileInstructions
|
|
99
|
-
.
|
|
100
|
-
.run('composer global require hirak/prestissimo');
|
|
116
|
+
.run(`chown -R ${os.userInfo().uid}:${os.userInfo().gid} /composer/home`);
|
|
101
117
|
}
|
|
102
118
|
|
|
103
119
|
dockerFileInstructions
|
|
104
120
|
.workDir(ctx.config.baseConfig.containerMagentoDir);
|
|
105
121
|
|
|
122
|
+
const imagePathEnv = imageDetails.Config.Env.find((env) => env.startsWith('PATH'));
|
|
123
|
+
|
|
124
|
+
dockerFileInstructions
|
|
125
|
+
.env({
|
|
126
|
+
PATH: `${ imagePathEnv.split('=').pop() }:${ path.join(ctx.config.baseConfig.containerMagentoDir, 'bin') }`
|
|
127
|
+
});
|
|
128
|
+
|
|
106
129
|
return dockerFileInstructions;
|
|
107
130
|
};
|
|
108
131
|
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { ExecAsyncSpawnOptions } from '../../../util/exec-async-command';
|
|
2
|
+
|
|
3
|
+
export interface SystemDFOptions<T extends boolean = false> {
|
|
4
|
+
format?: string
|
|
5
|
+
formatToJSON?: T
|
|
6
|
+
verbose?: boolean
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface SystemDFResult {
|
|
10
|
+
Images: {
|
|
11
|
+
Containers: string
|
|
12
|
+
CreatedAt: string
|
|
13
|
+
CreatedSince: string
|
|
14
|
+
Digest: string
|
|
15
|
+
ID: string
|
|
16
|
+
Repository: string
|
|
17
|
+
SharedSize: string
|
|
18
|
+
Size: string
|
|
19
|
+
Tag: string
|
|
20
|
+
UniqueSize: string
|
|
21
|
+
VirtualSize: string
|
|
22
|
+
}[]
|
|
23
|
+
Containers: {
|
|
24
|
+
Command: string
|
|
25
|
+
CreatedAt: string
|
|
26
|
+
ID: string
|
|
27
|
+
Image: string
|
|
28
|
+
Labels: string
|
|
29
|
+
LocalVolumes: string
|
|
30
|
+
Mounts: string
|
|
31
|
+
Names: string
|
|
32
|
+
Networks: string
|
|
33
|
+
Ports: StreamPipeOptions
|
|
34
|
+
RunningFor: string
|
|
35
|
+
Size: string
|
|
36
|
+
State: string
|
|
37
|
+
Status: string
|
|
38
|
+
}[]
|
|
39
|
+
Volumes: {
|
|
40
|
+
Driver: string
|
|
41
|
+
Labels: string
|
|
42
|
+
Links: string
|
|
43
|
+
Mountpoint: string
|
|
44
|
+
Name: string
|
|
45
|
+
Scope: string
|
|
46
|
+
Size: string
|
|
47
|
+
}[]
|
|
48
|
+
BuildCache: {
|
|
49
|
+
CacheType: string
|
|
50
|
+
CreatedAt: string
|
|
51
|
+
CreatedSince: string
|
|
52
|
+
Description: string
|
|
53
|
+
ID: string
|
|
54
|
+
InUse: string
|
|
55
|
+
LastUsedAt: string
|
|
56
|
+
LastUsedSince: string
|
|
57
|
+
Parent: string
|
|
58
|
+
Shared: string
|
|
59
|
+
Size: string
|
|
60
|
+
UsageCount: string
|
|
61
|
+
}[]
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function df(
|
|
65
|
+
options?: SystemDFOptions,
|
|
66
|
+
execOptions?: ExecAsyncSpawnOptions<false>
|
|
67
|
+
): Promise<string>
|
|
68
|
+
export function df(
|
|
69
|
+
options?: SystemDFOptions<true>,
|
|
70
|
+
execOptions?: ExecAsyncSpawnOptions<false>
|
|
71
|
+
): Promise<SystemDFResult>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const { execAsyncSpawn } = require('../../../util/exec-async-command');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {import('./system-api').SystemDFOptions} options
|
|
5
|
+
* @param {import('../../../util/exec-async-command').ExecAsyncSpawnOptions} execOptions
|
|
6
|
+
*/
|
|
7
|
+
const df = async (options, execOptions = {}) => {
|
|
8
|
+
const {
|
|
9
|
+
format,
|
|
10
|
+
formatToJSON,
|
|
11
|
+
verbose
|
|
12
|
+
} = options;
|
|
13
|
+
|
|
14
|
+
const formatArg = !formatToJSON && format
|
|
15
|
+
? `--format=${format}`
|
|
16
|
+
: formatToJSON && '--format=\'{{json .}}\'';
|
|
17
|
+
const verboseArg = verbose && '--verbose';
|
|
18
|
+
|
|
19
|
+
const args = [
|
|
20
|
+
formatArg,
|
|
21
|
+
verboseArg
|
|
22
|
+
].filter(Boolean).join(' ');
|
|
23
|
+
|
|
24
|
+
return execAsyncSpawn(`docker system df ${args}`, execOptions);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
module.exports = {
|
|
28
|
+
df
|
|
29
|
+
};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
const volumeApi = require('./volume-api');
|
|
2
|
-
const { createVolumes, removeVolumes } = require('./tasks');
|
|
2
|
+
const { createVolumes, removeVolumes, removeLocalVolumes } = require('./tasks');
|
|
3
3
|
|
|
4
4
|
module.exports = {
|
|
5
5
|
createVolumes,
|
|
6
6
|
removeVolumes,
|
|
7
|
+
removeLocalVolumes,
|
|
7
8
|
volumeApi
|
|
8
9
|
};
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const pathExists = require('../../../util/path-exists');
|
|
3
|
+
const { containerApi } = require('../containers');
|
|
4
|
+
const volumeApi = require('./volume-api');
|
|
3
5
|
|
|
4
6
|
/**
|
|
5
7
|
* @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
|
|
@@ -7,10 +9,12 @@ const { create } = require('./volume-api');
|
|
|
7
9
|
const createVolumes = () => ({
|
|
8
10
|
title: 'Creating volumes',
|
|
9
11
|
task: async ({ config: { docker } }, task) => {
|
|
10
|
-
const volumeList =
|
|
12
|
+
const volumeList = await volumeApi.ls({
|
|
13
|
+
formatToJSON: true
|
|
14
|
+
});
|
|
11
15
|
|
|
12
16
|
const missingVolumes = Object.values(docker.volumes).filter(
|
|
13
|
-
({ name }) => !volumeList.
|
|
17
|
+
({ name }) => !volumeList.some((v) => v.Name === name)
|
|
14
18
|
);
|
|
15
19
|
|
|
16
20
|
if (missingVolumes.length === 0) {
|
|
@@ -18,7 +22,15 @@ const createVolumes = () => ({
|
|
|
18
22
|
return;
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
await Promise.all(missingVolumes.map((volume) =>
|
|
25
|
+
await Promise.all(missingVolumes.map(async (volume) => {
|
|
26
|
+
if (volume.opt && volume.opt.device && !await pathExists(volume.opt.device)) {
|
|
27
|
+
await fs.promises.mkdir(volume.opt.device, {
|
|
28
|
+
recursive: true
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}));
|
|
32
|
+
|
|
33
|
+
await Promise.all(missingVolumes.map((volume) => volumeApi.create(volume)));
|
|
22
34
|
}
|
|
23
35
|
});
|
|
24
36
|
|
|
@@ -28,10 +40,12 @@ const createVolumes = () => ({
|
|
|
28
40
|
const removeVolumes = () => ({
|
|
29
41
|
title: 'Removing volumes',
|
|
30
42
|
task: async ({ config: { docker } }, task) => {
|
|
31
|
-
const volumeList =
|
|
43
|
+
const volumeList = await volumeApi.ls({
|
|
44
|
+
formatToJSON: true
|
|
45
|
+
});
|
|
32
46
|
|
|
33
47
|
const deployedVolumes = Object.values(docker.volumes).filter(
|
|
34
|
-
({ name }) => volumeList.
|
|
48
|
+
({ name }) => volumeList.some((v) => v.Name === name)
|
|
35
49
|
);
|
|
36
50
|
|
|
37
51
|
if (deployedVolumes.length === 0) {
|
|
@@ -39,11 +53,55 @@ const removeVolumes = () => ({
|
|
|
39
53
|
return;
|
|
40
54
|
}
|
|
41
55
|
|
|
42
|
-
await
|
|
56
|
+
await volumeApi.rm({
|
|
57
|
+
volumes: deployedVolumes.map(({ name }) => name)
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* @type {() => import('listr2').ListrTask<import('../../../../typings/context').ListrContext>}
|
|
64
|
+
*/
|
|
65
|
+
const removeLocalVolumes = () => ({
|
|
66
|
+
title: 'Removing local volumes',
|
|
67
|
+
task: async (ctx, task) => {
|
|
68
|
+
const volumeList = await volumeApi.ls({
|
|
69
|
+
formatToJSON: true
|
|
70
|
+
});
|
|
71
|
+
const { volumes } = ctx.config.docker;
|
|
72
|
+
|
|
73
|
+
const localVolumes = Object.values(volumes).filter(
|
|
74
|
+
(volume) => volume.opt && volume.opt.device
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
const existingLocalVolumes = localVolumes.filter(
|
|
78
|
+
(volume) => volumeList.some((v) => v.Name === volume.name)
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
if (existingLocalVolumes.length > 0) {
|
|
82
|
+
const existingLocalVolumesDetails = await Promise.all(
|
|
83
|
+
existingLocalVolumes.map((v) => volumeApi.inspect({ volume: v.name, formatToJSON: true }))
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
await Promise.all(existingLocalVolumesDetails.map(async (v) => {
|
|
87
|
+
if (v.Containers && Object.entries(v.Containers).length > 0) {
|
|
88
|
+
await Promise.all(Object.values(v.Containers).map(async (c) => {
|
|
89
|
+
await containerApi.stop([c.Name]);
|
|
90
|
+
await containerApi.rm([c.Name]);
|
|
91
|
+
}));
|
|
92
|
+
}
|
|
93
|
+
}));
|
|
94
|
+
await volumeApi.rm({
|
|
95
|
+
volumes: existingLocalVolumes.map((volume) => volume.name)
|
|
96
|
+
});
|
|
97
|
+
} else {
|
|
98
|
+
task.skip();
|
|
99
|
+
}
|
|
43
100
|
}
|
|
44
101
|
});
|
|
45
102
|
|
|
46
103
|
module.exports = {
|
|
47
104
|
createVolumes,
|
|
48
|
-
removeVolumes
|
|
105
|
+
removeVolumes,
|
|
106
|
+
removeLocalVolumes
|
|
49
107
|
};
|