UNPKG

3.99 kBPlain TextView Raw
1import { spawn } from 'p-spawn';
2import { Block, buildBlock, loadDockerBlocks } from './block';
3import { callHook } from './hook';
4import { getRemoteImageName, Realm } from './realm';
5import { addSessionState, hasSessionState } from './session';
6import { asNames, now, printLog } from './utils';
7
8
9/**
10 * Push the local docker image for the service(s) to the remote (tag and push)
11 * Assumptions:
12 * - Assume the service names match the docker image convention as is on a local docker repo (localhost:5000/...)
13 * - Today assume remote is gcloud
14 * @param realm
15 * @param serviceNames
16 */
17export async function push(realm: Realm, serviceNames?: string | string[]) {
18 let names: string[];
19 const dockerBlocks = await loadDockerBlocks();
20
21 if (serviceNames) {
22 names = asNames(serviceNames);
23 } else {
24 const dockerBlocks = await loadDockerBlocks();
25 names = Object.keys(dockerBlocks)
26 }
27
28 if (realm.registry == null) {
29 throw new Error(`Realm '${realm.name}' does not have registry, cannot push docker image.`);
30 }
31
32 //// Call prep hook the docker push
33 await callHook(realm, "dpush_prep", names);
34
35 //// For each service, push the docker image
36 for (let serviceName of names) {
37 const block = dockerBlocks[serviceName];
38 if (!block) {
39 throw new Error(`Block ${serviceName} not found`);
40 }
41 let sourceImage = getLocalImageName(block);
42 let remoteImage = getRemoteImageName(block, realm);
43
44 console.log(`----- Pushing service ${serviceName} : ${remoteImage}`);
45
46 // we make sure the tag exist
47 await spawn('docker', ['tag', sourceImage, remoteImage]);
48
49 // This assume gcloud has been setup on the local machine
50 // Note: gcloud requires `gcloud auth configure-docker` and just use `docker push...
51 try {
52 await spawn('docker', ['push', remoteImage]);
53 } catch (ex) {
54 // Note: Allow the hook to eventually recorver.
55 const passed = await callHook(realm, 'dpush_image_ex', ex, remoteImage);
56 // If the dpush_image_ex return true, means it was recovered.
57 // Otherwise there might not have been any hook or could not recover. (note that the hook could throw ex as well)
58 if (passed !== true) {
59 throw ex;
60 }
61 }
62 console.log(`----- /DONE pushing ${serviceName} : ${remoteImage} ------\n`);
63 }
64}
65
66
67export async function buildDockerImage(block: Block) {
68 const dir = block.dir;
69 const imageName = getLocalImageName(block);
70
71 const start = now();
72
73 console.log(`============ BUILDING docker image: ${imageName}\n`);
74
75 // check if this block has a dbuildDependencies
76 const dbuildDeps = asNames(block.dbuildDependencies);
77 for (let dep of dbuildDeps) {
78 await buildBlock(dep);
79 }
80
81 // make sure we build the service first
82 await buildBlock(block.name);
83
84 // build the image
85 console.log(`------ docker build ... ${imageName}`);
86 await spawn('docker', ['build', '--rm', '-t', imageName, '.'], { cwd: dir });
87 console.log(`------ DONE - docker build ... ${imageName}`);
88
89 console.log();
90
91 // it can be use by future k8s after push
92 let status = 'DONE';
93 console.log(`------ docker push ... ${imageName}`);
94 try {
95 if (!hasSessionState('NO_LOCAL_REGISTRY')) {
96 await spawn('docker', ['push', imageName]);
97 }
98 } catch (ex) {
99 addSessionState('NO_LOCAL_REGISTRY');
100 }
101 if (hasSessionState('NO_LOCAL_REGISTRY')) {
102 console.log('INFO - No Local Registry (http://localhost:5000/) - Skipping push to local registry');
103 status = "SKIPPING";
104 }
105
106 console.log(`------ ${status} - docker push ... ${imageName}`);
107
108 printLog(`\n============ DONE - BUILDING docker image: ${imageName}`, start);
109}
110
111
112//#region ---------- docker naming ----------
113export function getLocalImageName(block: Block) {
114 return _getImageName(block, 'localhost:5000/');
115}
116
117export function _getImageName(block: Block, basePath: string) {
118 const repoName = getRepositoryName(block);
119 return `${basePath}${repoName}:${block.imageTag}`;
120}
121
122export function getRepositoryName(block: Block) {
123 return `${block.system}-${block.name}`;
124}
125
126//#endregion ---------- /docker naming ----------
\No newline at end of file