@sapphirecode/dcm
Advanced tools
Comparing version 1.0.2 to 1.0.3
@@ -5,7 +5,9 @@ export declare class Service { | ||
passive: boolean; | ||
buildable: boolean; | ||
images: string[]; | ||
constructor(name: string, passive: boolean); | ||
get directory(): string; | ||
pull(): Promise<void>; | ||
get compose_file(): string; | ||
up(): Promise<void>; | ||
down(): Promise<void>; | ||
} |
@@ -44,2 +44,4 @@ "use strict"; | ||
this.depends_on = []; | ||
this.buildable = false; | ||
this.images = []; | ||
this.name = name; | ||
@@ -55,23 +57,9 @@ this.passive = passive; | ||
}); | ||
Service.prototype.pull = function () { | ||
return __awaiter(this, void 0, void 0, function () { | ||
return __generator(this, function (_a) { | ||
switch (_a.label) { | ||
case 0: return [4 /*yield*/, (0, exec_1.exec_command)('docker', [ | ||
'compose', | ||
'pull' | ||
], this.directory)]; | ||
case 1: | ||
_a.sent(); | ||
return [4 /*yield*/, (0, exec_1.exec_command)('docker', [ | ||
'compose', | ||
'build' | ||
], this.directory)]; | ||
case 2: | ||
_a.sent(); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}); | ||
}; | ||
Object.defineProperty(Service.prototype, "compose_file", { | ||
get: function () { | ||
return "".concat(this.directory, "/docker-compose.yml"); | ||
}, | ||
enumerable: false, | ||
configurable: true | ||
}); | ||
Service.prototype.up = function () { | ||
@@ -78,0 +66,0 @@ return __awaiter(this, void 0, void 0, function () { |
@@ -54,2 +54,5 @@ "use strict"; | ||
var promises_1 = __importDefault(require("fs/promises")); | ||
var tasks_1 = require("@sapphirecode/tasks"); | ||
var exec_1 = require("./exec"); | ||
var docker_interface_1 = require("./docker_interface"); | ||
function init_structure(store) { | ||
@@ -99,5 +102,11 @@ return __awaiter(this, void 0, void 0, function () { | ||
_b.sent(); | ||
if (!pull) return [3 /*break*/, 3]; | ||
return [4 /*yield*/, do_pull(store)]; | ||
case 2: | ||
_b.sent(); | ||
_b.label = 3; | ||
case 3: | ||
_i = 0, _a = store.services; | ||
_b.label = 2; | ||
case 2: | ||
_b.label = 4; | ||
case 4: | ||
if (!(_i < _a.length)) return [3 /*break*/, 7]; | ||
@@ -107,8 +116,3 @@ service = _a[_i]; | ||
return [3 /*break*/, 6]; | ||
if (!pull) return [3 /*break*/, 4]; | ||
return [4 /*yield*/, service.pull()]; | ||
case 3: | ||
_b.sent(); | ||
_b.label = 4; | ||
case 4: return [4 /*yield*/, service.up()]; | ||
return [4 /*yield*/, service.up()]; | ||
case 5: | ||
@@ -119,3 +123,3 @@ _b.sent(); | ||
_i++; | ||
return [3 /*break*/, 2]; | ||
return [3 /*break*/, 4]; | ||
case 7: return [2 /*return*/]; | ||
@@ -153,19 +157,51 @@ } | ||
return __awaiter(this, void 0, void 0, function () { | ||
var _i, _a, service; | ||
return __generator(this, function (_b) { | ||
switch (_b.label) { | ||
var all_images, buildable, _i, _a, service, images, tasks, task_list, _loop_1, _b, buildable_1, buildable_service, _c, images_1, pullable, tl; | ||
return __generator(this, function (_d) { | ||
switch (_d.label) { | ||
case 0: | ||
_i = 0, _a = store.services; | ||
_b.label = 1; | ||
all_images = []; | ||
buildable = []; | ||
for (_i = 0, _a = store.services; _i < _a.length; _i++) { | ||
service = _a[_i]; | ||
all_images.push.apply(all_images, service.images); | ||
if (service.buildable) | ||
buildable.push(service); | ||
} | ||
images = all_images.filter(function (v, i, a) { return a.indexOf(v) === i; }); | ||
tasks = []; | ||
task_list = new tasks_1.TaskListVertical; | ||
_loop_1 = function (buildable_service) { | ||
var tl = new tasks_1.TaskListHorizontal; | ||
task_list.tasks.push(tl); | ||
tl.label = "Building ".concat(buildable_service.name); | ||
tl.label_length = 20; | ||
tl.display_percentage = false; | ||
var task = new tasks_1.Task; | ||
tl.tasks.push(task); | ||
task.progress = 0.5; | ||
tasks.push((0, exec_1.exec_command)('docker', [ | ||
'compose', | ||
'build' | ||
], buildable_service.directory) | ||
.then(function () { | ||
task.progress = 1; | ||
task.completed = true; | ||
})); | ||
}; | ||
for (_b = 0, buildable_1 = buildable; _b < buildable_1.length; _b++) { | ||
buildable_service = buildable_1[_b]; | ||
_loop_1(buildable_service); | ||
} | ||
for (_c = 0, images_1 = images; _c < images_1.length; _c++) { | ||
pullable = images_1[_c]; | ||
tl = new tasks_1.TaskListHorizontal; | ||
task_list.tasks.push(tl); | ||
tl.label_length = 20; | ||
tasks.push((0, docker_interface_1.pull_image)(pullable, tl)); | ||
} | ||
task_list.update(); | ||
return [4 /*yield*/, Promise.all(tasks)]; | ||
case 1: | ||
if (!(_i < _a.length)) return [3 /*break*/, 4]; | ||
service = _a[_i]; | ||
return [4 /*yield*/, service.pull()]; | ||
case 2: | ||
_b.sent(); | ||
_b.label = 3; | ||
case 3: | ||
_i++; | ||
return [3 /*break*/, 1]; | ||
case 4: return [2 /*return*/]; | ||
_d.sent(); | ||
return [2 /*return*/]; | ||
} | ||
@@ -172,0 +208,0 @@ }); |
@@ -45,2 +45,3 @@ "use strict"; | ||
var assert_1 = __importDefault(require("assert")); | ||
var yaml_1 = __importDefault(require("yaml")); | ||
var Network_1 = require("./classes/Network"); | ||
@@ -154,3 +155,3 @@ var Service_1 = require("./classes/Service"); | ||
return __awaiter(this, void 0, void 0, function () { | ||
var passive, dependencies, list, services, _i, list_1, file, stat, err_1, service, _loop_1, _a, services_1, service, added, last, _b, services_2, service; | ||
var passive, dependencies, list, services, _loop_1, _i, list_1, file, _loop_2, _a, services_1, service, added, last, _b, services_2, service; | ||
return __generator(this, function (_c) { | ||
@@ -171,40 +172,62 @@ switch (_c.label) { | ||
services = []; | ||
_loop_1 = function (file) { | ||
var service, stat, err_1, contents, _d, _e, images; | ||
return __generator(this, function (_f) { | ||
switch (_f.label) { | ||
case 0: | ||
if (file.startsWith('.')) | ||
return [2 /*return*/, "continue"]; | ||
service = new Service_1.Service(file, passive.includes(file)); | ||
return [4 /*yield*/, promises_1.default.stat(service.directory)]; | ||
case 1: | ||
stat = _f.sent(); | ||
if (!stat.isDirectory()) | ||
return [2 /*return*/, "continue"]; | ||
_f.label = 2; | ||
case 2: | ||
_f.trys.push([2, 4, , 5]); | ||
return [4 /*yield*/, promises_1.default.access(service.compose_file)]; | ||
case 3: | ||
_f.sent(); | ||
return [3 /*break*/, 5]; | ||
case 4: | ||
err_1 = _f.sent(); | ||
console.warn("".concat(file, ": error reading docker-compose.yml: ").concat(err_1)); | ||
return [2 /*return*/, "continue"]; | ||
case 5: | ||
if (typeof dependencies[file] !== 'undefined') { | ||
if (Array.isArray(dependencies[file])) | ||
service.depends_on = dependencies[file]; | ||
else | ||
console.warn("".concat(file, ": dependencies is not an array")); | ||
} | ||
_e = (_d = yaml_1.default).parse; | ||
return [4 /*yield*/, promises_1.default.readFile(service.compose_file, 'utf-8')]; | ||
case 6: | ||
contents = _e.apply(_d, [_f.sent()]); | ||
(0, assert_1.default)(typeof contents.services === 'object', "no service configuration in ".concat(service.compose_file)); | ||
images = Object.keys(contents.services) | ||
.map(function (key) { return contents.services[key].image; }) | ||
.filter(function (v, i, a) { return a.indexOf(v === i); }); | ||
service.images = images.filter(function (v) { return typeof v === 'string'; }); | ||
service.buildable = images.length > service.images.length; | ||
services.push(service); | ||
return [2 /*return*/]; | ||
} | ||
}); | ||
}; | ||
_i = 0, list_1 = list; | ||
_c.label = 4; | ||
case 4: | ||
if (!(_i < list_1.length)) return [3 /*break*/, 11]; | ||
if (!(_i < list_1.length)) return [3 /*break*/, 7]; | ||
file = list_1[_i]; | ||
if (file.startsWith('.')) | ||
return [3 /*break*/, 10]; | ||
return [4 /*yield*/, promises_1.default.stat("./services/".concat(file))]; | ||
return [5 /*yield**/, _loop_1(file)]; | ||
case 5: | ||
stat = _c.sent(); | ||
if (!stat.isDirectory()) | ||
return [3 /*break*/, 10]; | ||
_c.sent(); | ||
_c.label = 6; | ||
case 6: | ||
_c.trys.push([6, 8, , 9]); | ||
return [4 /*yield*/, promises_1.default.access("./services/".concat(file, "/docker-compose.yml"))]; | ||
case 7: | ||
_c.sent(); | ||
return [3 /*break*/, 9]; | ||
case 8: | ||
err_1 = _c.sent(); | ||
console.warn("".concat(file, ": error reading docker-compose.yml: ").concat(err_1)); | ||
return [3 /*break*/, 10]; | ||
case 9: | ||
service = new Service_1.Service(file, passive.includes(file)); | ||
if (typeof dependencies[file] !== 'undefined') { | ||
if (Array.isArray(dependencies[file])) | ||
service.depends_on = dependencies[file]; | ||
else | ||
console.warn("".concat(file, ": dependencies is not an array")); | ||
} | ||
services.push(service); | ||
_c.label = 10; | ||
case 10: | ||
_i++; | ||
return [3 /*break*/, 4]; | ||
case 11: | ||
_loop_1 = function (service) { | ||
case 7: | ||
_loop_2 = function (service) { | ||
service.depends_on = service.depends_on.filter(function (d) { | ||
@@ -225,3 +248,3 @@ if (typeof d !== 'string') { | ||
service = services_1[_a]; | ||
_loop_1(service); | ||
_loop_2(service); | ||
} | ||
@@ -228,0 +251,0 @@ added = []; |
@@ -7,2 +7,4 @@ import { exec_command } from '../exec'; | ||
public passive; | ||
public buildable = false; | ||
public images: string[] = []; | ||
@@ -18,11 +20,4 @@ public constructor (name: string, passive: boolean) { | ||
public async pull (): Promise<void> { | ||
await exec_command ('docker', [ | ||
'compose', | ||
'pull' | ||
], this.directory); | ||
await exec_command ('docker', [ | ||
'compose', | ||
'build' | ||
], this.directory); | ||
public get compose_file (): string { | ||
return `${this.directory}/docker-compose.yml`; | ||
} | ||
@@ -29,0 +24,0 @@ |
import path from 'path'; | ||
import fs from 'fs/promises'; | ||
import { | ||
Task, | ||
TaskListHorizontal, | ||
TaskListVertical | ||
} from '@sapphirecode/tasks'; | ||
import { Store } from './store'; | ||
import { exec_command } from './exec'; | ||
import { Service } from './classes/Service'; | ||
import { pull_image } from './docker_interface'; | ||
@@ -18,7 +26,7 @@ async function init_structure (store: Store): Promise<void> { | ||
await init_structure (store); | ||
if (pull) | ||
await do_pull (store); | ||
for (const service of store.services) { | ||
if (service.passive && !include_passive) | ||
continue; | ||
if (pull) | ||
await service.pull (); | ||
await service.up (); | ||
@@ -34,4 +42,44 @@ } | ||
export async function do_pull (store: Store): Promise<void> { | ||
for (const service of store.services) | ||
await service.pull (); | ||
const all_images: string[] = []; | ||
const buildable: Service[] = []; | ||
for (const service of store.services) { | ||
all_images.push (...service.images); | ||
if (service.buildable) | ||
buildable.push (service); | ||
} | ||
const images = all_images.filter ((v, i, a) => a.indexOf (v) === i); | ||
const tasks = []; | ||
const task_list = new TaskListVertical; | ||
for (const buildable_service of buildable) { | ||
const tl = new TaskListHorizontal; | ||
task_list.tasks.push (tl); | ||
tl.label = `Building ${buildable_service.name}`; | ||
tl.label_length = 20; | ||
tl.display_percentage = false; | ||
const task = new Task; | ||
tl.tasks.push (task); | ||
task.progress = 0.5; | ||
tasks.push (exec_command ('docker', [ | ||
'compose', | ||
'build' | ||
], buildable_service.directory) | ||
.then (() => { | ||
task.progress = 1; | ||
task.completed = true; | ||
})); | ||
} | ||
for (const pullable of images) { | ||
const tl = new TaskListHorizontal; | ||
task_list.tasks.push (tl); | ||
tl.label_length = 20; | ||
tasks.push (pull_image (pullable, tl)); | ||
} | ||
task_list.update (); | ||
await Promise.all (tasks); | ||
} | ||
@@ -38,0 +86,0 @@ |
import fs from 'fs/promises'; | ||
import assert from 'assert'; | ||
import YAML from 'yaml'; | ||
import { Network } from './classes/Network'; | ||
@@ -86,7 +87,11 @@ import { Service } from './classes/Service'; | ||
continue; | ||
const stat = await fs.stat (`./services/${file}`); | ||
const service = new Service (file, passive.includes (file)); | ||
const stat = await fs.stat (service.directory); | ||
if (!stat.isDirectory ()) | ||
continue; | ||
try { | ||
await fs.access (`./services/${file}/docker-compose.yml`); | ||
await fs.access (service.compose_file); | ||
} | ||
@@ -97,3 +102,2 @@ catch (err) { | ||
} | ||
const service = new Service (file, passive.includes (file)); | ||
if (typeof dependencies[file] !== 'undefined') { | ||
@@ -105,2 +109,18 @@ if (Array.isArray (dependencies[file])) | ||
} | ||
const contents = YAML.parse ( | ||
await fs.readFile (service.compose_file, 'utf-8') | ||
); | ||
assert ( | ||
typeof contents.services === 'object', | ||
`no service configuration in ${service.compose_file}` | ||
); | ||
const images = Object.keys (contents.services) | ||
.map ((key) => contents.services[key].image) | ||
.filter ((v, i, a) => a.indexOf (v === i)); | ||
service.images = images.filter ((v) => typeof v === 'string'); | ||
service.buildable = images.length > service.images.length; | ||
services.push (service); | ||
@@ -107,0 +127,0 @@ } |
{ | ||
"name": "@sapphirecode/dcm", | ||
"version": "1.0.2", | ||
"version": "1.0.3", | ||
"main": "index.js", | ||
@@ -26,2 +26,3 @@ "description": "Managing docker compose configurations, volumes and networks", | ||
"@sapphirecode/eslint-config-ts": "^1.2.2", | ||
"@types/dockerode": "^3.3.23", | ||
"@types/node": "^20.5.7", | ||
@@ -43,6 +44,10 @@ "eslint": "^8.48.0", | ||
"dependencies": { | ||
"@sapphirecode/tasks": "^1.0.3", | ||
"chalk": "4", | ||
"class-transformer": "^0.5.1", | ||
"class-validator": "^0.14.0", | ||
"reflect-metadata": "^0.1.13" | ||
"dockerode": "^4.0.0", | ||
"reflect-metadata": "^0.1.13", | ||
"yaml": "^2.3.4" | ||
} | ||
} |
78907
33
1736
7
6
+ Added@sapphirecode/tasks@^1.0.3
+ Addedchalk@4
+ Addeddockerode@^4.0.0
+ Addedyaml@^2.3.4
+ Added@balena/dockerignore@1.0.2(transitive)
+ Added@grpc/grpc-js@1.12.6(transitive)
+ Added@grpc/proto-loader@0.7.13(transitive)
+ Added@js-sdsl/ordered-map@4.4.2(transitive)
+ Added@protobufjs/aspromise@1.1.2(transitive)
+ Added@protobufjs/base64@1.1.2(transitive)
+ Added@protobufjs/codegen@2.0.4(transitive)
+ Added@protobufjs/eventemitter@1.1.0(transitive)
+ Added@protobufjs/fetch@1.1.0(transitive)
+ Added@protobufjs/float@1.0.2(transitive)
+ Added@protobufjs/inquire@1.1.0(transitive)
+ Added@protobufjs/path@1.1.2(transitive)
+ Added@protobufjs/pool@1.1.0(transitive)
+ Added@protobufjs/utf8@1.1.0(transitive)
+ Added@sapphirecode/tasks@1.1.10(transitive)
+ Added@types/node@22.13.4(transitive)
+ Addedansi-regex@5.0.1(transitive)
+ Addedansi-styles@4.3.0(transitive)
+ Addedasn1@0.2.6(transitive)
+ Addedbase64-js@1.5.1(transitive)
+ Addedbcrypt-pbkdf@1.0.2(transitive)
+ Addedbl@4.1.0(transitive)
+ Addedbuffer@5.7.1(transitive)
+ Addedbuildcheck@0.0.6(transitive)
+ Addedchalk@4.1.2(transitive)
+ Addedchownr@1.1.4(transitive)
+ Addedcliui@8.0.1(transitive)
+ Addedcolor-convert@2.0.1(transitive)
+ Addedcolor-name@1.1.4(transitive)
+ Addedcpu-features@0.0.10(transitive)
+ Addeddebug@4.4.0(transitive)
+ Addeddocker-modem@5.0.6(transitive)
+ Addeddockerode@4.0.4(transitive)
+ Addedemoji-regex@8.0.0(transitive)
+ Addedend-of-stream@1.4.4(transitive)
+ Addedescalade@3.2.0(transitive)
+ Addedfs-constants@1.0.0(transitive)
+ Addedget-caller-file@2.0.5(transitive)
+ Addedhas-flag@4.0.0(transitive)
+ Addedieee754@1.2.1(transitive)
+ Addedinherits@2.0.4(transitive)
+ Addedis-fullwidth-code-point@3.0.0(transitive)
+ Addedlodash.camelcase@4.3.0(transitive)
+ Addedlong@5.3.0(transitive)
+ Addedmkdirp-classic@0.5.3(transitive)
+ Addedms@2.1.3(transitive)
+ Addednan@2.22.0(transitive)
+ Addedonce@1.4.0(transitive)
+ Addedprotobufjs@7.4.0(transitive)
+ Addedpump@3.0.2(transitive)
+ Addedreadable-stream@3.6.2(transitive)
+ Addedrequire-directory@2.1.1(transitive)
+ Addedsafe-buffer@5.2.1(transitive)
+ Addedsafer-buffer@2.1.2(transitive)
+ Addedsplit-ca@1.0.1(transitive)
+ Addedssh2@1.16.0(transitive)
+ Addedstring-width@4.2.3(transitive)
+ Addedstring_decoder@1.3.0(transitive)
+ Addedstrip-ansi@6.0.1(transitive)
+ Addedsupports-color@7.2.0(transitive)
+ Addedtar-fs@2.0.1(transitive)
+ Addedtar-stream@2.2.0(transitive)
+ Addedtweetnacl@0.14.5(transitive)
+ Addedundici-types@6.20.0(transitive)
+ Addedutil-deprecate@1.0.2(transitive)
+ Addeduuid@10.0.0(transitive)
+ Addedwrap-ansi@7.0.0(transitive)
+ Addedwrappy@1.0.2(transitive)
+ Addedy18n@5.0.8(transitive)
+ Addedyaml@2.7.0(transitive)
+ Addedyargs@17.7.2(transitive)
+ Addedyargs-parser@21.1.1(transitive)