Compare commits

..

71 Commits

Author SHA1 Message Date
23266ca459 1.0.93 2020-03-23 00:01:46 +00:00
a91e69b6db fix(core): update 2020-03-23 00:01:45 +00:00
015ccfad48 1.0.92 2020-03-22 23:53:32 +00:00
06d2fcb750 fix(core): update 2020-03-22 23:53:31 +00:00
f3e4bc0350 1.0.91 2019-11-20 13:36:36 +00:00
6de3abe3bf fix(readme): update 2019-11-20 13:36:36 +00:00
eaa4140f2f 1.0.90 2019-11-20 13:36:04 +00:00
b21fe80109 fix(structure): formatted, ci updates and new readme 2019-11-20 13:36:03 +00:00
96a2992432 1.0.89 2019-11-20 13:27:18 +00:00
870b5f2c07 fix(dependencies): update smartnetwork 2019-11-20 13:27:17 +00:00
212edf1db7 1.0.88 2019-11-19 18:45:10 +00:00
46dbd81bcc fix(dependencies): update 2019-11-19 18:45:09 +00:00
8f5678502d 1.0.87 2019-11-19 18:42:16 +00:00
959d7aaed1 fix(core): update 2019-11-19 18:42:15 +00:00
5aa10653b6 1.0.86 2019-10-05 15:59:37 +02:00
e120d6527e fix(core): update 2019-10-05 15:59:36 +02:00
c80da05fbb 1.0.85 2019-10-05 15:56:49 +02:00
b9c3475b86 fix(core): update 2019-10-05 15:56:46 +02:00
de2d7e647b 1.0.84 2019-09-24 20:20:37 +02:00
d9348bd016 fix(Image().getVersion()): now returns 0.0.0 for unavailable versions to make SemVer work later on 2019-09-24 20:20:37 +02:00
034fbc3994 1.0.83 2019-09-23 13:52:52 +02:00
a33a6a1f7f fix(core): update 2019-09-23 13:52:52 +02:00
9dd403821b 1.0.82 2019-09-23 13:41:06 +02:00
601d82ea74 fix(core): update 2019-09-23 13:41:06 +02:00
784bb22511 1.0.81 2019-09-22 23:42:30 +02:00
71c89ac9bc fix(core): update 2019-09-22 23:42:29 +02:00
0b3e3b68c9 1.0.80 2019-09-22 17:42:29 +02:00
f3779faaaf fix(core): update 2019-09-22 17:42:28 +02:00
73476c2c39 1.0.79 2019-09-22 17:03:53 +02:00
942f65268d fix(core): update 2019-09-22 17:03:53 +02:00
a965647c1f 1.0.78 2019-09-22 15:11:57 +02:00
db88c7f86c fix(core): update 2019-09-22 15:11:57 +02:00
3f18cb68bf 1.0.77 2019-09-22 15:02:29 +02:00
dae3b59e3b fix(core): update 2019-09-22 15:02:29 +02:00
53062e70d4 1.0.76 2019-09-22 14:32:48 +02:00
3e70dc465b fix(core): update 2019-09-22 14:32:48 +02:00
49445d93c6 1.0.75 2019-09-21 21:57:57 +02:00
4f838837f8 fix(core): update 2019-09-21 21:57:57 +02:00
c76968bbe8 1.0.74 2019-09-20 16:29:44 +02:00
6c5e5644b1 fix(core): update 2019-09-20 16:29:43 +02:00
5cf80944fe 1.0.73 2019-09-19 20:05:57 +02:00
cdb69c5f17 fix(core): update 2019-09-19 20:05:56 +02:00
178c1d2df1 1.0.72 2019-09-18 17:29:43 +02:00
43d9da808b fix(core): update 2019-09-18 17:29:43 +02:00
15f5c38eb0 1.0.71 2019-09-15 15:08:48 +02:00
225c1be14c fix(core): update 2019-09-15 15:08:48 +02:00
44f2aab2f6 1.0.70 2019-09-13 23:08:17 +02:00
b69315f1d3 1.0.69 2019-09-13 23:05:56 +02:00
7d20804986 fix(core): update 2019-09-13 23:05:55 +02:00
0aab639fbd 1.0.68 2019-09-13 22:43:30 +02:00
794bb60dfc fix(core): update 2019-09-13 22:43:29 +02:00
b182a379af 1.0.67 2019-09-13 22:37:38 +02:00
5c6c06dee6 fix(core): update 2019-09-13 22:37:38 +02:00
a48e1e035e 1.0.66 2019-09-13 22:31:03 +02:00
8836c06b56 fix(core): update 2019-09-13 22:31:03 +02:00
7af8e0739b 1.0.65 2019-09-13 22:09:35 +02:00
684185e951 fix(core): update 2019-09-13 22:09:35 +02:00
21e6fff3fb 1.0.64 2019-09-13 18:20:12 +02:00
83c49a6234 fix(core): update 2019-09-13 18:20:12 +02:00
ad67849d45 1.0.63 2019-09-13 18:16:22 +02:00
0e4e07a912 fix(core): update 2019-09-13 18:16:21 +02:00
1fbc09f557 1.0.62 2019-09-13 18:15:46 +02:00
d6201b864c fix(core): update 2019-09-13 18:15:45 +02:00
ea5e552192 1.0.61 2019-09-13 17:54:18 +02:00
1afe5c6e16 fix(core): update 2019-09-13 17:54:17 +02:00
eb0dc96dbd 1.0.60 2019-09-13 16:57:22 +02:00
55f45b1c3a fix(core): update 2019-09-13 16:57:21 +02:00
87ff0f01bb 1.0.59 2019-09-13 14:45:35 +02:00
dd1939d7b2 fix(core): update 2019-09-13 14:45:35 +02:00
5a2a5f1248 1.0.58 2019-09-13 14:40:38 +02:00
9767b8767a fix(core): update 2019-09-13 14:40:38 +02:00
18 changed files with 1261 additions and 1107 deletions

4
.gitignore vendored
View File

@ -15,8 +15,6 @@ node_modules/
# builds # builds
dist/ dist/
dist_web/ dist_*/
dist_serve/
dist_ts_web/
# custom # custom

View File

@ -3,14 +3,14 @@ image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
cache: cache:
paths: paths:
- .npmci_cache/ - .npmci_cache/
key: "$CI_BUILD_STAGE" key: '$CI_BUILD_STAGE'
stages: stages:
- security - security
- test - test
- release - release
- metadata - metadata
# ==================== # ====================
# security stage # security stage
@ -18,62 +18,66 @@ stages:
mirror: mirror:
stage: security stage: security
script: script:
- npmci git mirror - npmci git mirror
tags: tags:
- docker - lossless
- notpriv - docker
- notpriv
snyk: audit:
image: registry.gitlab.com/hosttoday/ht-docker-node:npmci
stage: security stage: security
script: script:
- npmci npm prepare - npmci npm prepare
- npmci command npm install -g snyk
- npmci command npm install --ignore-scripts - npmci command npm install --ignore-scripts
- npmci command snyk test - npmci command npm config set registry https://registry.npmjs.org
- npmci command npm audit --audit-level=high
tags: tags:
- docker - lossless
- notpriv - docker
- notpriv
# ==================== # ====================
# test stage # test stage
# ==================== # ====================
testLTS: testStable:
services:
- docker:18-dind
stage: test stage: test
script: script:
- npmci npm prepare - npmci npm prepare
- npmci node install lts - npmci node install stable
- npmci npm install - npmci npm install
- npmci npm test - npmci npm test
coverage: /\d+.?\d+?\%\s*coverage/ coverage: /\d+.?\d+?\%\s*coverage/
tags: tags:
- docker - lossless
- priv - docker
- priv
testBuild: testBuild:
stage: test stage: test
script: script:
- npmci npm prepare - npmci npm prepare
- npmci node install lts - npmci node install stable
- npmci npm install - npmci npm install
- npmci command npm run build - npmci command npm run build
coverage: /\d+.?\d+?\%\s*coverage/ coverage: /\d+.?\d+?\%\s*coverage/
tags: tags:
- docker - lossless
- notpriv - docker
- notpriv
release: release:
stage: release stage: release
script: script:
- npmci node install lts - npmci node install stable
- npmci npm publish - npmci npm publish
only: only:
- tags - tags
tags: tags:
- docker - lossless
- notpriv - docker
- notpriv
# ==================== # ====================
# metadata stage # metadata stage
@ -83,33 +87,35 @@ codequality:
allow_failure: true allow_failure: true
script: script:
- npmci command npm install -g tslint typescript - npmci command npm install -g tslint typescript
- npmci npm prepare
- npmci npm install - npmci npm install
- npmci command "tslint -c tslint.json ./ts/**/*.ts" - npmci command "tslint -c tslint.json ./ts/**/*.ts"
tags: tags:
- docker - lossless
- priv - docker
- priv
trigger: trigger:
stage: metadata stage: metadata
script: script:
- npmci trigger - npmci trigger
only: only:
- tags - tags
tags: tags:
- docker - lossless
- notpriv - docker
- notpriv
pages: pages:
image: hosttoday/ht-docker-dbase:npmci
services:
- docker:18-dind
stage: metadata stage: metadata
script: script:
- npmci node install lts
- npmci command npm install -g @gitzone/tsdoc - npmci command npm install -g @gitzone/tsdoc
- npmci npm prepare - npmci npm prepare
- npmci npm install - npmci npm install
- npmci command tsdoc - npmci command tsdoc
tags: tags:
- lossless
- docker - docker
- notpriv - notpriv
only: only:
@ -117,5 +123,5 @@ pages:
artifacts: artifacts:
expire_in: 1 week expire_in: 1 week
paths: paths:
- public - public
allow_failure: true allow_failure: true

9
.snyk Normal file
View File

@ -0,0 +1,9 @@
# Snyk (https://snyk.io) policy file, patches or ignores known vulnerabilities.
version: v1.13.5
# ignores vulnerabilities until expiry date; change duration by modifying expiry date
ignore:
SNYK-JS-HTTPSPROXYAGENT-469131:
- '@pushrocks/smartnetwork > speedtest-net > https-proxy-agent':
reason: None given
expires: '2019-11-04T13:59:28.695Z'
patch: {}

26
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,26 @@
{
"json.schemas": [
{
"fileMatch": ["/npmextra.json"],
"schema": {
"type": "object",
"properties": {
"npmci": {
"type": "object",
"description": "settings for npmci"
},
"gitzone": {
"type": "object",
"description": "settings for gitzone",
"properties": {
"projectType": {
"type": "string",
"enum": ["website", "element", "service", "npm"]
}
}
}
}
}
}
]
}

View File

@ -10,6 +10,7 @@
"npmRegistryUrl": "registry.npmjs.org" "npmRegistryUrl": "registry.npmjs.org"
}, },
"gitzone": { "gitzone": {
"projectType": "npm",
"module": { "module": {
"githost": "gitlab.com", "githost": "gitlab.com",
"gitscope": "mojoio", "gitscope": "mojoio",

1786
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
{ {
"name": "@mojoio/docker", "name": "@mojoio/docker",
"version": "1.0.57", "version": "1.0.93",
"description": "easy communication with docker remote api from node, TypeScript ready", "description": "easy communication with docker remote api from node, TypeScript ready",
"private": false, "private": false,
"main": "dist/index.js", "main": "dist_ts/index.js",
"typings": "dist/index.d.ts", "typings": "dist_ts/index.d.ts",
"scripts": { "scripts": {
"test": "tstest test/", "test": "tstest test/",
"build": "tsbuild" "build": "tsbuild"
@ -27,32 +27,36 @@
}, },
"homepage": "https://gitlab.com/pushrocks/dockersock#README", "homepage": "https://gitlab.com/pushrocks/dockersock#README",
"dependencies": { "dependencies": {
"@pushrocks/lik": "^3.0.11", "@pushrocks/lik": "^3.0.19",
"@pushrocks/smartjson": "^3.0.8", "@pushrocks/smartfile": "^7.0.11",
"@pushrocks/smartlog": "^2.0.19", "@pushrocks/smartjson": "^3.0.10",
"@pushrocks/smartnetwork": "^1.1.14", "@pushrocks/smartlog": "^2.0.21",
"@pushrocks/smartpromise": "^3.0.2", "@pushrocks/smartnetwork": "^1.1.18",
"@pushrocks/smartrequest": "^1.1.26", "@pushrocks/smartpath": "^4.0.1",
"@pushrocks/smartstring": "^3.0.10", "@pushrocks/smartpromise": "^3.0.6",
"@pushrocks/smartrequest": "^1.1.47",
"@pushrocks/smartstring": "^3.0.18",
"@pushrocks/smartversion": "^2.0.4", "@pushrocks/smartversion": "^2.0.4",
"rxjs": "^6.5.3" "@tsclass/tsclass": "^3.0.13",
"rxjs": "^6.5.4"
}, },
"devDependencies": { "devDependencies": {
"@gitzone/tsbuild": "^2.1.17", "@gitzone/tsbuild": "^2.1.22",
"@gitzone/tsrun": "^1.2.8", "@gitzone/tsrun": "^1.2.8",
"@gitzone/tstest": "^1.0.24", "@gitzone/tstest": "^1.0.28",
"@pushrocks/tapbundle": "^3.0.13", "@pushrocks/tapbundle": "^3.2.1",
"@types/node": "^12.7.4", "@types/node": "^13.9.3",
"tslint": "^5.19.0", "tslint": "^6.1.0",
"tslint-config-prettier": "^1.18.0" "tslint-config-prettier": "^1.18.0"
}, },
"files": [ "files": [
"ts/*", "ts/**/*",
"ts_web/*", "ts_web/**/*",
"dist/*", "dist/**/*",
"dist_web/*", "dist_*/**/*",
"dist_ts_web/*", "dist_ts/**/*",
"assets/*", "dist_ts_web/**/*",
"assets/**/*",
"cli.js", "cli.js",
"npmextra.json", "npmextra.json",
"readme.md" "readme.md"

View File

@ -8,7 +8,7 @@ unofficial docker engine api abstraction package written in TypeScript
* [docs (typedoc)](https://mojoio.gitlab.io/docker/) * [docs (typedoc)](https://mojoio.gitlab.io/docker/)
## Status for master ## Status for master
[![build status](https://gitlab.com/mojoio/docker/badges/master/build.svg)](https://gitlab.com/mojoio/docker/commits/master) [![pipeline status](https://gitlab.com/mojoio/docker/badges/master/pipeline.svg)](https://gitlab.com/mojoio/docker/commits/master)
[![coverage report](https://gitlab.com/mojoio/docker/badges/master/coverage.svg)](https://gitlab.com/mojoio/docker/commits/master) [![coverage report](https://gitlab.com/mojoio/docker/badges/master/coverage.svg)](https://gitlab.com/mojoio/docker/commits/master)
[![npm downloads per month](https://img.shields.io/npm/dm/@mojoio/docker.svg)](https://www.npmjs.com/package/@mojoio/docker) [![npm downloads per month](https://img.shields.io/npm/dm/@mojoio/docker.svg)](https://www.npmjs.com/package/@mojoio/docker)
[![Known Vulnerabilities](https://snyk.io/test/npm/@mojoio/docker/badge.svg)](https://snyk.io/test/npm/@mojoio/docker) [![Known Vulnerabilities](https://snyk.io/test/npm/@mojoio/docker/badge.svg)](https://snyk.io/test/npm/@mojoio/docker)
@ -30,6 +30,10 @@ const run = async () => {
}; };
``` ```
## Contribution
We are always happy for code contributions. If you are not the code contributing type that is ok. Still, maintaining Open Source repositories takes considerable time and thought. If you like the quality of what we do and our modules are useful to you we would appreciate a little monthly contribution: You can [contribute one time](https://lossless.link/contribute-onetime) or [contribute monthly](https://lossless.link/contribute). :)
For further information read the linked docs at the top of this readme. For further information read the linked docs at the top of this readme.
> MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh) > MIT licensed | **©** [Lossless GmbH](https://lossless.gmbh)

11
scripts/testauth.ts Normal file
View File

@ -0,0 +1,11 @@
import * as docker from '../ts';
import * as smartstring from '@pushrocks/smartstring';
const run = async () => {
const dockerHost = new docker.DockerHost();
await docker.DockerImage.createFromRegistry(dockerHost, {
imageUrl: 'registry.gitlab.com/servezone/private/cloudly:latest'
});
};
run();

View File

@ -1,6 +1,5 @@
import { expect, tap } from '@pushrocks/tapbundle'; import { expect, tap } from '@pushrocks/tapbundle';
import * as docker from '../ts/index'; import * as docker from '../ts/index';
import { DockerService } from '../ts/index';
let testDockerHost: docker.DockerHost; let testDockerHost: docker.DockerHost;
@ -61,6 +60,7 @@ tap.test('should return a change Observable', async tools => {
tap.test('should create a secret', async () => { tap.test('should create a secret', async () => {
const mySecret = await docker.DockerSecret.createSecret(testDockerHost, { const mySecret = await docker.DockerSecret.createSecret(testDockerHost, {
name: 'testSecret', name: 'testSecret',
version: '1.0.3',
contentArg: `{ "hi": "wow"}`, contentArg: `{ "hi": "wow"}`,
labels: {} labels: {}
}); });
@ -72,7 +72,6 @@ tap.test('should remove a secret by name', async () => {
await mySecret.remove(); await mySecret.remove();
}); });
// SERVICES // SERVICES
tap.test('should activate swarm mode', async () => { tap.test('should activate swarm mode', async () => {
await testDockerHost.activateSwarm(); await testDockerHost.activateSwarm();
@ -88,24 +87,24 @@ tap.test('should create a service', async () => {
Name: 'testNetwork' Name: 'testNetwork'
}); });
const testSecret = await docker.DockerSecret.createSecret(testDockerHost, { const testSecret = await docker.DockerSecret.createSecret(testDockerHost, {
name: 'serviceSecret', name: 'testSecret',
version: '0.0.1',
labels: {}, labels: {},
contentArg: '{"hi": "wow"}' contentArg: '{"hi": "wow"}'
}); });
const testService = await DockerService.createService(testDockerHost, { const testImage = await docker.DockerImage.createFromRegistry(testDockerHost, {
Image: 'nginx:latest', imageUrl: 'registry.gitlab.com/hosttoday/ht-docker-static'
Labels: { });
'testlabel': 'hi' const testService = await docker.DockerService.createService(testDockerHost, {
}, image: testImage,
Name: 'testService', labels: {},
name: 'testService',
networks: [testNetwork], networks: [testNetwork],
networkAlias: 'testService', networkAlias: 'testService',
secrets: [testSecret] secrets: [testSecret],
ports: ['3000:80']
}); });
await testSecret.update(`{"updated": "socool"}`);
await testService.update();
await testService.remove(); await testService.remove();
await testNetwork.remove(); await testNetwork.remove();
await testSecret.remove(); await testSecret.remove();

View File

@ -3,11 +3,18 @@ import { DockerContainer } from './docker.classes.container';
import { DockerNetwork } from './docker.classes.network'; import { DockerNetwork } from './docker.classes.network';
import { DockerService } from './docker.classes.service'; import { DockerService } from './docker.classes.service';
export interface IAuthData {
serveraddress: string;
username: string;
password: string;
}
export class DockerHost { export class DockerHost {
/** /**
* the path where the docker sock can be found * the path where the docker sock can be found
*/ */
public socketPath: string; public socketPath: string;
private registryToken: string = '';
/** /**
* the constructor to instantiate a new docker sock instance * the constructor to instantiate a new docker sock instance
@ -30,11 +37,31 @@ export class DockerHost {
* @param userArg * @param userArg
* @param passArg * @param passArg
*/ */
public async auth(registryUrl: string, userArg: string, passArg: string) { public async auth(authData: IAuthData) {
const response = await this.request('POST', '/auth', { const response = await this.request('POST', '/auth', authData);
serveraddress: registryUrl, if (response.body.Status !== 'Login Succeeded') {
username: userArg, console.log(`Login failed with ${response.body.Status}`);
password: passArg, throw new Error(response.body.Status);
}
console.log(response.body.Status);
this.registryToken = plugins.smartstring.base64.encode(
plugins.smartjson.Smartjson.stringify(authData, {})
);
}
/**
* gets the token from the .docker/config.json file for GitLab registry
*/
public async getGitlabComTokenFromDockerConfig() {
const dockerConfigPath = plugins.smartpath.get.home('~/.docker/config.json');
const configObject = plugins.smartfile.fs.toObjectSync(dockerConfigPath);
const gitlabAuthBase64 = configObject.auths['registry.gitlab.com'].auth;
const gitlabAuth: string = plugins.smartstring.base64.decode(gitlabAuthBase64);
const gitlabAuthArray = gitlabAuth.split(':');
await this.auth({
username: gitlabAuthArray[0],
password: gitlabAuthArray[1],
serveraddress: 'registry.gitlab.com'
}); });
} }
@ -45,6 +72,10 @@ export class DockerHost {
return await DockerNetwork.getNetworks(this); return await DockerNetwork.getNetworks(this);
} }
/**
*
*/
/** /**
* gets all containers * gets all containers
*/ */
@ -122,6 +153,7 @@ export class DockerHost {
method: methodArg, method: methodArg,
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'X-Registry-Auth': this.registryToken,
Host: 'docker.sock' Host: 'docker.sock'
}, },
requestBody: dataArg, requestBody: dataArg,
@ -141,6 +173,7 @@ export class DockerHost {
method: methodArg, method: methodArg,
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',
'X-Registry-Auth': this.registryToken,
Host: 'docker.sock' Host: 'docker.sock'
}, },
requestBody: null, requestBody: null,

View File

@ -15,16 +15,20 @@ export class DockerImage {
public static async findImageByName(dockerHost: DockerHost, imageNameArg: string) { public static async findImageByName(dockerHost: DockerHost, imageNameArg: string) {
const images = await this.getImages(dockerHost); const images = await this.getImages(dockerHost);
return images.find(image => { const result = images.find(image => {
return image.RepoTags.includes(imageNameArg); if (image.RepoTags) {
return image.RepoTags.includes(imageNameArg);
} else {
return false;
}
}); });
return result;
} }
public static async createFromRegistry( public static async createFromRegistry(
dockerHostArg: DockerHost, dockerHostArg: DockerHost,
creationObject: interfaces.IImageCreationDescriptor creationObject: interfaces.IImageCreationDescriptor
): Promise<DockerImage> { ): Promise<DockerImage> {
// lets create a sanatized imageUrlObject // lets create a sanatized imageUrlObject
const imageUrlObject: { const imageUrlObject: {
imageUrl: string; imageUrl: string;
@ -40,9 +44,7 @@ export class DockerImage {
const imageTag = imageUrlObject.imageUrl.split(':')[1]; const imageTag = imageUrlObject.imageUrl.split(':')[1];
if (imageUrlObject.imageTag) { if (imageUrlObject.imageTag) {
throw new Error( throw new Error(
`imageUrl ${imageUrlObject.imageUrl} can't be tagged with ${ `imageUrl ${imageUrlObject.imageUrl} can't be tagged with ${imageUrlObject.imageTag} because it is already tagged with ${imageTag}`
imageUrlObject.imageTag
} because it is already tagged with ${imageTag}`
); );
} else { } else {
imageUrlObject.imageUrl = imageUrl; imageUrlObject.imageUrl = imageUrl;
@ -113,7 +115,13 @@ export class DockerImage {
}); });
} }
public tagImage(newTag) {} /**
* tag an image
* @param newTag
*/
public async tagImage(newTag) {
throw new Error('.tagImage is not yet implemented');
}
/** /**
* pulls the latest version from the registry * pulls the latest version from the registry
@ -126,4 +134,13 @@ export class DockerImage {
// TODO: Compare image digists before and after // TODO: Compare image digists before and after
return true; return true;
} }
// get stuff
public async getVersion() {
if (this.Labels && this.Labels.version) {
return this.Labels.version;
} else {
return '0.0.0';
}
}
} }

View File

@ -2,6 +2,7 @@ import * as plugins from './docker.plugins';
import * as interfaces from './interfaces'; import * as interfaces from './interfaces';
import { DockerHost } from './docker.classes.host'; import { DockerHost } from './docker.classes.host';
import { DockerService } from './docker.classes.service';
export class DockerNetwork { export class DockerNetwork {
public static async getNetworks(dockerHost: DockerHost): Promise<DockerNetwork[]> { public static async getNetworks(dockerHost: DockerHost): Promise<DockerNetwork[]> {
@ -29,17 +30,17 @@ export class DockerNetwork {
CheckDuplicate: true, CheckDuplicate: true,
Driver: 'overlay', Driver: 'overlay',
EnableIPv6: false, EnableIPv6: false,
IPAM: { /* IPAM: {
Driver: 'default', Driver: 'default',
Config: [ Config: [
{ {
Subnet: '172.20.10.0/16', Subnet: `172.20.${networkCreationDescriptor.NetworkNumber}.0/16`,
IPRange: '172.20.10.0/24', IPRange: `172.20.${networkCreationDescriptor.NetworkNumber}.0/24`,
Gateway: '172.20.10.11' Gateway: `172.20.${networkCreationDescriptor.NetworkNumber}.11`
} }
] ]
}, }, */
Internal: true, Internal: false,
Attachable: true, Attachable: true,
Ingress: false Ingress: false
}); });
@ -90,4 +91,30 @@ export class DockerNetwork {
public async remove() { public async remove() {
const response = await this.dockerHost.request('DELETE', `/networks/${this.Id}`); const response = await this.dockerHost.request('DELETE', `/networks/${this.Id}`);
} }
public async getContainersOnNetwork(): Promise<
Array<{
Name: string;
EndpointID: string;
MacAddress: string;
IPv4Address: string;
IPv6Address: string;
}>
> {
const returnArray = [];
const response = await this.dockerHost.request('GET', `/networks/${this.Id}`);
for (const key of Object.keys(response.body.Containers)) {
returnArray.push(response.body.Containers[key]);
}
return returnArray;
}
public async getContainersOnNetworkForService(serviceArg: DockerService) {
const containersOnNetwork = await this.getContainersOnNetwork();
const containersOfService = containersOnNetwork.filter(container => {
return container.Name.startsWith(serviceArg.Spec.Name);
});
return containersOfService;
}
} }

View File

@ -17,26 +17,36 @@ export class DockerSecret {
return secrets; return secrets;
} }
public static async getSecretByID (dockerHostArg: DockerHost, idArg: string) { public static async getSecretByID(dockerHostArg: DockerHost, idArg: string) {
const secrets = await this.getSecrets(dockerHostArg); const secrets = await this.getSecrets(dockerHostArg);
return secrets.find(secret => secret.ID === idArg); return secrets.find(secret => secret.ID === idArg);
} }
public static async getSecretByName (dockerHostArg: DockerHost, nameArg: string) { public static async getSecretByName(dockerHostArg: DockerHost, nameArg: string) {
const secrets = await this.getSecrets(dockerHostArg); const secrets = await this.getSecrets(dockerHostArg);
return secrets.find(secret => secret.Spec.Name === nameArg); return secrets.find(secret => secret.Spec.Name === nameArg);
} }
public static async createSecret(dockerHostArg: DockerHost, secretDescriptor: interfaces.ISecretCreationDescriptor) { public static async createSecret(
dockerHostArg: DockerHost,
secretDescriptor: interfaces.ISecretCreationDescriptor
) {
const labels: interfaces.TLabels = {
...secretDescriptor.labels,
version: secretDescriptor.version
};
const response = await dockerHostArg.request('POST', '/secrets/create', { const response = await dockerHostArg.request('POST', '/secrets/create', {
Name: secretDescriptor.name, Name: secretDescriptor.name,
Labels: secretDescriptor.labels, Labels: labels,
Data: plugins.smartstring.base64.encode(secretDescriptor.contentArg) Data: plugins.smartstring.base64.encode(secretDescriptor.contentArg)
}); });
const newSecretInstance = new DockerSecret(dockerHostArg); const newSecretInstance = new DockerSecret(dockerHostArg);
Object.assign(newSecretInstance, response.body); Object.assign(newSecretInstance, response.body);
Object.assign (newSecretInstance, await DockerSecret.getSecretByID(dockerHostArg, newSecretInstance.ID)); Object.assign(
newSecretInstance,
await DockerSecret.getSecretByID(dockerHostArg, newSecretInstance.ID)
);
return newSecretInstance; return newSecretInstance;
} }
@ -46,9 +56,9 @@ export class DockerSecret {
Name: string; Name: string;
Labels: interfaces.TLabels; Labels: interfaces.TLabels;
}; };
Version: { public Version: {
Index:string; Index: string;
} };
public dockerHost: DockerHost; public dockerHost: DockerHost;
constructor(dockerHostArg: DockerHost) { constructor(dockerHostArg: DockerHost) {
@ -58,16 +68,25 @@ export class DockerSecret {
/** /**
* updates a secret * updates a secret
*/ */
public async update (contentArg: string) { public async update(contentArg: string) {
const route = `/secrets/${this.ID}/update?=version=${this.Version.Index}`; const route = `/secrets/${this.ID}/update?=version=${this.Version.Index}`;
const response = await this.dockerHost.request('POST', `/secrets/${this.ID}/update?version=${this.Version.Index}`, { const response = await this.dockerHost.request(
Name: this.Spec.Name, 'POST',
Labels: this.Spec.Labels, `/secrets/${this.ID}/update?version=${this.Version.Index}`,
Data: plugins.smartstring.base64.encode(contentArg) {
}); Name: this.Spec.Name,
Labels: this.Spec.Labels,
Data: plugins.smartstring.base64.encode(contentArg)
}
);
} }
public async remove () { public async remove() {
await this.dockerHost.request('DELETE', `/secrets/${this.ID}`); await this.dockerHost.request('DELETE', `/secrets/${this.ID}`);
} }
}
// get things
public async getVersion() {
return this.Spec.Labels.version;
}
}

View File

@ -39,16 +39,57 @@ export class DockerService {
// lets get the image // lets get the image
plugins.smartlog.defaultLogger.log( plugins.smartlog.defaultLogger.log(
'info', 'info',
`downloading image for service ${serviceCreationDescriptor.Name}` `now creating service ${serviceCreationDescriptor.name}`
); );
const serviceImage = await DockerImage.createFromRegistry(dockerHost, {
imageUrl: serviceCreationDescriptor.Image
});
const serviceVersion = serviceImage.Labels.version; // await serviceCreationDescriptor.image.pullLatestImageFromRegistry();
serviceCreationDescriptor.Labels.version = serviceVersion; const serviceVersion = await serviceCreationDescriptor.image.getVersion();
const labels: interfaces.TLabels = {
...serviceCreationDescriptor.labels,
version: serviceVersion
};
const mounts: Array<{
/**
* the target inside the container
*/
Target: string;
/**
* The Source from which to mount the data (Volume or host path)
*/
Source: string;
Type: 'bind' | 'volume' | 'tmpfs' | 'npipe';
ReadOnly: boolean;
Consistency: 'default' | 'consistent' | 'cached' | 'delegated';
}> = [];
if (serviceCreationDescriptor.accessHostDockerSock) {
mounts.push({
Target: '/var/run/docker.sock',
Source: '/var/run/docker.sock',
Consistency: 'default',
ReadOnly: false,
Type: 'bind'
});
}
if (serviceCreationDescriptor.resources && serviceCreationDescriptor.resources.volumeMounts) {
for(const volumeMount of serviceCreationDescriptor.resources.volumeMounts) {
mounts.push({
Target: volumeMount.containerFsPath,
Source: volumeMount.hostFsPath,
Consistency: 'default',
ReadOnly: false,
Type: 'bind'
});
}
}
const networkArray: Array<{
Target: string;
Aliases: string[];
}> = [];
const networkArray: any[] = [];
for (const network of serviceCreationDescriptor.networks) { for (const network of serviceCreationDescriptor.networks) {
networkArray.push({ networkArray.push({
Target: network.Name, Target: network.Name,
@ -56,11 +97,24 @@ export class DockerService {
}); });
} }
const ports = [];
for (const port of serviceCreationDescriptor.ports) {
const portArray = port.split(':');
const hostPort = portArray[0];
const containerPort = portArray[1];
ports.push({
Protocol: 'tcp',
PublishedPort: parseInt(hostPort, 10),
TargetPort: parseInt(containerPort, 10)
});
}
// lets configure secrets
const secretArray: any[] = []; const secretArray: any[] = [];
for (const secret of serviceCreationDescriptor.secrets) { for (const secret of serviceCreationDescriptor.secrets) {
secretArray.push({ secretArray.push({
File: { File: {
Name: 'secret.json', Name: 'secret.json', // TODO: make sure that works with multiple secrets
UID: '33', UID: '33',
GID: '33', GID: '33',
Mode: 384 Mode: 384
@ -70,13 +124,32 @@ export class DockerService {
}); });
} }
// lets configure limits
const memoryLimitMB =
serviceCreationDescriptor.resources && serviceCreationDescriptor.resources.memorySizeMB
? serviceCreationDescriptor.resources.memorySizeMB
: 1000;
const limits = {
MemoryBytes: memoryLimitMB * 1000000
};
if (serviceCreationDescriptor.resources) {
limits.MemoryBytes = serviceCreationDescriptor.resources.memorySizeMB * 1000000;
}
const response = await dockerHost.request('POST', '/services/create', { const response = await dockerHost.request('POST', '/services/create', {
Name: serviceCreationDescriptor.Name, Name: serviceCreationDescriptor.name,
TaskTemplate: { TaskTemplate: {
ContainerSpec: { ContainerSpec: {
Image: serviceCreationDescriptor.Image, Image: serviceCreationDescriptor.image.RepoTags[0],
Labels: serviceCreationDescriptor.Labels, Labels: labels,
Secrets: secretArray Secrets: secretArray,
Mounts: mounts
/* DNSConfig: {
Nameservers: ['1.1.1.1']
} */
}, },
UpdateConfig: { UpdateConfig: {
Parallelism: 0, Parallelism: 0,
@ -85,15 +158,28 @@ export class DockerService {
Monitor: 15000000000, Monitor: 15000000000,
MaxFailureRatio: 0.15 MaxFailureRatio: 0.15
}, },
ForceUpdate: 1 ForceUpdate: 1,
Resources: {
Limits: limits
},
LogDriver: {
Name: 'json-file',
Options: {
'max-file': '3',
'max-size': '10M'
}
}
}, },
Labels: serviceCreationDescriptor.Labels, Labels: labels,
Networks: networkArray Networks: networkArray,
EndpointSpec: {
Ports: ports
}
}); });
const createdService = await DockerService.getServiceByName( const createdService = await DockerService.getServiceByName(
dockerHost, dockerHost,
serviceCreationDescriptor.Name serviceCreationDescriptor.name
); );
return createdService; return createdService;
} }
@ -134,32 +220,13 @@ export class DockerService {
this.dockerHostRef = dockerHostArg; this.dockerHostRef = dockerHostArg;
} }
public async update() {
const labels: interfaces.TLabels = {
...this.Spec.Labels,
version: 'x.x.x'
};
const dockerData = await this.dockerHostRef.request(
'POST',
`/services/${this.ID}/update?version=${this.Version.Index}`,
{
Name: this.Spec.Name,
TaskTemplate: this.Spec.TaskTemplate,
Labels: labels,
Networks: this.Spec.Networks
}
);
Object.assign(this, dockerData);
}
public async remove() { public async remove() {
await this.dockerHostRef.request('DELETE', `/services/${this.ID}`); await this.dockerHostRef.request('DELETE', `/services/${this.ID}`);
} }
public async reReadFromDockerEngine() { public async reReadFromDockerEngine() {
const dockerData = await this.dockerHostRef.request('GET', `/services/${this.ID}`); const dockerData = await this.dockerHostRef.request('GET', `/services/${this.ID}`);
Object.assign(this, dockerData); // TODO: Better assign: Object.assign(this, dockerData);
} }
public async needsUpdate(): Promise<boolean> { public async needsUpdate(): Promise<boolean> {
@ -179,10 +246,4 @@ export class DockerService {
console.log(`service ${this.Spec.Name} is up to date.`); console.log(`service ${this.Spec.Name} is up to date.`);
} }
} }
public async updateFromRegistry() {
if (await this.needsUpdate()) {
this.update();
}
}
} }

View File

@ -1,16 +1,41 @@
// node native path
import * as path from 'path';
export { path };
// @pushrocks scope // @pushrocks scope
import * as lik from '@pushrocks/lik'; import * as lik from '@pushrocks/lik';
import * as smartfile from '@pushrocks/smartfile';
import * as smartjson from '@pushrocks/smartjson'; import * as smartjson from '@pushrocks/smartjson';
import * as smartlog from '@pushrocks/smartlog'; import * as smartlog from '@pushrocks/smartlog';
import * as smartnetwork from '@pushrocks/smartnetwork'; import * as smartnetwork from '@pushrocks/smartnetwork';
import * as smartpath from '@pushrocks/smartpath';
import * as smartpromise from '@pushrocks/smartpromise'; import * as smartpromise from '@pushrocks/smartpromise';
import * as smartrequest from '@pushrocks/smartrequest'; import * as smartrequest from '@pushrocks/smartrequest';
import * as smartstring from '@pushrocks/smartstring' import * as smartstring from '@pushrocks/smartstring';
import * as smartversion from '@pushrocks/smartversion'; import * as smartversion from '@pushrocks/smartversion';
smartlog.defaultLogger.enableConsole(); smartlog.defaultLogger.enableConsole();
export { lik, smartjson, smartlog, smartnetwork, smartpromise, smartrequest, smartstring, smartversion }; export {
lik,
smartfile,
smartjson,
smartlog,
smartnetwork,
smartpath,
smartpromise,
smartrequest,
smartstring,
smartversion
};
// @tsclass scope
import * as tsclass from '@tsclass/tsclass';
export {
tsclass
};
// third party // third party
import * as rxjs from 'rxjs'; import * as rxjs from 'rxjs';

View File

@ -2,6 +2,7 @@ import * as interfaces from './';
export interface ISecretCreationDescriptor { export interface ISecretCreationDescriptor {
name: string; name: string;
version: string;
contentArg: any; contentArg: any;
labels: interfaces.TLabels; labels: interfaces.TLabels;
} }

View File

@ -1,12 +1,21 @@
import * as plugins from '../docker.plugins';
import * as interfaces from './'; import * as interfaces from './';
import { DockerNetwork } from '../docker.classes.network'; import { DockerNetwork } from '../docker.classes.network';
import { DockerSecret } from '../docker.classes.secret'; import { DockerSecret } from '../docker.classes.secret';
import { DockerImage } from '../docker.classes.image';
export interface IServiceCreationDescriptor { export interface IServiceCreationDescriptor {
Name: string; name: string;
Image: string; image: DockerImage;
Labels: interfaces.TLabels; labels: interfaces.TLabels;
networks: DockerNetwork[]; networks: DockerNetwork[];
networkAlias: string; networkAlias: string;
secrets: DockerSecret[]; secrets: DockerSecret[];
ports: string[];
accessHostDockerSock?: boolean;
resources?: {
memorySizeMB?: number;
volumeMounts: plugins.tsclass.container.IVolumeMount[]
};
} }