ide/deploy/deploy.js (116 lines of code) (raw):

// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, // software distributed under the License is distributed on an // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. const { spawnSync } = require("child_process"); const fs = require("fs"); const MAINS = ["__main__.py", "index.js", "index.php", "main.go"]; const queue = []; const activeDeployments = new Map(); let dryRun = false; export function setDryRun(b) { dryRun = b; } function exec(cmd) { console.log("$", cmd); if (!dryRun) { spawnSync(cmd, { shell: true, env: process.env, stdio: "inherit" }); } } function extractArgs(files) { const res = []; for (const file of files) { if (fs.existsSync(file)) { const lines = fs.readFileSync(file, "utf-8").split("\n"); for (const line of lines) { if (line.startsWith("#-")) { res.push(line.trim().substring(1)); } if (line.startsWith("//-")) { res.push(line.trim().substring(2)); } } } } return res; } const packageDone = new Set(); export function deployPackage(pkg) { const ppath = `packages/${pkg}.args`; const pargs = extractArgs([ppath]).join(" "); const cmd = `$OPS package update ${pkg} ${pargs}`; if (!packageDone.has(cmd)) { exec(cmd); packageDone.add(cmd); } } export function buildZip(pkg, action) { exec(`$OPS ide util zip A=${pkg}/${action}`); return `packages/${pkg}/${action}.zip`; } export function buildAction(pkg, action) { exec(`$OPS ide util action A=${pkg}/${action}`); return `packages/${pkg}/${action}.zip`; } export function deployAction(artifact) { let pkg = '', name='', typ = ''; if (activeDeployments.has(artifact)) { queue.push(artifact); return; } activeDeployments.set(artifact, true); const indexInQueue = queue.indexOf(artifact); if (indexInQueue>-1) { console.log(`> Deploying ${artifact} (from queue: ${indexInQueue})`); } try { const sp = artifact.split("/"); const spData = sp[sp.length - 1].split("."); name = spData[0]; typ = spData[1]; pkg = sp[1]; } catch { console.log("! cannot deploy", artifact); return; } deployPackage(pkg); let toInspect; if (typ === "zip") { const base = artifact.slice(0, -4); toInspect = MAINS.map((m) => `${base}/${m}`); } else { toInspect = [artifact]; } const args = extractArgs(toInspect).join(" "); const actionName = `${pkg}/${name}`; exec(`$OPS action update ${actionName} ${artifact} ${args}`); activeDeployments.delete(artifact); if (queue.length > 0) { const nextArtifact = queue.shift(); console.debug(`deploying from queue artifact ${nextArtifact}`); deploy(nextArtifact); } } /** * Deploy a `file` * @param file */ export function deploy(file) { // Uncomment the lines below to test specific files // const file = "packages/deploy/hello.py"; // const file = "packages/deploy/multi.zip"; // const file = "packages/deploy/multi/__main__.py"; // const file = "packages/deploy/multi/requirements.txt"; if (fs.lstatSync(file).isDirectory()) { for (const start of MAINS) { const sub = `${file}/${start}`; if (fs.existsSync(sub)) { file = sub; break; } } } const sp = file.split("/"); if (sp.length > 3) { buildZip(sp[1], sp[2]); file = buildAction(sp[1], sp[2]); } deployAction(file); } /** * Deploy a `manifest.yaml` file using `ops -wsk project` * @param artifact */ export function deployProject(artifact) { if (fs.existsSync(artifact)) { const manifestContent = fs.readFileSync(artifact); if (manifestContent.indexOf('packages:')!==-1) { exec(`$OPS -wsk project deploy --manifest ${artifact}`); } else { console.log(`Wanring: it seems that the ${artifact} file is not a valid manifest file. Skipping`); } } }