This is an automated email from the ASF dual-hosted git repository.
msciabarra pushed a commit to branch 0.1.0
in repository https://gitbox.apache.org/repos/asf/openserverless-task.git
The following commit(s) were added to refs/heads/0.1.0 by this push:
new 2b396ae updated to latest main
2b396ae is described below
commit 2b396ae289289fa74751eb228f0ea1329851d8a7
Author: Michele Sciabarra <“[email protected]”>
AuthorDate: Tue Feb 24 07:50:52 2026 +0000
updated to latest main
---
admin/docopts.md | 3 +-
admin/opsfile.yml | 7 +-
config/docopts.md | 11 +-
config/opsfile.yml | 64 ++++-
ide/deploy/bun.lockb | Bin 17094 -> 17804 bytes
ide/deploy/client.js | 56 ++---
ide/deploy/deploy.js | 48 ++--
ide/deploy/env_utils.js | 2 +-
ide/deploy/index.js | 54 ++++-
ide/deploy/info.js | 21 +-
ide/deploy/package.json | 3 +-
ide/deploy/scan.js | 48 ++--
ide/deploy/serve.js | 120 +++++++---
ide/deploy/syncDeployInfo.js | 124 ++++++++++
ide/deploy/undeploy.js | 122 ++++++++++
ide/docopts.md | 15 +-
ide/nodejs/build-node.sh | 3 +-
ide/opsfile.yml | 169 ++++++++------
ide/python/build-venv.sh | 8 +-
ide/python/installer.code-workspace | 17 ++
ide/util/opsfile.yml | 4 +-
opsroot.json | 4 +-
prereq.yml | 72 +++---
setup/docker/ingress-deploy.yaml | 258 +--------------------
setup/docker/kind.yaml | 76 ++----
setup/docker/opsfile.yml | 96 ++++----
setup/docopts.md | 6 +-
setup/kubernetes/crds/whisk-crd.yaml | 57 ++++-
setup/kubernetes/operator.yaml | 14 +-
setup/kubernetes/opsfile.yml | 76 +++---
setup/kubernetes/whisk.yaml | 17 +-
setup/nuvolaris/opsfile.yml | 44 ++--
setup/nuvolaris/streamer/nginx-template.yaml | 11 +
setup/nuvolaris/streamer/opsfile.yml | 48 ++--
setup/nuvolaris/streamer/traefik-template.yaml | 16 +-
.../system-api/deploy/buildkit/buildkitd.toml | 40 ++--
setup/nuvolaris/system-api/opsfile.yml | 73 ++++--
setup/opsfile.yml | 76 +++---
update/opsfile.yml | 6 +-
util/docopts.md | 8 +-
util/freeze/opsfile.yml | 176 ++++++++++++++
util/kube/opsfile.yml | 18 +-
util/opsfile.yml | 60 +++--
43 files changed, 1314 insertions(+), 837 deletions(-)
diff --git a/admin/docopts.md b/admin/docopts.md
index dffa362..19c836f 100644
--- a/admin/docopts.md
+++ b/admin/docopts.md
@@ -27,7 +27,7 @@ You can create namespaces and choose which services to enable.
```text
Usage:
- admin adduser <username> <email> <password> [--all] [--redis] [--mongodb]
[--minio] [--postgres] [--milvus] [--storagequota=<quota>|auto]
+ admin adduser <username> <email> <password> [--all] [--redis] [--mongodb]
[--minio|--seaweedfs] [--postgres] [--milvus] [--storagequota=<quota>|auto]
admin deleteuser <username>
admin listuser [<username>]
admin compact [--ttl=<ttl>|10]
@@ -49,6 +49,7 @@ Usage:
--redis enable redis
--mongodb enable mongodb
--minio enable minio
+ --seaweedfs enable seaweedfs
--postgres enable postgres
--milvus enable milvus vector db
--storagequota=<quota>
diff --git a/admin/opsfile.yml b/admin/opsfile.yml
index 0898a4b..415699c 100644
--- a/admin/opsfile.yml
+++ b/admin/opsfile.yml
@@ -119,17 +119,18 @@ tasks:
fi
fi
- if {{.__minio}} || {{.__all}}
+ if {{.__minio}} || {{.__seaweedfs}} || {{.__all}}
then
- if $OPERATOR_COMPONENT_MINIO
+ if $OPERATOR_COMPONENT_MINIO || $OPERATOR_COMPONENT_SEAWEEDFS
then
MINIO_DATA_ENABLED=true
MINIO_STATIC_ENABLED=true
else
- die "Error! Minio is not enabled in OpenServerless"
+ die "Error! Minio or Seaweedfs are not enabled in OpenServerless"
fi
fi
+
if test -n "{{.__storagequota}}"
then MINIO_STORAGE_QUOTA={{.__storagequota}}
fi
diff --git a/config/docopts.md b/config/docopts.md
index a41be77..54b69bd 100644
--- a/config/docopts.md
+++ b/config/docopts.md
@@ -24,13 +24,14 @@ Configure OpenServerless
```text
Usage:
- config (enable|disable) [--all] [--redis] [--mongodb] [--minio] [--cron]
[--static] [--postgres] [--prometheus] [--slack] [--mail] [--affinity]
[--tolerations] [--quota] [--milvus] [--registry]
+ config (enable|disable) [--all] [--redis] [--mongodb] [--minio] [--cron]
[--static] [--postgres] [--prometheus] [--slack] [--mail] [--affinity]
[--tolerations] [--quota] [--milvus] [--registry] [--seaweedfs]
config apihost (<apihost>|auto) [--tls=<email>]
[--protocol=<http/https>|auto]
config runtimes [<runtimesjson>]
config slack [--apiurl=<slackapiurl>] [--channel=<slackchannel>]
config mail [--mailuser=<mailuser>] [--mailpwd=<mailpwd>]
[--mailfrom=<mailfrom>] [--mailto=<mailto>]
- config volumes [--couchdb=<couchdb>] [--kafka=<kafka>] [--pgvol=<postgres>]
[--storage=<storage>] [--alerting=<alerting>] [--zookeeper=<zookeeper>]
[--redisvol=<redis>] [--mongodbvol=<mongodb>] [--etcdvol=<etcd>]
[--mvvol=<milvus>] [--mvzookvol=<milvuszook>]
[--pulsarjournalvol=<pulsarjournal>] [--pulsarledgelvol=<pulsarledge>]
+ config volumes [--couchdb=<couchdb>] [--kafka=<kafka>] [--pgvol=<postgres>]
[--storage=<storage>] [--alerting=<alerting>] [--zookeeper=<zookeeper>]
[--redisvol=<redis>] [--mongodbvol=<mongodb>] [--etcdvol=<etcd>]
[--mvvol=<milvus>] [--mvzookvol=<milvuszook>]
[--pulsarjournalvol=<pulsarjournal>] [--pulsarledgelvol=<pulsarledge>]
[--seaweedfsvol=<seaweedfsvol>]
config controller [--javaopts=<javaopts>] [--loglevel=<loglevel>]
[--replicas=<replicas>]
+ config ingress [--class=<auto|nginx|traefik|public>]
config invoker [--javaopts=<javaopts>] [--poolmemory=<poolmemory>]
[--timeoutsrun=<timeoutsrun>] [--timeoutslogs=<timeoutslogs>]
[--loglevel=<loglevel>] [--replicas=<replicas>]
config limits [--time=<time>] [--memory=<memory>]
[--sequencelength=<sequencelength>] [--perminute=<perminute>]
[--concurrent=<concurrent>] [--triggerperminute=<triggerperminute>]
[--activation_max_payload=<activation_max_payload>]
[--blackbox_fraction=<blackbox_fraction>]
config storage [--class=<storage_class>]
[--provisioner=<storage_provisioner>]
@@ -45,7 +46,8 @@ Usage:
config azcloud [--project=<project>] [--region=<region>] [--vm=<vm>]
[--disk=<disk>] [--key=<key>] [--image=<image>]
config aks [--project=<project>] [--name=<name>] [--region=<region>]
[--count=<count>] [--vm=<vm>] [--disk=<disk>] [--key=<key>]
config externalregistry [--regurl=<regurl>] [--reguser=<reguser>]
[--regpassword=<regpassword>]
- config registry [--disk=<disk>] [--ingress]
+ config registry [--disk=<disk>] [--ingress]
+ config seaweedfs [--s3] [--console]
config (status|export|reset)
config use [<n>] [--delete] [--rename=<rename>]
config minimal
@@ -63,6 +65,7 @@ Usage:
config mail configure Alert Manager over a gmail account
config volumes configure the volume size distinguished in 3
categories (openwhisk couchdb & kafka, database, minio storage, alerting,
milvus)
config controller configure Openwhisk enterprise controller java
options
+ config ingress configure OpenServerless ingress class
config invoker configure Openwhisk enterprise invoker options
config limits configure Openwhisk actions limits
config storage allows to customize storage persistence class and
provider
@@ -120,4 +123,6 @@ Usage:
--quota select quota checker module
--milvus select MILVUS vector database
--registry activate the support for a private image registry for
custom actions (by default it will install one)
+ --class specify the ingress class. It can be auto, traefik,
nginx. On microk8s it should be public.
+ --seaweedfs activate the support of SEAWEEDFS as S3 api and
buckets provider
```
diff --git a/config/opsfile.yml b/config/opsfile.yml
index d8f92f0..9cb5c90 100644
--- a/config/opsfile.yml
+++ b/config/opsfile.yml
@@ -124,7 +124,12 @@ tasks:
then
config OPERATOR_COMPONENT_REGISTRY=true
config REGISTRY_CONFIG_SECRET_PUSH_PULL="$(random --str 12)"
- fi
+ fi
+ - |
+ if {{.__seaweedfs}} || {{.__all}}
+ then
+ config OPERATOR_COMPONENT_SEAWEEDFS=true
+ fi
- config CONFIGURED=true
- task: status
@@ -197,14 +202,19 @@ tasks:
- |
if {{.__milvus}} || {{.__all}}
then
- config OPERATOR_CONFIG_MILVUS=false
- config OPERATOR_CONFIG_ETCD=false
+ config OPERATOR_COMPONENT_MILVUS=false
+ config OPERATOR_COMPONENT_ETCD=false
fi
- |
if {{.__registry}} || {{.__all}}
then
- config OPERATOR_CONFIG_REGISTRY=false
- fi
+ config OPERATOR_COMPONENT_REGISTRY=false
+ fi
+ - |
+ if {{.__seaweedfs}} || {{.__all}}
+ then
+ config OPERATOR_COMPONENT_SEAWEEDFS=false
+ fi
- task: status
status:
@@ -870,7 +880,16 @@ tasks:
HINT: |
Specifies an integer value
VAL: "{{.__pulsarledgelvol}}"
- DEF: "20"
+ DEF: "20"
+ - task: read
+ vars:
+ MSG: "SEAWEEDFS Volume size"
+ VAR: "STORAGE_SIZE_SEAWEEDFS"
+ HINT: |
+ Specifies an integer value
+ VAL: "{{.__seaweedfsvol}}"
+ DEF: "60"
+
controller:
silent: true
@@ -1080,7 +1099,6 @@ tasks:
then config MINIO_CONFIG_INGRESS_CONSOLE=true
fi
-
etcd:
silent: true
cmds:
@@ -1158,7 +1176,18 @@ tasks:
Specifies the volume size assigned to the image registry
VAL: "{{.__disk}}"
DEF: "50"
-
+
+ seaweefs:
+ silent: true
+ cmds:
+ - |
+ if {{.__s3}}
+ then config SEAWEEDFS_CONFIG_INGRESS_S3_ENABLED=true
+ fi
+ - |
+ if {{.__console}}
+ then config SEAWEEDFS_CONFIG_INGRESS_CONSOLE_ENABLED=true
+ fi
minimal:
silent: true
@@ -1169,7 +1198,7 @@ tasks:
- |
config OPERATOR_COMPONENT_MONGODB=true
- |
- config OPERATOR_COMPONENT_MINIO=true
+ config OPERATOR_COMPONENT_SEAWEEDFS=true
- |
config OPERATOR_COMPONENT_CRON=true
- |
@@ -1188,13 +1217,14 @@ tasks:
config OPERATOR_COMPONENT_KAFKA=false
config OPERATOR_COMPONENT_REDIS=true
config OPERATOR_COMPONENT_MONGODB=true
- config OPERATOR_COMPONENT_MINIO=true
+ config OPERATOR_COMPONENT_MINIO=false
+ config OPERATOR_COMPONENT_SEAWEEDFS=true
config OPERATOR_COMPONENT_CRON=true
config OPERATOR_COMPONENT_STATIC=true
config OPERATOR_COMPONENT_POSTGRES=true
config OPERATOR_COMPONENT_ETCD=true
config OPERATOR_COMPONENT_MILVUS=true
- config MINIO_CONFIG_INGRESS_S3=true
+ config SEAWEEDFS_CONFIG_INGRESS_S3_ENABLED=true
config ETCD_CONFIG_REPLICAS=1
config POSTGRES_CONFIG_REPLICAS=1
config OPERATOR_CONFIG_SLIM=true
@@ -1205,3 +1235,15 @@ tasks:
config OPENWHISK_INVOKER_CONTAINER_POOL_MEMORY=6g
- task: status
- config CONFIGURED=true
+
+ ingress:
+ silent: true
+ cmds:
+ - task: read
+ vars:
+ MSG: "Ingress Class"
+ VAR: "OPERATOR_CONFIG_INGRESSCLASS"
+ HINT: |
+ Specify the ingress class.
+ VAL: "{{.__class}}"
+ DEF: "auto"
\ No newline at end of file
diff --git a/ide/deploy/bun.lockb b/ide/deploy/bun.lockb
old mode 100644
new mode 100755
index 47fe67b..526bb27
Binary files a/ide/deploy/bun.lockb and b/ide/deploy/bun.lockb differ
diff --git a/ide/deploy/client.js b/ide/deploy/client.js
index 307f7ed..e9ce791 100644
--- a/ide/deploy/client.js
+++ b/ide/deploy/client.js
@@ -18,12 +18,27 @@
import {readFile} from 'fs/promises';
import {resolve} from 'path';
import process from 'process';
-import {createInterface} from 'readline';
-import {globalWatcher} from './watch';
-import {expandEnv} from './env_utils';
+import {globalWatcher} from './watch.js';
+import {expandEnv} from './env_utils.js';
const { parse } = await import('shell-quote');
export let globalProc = undefined;
+async function signalHandler() {
+ if (globalProc) {
+ console.log(`🔥Killing process pid ${globalProc.pid}`);
+ globalProc.kill();
+ }
+ if (globalWatcher) {
+ console.log("☠️ Stopping watcher");
+ await globalWatcher.close();
+ }
+ process.exit(0);
+}
+
+// Register signal handlers once at module level
+process.on('SIGINT', signalHandler);
+process.on('SIGTERM', signalHandler);
+
/**
* Read a key from OpenServerless configuration added to a `package.json` file
in the
* root of the project
@@ -44,20 +59,7 @@ export async function getOpenServerlessConfig(key,
defaultValue) {
}
/**
- * This function creates a line-by-line interface over the provided input
stream
- * and logs each line to the console as it is received.
- * @param {ReadableStream} inp - The input stream to read lines from.
- * @returns {void}
- */
-function readlines(inp) {
- const rl = createInterface({input: inp, terminal: false});
- rl.on('line', (line) => {
- console.log(line);
- });
-}
-
-/**
- * laungh a process with the command taken from OpenServerless Config
+ * launch a process with the command taken from OpenServerless Config
* (see `getOpenServerlessConfig`)
* @param key
* @param defaultValue
@@ -65,7 +67,7 @@ function readlines(inp) {
export async function launch(key, defaultValue) {
const cmd = await getOpenServerlessConfig(key, defaultValue);
const cmdArgs = parse(cmd).filter(arg => typeof arg === "string");
- const proc = Bun.spawn(cmdArgs, {
+ Bun.spawn(cmdArgs, {
shell: true,
env: process.env,
cwd: process.env.OPS_PWD,
@@ -78,7 +80,7 @@ export async function launch(key, defaultValue) {
* through `getOpenServerlessConfig` mechanism
*/
export async function serve() {
- await launch('devel', 'ops ide serve');
+ launch('devel', 'ops ide serve');
}
/**
@@ -86,17 +88,7 @@ export async function serve() {
* through `getOpenServerlessConfig` mechanism
*/
export async function logs() {
- await launch('logs', 'ops activation poll');
-}
-
-async function signalHandler() {
- console.log(`🔥Killing process pid ${globalProc.pid}`);
- if (globalWatcher) {
- console.log("☠️ Stopping watcher");
- await globalWatcher.close();
- }
- globalProc.kill();
- process.exit(0);
+ launch('logs', 'ops activation poll');
}
/**
@@ -122,10 +114,6 @@ export async function build() {
console.log(`✈️ Deploy Child process: ${deploy} has PID:
${globalProc.pid}`);
- // Register signal handlers
- process.on('SIGINT', signalHandler);
- process.on('SIGTERM', signalHandler);
-
// Await its completion
try {
const code = await globalProc.exited;
diff --git a/ide/deploy/deploy.js b/ide/deploy/deploy.js
index 293ed50..28f16bc 100644
--- a/ide/deploy/deploy.js
+++ b/ide/deploy/deploy.js
@@ -15,9 +15,9 @@
// specific language governing permissions and limitations
// under the License.
-import fs from 'fs/promises';
-import { expandEnv } from './env_utils';
-const { parse } = await import('shell-quote');
+import fs from "fs/promises";
+import { expandEnv } from "./env_utils";
+const { parse } = await import("shell-quote");
const MAINS = ["__main__.py", "index.js", "index.php", "main.go"];
@@ -33,13 +33,13 @@ export function setDryRun(b) {
async function exec(cmd) {
console.log("$", cmd);
cmd = expandEnv(cmd);
- const cmdArgs = parse(cmd).filter(arg => typeof arg === "string");
-
+ const cmdArgs = parse(cmd).filter((arg) => typeof arg === "string");
+
const proc = Bun.spawn(cmdArgs, {
shell: true,
env: process.env,
cwd: process.env.OPS_PWD,
- stdio: ['inherit', 'inherit', 'inherit']
+ stdio: ["inherit", "inherit", "inherit"],
});
await proc.exited;
}
@@ -51,11 +51,13 @@ async function extractArgs(files) {
const fileContent = await fs.readFile(file, "utf-8");
const lines = fileContent.split("\n");
for (const line of lines) {
- if (line.startsWith("#-")) {
- res.push(line.trim().substring(1));
+ // python style comment
+ if (line.match(/^#[ ]?-{1,2}[^\s-].+/)) {
+ res.push(line.trim().substring(1).trim());
}
- if (line.startsWith("//-")) {
- res.push(line.trim().substring(2));
+ // js style comment
+ if (line.match(/^\/\/[ ]?-{1,2}[^\s-].+/)) {
+ res.push(line.trim().substring(2).trim());
}
}
}
@@ -87,7 +89,9 @@ export async function buildAction(pkg, action) {
}
export async function deployAction(artifact) {
- let pkg = '', name='', typ = '';
+ let pkg = "",
+ name = "",
+ typ = "";
if (activeDeployments.has(artifact)) {
queue.push(artifact);
@@ -96,7 +100,7 @@ export async function deployAction(artifact) {
activeDeployments.set(artifact, true);
const indexInQueue = queue.indexOf(artifact);
- if (indexInQueue>-1) {
+ if (indexInQueue > -1) {
console.log(`⚙️ Deploying ${artifact} (from queue: ${indexInQueue})`);
}
@@ -106,11 +110,12 @@ export async function deployAction(artifact) {
name = spData[0];
typ = spData[1];
pkg = sp[1];
- } catch {
- console.log("❌ cannot deploy", artifact);
+ } catch(error) {
+
+ console.log("❌ cannot deploy", artifact, "Error:", error.message);
return;
}
-
+
await deployPackage(pkg);
let toInspect;
@@ -134,7 +139,6 @@ export async function deployAction(artifact) {
}
}
-
/**
* Deploy a `file`
* @param file
@@ -146,7 +150,7 @@ export async function deploy(file) {
// const file = "packages/deploy/multi/__main__.py";
// const file = "packages/deploy/multi/requirements.txt";
- const stat = await fs.stat(file)
+ const stat = await fs.stat(file);
if (stat.isDirectory()) {
for (const start of MAINS) {
@@ -157,10 +161,10 @@ export async function deploy(file) {
}
}
}
-
+
const sp = file.split("/");
if (sp.length > 3) {
- buildZip(sp[1], sp[2]);
+ await buildZip(sp[1], sp[2]);
file = await buildAction(sp[1], sp[2]);
}
console.log(`Deploying ${file}`);
@@ -174,10 +178,12 @@ export async function deploy(file) {
export async function deployProject(artifact) {
if (await fs.exists(artifact)) {
const manifestContent = await Bun.file(artifact).text();
- if (manifestContent.indexOf('packages:')!==-1) {
+ if (manifestContent.indexOf("packages:") !== -1) {
await exec(`ops -wsk project deploy --manifest ${artifact}`);
} else {
- console.log(`⚠️ Warning: it seems that the ${artifact} file is not a
valid manifest file. Skipping`);
+ console.log(
+ `⚠️ Warning: it seems that the ${artifact} file is not a valid
manifest file. Skipping`
+ );
}
}
}
diff --git a/ide/deploy/env_utils.js b/ide/deploy/env_utils.js
index e793551..4670b14 100644
--- a/ide/deploy/env_utils.js
+++ b/ide/deploy/env_utils.js
@@ -47,7 +47,7 @@ export function expandEnv(str, env = process.env) {
const name = varMatch[1];
let val;
if (name === "$") val = process.pid;
- else if (name === "?") val = "0"; // impossibile sapere senza
contesto
+ else if (name === "?") val = "0"; // Cannot determine actual exit
code without execution context
else if (name === "#") val = "0";
else if (name === "!") val = "";
else val = env[name] ?? "";
diff --git a/ide/deploy/index.js b/ide/deploy/index.js
index 2889f02..d4c7dde 100644
--- a/ide/deploy/index.js
+++ b/ide/deploy/index.js
@@ -22,6 +22,7 @@ import {program} from 'commander';
import {scan} from './scan.js';
import {watchAndDeploy, globalWatcher} from './watch.js';
import {setDryRun, deploy} from './deploy.js';
+import {undeploy, setDryRun as setUndeployDryRun} from './undeploy.js';
import {build} from './client.js';
@@ -34,8 +35,11 @@ async function signalHandler() {
await globalWatcher.close();
}
- unlinkSync(expanduser('~/.ops/tmp/deploy.pid'));
- process.kill(process.getpgrp(), 'SIGKILL');
+ const pidPath = expanduser('~/.ops/tmp/deploy.pid');
+ if (existsSync(pidPath)) {
+ unlinkSync(pidPath);
+ }
+ process.kill(process.pid, 'SIGTERM');
process.exit(0); // should not be reached but just in case...
}
@@ -44,7 +48,7 @@ function checkPort() {
server.listen(8080, '127.0.0.1');
server.on('error', () => {
console.log('deployment mode already active (or something listening in
127.0.0.1:8080)');
- server.close();
+ server.close();
});
server.on('listening', () => server.close());
}
@@ -59,7 +63,6 @@ async function main() {
process.on('SIGTERM', signalHandler);
- process.on('SIGKILL', signalHandler);
const pidfile = expanduser('~/.ops/tmp/deploy.pid');
console.log('PID', pid);
@@ -74,15 +77,52 @@ async function main() {
.option('-d, --deploy', 'Deploy')
.option('-w, --watch', 'Watch for changes')
.option('-s, --single <string>', 'Deploy a single action, either a
single file or a directory.', '')
+ .option('-u, --undeploy', 'Undeploy actions and packages from the
current project')
.parse(process.argv);
const options = program.opts();
const directory = program.args[0];
setDryRun(options.dryRun);
+ setUndeployDryRun(options.dryRun);
+
+ if (!existsSync(directory)) {
+ console.error(`❌ Error: Directory ${directory} does not exist`);
+ process.exit(1);
+ }
process.chdir(directory);
- if (options.watch) {
+ if (options.undeploy) {
+ // Undeploy actions and packages from the current project
+ let success;
+
+ if (options.single !== '') {
+ // If a single action is specified, undeploy just that action
+ let action = options.single;
+ if (!action.startsWith('packages/')) {
+ action = `packages/${action}`;
+ }
+
+ // Extract the package and action name
+ const parts = action.split('/');
+ if (parts.length >= 3) {
+ const pkg = parts[1];
+ const actionName = parts[2].split('.')[0]; // Remove file
extension if present
+ success = undeploy(`${pkg}/${actionName}`);
+ } else {
+ // If the format is already package/action
+ success = undeploy(action);
+ }
+ } else {
+ // Otherwise, undeploy all actions and packages from the current
project
+ success = undeploy();
+ }
+
+ if (!success) {
+ process.exit(1);
+ }
+ process.exit(0);
+ } else if (options.watch) {
checkPort();
if (!options.fast) {
await scan();
@@ -92,7 +132,7 @@ async function main() {
} else if (options.deploy) {
await scan();
- await build()
+ await build();
process.exit(0);
} else if (options.single !== '') {
let action = options.single;
@@ -115,5 +155,3 @@ main().catch(err => {
console.error(err);
process.exit(1);
});
-
-setInterval(() => {}, 1000);
\ No newline at end of file
diff --git a/ide/deploy/info.js b/ide/deploy/info.js
index 757ba9b..ee7025d 100644
--- a/ide/deploy/info.js
+++ b/ide/deploy/info.js
@@ -1,11 +1,28 @@
+// 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.
+
import { getOpenServerlessConfig} from './client.js';
import {program} from "commander";
import process from "process";
program
.description('Deployer info')
- .argument('<param>', 'The key to query')
- .argument('<param>', 'The default value')
+ .argument('<key>', 'The key to query')
+ .argument('[default]', 'The default value')
.parse(process.argv);
const key = program.args[0];
diff --git a/ide/deploy/package.json b/ide/deploy/package.json
index 264d8d3..c490dc7 100644
--- a/ide/deploy/package.json
+++ b/ide/deploy/package.json
@@ -4,7 +4,8 @@
"commander": "=13.1.0",
"dotenv": "^16.4.7",
"glob": "=11.0.1",
- "shell-quote": "^1.8.3"
+ "shell-quote": "^1.8.3",
+ "mime-types": "^2.1.35"
},
"devDependencies": {
"@types/bun": "=1.2.2"
diff --git a/ide/deploy/scan.js b/ide/deploy/scan.js
index 8962819..484089d 100644
--- a/ide/deploy/scan.js
+++ b/ide/deploy/scan.js
@@ -19,6 +19,7 @@ import {glob} from 'glob';
import {buildAction, buildZip, deployAction, deployPackage, deployProject}
from './deploy.js';
import {getOpenServerlessConfig} from './client.js';
import {config} from "dotenv";
+import {syncDeployInfo} from "./syncDeployInfo";
/**
* This function will prepare and deploy the functions in `packages` directory.
@@ -52,21 +53,19 @@ export async function scan() {
// load user defined requirements or use `defaultReqsGlobs`
const packageGlobs = await getOpenServerlessConfig("requirements",
defaultReqsGlobs);
// requirements
- const reqs = [];
+ const reqsSet = new Set();
// Check for additional packages from each package
- // and add them to the requirements array
+ // and add them to the requirements set
for (const pkgGlob of packageGlobs) {
const items = await glob(pkgGlob);
for (const item of items) {
- if (!reqs.includes(item)) {
- reqs.push(item);
- }
+ reqsSet.add(item);
}
}
// let's package the functions that have requirements
- for (const req of reqs) {
+ for (const req of reqsSet) {
console.log(">> Requirements:", req);
const sp = req.split("/");
const act = await buildZip(sp[1], sp[2]);
@@ -83,18 +82,16 @@ export async function scan() {
];
// load user defined main functions or use `defaultMainsGlobs`
const mainsGlobs = await getOpenServerlessConfig("mains",
defaultMainsGlobs);
- const mains = [];
+ const mainsSet = new Set();
for (const mainGlob of mainsGlobs) {
const items = await glob(mainGlob);
for (const item of items) {
- if (!mains.includes(item)) {
- mains.push(item);
- }
+ mainsSet.add(item);
}
}
- for (const main of mains) {
+ for (const main of mainsSet) {
console.log(">> Main:", main);
const sp = main.split("/");
const act = await buildAction(sp[1], sp[2]);
@@ -110,18 +107,16 @@ export async function scan() {
"packages/*/*.go"
];
const singlesGlobs = await getOpenServerlessConfig("singles",
defaultSinglesGlobs);
- const singles = [];
+ const singlesSet = new Set();
for (const singleGlob of singlesGlobs) {
const items = await glob(singleGlob);
for (const item of items) {
- if (!singles.includes(item)) {
- singles.push(item);
- }
+ singlesSet.add(item);
}
}
- for (const single of singles) {
+ for (const single of singlesSet) {
console.log(">> Action:", single);
const sp = single.split("/");
deployments.add(single);
@@ -146,25 +141,30 @@ export async function scan() {
"packages/*/*.yaml",
];
const manifestsGlobs = await getOpenServerlessConfig("manifests",
defaultProjectGlobs);
- const manifests = [];
+ const manifestsSet = new Set();
for (const manifestGlobs of manifestsGlobs) {
const items = await glob(manifestGlobs);
for (const item of items) {
- if (!manifests.includes(item)) {
- manifests.push(item);
- }
+ manifestsSet.add(item);
}
- manifests.sort((a, b) => a.localeCompare(b));
}
- if (manifests.length >0 ) {
- if (Bun.file('packeges/.env')) {
+ const manifests = Array.from(manifestsSet).sort((a, b) =>
a.localeCompare(b));
+ if (manifests.length > 0) {
+ if (await Bun.file('packages/.env').exists()) {
console.log("Found packages .env file. Reading it");
- config({ path: "./package/.env" });
+ config({ path: "./packages/.env" });
}
for (const manifest of manifests) {
console.log(">>> Manifest:", manifest);
await deployProject(manifest);
}
}
+
+ try {
+ // Save deployment information with the new structure
+ syncDeployInfo(packages, deployments);
+ } catch (error) {
+ console.error("Error saving deployment information:", error);
+ }
}
diff --git a/ide/deploy/serve.js b/ide/deploy/serve.js
index 549e89d..7d22e8e 100644
--- a/ide/deploy/serve.js
+++ b/ide/deploy/serve.js
@@ -17,6 +17,7 @@
import {stat} from "fs/promises";
import {resolve, extname} from "path";
+import {lookup as lookupMime} from 'mime-types';
import {parse} from "url";
import process from 'process';
import { file } from "bun";
@@ -54,16 +55,44 @@ async function findAvailablePort(host, startPort = 8080) {
* @returns {Promise<Buffer<ArrayBuffer>>}
*/
async function toBuffer(stream) {
- const list = []
- const reader = stream.getReader();
- while (true) {
- const {value, done} = await reader.read();
- if (value)
- list.push(value)
- if (done)
- break
+ // If there's no body (e.g. OPTIONS requests or empty bodies), return null
+ if (!stream) return null;
+
+ // Some runtimes provide a ReadableStream with getReader(), others may
give a Node-style stream
+ if (typeof stream.getReader === 'function') {
+ const list = [];
+ const reader = stream.getReader();
+ while (true) {
+ const {value, done} = await reader.read();
+ if (value)
+ list.push(value);
+ if (done)
+ break;
+ }
+ return Buffer.concat(list);
+ }
+
+ // If it's already a Buffer or ArrayBuffer-like
+ if (Buffer.isBuffer(stream)) return stream;
+ if (stream instanceof ArrayBuffer) return Buffer.from(new
Uint8Array(stream));
+
+ // If it's an async iterator (Node readable), consume it
+ if (stream[Symbol.asyncIterator]) {
+ const list = [];
+ for await (const chunk of stream) {
+ list.push(Buffer.from(chunk));
+ }
+ return Buffer.concat(list);
}
- return Buffer.concat(list)
+
+ // Unknown type: try to stringify
+ try {
+ const s = String(stream);
+ return Buffer.from(s, 'utf8');
+ } catch (e) {
+ return null;
+ }
+
}
//
@@ -73,20 +102,10 @@ async function toBuffer(stream) {
* @returns {*|string}
*/
function getMimeType(filePath) {
- const ext = extname(filePath).toLowerCase();
- const mimeTypes = {
- ".html": "text/html",
- ".css": "text/css",
- ".js": "application/javascript",
- ".json": "application/json",
- ".png": "image/png",
- ".jpg": "image/jpeg",
- ".gif": "image/gif",
- ".svg": "image/svg+xml",
- ".txt": "text/plain",
- // Add more mimetypes as needed
- };
- return mimeTypes[ext] || "application/octet-stream";
+ // Use the mime-types package to resolve mimetypes for a broad set of
extensions.
+ // Fallback to application/octet-stream when unknown.
+ const m = lookupMime(filePath);
+ return m || "application/octet-stream";
}
const excludedAssets = ['favicon.ico'];
@@ -154,15 +173,45 @@ async function main() {
if (fileStats.isFile()) {
const mimeType = flags.mimeType || getMimeType(filePath);
+
+ // Compute caching headers
+ const lastModified = fileStats.mtime.toUTCString();
+ // Simple ETag based on inode/size/mtime if available
+ const etag = `W/"${fileStats.size}-${fileStats.mtimeMs}"`;
+
+ // Handle conditional requests
+ const ifNoneMatch = req.headers.get('if-none-match');
+ const ifModifiedSince =
req.headers.get('if-modified-since');
+ if (ifNoneMatch && ifNoneMatch === etag) {
+ return new Response(null, {status: 304, headers:
{"ETag": etag}});
+ }
+ if (ifModifiedSince) {
+ const since = new Date(ifModifiedSince);
+ if (!isNaN(since.getTime()) && fileStats.mtime <=
since) {
+ return new Response(null, {status: 304, headers:
{"Last-Modified": lastModified, "ETag": etag}});
+ }
+ }
+
const headers = {
"Content-Type": mimeType,
+ "Content-Length": String(fileStats.size),
+ "Last-Modified": lastModified,
+ "ETag": etag,
};
if (flags.cacheTime) {
headers["Cache-Control"] =
`max-age=${flags.cacheTime}`;
}
console.log(`[200] - Serving file ${pathname} from
filesystem`);
- const data = await Bun.file(filePath).text();
- return new Response(data, {headers});
+ // Stream the file to avoid loading the whole file into
memory
+ // Bun.file(filePath).stream() returns a ReadableStream
+ try {
+ const stream = Bun.file(filePath).stream();
+ return new Response(stream, {headers});
+ } catch (e) {
+ // Fallback: read as arrayBuffer if stream isn't
available
+ const ab = await Bun.file(filePath).arrayBuffer();
+ return new Response(ab, {headers});
+ }
}
} catch (err) {
let shouldExclude = (excludedAssets.indexOf(pathname) !== -1);
@@ -189,12 +238,21 @@ async function main() {
method: req.method,
headers: newHeaders,
};
- if (req.method.toLowerCase() !== 'get') {
- let body = await toBuffer(req.body);
- body = body.toString('utf8');
-
- if (body !== undefined) {
- init['body'] = body;
+ // Only forward a body when the method permits it and a
body exists
+ const method = req.method.toLowerCase();
+ const canHaveBody = (method !== 'get' && method !== 'head'
&& method !== 'options');
+ if (canHaveBody && req.body) {
+ const buf = await toBuffer(req.body);
+ if (buf && buf.length > 0) {
+ // prefer sending string when it's valid UTF-8 text
+ let bodyToSend = buf;
+ try {
+ const text = buf.toString('utf8');
+ bodyToSend = text;
+ } catch (e) {
+ bodyToSend = buf;
+ }
+ init['body'] = bodyToSend;
}
}
const respP = await fetch(destProxyUrl, init);
diff --git a/ide/deploy/syncDeployInfo.js b/ide/deploy/syncDeployInfo.js
new file mode 100644
index 0000000..6865019
--- /dev/null
+++ b/ide/deploy/syncDeployInfo.js
@@ -0,0 +1,124 @@
+// 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.
+
+import {existsSync, mkdirSync, writeFileSync, readFileSync} from "fs";
+
+/**
+ * Synchronizes deployment information by saving the provided package and
deployment data
+ * to a persisted `.ops/deployment.json` file. If the directory `.ops` does
not exist, it
+ * is created before saving the information.
+ *
+ * The deployment information is organized by packages, with each package
containing an array
+ * of its actions. This allows for more granular control when undeploying
specific actions.
+ *
+ * @param {Set<string>} packages - A set of package names to include in the
deployment data.
+ * @param {Set<string>} deployments - A set of deployment identifiers to
include in the deployment data.
+ * @return {void}
+ */
+export function syncDeployInfo(packages, deployments) {
+ if (!existsSync('.ops')) {
+ mkdirSync('.ops', { recursive: true });
+ }
+
+ // Create a structured object with packages as keys and arrays of actions
as values
+ const packageActions = {};
+
+ // Initialize packages with empty arrays
+ for (const pkg of packages) {
+ packageActions[pkg] = [];
+ }
+
+ // Add actions to their respective packages
+ for (const deployment of deployments) {
+ try {
+ const sp = deployment.split("/");
+ const spData = sp[sp.length - 1].split(".");
+ const name = spData[0];
+ const pkg = sp[1];
+
+ // If the package exists in our structure, add the action to it
+ if (packageActions[pkg]) {
+ packageActions[pkg].push(name);
+ }
+ } catch (error) {
+ console.error(`Error parsing deployment path ${deployment}:`,
error);
+ }
+ }
+
+ const deploymentInfo = {
+ packages: Array.from(packages),
+ packageActions: packageActions
+ };
+
+ writeFileSync('.ops/deployment.json', JSON.stringify(deploymentInfo, null,
2));
+ console.log("> Saved deployment information to .ops/deployment.json");
+}
+
+/**
+ * Removes a specific action from the deployment information.
+ *
+ * @param {string} actionName - The name of the action to remove in the format
"package/action".
+ * @return {boolean} - True if the action was found and removed, false
otherwise.
+ */
+export function removeActionFromDeployInfo(actionName) {
+ if (!existsSync('.ops/deployment.json')) {
+ console.error('Error: No deployment information found.');
+ return false;
+ }
+
+ try {
+ const deploymentInfo = JSON.parse(readFileSync('.ops/deployment.json',
'utf8'));
+ const [pkg, action] = actionName.split('/');
+
+ if (!deploymentInfo.packageActions ||
!deploymentInfo.packageActions[pkg]) {
+ console.error(`❌ Error: Package ${pkg} not found in deployment
information.`);
+ return false;
+ }
+
+ const actionIndex = deploymentInfo.packageActions[pkg].indexOf(action);
+ if (actionIndex === -1) {
+ console.error(`❌ Error: Action ${action} not found in package
${pkg}.`);
+ return false;
+ }
+
+ // Remove the action from the package
+ deploymentInfo.packageActions[pkg].splice(actionIndex, 1);
+
+ // If the package has no more actions, remove it from the packages list
+ if (deploymentInfo.packageActions[pkg].length === 0) {
+ const packageIndex = deploymentInfo.packages.indexOf(pkg);
+ if (packageIndex !== -1) {
+ deploymentInfo.packages.splice(packageIndex, 1);
+ }
+ delete deploymentInfo.packageActions[pkg];
+ }
+
+ writeFileSync('.ops/deployment.json', JSON.stringify(deploymentInfo,
null, 2));
+ console.log(`> Removed ${actionName} from deployment information.`);
+ return true;
+ } catch (error) {
+ console.error("❌ Error updating deployment information:", error);
+ return false;
+ }
+}
+
+/**
+ * Cleans up deployment information by resetting and synchronizing deployment
data.
+ */
+export function cleanupDeployInfo() {
+ syncDeployInfo(new Set(), new Set());
+}
diff --git a/ide/deploy/undeploy.js b/ide/deploy/undeploy.js
new file mode 100644
index 0000000..74aa9c3
--- /dev/null
+++ b/ide/deploy/undeploy.js
@@ -0,0 +1,122 @@
+// 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.
+
+import { existsSync, readFileSync } from 'fs';
+import { spawnSync } from 'child_process';
+import { cleanupDeployInfo, removeActionFromDeployInfo } from
"./syncDeployInfo.js";
+import { expandEnv } from './env_utils.js';
+
+let dryRun = false;
+
+export function setDryRun(b) {
+ dryRun = b;
+}
+
+function exec(cmd) {
+ console.log("$", cmd);
+ if (!dryRun) {
+ cmd = expandEnv(cmd);
+ const result = spawnSync(cmd, { shell: true, env: process.env, stdio:
"inherit" });
+ if (result.error) {
+ console.error(`Command failed: ${cmd}`, result.error);
+ throw result.error;
+ }
+ return result;
+ }
+}
+
+/**
+ * Undeploy a specific action and update the deployment information
+ * @param {string} actionName - The name of the action to undeploy in the
format "package/action"
+ * @returns {boolean} true if successful, false if error
+ */
+export function undeployAction(actionName) {
+ console.log(`> Undeploying action: ${actionName}`);
+
+ try {
+ // Execute the undeploy command
+ exec(`$OPS action delete ${actionName}`);
+
+ // Update the deployment information
+ const success = removeActionFromDeployInfo(actionName);
+ if (success) {
+ console.log(`> Action ${actionName} successfully undeployed and removed
from deployment information.`);
+ return true;
+ } else {
+ console.error(`> Action ${actionName} was undeployed but could not be
removed from deployment information.`);
+ return false;
+ }
+ } catch (error) {
+ console.error(`Error undeploying action ${actionName}:`, error);
+ return false;
+ }
+}
+
+/**
+ * Undeploy actions and packages based on the deployment information in
.ops/deployment.json
+ * If no deployment information is found, return an error
+ * @param {string} [specificAction] - Optional specific action to undeploy
+ * @returns {boolean} true if successful, false if error
+ */
+export function undeploy(specificAction) {
+ // If a specific action is provided, undeploy just that action
+ if (specificAction) {
+ return undeployAction(specificAction);
+ }
+
+ // Otherwise, undeploy all actions and packages from the current project
+ if (!existsSync('.ops/deployment.json')) {
+ console.error('❌ Error: No OpenServerless project found in the current
directory.');
+ console.error('❌ Please run this command in a directory with an
OpenServerless project.');
+ return false;
+ }
+
+ try {
+ const deploymentInfo = JSON.parse(readFileSync('.ops/deployment.json',
'utf8'));
+ const { packages, packageActions } = deploymentInfo;
+
+ if (!packages || !packageActions || packages.length === 0) {
+ console.error('❌ Error: No deployment information found.');
+ return false;
+ }
+
+ console.log("> Undeploy actions and packages from the current project:");
+
+ // Undeploy actions
+ for (const pkg of packages) {
+ const actions = packageActions[pkg] || [];
+ for (const action of actions) {
+ const actionName = `${pkg}/${action}`;
+ console.log(`>> Undeploy action: ${actionName}`);
+ exec(`$OPS action delete ${actionName}`);
+ }
+ }
+
+ // Undeploy packages
+ for (const pkg of packages) {
+ console.log(`>> Undeploy package: ${pkg}`);
+ exec(`$OPS package delete ${pkg}`);
+ }
+
+ cleanupDeployInfo();
+ console.log("> Undeployment completed successfully.");
+ return true;
+ } catch (error) {
+ console.error("❌ Error undeploy:", error);
+ return false;
+ }
+}
diff --git a/ide/docopts.md b/ide/docopts.md
index 5b4d4b6..8b35feb 100644
--- a/ide/docopts.md
+++ b/ide/docopts.md
@@ -24,12 +24,12 @@ OpenServerless Ide Development Utilities.
```text
Usage:
- ide login [<username>] [<apihost>]
+ ide login [<username>] [<apihost>] [--pin]
ide devel [--fast] [--dry-run]
- ide deploy [<action>] [--dry-run]
+ ide deploy [<action>|--packages|--web] [--dry-run]
ide undeploy [<action>] [--dry-run]
ide clean
- ide setup
+ ide setup
ide serve
ide poll
ide shell
@@ -45,7 +45,7 @@ Usage:
ide login login in openserverless
ide devel activate development mode
ide deploy deploy everything or just one action
- ide undeploy undeploy everything or just one action
+ ide undeploy undeploy actions and packages from the current
project or just one action
ide clean clean the temporay files
ide setup setup the ide
ide serve serve web area
@@ -60,6 +60,9 @@ Usage:
## Options
```
+--dry-run Simulates the execution without making any actual changes
+--packages Only deploy packages, skip web upload
+--web Only deploy web folder, skip packages
--fast Skip the initial deployment step and go in incremental update
mode
---dry-run Simulates the execution without making any actual changes
-```
\ No newline at end of file
+--pin Pin the current auth in the .env to check you are not
deploying on the wrong user
+```
diff --git a/ide/nodejs/build-node.sh b/ide/nodejs/build-node.sh
index 9235046..a8f77d5 100644
--- a/ide/nodejs/build-node.sh
+++ b/ide/nodejs/build-node.sh
@@ -19,8 +19,7 @@
DIR="${1:?directory}"
ZIP="${2:?zip file}"
cd "$DIR"
-npm install
-touch node_modules/.package-lock.json
+bun install
if test -f "$ZIP"
then rm "$ZIP"
fi
diff --git a/ide/opsfile.yml b/ide/opsfile.yml
index 25f4ad8..75d28e8 100644
--- a/ide/opsfile.yml
+++ b/ide/opsfile.yml
@@ -22,7 +22,7 @@ vars:
API_HOST:
sh: |
echo "http://localhost:80"
-
+
DEPLOY_CURRENT_HASH:
sh: |
if test -e "$OPS_ROOT/ide/deploy/bun.lockb"
@@ -36,22 +36,18 @@ vars:
then cat "$OPS_ROOT/ide/deploy/hash.lock"
else echo "0"
fi
-
+
tasks:
prereq:
silent: true
- vars:
+ vars:
MSG: |
This command must be run inside a devcontainer.
Please use 'ops ide devcontainer' to create a configuration and
enter in a devcontainer.
You can then use 'ops ide devel' and 'ops ide deploy'.
You can also reopen the project with VSCode and use the command
'Reopen in Container'.
cmds:
- - test -e "/.dockerenv" || die "{{.MSG}}"
- - test "$(python3 -V | awk -F. '{print $2}')" -ge 10 || die "python 3.10
or greater not available"
- - test -x "$(which virtualenv)" || die "you need python virtualenv"
- - test "$(node -v | awk -F. '{print substr($1,2) }')" -ge 18 || die
"nodejs 18 or greater not available"
- test "$(printf '%s\n' "$(bun -v)" "1.1.18" | sort -V | head -n 1)" =
"1.1.18" || die "bun 1.1.18 or greater not available"
- test -d "$OPS_PWD/packages" || die "no packages in current directory"
- test -e ~/.wskprops || die "please run 'ops ide login' first"
@@ -59,7 +55,7 @@ tasks:
- test "$(ops -wsk property get --namespace | awk '{ print $3 }')" =
"$OPSDEV_USERNAME" || die "Repeat the login"
- |
if ! test -d "$OPS_ROOT/ide/deploy/node_modules" || [
"{{.DEPLOY_CURRENT_HASH}}" != "{{.DEPLOY_PREVIOUS_HASH}}" ]
- then
+ then
cd $OPS_ROOT/ide/deploy && bun install && rm -f
$OPS_ROOT/ide/deploy/hash.lock && bun $OPS_ROOT/ide/deploy/bun.lockb --hash >
$OPS_ROOT/ide/deploy/hash.lock
fi
- |
@@ -67,9 +63,9 @@ tasks:
then if ! test -d "$OPS_PWD/node_modules"
then cd $OPS_PWD ; bun install
fi
- fi
+ fi
- task: kill
-
+
devcontainer:
silent: true
desc: add a devcontainer to your project
@@ -77,13 +73,13 @@ tasks:
- |
if test -e "$OPS_PWD/.devcontainer/devcontainer.json"
then echo "a .devcontainer already exists"
- else
+ else
mkdir -p "$OPS_PWD/.devcontainer"
cp devcontainer.json "$OPS_PWD/.devcontainer/"
echo "devcontainer created in .devcontainer - please use VSCode and
the command 'Reopen in Container'"
fi
- |
- if echo "$OPS_PWD/" | rg ' '
+ if echo "$OPS_PWD/" | rg ' '
then die "please place your workspace in a folder WITHOUT SPACES IN
THE FOLDER NAME!!!!"
fi
- bun x @devcontainers/cli up --workspace-folder "$OPS_PWD"
@@ -98,22 +94,22 @@ tasks:
PIDFILE=$(ops -opspath ~/.ops/tmp/deploy.pid)
echo $PIDFILE
if test -e $PIDFILE
- then
+ then
PID=$(cat $PIDFILE)
-
+
if [ ! -z "$PID" ]; then
if ps -p "$PID" > /dev/null;
then
echo "Found previous deploy pid: $PID"
kill "$PID"
- # PGRP=$(ps -o 'pgid=' -p $PID | xargs)
+ # PGRP=$(ps -o 'pgid=' -p $PID | xargs)
# if [ ! -z "$PGRP" ];
- # then
+ # then
# echo "Terminating deploy process group $PGRP"
# kill "$PGRP"
# else
# echo "Terminating deploy process $PID"
- # kill "$PID"
+ # kill "$PID"
# fi
fi
fi
@@ -141,40 +137,48 @@ tasks:
login:
- silent: true
+ silent: false
desc: login in you OpenServerless host
cmds:
- |
+ set -a
if test -e "$OPS_PWD/.env"
then source "$OPS_PWD/.env"
fi
+ if test -n "$OPS_USERNAME"
+ then echo "Please use OPS_USER, OPS_USERNAME is deprecated"
+ fi
if test -n "{{._apihost_}}"
- then OPSDEV_APIHOST="{{._apihost_}}"
+ then export OPSDEV_APIHOST="{{._apihost_}}"
fi
echo "*** Configuring Access to OpenServerless ***"
- if test -z "{{._apihost_}}"
- then
- if test -z "$OPS_APIHOST"
+ if test -z "{{._username_}}"
+ then
+ if test -n "$OPS_USER"
then
- echo -n "Enter Apihost: "
- read OPSDEV_APIHOST
- OPSDEV_APIHOST="$(echo $OPSDEV_APIHOST | tr -d '\r')"
+ export OPSDEV_USERNAME="$OPS_USER"
else
- OPSDEV_APIHOST="$OPS_APIHOST"
+ echo -n "Enter Username: "
+ read OPSDEV_USERNAME
+ export OPSDEV_USERNAME="$(echo $OPSDEV_USERNAME | tr -d '\r')"
+ fi
+ else
+ export OPSDEV_USERNAME="{{._username_}}"
+ if test -e "$OPS_PWD/.env.{{._username_}}"
+ then source "$OPS_PWD/.env.{{._username_}}"
fi
- else OPSDEV_APIHOST="{{._apihost_}}"
fi
- if test -z "{{._username_}}"
+ if test -z "{{._apihost_}}"
then
- if test -n "$OPS_USERNAME"
+ if test -z "$OPS_APIHOST"
then
- OPSDEV_USERNAME="$OPS_USERNAME"
+ echo -n "Enter Apihost: "
+ read OPSDEV_APIHOST
+ export OPSDEV_APIHOST="$(echo $OPSDEV_APIHOST | tr -d '\r')"
else
- echo -n "Enter Username: "
- read OPSDEV_USERNAME
- OPSDEV_USERNAME="$(echo $OPSDEV_USERNAME | tr -d '\r')"
+ export OPSDEV_APIHOST="$OPS_APIHOST"
fi
- else OPSDEV_USERNAME="{{._username_}}"
+ else export OPSDEV_APIHOST="{{._apihost_}}"
fi
echo "Logging user $OPSDEV_USERNAME in $OPSDEV_APIHOST"
if test -n "$OPS_PASSWORD"
@@ -188,10 +192,17 @@ tasks:
config OPSDEV_USERNAME="$OPSDEV_USERNAME"
config
OPSDEV_HOST="$OPSDEV_HOST_PROT://$OPSDEV_USERNAME.$OPSDEV_HOST_URL"
source ~/.wskprops
- else
- false
fi
-
+ if {{.__pin}}
+ then
+ touch $OPS_PWD/.env
+ mv $OPS_PWD/.env $OPS_PWD/.env.$$
+ cat $OPS_PWD/.env.$$ | rg -v "AUTH_CHECK=" >$OPS_PWD/.env || true
+ echo "AUTH_CHECK=$AUTH" >>$OPS_PWD/.env
+ fi
+
+
+
poll:
silent: true
desc: poll activation logs
@@ -223,73 +234,86 @@ tasks:
then source $OPS_PWD/packages/.env
fi
if test -n "$AUTH_CHECK"
- then if test "$AUTH_CHECK" != "$AUTH"
- then echo "WARNING: wrong deploy! You are logged in a different
user than your configured AUTH_CHECK" ; exit 1
+ then if test "$AUTH_CHECK" != "$AUTH"
+ then echo "WARNING: wrong deploy! You are logged in a different
user than your pinned one and configured in .env as AUTH_CHECK" ; exit 1
fi
fi
+
if {{.__dry_run}}
then DRY="--dry-run" ; ECHO='echo'
else DRY="" ; ECHO=""
fi
- if test -z "{{._action_}}"
+
+ if {{.__web}}
+ then deploy_packages=""
+ else deploy_packages="1"
+ fi
+
+ if {{.__packages}}
+ then deploy_web=""
+ else deploy_web="1"
+ fi
+
+ if test -n "{{._action_}}"
then
- bun {{.TASKFILE_DIR}}/deploy/index.js "$OPS_PWD" -d $DRY
- OPS_UPLOAD_FOLDER=`bun {{.TASKFILE_DIR}}/deploy/info.js upload web`
- echo "UPLOAD ASSETS FROM ${OPS_UPLOAD_FOLDER}"
- $ECHO $OPS util upload ${OPS_UPLOAD_FOLDER:-web}
- echo "URL: $OPSDEV_HOST"
+ bun {{.TASKFILE_DIR}}/deploy/index.js "$OPS_PWD" -s
"{{._action_}}" $DRY
else
- bun {{.TASKFILE_DIR}}/deploy/index.js "$OPS_PWD" -s
"{{._action_}}" $DRY
+ if [ -n "$deploy_packages" ]
+ then
+ bun {{.TASKFILE_DIR}}/deploy/index.js "$OPS_PWD" -d $DRY
+ fi
+ if [ -n "$deploy_web" ]
+ then
+ OPS_UPLOAD_FOLDER=`bun {{.TASKFILE_DIR}}/deploy/info.js upload
web`
+ echo "UPLOAD ASSETS FROM ${OPS_UPLOAD_FOLDER}"
+ $ECHO $OPS util upload ${OPS_UPLOAD_FOLDER:-web}
+ echo "URL: $OPSDEV_HOST"
+ fi
fi
undeploy:
- desc: undeploy all the actions
- prompt: "are you sure you want to remove all actions and packages?"
+ desc: undeploy actions and packages from the current project
silent: true
cmds:
- task: prereq
- - >
- $OPS action list
- | awk 'NR>1 { print $1}'
- | while read action ;
- do if {{.__dry_run}}
- then echo '$' $OPS action delete "$action"
- else $OPS action delete "$action"
- fi
- done
- - >
- $OPS package list
- | awk 'NR>1 { print $1}'
- | while read package ;
- do if {{.__dry_run}}
- then echo '$' $OPS package delete "$package"
- else $OPS package delete "$package"
- fi
- done
+ - |
+ if {{.__dry_run}}
+ then DRY="--dry-run"
+ else DRY=""
+ fi
+ # Check if an action argument is provided
+ if test -n "{{._action_}}"
+ then
+ # Undeploy a specific action
+ echo "Undeploying specific action: {{._action_}}"
+ bun {{.TASKFILE_DIR}}/deploy/index.js "$OPS_PWD" -u -s
"{{._action_}}" $DRY
+ else
+ # Undeploy all actions and packages from the current project
+ bun {{.TASKFILE_DIR}}/deploy/index.js "$OPS_PWD" -u $DRY
+ fi
- >
if {{.__dry_run}}
then echo '$' $OPS util clean
else $OPS util clean
fi
-
+
clean:
silent: true
cmds:
- task: kill
- |
- if test -d "$OPS_PWD/packages"
- then
+ if test -d "$OPS_PWD/packages"
+ then
echo "*** removing virtualenv"
/bin/rm -rvf "$OPS_PWD"/packages/*/*/virtualenv/
echo "*** removing node_modules"
/bin/rm -rvf "$OPS_PWD"/packages/*/*/node_modules/
echo "*** removing .zip"
- /bin/rm -vf "$OPS_PWD"/packages/*/*.zip
+ /bin/rm -vf "$OPS_PWD"/packages/*/*.zip
else die "no packages in current directory"
fi
-
devel:
interactive: true
silent: true
@@ -305,7 +329,7 @@ tasks:
then source $OPS_PWD/packages/.env
fi
if test -n "$AUTH_CHECK"
- then if test "$AUTH_CHECK" != "$AUTH"
+ then if test "$AUTH_CHECK" != "$AUTH"
then echo "WARNING: wrong deploy! You are logged in a different
user than your configured AUTH_CHECK" ; exit 1
fi
fi
@@ -334,7 +358,6 @@ tasks:
bun {{.TASKFILE_DIR}}/deploy/index.js "$OPS_PWD" -w $FAST $DRY
true
-
shell:
desc: open a bash shell with the current environment
interactive: true
diff --git a/ide/python/build-venv.sh b/ide/python/build-venv.sh
index cf94ce5..2a806a1 100644
--- a/ide/python/build-venv.sh
+++ b/ide/python/build-venv.sh
@@ -20,13 +20,9 @@ DIR="${1:?directory}"
ZIP="${2:?zip file}"
cd "$DIR"
if ! test -d virtualenv
- then virtualenv virtualenv
+then uv venv virtualenv --python=/usr/bin/python3
fi
-source virtualenv/bin/activate
-pip install --upgrade pip
-pip install -r requirements.txt
-virtualenv/bin/python -m pip uninstall -y -q setuptools wheel pip
-touch virtualenv/bin/activate
+uv pip install --python=virtualenv/bin/python -r requirements.txt
if test -f "$ZIP"
then rm "$ZIP"
fi
diff --git a/ide/python/installer.code-workspace
b/ide/python/installer.code-workspace
new file mode 100644
index 0000000..0a4554e
--- /dev/null
+++ b/ide/python/installer.code-workspace
@@ -0,0 +1,17 @@
+{
+ "folders": [
+ {
+ "path": "../../.."
+ },
+ {
+ "path": "../../../../python-starter"
+ }
+ ],
+ "settings": {
+ "workbench.colorCustomizations": {
+ "activityBar.background": "#5A0F2E",
+ "titleBar.activeBackground": "#7E1541",
+ "titleBar.activeForeground": "#FEFBFD"
+ }
+ }
+}
\ No newline at end of file
diff --git a/ide/util/opsfile.yml b/ide/util/opsfile.yml
index 0d30e1b..7ff0c9d 100644
--- a/ide/util/opsfile.yml
+++ b/ide/util/opsfile.yml
@@ -30,11 +30,11 @@ tasks:
then $OPS ide python zip DIR="$($OPS -opspath "packages/{{.A}}")"
elif test -e "packages/{{.A}}/package.json"
then $OPS ide nodejs zip DIR="$($OPS -opspath "packages/{{.A}}")"
- else echo "no zip environment"
+ else true #echo "no zip environment"
fi
action:
- desc: build an action filling its zip file
+ desc: build an action filling its zip file
silent: true
requires: { vars: [A]}
cmds:
diff --git a/opsroot.json b/opsroot.json
index ac25685..677fac3 100644
--- a/opsroot.json
+++ b/opsroot.json
@@ -5,11 +5,11 @@
"coreutils": "arch b2sum b3sum base32 basename basenc cat chgrp
chmod chown chroot cksum comm cp csplit cut date dd df dir dircolors dirname du
env expand expr factor fmt fold groups hashsum head hostid hostname id install
join kill link ln logname ls md5sum mkdir mkfifo mknod mktemp more mv nice nl
nohup nproc numfmt od paste pathchk pinky pr printenv printf ptx pwd readlink
realpath rm rmdir seq sha1sum sha224sum sha256sum sha3-224sum sha3-256sum
sha3-384sum sha3-512sum sha384sum [...]
},
"images": {
- "operator":
"registry.hub.docker.com/apache/openserverless-operator:0.1.0-incubating.2510012114",
+ "operator":
"registry.hub.docker.com/apache/openserverless-operator:0.1.0-incubating.2512151437",
"controller":
"ghcr.io/nuvolaris/openwhisk-controller:3.1.0-mastrogpt.2402101445",
"invoker":
"ghcr.io/nuvolaris/openwhisk-invoker:3.1.0-mastrogpt.2402101445",
"streamer":
"registry.hub.docker.com/apache/openserverless-streamer:0.1.0-incubating.2505031325",
- "systemapi":
"registry.hub.docker.com/apache/openserverless-admin-api:0.1.0-incubating.2508161629"
+ "systemapi":
"registry.hub.docker.com/apache/openserverless-admin-api:0.1.0-incubating.2512101357"
}
}
}
diff --git a/prereq.yml b/prereq.yml
index 6bc8edd..e5bac6d 100644
--- a/prereq.yml
+++ b/prereq.yml
@@ -8,15 +8,15 @@ vars:
DRY: ""
tasks:
-
+
download-and-extract:
requires:
- vars:
+ vars:
- FILE
- URL
- OUT
cmds:
- - echo "{{.OUT}} {{.FILE}} {{.URL}} {{.FILETAR}}"
+ - echo "{{.OUT}} {{.FILE}} {{.URL}} {{.FILETAR}}"
- curl -sL "{{.URL}}" -o {{.FILE}}
- extract "{{.FILE}}" "{{.OUT}}{{.EXE}}"
- remove "{{.FILE}}"
@@ -48,7 +48,7 @@ tasks:
cmds:
- curl -sL "{{.URL}}" -o "{{.FILE}}"
- |
- if test "{{.OS}}" == "windows"
+ if test "{{.OS}}" == "windows"
then rename 7zr.exe 7zz.exe
else extract "{{.FILE}}" 7zz
fi
@@ -66,11 +66,11 @@ tasks:
linux-amd64) echo "x86_64-unknown-linux-gnu" ;;
linux-arm64) echo "aarch64-unknown-linux-gnu" ;;
darwin-amd64) echo "x86_64-apple-darwin" ;;
- darwin-arm64) echo "aarch64-apple-darwin" ;;
+ darwin-arm64) echo "aarch64-apple-darwin" ;;
windows-*) echo "x86_64-pc-windows-gnu" ;;
*) echo "unknown" ;;
esac
- URL:
"https://github.com/uutils/coreutils/releases/download/{{.VERSION}}/coreutils-{{.VERSION}}-{{.SUFFIX}}{{.ARC}}"
+ URL:
"https://github.com/uutils/coreutils/releases/download/{{.VERSION}}/coreutils-{{.VERSION}}-{{.SUFFIX}}{{.ARC}}"
FILE: "{{base .URL}}"
OUT: coreutils
cmds:
@@ -106,7 +106,7 @@ tasks:
kind:
desc: download kind
vars:
- VERSION: 0.29.0
+ VERSION: 0.30.0
cmds:
- task: download
vars:
@@ -118,7 +118,7 @@ tasks:
vars:
VERSION: 0.13.6
BASE: "https://github.com/alexellis/k3sup/releases/download/{{.VERSION}}"
- FILE:
+ FILE:
sh: |
case {{.OS}}-{{.ARCH}} in
(linux-amd64) echo k3sup ;;
@@ -132,7 +132,7 @@ tasks:
vars:
URL: "{{.BASE}}/{{.FILE}}"
OUT: k3sup
-
+
rg:
desc: download ripgrep
vars:
@@ -145,11 +145,11 @@ tasks:
linux-amd64) echo "x86_64-unknown-linux-musl" ;;
linux-arm64) echo "aarch64-unknown-linux-gnu" ;;
darwin-amd64) echo "x86_64-apple-darwin" ;;
- darwin-arm64) echo "aarch64-apple-darwin" ;;
+ darwin-arm64) echo "aarch64-apple-darwin" ;;
windows-*) echo "x86_64-pc-windows-msvc" ;;
*) echo "unknown" ;;
esac
- URL:
"https://github.com/BurntSushi/ripgrep/releases/download/{{.VERSION}}/ripgrep-{{.VERSION}}-{{.SUFFIX}}{{.ARC}}"
+ URL:
"https://github.com/BurntSushi/ripgrep/releases/download/{{.VERSION}}/ripgrep-{{.VERSION}}-{{.SUFFIX}}{{.ARC}}"
FILE: "{{base .URL}}"
OUT: rg
cmds:
@@ -280,7 +280,7 @@ tasks:
fi
EOF
executable zip
- ;;
+ ;;
windows-*)
curl -sL "{{.ZIP_EXE}}" -o zip.exe
executable zip.exe
@@ -290,31 +290,31 @@ tasks:
#kubefwd:
# desc: download kubefwd
# vars:
- # VERSION: "1.25.8"
+ # VERSION: "1.25.3"
# SUFFIX:
# sh: |
# case "{{.OS}}-{{.ARCH}}" in
- # linux-amd64) echo "_Linux_x86_64" ;;
- # linux-arm64) echo "_Linux_arm64" ;;
- # darwin-amd64) echo "_Darwin_x86_64" ;;
- # darwin-arm64) echo "_Darwin_arm64" ;;
- # windows-*) echo "_Windows_x86_64" ;;
- # *) echo "unknown" ;;
- # esac
- #
#https://github.com/txn2/kubefwd/releases/download/1.22.5/kubefwd_Darwin_x86_64.tar.gz
- # URL:
"https://github.com/txn2/kubefwd/releases/download/{{.VERSION}}/kubefwd{{.SUFFIX}}{{.ARC}}"
- # FILE: "{{base .URL}}"
- # OUT: kubefwd
- # cmds:
- # - task: download-and-extract
- # vars:
- # URL: "{{.URL}}"
- # FILE: "{{.FILE}}"
- # OUT: kubefwd
+ # linux-amd64) echo "_Linux_x86_64" ;;
+ # linux-arm64) echo "_Linux_arm64" ;;
+ # darwin-amd64) echo "_Darwin_x86_64" ;;
+ # darwin-arm64) echo "_Darwin_arm64" ;;
+ # windows-*) echo "_Windows_x86_64" ;;
+ # *) echo "unknown" ;;
+ # esac
+ #
#https://github.com/txn2/kubefwd/releases/download/1.22.5/kubefwd_Darwin_x86_64.tar.gz
+ # URL:
"https://github.com/txn2/kubefwd/releases/download/{{.VERSION}}/kubefwd{{.SUFFIX}}{{.ARC}}"
+ # FILE: "{{base .URL}}"
+ # OUT: kubefwd
+ # cmds:
+ # - task: download-and-extract
+ # vars:
+ # URL: "{{.URL}}"
+ # FILE: "{{.FILE}}"
+ # OUT: kubefwd
all:
- task: 7zz
- - task: coreutils
+ - task: coreutils
- task: bun
- task: kind
- task: k3sup
@@ -322,14 +322,14 @@ tasks:
- task: rg
- task: uv
- task: helm
- #- task: kubefwd
- task: yq
# do not test zip as it is a special case
#- task: zip
# commented out for now
+ #- task: kubefwd
#- task: hugo
#- task: k3d
-
+
test:
vars:
DIR: "{{.OPS_PWD}}/bin/{{.OS}}-{{.ARCH}}"
@@ -340,7 +340,7 @@ tasks:
cd "{{.DIR}}"
{{.DRY}} ops -task -t ../../prereq.yml -d "{{.DIR}}" all
- task: check
-
+
check:
vars:
DIR: "{{.OPS_PWD}}/bin/{{.OS}}-{{.ARCH}}"
@@ -359,11 +359,11 @@ tasks:
cmds:
- for: sources
cmd: filetype -m "{{.ITEM}}" | rg {{.FILETYPE}}
-
+
tests:
- __OS=linux __ARCH=amd64 ops -task -t prereq.yml test
- __OS=linux __ARCH=arm64 ops -task -t prereq.yml test
- __OS=darwin __ARCH=amd64 ops -task -t prereq.yml test
- __OS=darwin __ARCH=arm64 ops -task -t prereq.yml test
- __OS=windows __ARCH=amd64 ops -task -t prereq.yml test
-
+
diff --git a/setup/docker/ingress-deploy.yaml b/setup/docker/ingress-deploy.yaml
index 55712e7..0e7a16c 100644
--- a/setup/docker/ingress-deploy.yaml
+++ b/setup/docker/ingress-deploy.yaml
@@ -36,18 +36,6 @@ metadata:
name: ingress-nginx
namespace: ingress-nginx
---
-apiVersion: v1
-kind: ServiceAccount
-metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: ingress-nginx
- app.kubernetes.io/name: ingress-nginx
- app.kubernetes.io/part-of: ingress-nginx
- app.kubernetes.io/version: 1.7.0
- name: ingress-nginx-admission
- namespace: ingress-nginx
----
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
@@ -139,26 +127,6 @@ rules:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
-kind: Role
-metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: ingress-nginx
- app.kubernetes.io/name: ingress-nginx
- app.kubernetes.io/part-of: ingress-nginx
- app.kubernetes.io/version: 1.7.0
- name: ingress-nginx-admission
- namespace: ingress-nginx
-rules:
-- apiGroups:
- - ""
- resources:
- - secrets
- verbs:
- - get
- - create
----
-apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
@@ -240,25 +208,6 @@ rules:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRole
-metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: ingress-nginx
- app.kubernetes.io/name: ingress-nginx
- app.kubernetes.io/part-of: ingress-nginx
- app.kubernetes.io/version: 1.7.0
- name: ingress-nginx-admission
-rules:
-- apiGroups:
- - admissionregistration.k8s.io
- resources:
- - validatingwebhookconfigurations
- verbs:
- - get
- - update
----
-apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
@@ -279,26 +228,6 @@ subjects:
namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
-kind: RoleBinding
-metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: ingress-nginx
- app.kubernetes.io/name: ingress-nginx
- app.kubernetes.io/part-of: ingress-nginx
- app.kubernetes.io/version: 1.7.0
- name: ingress-nginx-admission
- namespace: ingress-nginx
-roleRef:
- apiGroup: rbac.authorization.k8s.io
- kind: Role
- name: ingress-nginx-admission
-subjects:
-- kind: ServiceAccount
- name: ingress-nginx-admission
- namespace: ingress-nginx
----
-apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
@@ -316,25 +245,6 @@ subjects:
name: ingress-nginx
namespace: ingress-nginx
---
-apiVersion: rbac.authorization.k8s.io/v1
-kind: ClusterRoleBinding
-metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: ingress-nginx
- app.kubernetes.io/name: ingress-nginx
- app.kubernetes.io/part-of: ingress-nginx
- app.kubernetes.io/version: 1.7.0
- name: ingress-nginx-admission
-roleRef:
- apiGroup: rbac.authorization.k8s.io
- kind: ClusterRole
- name: ingress-nginx-admission
-subjects:
-- kind: ServiceAccount
- name: ingress-nginx-admission
- namespace: ingress-nginx
----
apiVersion: v1
data:
allow-snippet-annotations: "true"
@@ -381,29 +291,6 @@ spec:
app.kubernetes.io/name: ingress-nginx
type: NodePort
---
-apiVersion: v1
-kind: Service
-metadata:
- labels:
- app.kubernetes.io/component: controller
- app.kubernetes.io/instance: ingress-nginx
- app.kubernetes.io/name: ingress-nginx
- app.kubernetes.io/part-of: ingress-nginx
- app.kubernetes.io/version: 1.7.0
- name: ingress-nginx-controller-admission
- namespace: ingress-nginx
-spec:
- ports:
- - appProtocol: https
- name: https-webhook
- port: 443
- targetPort: webhook
- selector:
- app.kubernetes.io/component: controller
- app.kubernetes.io/instance: ingress-nginx
- app.kubernetes.io/name: ingress-nginx
- type: ClusterIP
----
apiVersion: apps/v1
kind: Deployment
metadata:
@@ -443,9 +330,6 @@ spec:
- --controller-class=k8s.io/ingress-nginx
- --ingress-class=nginx
- --configmap=$(POD_NAMESPACE)/ingress-nginx-controller
- - --validating-webhook=:8443
- - --validating-webhook-certificate=/usr/local/certificates/cert
- - --validating-webhook-key=/usr/local/certificates/key
- --watch-ingress-without-class=true
- --publish-status-address=localhost
env:
@@ -459,7 +343,7 @@ spec:
fieldPath: metadata.namespace
- name: LD_PRELOAD
value: /usr/local/lib/libmimalloc.so
- image:
registry.k8s.io/ingress-nginx/controller:v1.7.0@sha256:7612338342a1e7b8090bef78f2a04fffcadd548ccaabe8a47bf7758ff549a5f7
+ image: registry.k8s.io/ingress-nginx/controller:v1.7.0
imagePullPolicy: IfNotPresent
lifecycle:
preStop:
@@ -486,9 +370,6 @@ spec:
hostPort: 443
name: https
protocol: TCP
- - containerPort: 8443
- name: webhook
- protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
@@ -511,10 +392,6 @@ spec:
drop:
- ALL
runAsUser: 101
- volumeMounts:
- - mountPath: /usr/local/certificates/
- name: webhook-cert
- readOnly: true
dnsPolicy: ClusterFirst
nodeSelector:
ingress-ready: "true"
@@ -528,106 +405,6 @@ spec:
- effect: NoSchedule
key: node-role.kubernetes.io/control-plane
operator: Equal
- volumes:
- - name: webhook-cert
- secret:
- secretName: ingress-nginx-admission
----
-apiVersion: batch/v1
-kind: Job
-metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: ingress-nginx
- app.kubernetes.io/name: ingress-nginx
- app.kubernetes.io/part-of: ingress-nginx
- app.kubernetes.io/version: 1.7.0
- name: ingress-nginx-admission-create
- namespace: ingress-nginx
-spec:
- template:
- metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: ingress-nginx
- app.kubernetes.io/name: ingress-nginx
- app.kubernetes.io/part-of: ingress-nginx
- app.kubernetes.io/version: 1.7.0
- name: ingress-nginx-admission-create
- spec:
- containers:
- - args:
- - create
- -
--host=ingress-nginx-controller-admission,ingress-nginx-controller-admission.$(POD_NAMESPACE).svc
- - --namespace=$(POD_NAMESPACE)
- - --secret-name=ingress-nginx-admission
- env:
- - name: POD_NAMESPACE
- valueFrom:
- fieldRef:
- fieldPath: metadata.namespace
- image:
registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f
- imagePullPolicy: IfNotPresent
- name: create
- securityContext:
- allowPrivilegeEscalation: false
- nodeSelector:
- kubernetes.io/os: linux
- restartPolicy: OnFailure
- securityContext:
- fsGroup: 2000
- runAsNonRoot: true
- runAsUser: 2000
- serviceAccountName: ingress-nginx-admission
----
-apiVersion: batch/v1
-kind: Job
-metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: ingress-nginx
- app.kubernetes.io/name: ingress-nginx
- app.kubernetes.io/part-of: ingress-nginx
- app.kubernetes.io/version: 1.7.0
- name: ingress-nginx-admission-patch
- namespace: ingress-nginx
-spec:
- template:
- metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: ingress-nginx
- app.kubernetes.io/name: ingress-nginx
- app.kubernetes.io/part-of: ingress-nginx
- app.kubernetes.io/version: 1.7.0
- name: ingress-nginx-admission-patch
- spec:
- containers:
- - args:
- - patch
- - --webhook-name=ingress-nginx-admission
- - --namespace=$(POD_NAMESPACE)
- - --patch-mutating=false
- - --secret-name=ingress-nginx-admission
- - --patch-failure-policy=Fail
- env:
- - name: POD_NAMESPACE
- valueFrom:
- fieldRef:
- fieldPath: metadata.namespace
- image:
registry.k8s.io/ingress-nginx/kube-webhook-certgen:v20230312-helm-chart-4.5.2-28-g66a760794@sha256:01d181618f270f2a96c04006f33b2699ad3ccb02da48d0f89b22abce084b292f
- imagePullPolicy: IfNotPresent
- name: patch
- securityContext:
- allowPrivilegeEscalation: false
- nodeSelector:
- kubernetes.io/os: linux
- restartPolicy: OnFailure
- securityContext:
- fsGroup: 2000
- runAsNonRoot: true
- runAsUser: 2000
- serviceAccountName: ingress-nginx-admission
---
apiVersion: networking.k8s.io/v1
kind: IngressClass
@@ -641,36 +418,3 @@ metadata:
name: nginx
spec:
controller: k8s.io/ingress-nginx
----
-apiVersion: admissionregistration.k8s.io/v1
-kind: ValidatingWebhookConfiguration
-metadata:
- labels:
- app.kubernetes.io/component: admission-webhook
- app.kubernetes.io/instance: ingress-nginx
- app.kubernetes.io/name: ingress-nginx
- app.kubernetes.io/part-of: ingress-nginx
- app.kubernetes.io/version: 1.7.0
- name: ingress-nginx-admission
-webhooks:
-- admissionReviewVersions:
- - v1
- clientConfig:
- service:
- name: ingress-nginx-controller-admission
- namespace: ingress-nginx
- path: /networking/v1/ingresses
- failurePolicy: Fail
- matchPolicy: Equivalent
- name: validate.nginx.ingress.kubernetes.io
- rules:
- - apiGroups:
- - networking.k8s.io
- apiVersions:
- - v1
- operations:
- - CREATE
- - UPDATE
- resources:
- - ingresses
- sideEffects: None
diff --git a/setup/docker/kind.yaml b/setup/docker/kind.yaml
index 4102b17..696eaa6 100644
--- a/setup/docker/kind.yaml
+++ b/setup/docker/kind.yaml
@@ -17,8 +17,14 @@
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
+containerdConfigPatches:
+- |-
+ [plugins."io.containerd.grpc.v1.cri".registry]
+ config_path = "/etc/containerd/certs.d"
+
nodes:
- role: control-plane
+ image: kindest/node:v1.33.1
kubeadmConfigPatches:
- |
kind: InitConfiguration
@@ -32,71 +38,29 @@ nodes:
- containerPort: 443
hostPort: 443
protocol: TCP
-- role: worker
+ - containerPort: 30222
+ hostPort: 2222
+ protocol: TCP
extraMounts:
- - hostPath: $DATADIR/data
+ - hostPath: "$DATADIR/data"
containerPath: /data
- - hostPath: $DATADIR/openwhisk/standalone
+ - hostPath: "$DATADIR/openwhisk/standalone"
containerPath: /openwhisk/standalone
- hostPath: $DATADIR/openwhisk/invoker
containerPath: /openwhisk/invoker
- - hostPath: $DATADIR/openwhisk/controller
+ - hostPath: "$DATADIR/openwhisk/controller"
containerPath: /openwhisk/controller
- - hostPath: $DATADIR/couchdb
+ - hostPath: "$DATADIR/couchdb"
containerPath: /couchdb
- - hostPath: $DATADIR/mongodb
+ - hostPath: "$DATADIR/mongodb"
containerPath: /mongodb
- - hostPath: $DATADIR/redis
+ - hostPath: "$DATADIR/redis"
containerPath: /redis
- - hostPath: $DATADIR/zookeper/data
+ - hostPath: "$DATADIR/zookeper/data"
containerPath: /zookeeper/data
- - hostPath: $DATADIR/zookeeper/log
+ - hostPath: "$DATADIR/zookeeper/log"
containerPath: /zookeeper/log
- - hostPath: $DATADIR/kafka
+ - hostPath: "$DATADIR/kafka"
containerPath: /kafka
- extraPortMappings:
- - containerPort: 30232
- hostPort: 3232
- protocol: TCP
- - containerPort: 30233
- hostPort: 3233
- protocol: TCP
- - containerPort: 30896
- hostPort: 7896
- protocol: TCP
- - containerPort: 30984
- hostPort: 5984
- protocol: TCP
- - containerPort: 30992
- hostPort: 9092
- protocol: TCP
- - containerPort: 30644
- hostPort: 9644
- protocol: TCP
- - containerPort: 6379
- hostPort: 30379
- protocol: TCP
- - containerPort: 28017
- hostPort: 32817
- protocol: TCP
- - containerPort: 32717
- hostPort: 27017
- protocol: TCP
- - containerPort: 32090
- hostPort: 9000
- protocol: TCP
- - containerPort: 32091
- hostPort: 9090
- protocol: TCP
- - containerPort: 9080
- hostPort: 9080
- protocol: TCP
- - containerPort: 9010
- hostPort: 9010
- protocol: TCP
- - containerPort: 32530
- hostPort: 19530
- protocol: TCP
- - containerPort: 32531
- hostPort: 9091
- protocol: TCP
+ - hostPath: "$OPS_HOME/workspace"
+ containerPath: /workspace
diff --git a/setup/docker/opsfile.yml b/setup/docker/opsfile.yml
index b40122c..e43b194 100644
--- a/setup/docker/opsfile.yml
+++ b/setup/docker/opsfile.yml
@@ -17,26 +17,28 @@
version: '3'
vars:
+ CLUSTER: nuvolaris
INGRESS:
"https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml"
env:
DATADIR:
- sh: echo $OPS_TMP/kind
- KUBECONFIG:
- sh: |-
+ sh: echo "$OPS_TMP/kind"
+ WORKSPACE:
+ sh: echo "$OPS_HOME/workspace"
+ KUBECONFIG:
+ sh: |-
if test -e "$OPS_TMP/kubeconfig"
then echo "$OPS_TMP/kubeconfig"
else echo ~/.kube/config
fi
tasks:
-
status:
silent: true
desc: status of the Apache OpenServerless cluster in Docker
cmds:
- |
- if kind get clusters | rg nuvolaris
+ if kind get clusters | rg {{.CLUSTER}}
then echo Cluster Apache OpenServerless up and running
else echo Cluster Apache OpenServerless not found
fi
@@ -51,7 +53,7 @@ tasks:
echo "=== Kind Version"
kind version
echo "=== Kind Clusters"
- kind get clusters
+ kind get clusters
if test -e $KUBECONFIG
then echo "=== Nodes"
kubectl get nodes
@@ -60,19 +62,32 @@ tasks:
cluster:
silent: true
cmds:
- - mkdir -p "$DATADIR"
+ - mkdir -p "$DATADIR" "$OPS_HOME/workspace"
- envsubst -i kind.yaml -o _kind.yaml
- - >
- kind create cluster
- --kubeconfig="$OPS_TMP/kubeconfig"
- --wait=1m --name=nuvolaris
+ - >
+ kind create cluster
+ --wait=2m --name=nuvolaris
--config=_kind.yaml
-
+ - |
+ docker exec nuvolaris-control-plane mkdir -p
/etc/containerd/certs.d/127.0.0.1:32000
+ docker exec nuvolaris-control-plane sh -c 'cat >
/etc/containerd/certs.d/127.0.0.1:32000/hosts.toml << EOF
+ server = "http://127.0.0.1:32000"
+
+ [host."http://127.0.0.1:32000"]
+ capabilities = ["pull", "resolve", "push"]
+ skip_verify = true
+ EOF'
+ docker exec nuvolaris-control-plane systemctl restart containerd
+ kind export kubeconfig -n nuvolaris --kubeconfig "$OPS_TMP/kubeconfig"
+ echo "waiting for kind ready..."
+ retry -t 100 -m 600 test -e $OPS_TMP/kubeconfig
+ retry kubectl --kubeconfig $OPS_TMP/kubeconfig cluster-info
+
ingress:
silent: true
cmds:
- - >
- kubectl --kubeconfig="$OPS_TMP/kubeconfig"
+ - >
+ retry kubectl --kubeconfig="$OPS_TMP/kubeconfig"
apply -f ingress-deploy.yaml
check-space:
@@ -81,38 +96,6 @@ tasks:
cmds:
- uv run space.py
- preload:
- silent: true
- desc: preload the Apache OpenServerless images in docker to speed up the
cluster creation
- ignore_errors: true
- status:
- - config SKIP_PRELOAD_IMAGES
- cmds:
- - |
- for image in "$IMAGES_STREAMER" "$IMAGES_OPERATOR" "$IMAGES_CONTROLLER"
- do
- docker pull "$image" --platform "linux/{{ARCH}}"
- if ! kind load docker-image "$image" --name nuvolaris
- then
- echo "*** Cannot preload images. You can disable preload with ops
-config SKIP_PRELOAD_IMAGES=1"
- echo "*** Workaround on Docker Desktop: disable 'Use containerd for
pulling and storing images' on General"
- echo "*** WARNING! If you skip preload, it can take a lot of time
before the system starts. Be patient."
- exit 1
- fi
- docker rmi "$image"
- done
- - |
- jq -r '.runtimes[][]
- | select(.default == true)
- | .image
- | "\(.prefix)/\(.name):\(.tag)"' <$OPS_ROOT/runtimes.json \
- | rg apache/openserverless-runtime \
- | while read -r image; do
- docker pull "$image" --platform "linux/{{ARCH}}"
- kind load docker-image "$image" --name nuvolaris
- docker rmi "$image"
- done
-
clean-all:
silent: true
desc: remove all images and containers from docker
@@ -121,7 +104,7 @@ tasks:
- echo "Cleaning all docker images and containers"
- docker ps -qa | while read a ; do docker rm -f "$a" ; done
- docker images -qa | while read a ; do docker rmi -f "$a" ; done
- - docker system prune -af
+ - docker system prune -af
- docker volume prune -af
- docker system df
@@ -129,18 +112,23 @@ tasks:
silent: true
desc: create the Apache OpenServerless cluster in Docker
cmds:
- - task: cluster
- - task: ingress
- - cp "$OPS_TMP/kubeconfig" "$OPS_TMP/kind.kubeconfig"
- status:
- - kind get clusters | rg nuvolaris
+ - |
+ if kind get clusters | rg {{.CLUSTER}}
+ then kind export kubeconfig --name {{.CLUSTER}} --kubeconfig
"$OPS_TMP/kubeconfig"
+ else
+ ops util freeze docker-load
+ ops setup docker cluster
+ ops util freeze kind-load
+ ops setup docker ingress
+ fi
+ - cp "$OPS_TMP/kubeconfig" "$OPS_TMP/kind-{{.CLUSTER}}.kubeconfig"
delete:
silent: true
desc: destroy the Apache OpenServerless cluster in Docker
cmds:
- - kind delete clusters nuvolaris
- - rm -f "$OPS_TMP/kubeconfig" "$OPS_TMP/kind.kubeconfig"
+ - kind delete clusters {{.CLUSTER}}
+ - rm -f "$OPS_TMP/kubeconfig" "$OPS_TMP/kind-{{.CLUSTER}}.kubeconfig"
kubeconfig:
desc: export kubeconfig
diff --git a/setup/docopts.md b/setup/docopts.md
index 926ce40..55e412a 100644
--- a/setup/docopts.md
+++ b/setup/docopts.md
@@ -24,19 +24,18 @@ Manage installation
```text
Usage:
- setup mini
+ setup mini [<apihost>]
setup devcluster [--uninstall|--status|[--skip-check-ports]
[--skip-preload-images]]
setup cluster [<context>] [--uninstall|--status]
setup server <server> [<user>] [--uninstall|--status]
setup status
setup uninstall
- setup prereq
```
## Commands
```
- setup mini deploy mini Apache OpenServerless, slim local
installation available as http://devel.miniops.me
+ setup mini deploy mini Apache OpenServerless, slim local
installation available as http://devel.miniops.me (or your local domain)
setup cluster deploy Apache OpenServerless in the Kubernetes cluster
using the <context>, default the current
setup devcluster deploy Apache OpenServerless in a devcluster created
locally
you need Docker Desktop available with at least 6G of
memory assigned
@@ -44,7 +43,6 @@ Usage:
the server must be accessible with ssh using the <user>
with sudo power, default root
setup status show the status of the last installation
setup uninstall uninstall the last installation
- setup prereq validate current configuration
```
## Options
diff --git a/setup/kubernetes/crds/whisk-crd.yaml
b/setup/kubernetes/crds/whisk-crd.yaml
index dff969c..73dc3e7 100644
--- a/setup/kubernetes/crds/whisk-crd.yaml
+++ b/setup/kubernetes/crds/whisk-crd.yaml
@@ -149,7 +149,10 @@ spec:
type: boolean
registry:
description: deploys a private registry to load on the
fly generated action runtimes (false by default)
- type: boolean
+ type: boolean
+ seaweedfs:
+ description: deploys an S3 compatible layer using a
standalone deployment of seaweedfs
+ type: boolean
required:
- openwhisk
- couchdb
@@ -835,7 +838,50 @@ spec:
- mode
- volume-size
- auth
- - hostname
+ - hostname
+ seaweedfs:
+ description: used to configure the internal saweedfs data
storage service
+ type: object
+ properties:
+ volume-size:
+ description: volume size in GB, default to 60GB
+ type: integer
+ default-bucket-quota:
+ description: default bucket quota, default to 1024MB
+ type: integer
+ nuvolaris:
+ description: used to configure the MINIO nuvolaris user
used for non administrative purposes
+ type: object
+ properties:
+ user:
+ type: string
+ password:
+ type: string
+ required:
+ - user
+ - password
+ ingress:
+ description: configuration option for global minio
ingresses exposure
+ type: object
+ properties:
+ s3-enabled:
+ description: boolean flag to activate SEAWEEDFS S3
compatible ingress. Default to false
+ type: boolean
+ s3-hostname:
+ description: ingress hostname to be used if true
(normally s3.<apihost>)
+ type: string
+ console-enabled:
+ description: boolean flag to expose SEAWEEDFS Filer
UI
+ type: boolean
+ console-hostname:
+ description: ingress hostname to be used (nora=mally
filer.<apihost>)
+ type: string
+ required:
+ - s3-enabled
+ - console-enabled
+ required:
+ - volume-size
+ - nuvolaris
status:
x-kubernetes-preserve-unknown-fields: true
# type: object
@@ -948,4 +994,9 @@ spec:
type: string
priority: 0
jsonPath: .status.whisk_create.registry
- description: Registry
\ No newline at end of file
+ description: Registry
+ - name: Seaweedfs
+ type: string
+ priority: 0
+ jsonPath: .status.whisk_create.seaweedfs
+ description: Seaweedfs
\ No newline at end of file
diff --git a/setup/kubernetes/operator.yaml b/setup/kubernetes/operator.yaml
index c2a4a9f..121296b 100644
--- a/setup/kubernetes/operator.yaml
+++ b/setup/kubernetes/operator.yaml
@@ -19,8 +19,8 @@ apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nuvolaris-operator
- namespace: nuvolaris
-spec:
+ namespace: nuvolaris
+spec:
replicas: 1
selector:
matchLabels:
@@ -67,18 +67,18 @@ spec:
- key: "nuvolaris-role"
operator: "Equal"
value: core
- effect: "NoSchedule"
+ effect: "NoSchedule"
securityContext:
runAsUser: 1001
- fsGroup: 1001
+ fsGroup: 1001
volumes:
- name: deploy
persistentVolumeClaim:
- claimName: nuvolaris-operator-deploy-pvc
+ claimName: nuvolaris-operator-deploy-pvc
containers:
- name: nuvolaris-operator
image: ${IMAGES_OPERATOR}
- imagePullPolicy: Always
+ imagePullPolicy: IfNotPresent
command: ["./run.sh"]
args: ["--verbose"]
securityContext:
@@ -87,4 +87,4 @@ spec:
- ALL
volumeMounts:
- name: deploy
- mountPath: "/home/nuvolaris/deploy"
\ No newline at end of file
+ mountPath: "/home/nuvolaris/deploy"
\ No newline at end of file
diff --git a/setup/kubernetes/opsfile.yml b/setup/kubernetes/opsfile.yml
index 6b536e3..733eb8c 100644
--- a/setup/kubernetes/opsfile.yml
+++ b/setup/kubernetes/opsfile.yml
@@ -31,44 +31,44 @@ env:
fi
# sets memory parameter for the controller invoker and corresponding pods
- OPENWHISK_CONTROLLER_JAVA_OPTS:
+ OPENWHISK_CONTROLLER_JAVA_OPTS:
sh: |
if [ -z "$OPENWHISK_CONTROLLER_JVMGB" ]
then echo -Xmx2G
else echo -Xmx"$OPENWHISK_CONTROLLER_JVMGB"G
fi
- OPENWHISK_INVOKER_JAVA_OPTS:
+ OPENWHISK_INVOKER_JAVA_OPTS:
sh: |
if [ -z "$OPENWHISK_INVOKER_JVMGB" ]
then echo -Xmx2G
else echo -Xmx"$OPENWHISK_INVOKER_JVMGB"G
fi
- OPENWHISK_INVOKER_CONTAINER_POOL_MEMORY:
+ OPENWHISK_INVOKER_CONTAINER_POOL_MEMORY:
sh: |
if [ -z "$OPENWHISK_INVOKER_CONTAINER_POOLMEMORYGB" ]
then echo 2048m
else pool=$OPENWHISK_INVOKER_CONTAINER_POOLMEMORYGB; echo $((pool*1024))m
fi
- OPENWHISK_CONTROLLER_RES_MIN_MEM:
+ OPENWHISK_CONTROLLER_RES_MIN_MEM:
sh: |
if [ -z "$OPENWHISK_CONTROLLER_JVMGB" ]
then echo 2G
else echo "$OPENWHISK_CONTROLLER_JVMGB"G
fi
- OPENWHISK_CONTROLLER_RES_MAX_MEM:
+ OPENWHISK_CONTROLLER_RES_MAX_MEM:
sh: |
if [ -z "$OPENWHISK_CONTROLLER_JVMGB" ]
then echo 3G
else mem=$OPENWHISK_CONTROLLER_JVMGB; echo $((mem+1))G
fi
- OPENWHISK_INVOKER_RES_MIN_MEM:
+ OPENWHISK_INVOKER_RES_MIN_MEM:
sh: |
if [ -z "$OPENWHISK_INVOKER_JVMGB" ]
- then echo 3G
+ then echo 3G
else mem=$OPENWHISK_INVOKER_JVMGB; echo $((mem))G
fi
- OPENWHISK_INVOKER_RES_MAX_MEM:
- sh: |
+ OPENWHISK_INVOKER_RES_MAX_MEM:
+ sh: |
if [ -z "$OPENWHISK_INVOKER_JVMGB" ] && [ -z
"$OPENWHISK_INVOKER_CONTAINER_POOLMEMORYGB" ]
then echo 4G
else mem=$OPENWHISK_INVOKER_JVMGB;
pool=$OPENWHISK_INVOKER_CONTAINER_POOLMEMORYGB; echo $((mem+1))G
@@ -89,10 +89,10 @@ env:
fi
tasks:
-
+
streamer:
desc: deploy streamer
-
+
status:
desc: show nuvolaris cluster status
silent: true
@@ -126,7 +126,7 @@ tasks:
status:
- test "{{.COND}}" != "true"
env:
- BAR:
+ BAR:
sh: printf "%*s" {{.RETRY}} "" | tr ' ' '#'
cmds:
- test -n "{{.OBJECT}}" || die "use OBJECT=<to-wait-for>"
@@ -146,7 +146,7 @@ tasks:
N=0
RES=false
while [[ $N -lt {{.RETRY}} ]]
- do
+ do
printf "\rwaiting for {{.OBJECT}} ready: [${BAR:0:$((N++))}]"
if kubectl -n nuvolaris wait --for=condition=Ready "{{.OBJECT}}"
--timeout={{.TIMEOUT}} >/dev/null 2>&1
then RES=true ; break
@@ -154,7 +154,7 @@ tasks:
done
printf "\n"
$RES
-
+
wait-pod:
#desc: wait for a pod to be available - leave the result in FILE
silent: true
@@ -166,7 +166,7 @@ tasks:
- COND
- FILE
env:
- BAR:
+ BAR:
sh: printf "%*s" {{.RETRY}} "" | tr ' ' '#'
cmds:
- |
@@ -214,7 +214,7 @@ tasks:
- kubectl -n nuvolaris apply -f _runtimes.yaml
vars:
RUNTIMES:
- sh: |
+ sh: |
if test -e "$OPS_TMP/runtimes.json"
then echo "$OPS_TMP/runtimes.json"
else echo "$OPS_ROOT/runtimes.json"
@@ -299,41 +299,53 @@ tasks:
- task: wait
vars:
OBJECT: po/redis-0
- COND:
+ COND:
sh: echo "$OPERATOR_COMPONENT_REDIS"
- task: wait
vars:
OBJECT: po/nuvolaris-mongodb-0
- COND:
+ COND:
sh: echo "$OPERATOR_COMPONENT_MONGODB"
- task: wait
vars:
OBJECT: pod/nuvolaris-postgres-1-0
- COND:
+ COND:
sh: echo "$OPERATOR_COMPONENT_POSTGRES"
- task: wait-pod
vars:
SELECTOR: "-l app=minio"
- COND:
+ COND:
sh: echo "$OPERATOR_COMPONENT_MINIO"
FILE: _minio
+ #- task: wait
+ # vars:
+ # OBJECT:
+ # sh: echo "pod/$(cat _minio)"
+ # COND:
+ # sh: echo "$OPERATOR_COMPONENT_MINIO"
+ - task: wait-pod
+ vars:
+ SELECTOR: "-l app=seaweedfs"
+ COND:
+ sh: echo "$OPERATOR_COMPONENT_SEAWEEDFS"
+ FILE: _seaweedfs
- task: wait
vars:
OBJECT:
- sh: echo "pod/$(cat _minio)"
- COND:
- sh: echo "$OPERATOR_COMPONENT_MINIO"
+ sh: echo "pod/$(cat _seaweedfs)"
+ COND:
+ sh: echo "$OPERATOR_COMPONENT_SEAWEEDFS"
- task: wait-pod
vars:
SELECTOR: "-l name=nuvolaris-milvus"
- COND:
+ COND:
sh: echo "$OPERATOR_COMPONENT_MILVUS"
FILE: _milvus
- task: wait
vars:
OBJECT:
sh: echo "pod/$(cat _milvus)"
- COND:
+ COND:
sh: echo "$OPERATOR_COMPONENT_MILVUS"
create:
@@ -357,7 +369,7 @@ tasks:
- config SKIP_OPERATOR_LAUNCH=1
- task: create
- config -r SKIP_OPERATOR_LAUNCH
-
+
deploy:
silent: true
desc: deploy in namespace (use namespace admin)
@@ -376,7 +388,7 @@ tasks:
desc: delete cluster
cmds:
- source forcedelete.src
- - kubectl delete clusterissuers/letsencrypt-issuer 2>/dev/null
+ - kubectl delete clusterissuers/letsencrypt-issuer 2>/dev/null
- kubectl -n nuvolaris delete sts/nuvolaris-operator --grace-period=0
- kubectl -n nuvolaris delete po,sts,job,deploy,svc --all
--grace-period=0
- kubectl -n nuvolaris delete cm,secret,sa,role --all
@@ -395,7 +407,7 @@ tasks:
desc: "unlock locked deletion (removing a finalizers)"
cmds:
- >
- kubectl -n nuvolaris patch wsk/controller --type=merge
+ kubectl -n nuvolaris patch wsk/controller --type=merge
--patch '{"metadata": {"finalizers":[] } }'
operator-update:
@@ -405,7 +417,7 @@ tasks:
- "kubectl apply -f crds"
- task: operator
- kubectl -n nuvolaris rollout restart statefulset nuvolaris-operator
- preconditions:
+ preconditions:
- sh: '[ $ENT_IMAGES_OPERATOR != $(nuv debug operator:version) ]'
msg: "Current OpenServerless operator it is already updated to newest
version. Request ignored."
@@ -414,9 +426,9 @@ tasks:
silent: true
cmds:
- ops setup kubernetes prepare
- - ops setup kubernetes whiskcrd
- - |
+ - ops setup kubernetes whiskcrd
+ - |
kubectl apply -f _whisk.yaml
- task: wait
vars:
- OBJECT: pod/controller-0
\ No newline at end of file
+ OBJECT: pod/controller-0
\ No newline at end of file
diff --git a/setup/kubernetes/whisk.yaml b/setup/kubernetes/whisk.yaml
index de6b164..93beb40 100644
--- a/setup/kubernetes/whisk.yaml
+++ b/setup/kubernetes/whisk.yaml
@@ -31,6 +31,7 @@ spec:
slim: ${OPERATOR_CONFIG_SLIM:-false}
affinity: ${OPERATOR_CONFIG_AFFINITY:-false}
tolerations: ${OPERATOR_CONFIG_TOLERATIONS:-false}
+ ingressclass: ${OPERATOR_CONFIG_INGRESSCLASS:-auto}
preload:
only-apache: ${OPERATOR_CONFIG_PRELOAD_ONLY_APACHE:-true}
components:
@@ -68,6 +69,8 @@ spec:
milvus: ${OPERATOR_COMPONENT_MILVUS:-false}
# REGISTRY enabled or not
registry: ${OPERATOR_COMPONENT_REGISTRY:-false}
+ # REGISTRY enabled or not
+ seaweedfs: ${OPERATOR_COMPONENT_SEAWEEDFS:-false}
tls:
acme-registered-email: ${OPERATOR_CONFIG_TLSEMAIL:[email protected]}
acme-server-url: https://acme-v02.api.letsencrypt.org/directory
@@ -247,7 +250,17 @@ spec:
volume-size: ${REGISTRY_CONFIG_VOLUME_SIZE:-50}
auth:
username: ${REGISTRY_CONFIG_USERNAME:-opsuser}
- password: $REGISTRY_CONFIG_SECRET_PUSH_PULL
+ password: ${REGISTRY_CONFIG_SECRET_PUSH_PULL:-changeme-registry}
hostname: ${REGISTRY_CONFIG_HOSTNAME:-auto}
ingress:
- enabled: ${REGISTRY_CONFIG_INGRESS_ENABLED:-false}
+ enabled: ${REGISTRY_CONFIG_INGRESS_ENABLED:-false}
+ seaweedfs:
+ volume-size: ${STORAGE_SIZE_SEAWEEDFS:-60}
+ nuvolaris:
+ user: nuvolaris
+ password: ${SECRET_SEAWEEDFS_NUVOLARIS:-changeme-seaweedfs}
+ ingress:
+ s3-enabled: ${SEAWEEDFS_CONFIG_INGRESS_S3_ENABLED:-true}
+ s3-hostname: ${SEAWEEDFS_CONFIG_INGRESS_S3_HOSTNAME:-auto}
+ console-enabled: ${SEAWEEDFS_CONFIG_INGRESS_CONSOLE_ENABLED:-false}
+ console-hostname: ${SEAWEEDFS_CONFIG_INGRESS_CONSOLE_HOSTNAME:-auto}
diff --git a/setup/nuvolaris/opsfile.yml b/setup/nuvolaris/opsfile.yml
index 558beed..b03be40 100644
--- a/setup/nuvolaris/opsfile.yml
+++ b/setup/nuvolaris/opsfile.yml
@@ -23,14 +23,14 @@ vars:
CAT: '{{if eq .D ""}}true{{else}}cat{{end}}'
RETRY: 100
TIMEOUT: 10
- ETC:
+ ETC:
sh: if $WSK_INSECURE ; then echo "-i" ; else echo "" ; fi
CFG: "kubectl -n nuvolaris get wsk/controller"
SLEEP: "500"
env:
- KUBECONFIG:
- sh: |
+ KUBECONFIG:
+ sh: |
if test -e "$OPS_TMP/kubeconfig"
then echo "$OPS_TMP/kubeconfig"
else echo ~/.kube/config
@@ -42,7 +42,7 @@ tasks:
#desc: wait for apihost available
silent: true
env:
- BAR:
+ BAR:
sh: printf "%*s" {{.RETRY}} "" | tr ' ' '#'
cmds:
- |
@@ -61,10 +61,10 @@ tasks:
echo $APIHOST
wait-cm:
- desc: wait for an annotation in nuvolaris cm/config
+ desc: wait for an annotation in nuvolaris cm/config
silent: true
env:
- BAR:
+ BAR:
sh: printf "%*s" {{.RETRY}} "" | tr ' ' '#'
cmds:
- test -n "{{.JSONPATH}}" || die "use
JSONPATH=<cm/config-jsonpath-lookup>"
@@ -72,13 +72,13 @@ tasks:
N=0
RES=false
while [[ $N -lt {{.RETRY}} ]]
- do
+ do
ANNOT_VALUE="$(kubectl -n nuvolaris get cm/config -o
jsonpath='{{.JSONPATH}}')"
if [[ -z "$ANNOT_VALUE" ]]
- then
+ then
printf "\rwaiting for completing system initialization:
[${BAR:0:$((N++))}]"
sleep 5
- else
+ else
RES=true; break
fi
done
@@ -89,7 +89,7 @@ tasks:
desc: wait for an annotation in nuvolaris cm/config to be set and have a
specific value
silent: true
env:
- BAR:
+ BAR:
sh: printf "%*s" {{.RETRY}} "" | tr ' ' '#'
cmds:
- test -n "{{.JSONPATH}}" || die "use
JSONPATH=<cm/config-jsonpath-lookup>"
@@ -101,10 +101,10 @@ tasks:
N=0
RES=false
while [[ $N -lt {{.RETRY}} ]]
- do
+ do
ANNOT_VALUE="$(kubectl -n nuvolaris get cm/config -o
jsonpath='{.metadata.annotations.system_action_status}')"
if [[ -z "$ANNOT_VALUE" ]]
- then
+ then
printf "\rwaiting for completing system initialization:
[${BAR:0:$((N++))}]"
sleep 5
else
@@ -120,11 +120,11 @@ tasks:
silent: true
cmds:
- |
- export OPSDEV_APIHOST=$(kubectl --kubeconfig="$KUBECONFIG" -n nuvolaris
get cm/config -o jsonpath='{.metadata.annotations.apihost}')
+ export OPSDEV_APIHOST=$(ops util kubeget cm/config
.metadata.annotations.apihost)
export OPSDEV_USERNAME=nuvolaris
- export AUTH=$(kubectl --kubeconfig="$KUBECONFIG" -n nuvolaris get
wsk/controller -ojsonpath='{.spec.openwhisk.namespaces.nuvolaris}')
+ export AUTH=$(ops util kubeget wsk/controller
.spec.openwhisk.namespaces.nuvolaris)
echo Checking connection...
- retry -t 100 -m 600 $OPS -wsk {{.ETC}} --apihost "$OPSDEV_APIHOST"
--auth "$AUTH" namespace list
+ retry -t 100 -m 600 ops -wsk {{.ETC}} --apihost "$OPSDEV_APIHOST" --auth
"$AUTH" namespace list
export OPS_PASSWORD=$(kubectl -n nuvolaris get wsk/controller -ojsonpath
-ojsonpath='{.spec.nuvolaris.password}')
ops -login "$OPSDEV_APIHOST" "$OPSDEV_USERNAME"
OPSDEV_HOST_PROT="$(echo "$OPSDEV_APIHOST" | awk -F '://' '{print $1}')"
@@ -167,7 +167,7 @@ tasks:
MONGODB_URL="$(kubectl -n nuvolaris get cm/config -o
jsonpath='{.metadata.annotations.mongodb_url}')"
{{.RUN}} wsk {{.ETC}} action update hello/mongodb mongodb.js -p
mongodb_url "$MONGODB_URL"
- "{{.RUN}} wsk {{.ETC}} action invoke hello/mongodb -r | rg 'hello'"
-
+
redis:
silent: true
desc: redis test
@@ -202,7 +202,7 @@ tasks:
postgres:
silent: true
desc: postgres test
- cmds:
+ cmds:
- "{{.RUN}} wsk {{.ETC}} package update hello"
- |
POSTGRES_URL="$(kubectl -n nuvolaris get cm/config -o
jsonpath='{.metadata.annotations.postgres_url}')"
@@ -210,7 +210,7 @@ tasks:
- "{{.RUN}} wsk {{.ETC}} action invoke hello/postgres -r"
sleep:
- desc: sleep
+ desc: sleep
silent: true
cmds:
- "{{.RUN}} wsk action update sleep sleep.js --web=true --timeout 300000"
@@ -259,10 +259,12 @@ tasks:
then ops -random --str 8
else echo "{{.P}}"
fi
+ FLAGS: '{{or .F "--all"}}'
+
env:
- APIHOST:
+ APIHOST:
sh: echo "$OPERATOR_CONFIG_HOSTPROTOCOL://$OPERATOR_CONFIG_APIHOST"
- HOST:
+ HOST:
sh: echo
"$OPERATOR_CONFIG_HOSTPROTOCOL://{{.USR}}.$OPERATOR_CONFIG_APIHOST"
cmds:
#- test ! -e ~/.ops/{{.USR}}.password || die "User {{.USR}} already exists
- check .ops/{{.USR}}.password in your home for password"
@@ -272,7 +274,7 @@ tasks:
fi
- echo "Creating user {{.USR}} in $APIHOST"
- |
- ops admin adduser "{{.USR}}" "{{.USR}}@example.com" '{{.PSW}}' --all
+ ops admin adduser "{{.USR}}" "{{.USR}}@example.com" '{{.PSW}}' {{.FLAGS}}
sleep 15
- |
export OPS_PASSWORD="{{.PSW}}"
diff --git a/setup/nuvolaris/streamer/nginx-template.yaml
b/setup/nuvolaris/streamer/nginx-template.yaml
index 7202022..beb7bbc 100644
--- a/setup/nuvolaris/streamer/nginx-template.yaml
+++ b/setup/nuvolaris/streamer/nginx-template.yaml
@@ -21,10 +21,21 @@ metadata:
nginx.ingress.kubernetes.io/proxy-connect-timeout: "300"
nginx.ingress.kubernetes.io/proxy-read-timeout: "300"
nginx.ingress.kubernetes.io/proxy-send-timeout: "300"
+
+$T cert-manager.io/cluster-issuer: letsencrypt-prod
+$T nginx.ingress.kubernetes.io/force-ssl-redirect: "true"
+
name: nuvolaris-streamer-api-ingress
namespace: nuvolaris
+
spec:
ingressClassName: nginx
+
+$T tls:
+$T - hosts:
+$T - stream.${STREAMER_API_HOSTNAME:-localhost}
+$T secretName: streamer-api-tls
+
rules:
- host: stream.${STREAMER_API_HOSTNAME:-localhost}
http:
diff --git a/setup/nuvolaris/streamer/opsfile.yml
b/setup/nuvolaris/streamer/opsfile.yml
index 97a7a8a..9a0b666 100644
--- a/setup/nuvolaris/streamer/opsfile.yml
+++ b/setup/nuvolaris/streamer/opsfile.yml
@@ -16,13 +16,14 @@
# under the License.
version: '3'
-vars:
+vars:
VAR: ""
MSG: ""
VAL: ""
RETRY: 100
TIMEOUT: 15s
CONTEXT: ""
+ DRY: ""
env:
@@ -33,47 +34,50 @@ env:
else echo ~/.kube/config
fi
- STREAMER_API_HOSTNAME:
+ STREAMER_API_HOSTNAME:
sh: |
- ops util kubectl -- -n nuvolaris get ingress/apihost -o
jsonpath='{.spec.rules[0].host}'
-
+ ops util kubeget ingress/apihost .spec.rules[0].host
+
OW_APIHOST:
sh: |
- HOST=$(ops util kubectl -- -n nuvolaris get ingress/apihost -o
jsonpath='{.spec.rules[0].host}')
- if [ $OPERATOR_COMPONENT_INVOKER = true ];
+ HOST=$(ops util kubeget ingress/apihost .spec.rules[0].host)
+ if [ $OPERATOR_COMPONENT_INVOKER = true ];
then echo "$HOST"
else echo "http://controller:3233"
- fi
+ fi
INGRESS_TYPE:
sh: ops util ingress-type
tasks:
- boh:
- desc: echo a message
- silent: true
- cmds:
- - echo "$host.Name"
-
deploy:
silent: true
ignore_error: false
- desc: deploy the streamer
+ desc: deploy the streamer
+ vars:
+ T:
+ sh: |
+ if ops util kubeget wsk/controller .status.whisk_create.tls | rg
on >/dev/null
+ then echo ""
+ else echo "#"
+ fi
cmds:
- test -e ${INGRESS_TYPE}-template.yaml || die "No avalable template for
ingress type ${INGRESS_TYPE}."
- test -n "$IMAGES_STREAMER" || die "IMAGES_STREAMER is not set. Please
set it to the desired image version."
- envsubst -i streamer-template.yaml -o _streamer.yaml > /dev/null 2>&1
- - envsubst -i "${INGRESS_TYPE}-template.yaml" -o _ingress.yaml > /dev/null
2>&1
- - kubectl -n nuvolaris apply -f _streamer.yaml
+ - |
+ export T="{{.T}}"
+ envsubst -i "${INGRESS_TYPE}-template.yaml" -o _ingress.yaml > /dev/null
2>&1
+ - "{{.DRY}} kubectl -n nuvolaris apply -f _streamer.yaml"
#- cat _ingress.yaml
- - kubectl -n nuvolaris apply -f _ingress.yaml
+ - "{{.DRY}} kubectl -n nuvolaris apply -f _ingress.yaml"
- |
echo "Streamer API deployed with HOSTNAME:
stream.${STREAMER_API_HOSTNAME} and OW_APIHOST: ${OW_APIHOST}"
undeploy:
silent: true
- desc: undeploy the streamer
+ desc: undeploy the streamer
ignore_error: true
cmds:
- kubectl -n nuvolaris delete sts/nuvolaris-streamer-api
ing/nuvolaris-streamer-api-ingress
@@ -82,16 +86,16 @@ tasks:
update:
silent: true
- desc: update the streamer
+ desc: update the streamer
cmds:
- task: deploy
- kubectl -n nuvolaris rollout restart statefulset nuvolaris-streamer-api
- preconditions:
+ preconditions:
- sh: '[ $IMAGES_STREAMER != $CURRENT_STREAMER_VERSION ]'
msg: "Current nuvolaris streamer API stateful set it is already
updated to newest version. Request ignored."
env:
CURRENT_STREAMER_VERSION:
sh: |
echo "$(kubectl -n nuvolaris get pod/nuvolaris-streamer-api-0
-ojsonpath='{.spec.containers[0].image}')"
-
-
+
+
diff --git a/setup/nuvolaris/streamer/traefik-template.yaml
b/setup/nuvolaris/streamer/traefik-template.yaml
index bf85cd1..24c7cb0 100644
--- a/setup/nuvolaris/streamer/traefik-template.yaml
+++ b/setup/nuvolaris/streamer/traefik-template.yaml
@@ -17,14 +17,26 @@ apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
- ingressClassName: traefik
nginx.ingress.kubernetes.io/proxy-body-size: 1024m
traefik.ingress.kubernetes.io/transport.respondingTimeouts.idleTimeout:
"600"
traefik.ingress.kubernetes.io/transport.respondingTimeouts.readTimeout:
"600"
traefik.ingress.kubernetes.io/transport.respondingTimeouts.writeTimeout:
"600"
+
+$T cert-manager.io/cluster-issuer: letsencrypt-prod
+$T traefik.ingress.kubernetes.io/router.tls: "true"
+$T traefik.ingress.kubernetes.io/router.entrypoints: websecure,web
+
name: nuvolaris-streamer-api-ingress
namespace: nuvolaris
+
spec:
+ ingressClassName: traefik
+
+$T tls:
+$T - hosts:
+$T - stream.${STREAMER_API_HOSTNAME:-localhost}
+$T secretName: streamer-api-tls
+
rules:
- host: stream.${STREAMER_API_HOSTNAME:-localhost}
http:
@@ -35,4 +47,4 @@ spec:
port:
number: 8080
path: /
- pathType: Prefix
\ No newline at end of file
+ pathType: Prefix
diff --git a/ide/python/build-venv.sh
b/setup/nuvolaris/system-api/deploy/buildkit/buildkitd.toml
similarity index 60%
copy from ide/python/build-venv.sh
copy to setup/nuvolaris/system-api/deploy/buildkit/buildkitd.toml
index cf94ce5..37460c4 100644
--- a/ide/python/build-venv.sh
+++ b/setup/nuvolaris/system-api/deploy/buildkit/buildkitd.toml
@@ -1,4 +1,3 @@
-#!/bin/bash
# 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
@@ -15,23 +14,28 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
+#
+# =========================
+# Worker OCI (rootlesskit)
+# =========================
+[worker.oci]
+ enabled = true
+ rootless = true
+ no-process-sandbox = true
+ snapshotter = "overlayfs" # usa overlayfs se il kernel lo consente
-DIR="${1:?directory}"
-ZIP="${2:?zip file}"
-cd "$DIR"
-if ! test -d virtualenv
- then virtualenv virtualenv
-fi
-source virtualenv/bin/activate
-pip install --upgrade pip
-pip install -r requirements.txt
-virtualenv/bin/python -m pip uninstall -y -q setuptools wheel pip
-touch virtualenv/bin/activate
-if test -f "$ZIP"
- then rm "$ZIP"
-fi
-7zz a "$ZIP" -tzip virtualenv >/dev/null
-ls -l $ZIP
-date >virtualenv/date
+[worker.containerd]
+ enabled = false
+# =========================
+# Registry HTTP insicuro
+# =========================
+[registry."nuvolaris-registry-svc:5000"]
+ #insecure = true
+ http = true
+# =========================
+# Logging
+# =========================
+[log]
+ level = "trace"
\ No newline at end of file
diff --git a/setup/nuvolaris/system-api/opsfile.yml
b/setup/nuvolaris/system-api/opsfile.yml
index 79a2768..f5e1767 100644
--- a/setup/nuvolaris/system-api/opsfile.yml
+++ b/setup/nuvolaris/system-api/opsfile.yml
@@ -36,54 +36,99 @@ env:
SYS_API_CDB_HOST: couchdb
SYS_API_CDB_USER:
- sh: $OPS debug kube ctl CMD="-n nuvolaris get wsk/controller -o
jsonpath='{.spec.couchdb.admin.user}'"
+ #sh: ops util kubectl -- --kubeconfig "$KUBECONFIG" -n nuvolaris get
wsk/controller -o jsonpath='{.spec.couchdb.admin.user}'
+ sh: ops util kubeget wsk/controller .spec.couchdb.admin.user
SYS_API_CDB_PASSWORD:
- sh: $OPS debug kube ctl CMD="-n nuvolaris get wsk/controller -o
jsonpath='{.spec.couchdb.admin.password}'"
+ #sh: ops util kubectl -- --kubeconfig "$KUBECONFIG" -n nuvolaris get
wsk/controller -o jsonpath='{.spec.couchdb.admin.password}'
+ sh: ops util kubeget wsk/controller .spec.couchdb.admin.password
SYS_API_HOSTNAME:
- sh: $OPS debug kube ctl CMD="-n nuvolaris get ingress/apihost -o
jsonpath='{.spec.rules[0].host}'"
+ #sh: ops util kubectl -- --kubeconfig "$KUBECONFIG" -n nuvolaris get
ingress/apihost -o jsonpath='{.spec.rules[0].host}'
+ sh: ops util kubeget ingress/apihost .spec.rules[0].host
+
+ REGISTRY_PASS:
+ #sh: ops util kubectl -- --kubeconfig "$KUBECONFIG" -n nuvolaris get
cm/config -o jsonpath='{.metadata.annotations.registry_password}'
+ sh: ops util kubeget cm/config .metadata.annotations.registry_password
INGRESS_TYPE:
- sh: $OPS util ingress-type
+ sh: ops util ingress-type
tasks:
+ install-toml:
+ desc: Update the buildkitd.toml file config map
+ silent: true
+ cmds:
+ - task: remove-toml
+ - kubectl -n nuvolaris create configmap nuvolaris-buildkitd-conf
--from-file="$OPS_ROOT/setup/nuvolaris/system-api/deploy/buildkit/buildkitd.toml"
+
+ remove-toml:
+ desc: Remove the buildkitd.toml config map
+ silent: true
+ cmds:
+ - |
+ if kubectl -n nuvolaris get cm nuvolaris-buildkitd-conf >/dev/null
2>&1;
+ then kubectl -n nuvolaris delete configmap nuvolaris-buildkitd-conf
+ fi
+
+ install-secret:
+ desc: Create secret to push to internal registry
+ silent: true
+ cmds:
+ - task: remove-secret
+ - |
+ if ! kubectl -n nuvolaris get secret registry-pull-secret-int
>/dev/null 2>&1;
+ then kubectl -n nuvolaris create secret docker-registry
registry-pull-secret-int --docker-server=http://nuvolaris-registry-svc:5000
--docker-username=opsuser --docker-password=${REGISTRY_PASS}
+ fi
+
+ remove-secret:
+ desc: Delete secret to push to internal registry
+ silent: true
+ cmds:
+ - |
+ if kubectl -n nuvolaris get secret registry-pull-secret-int >/dev/null
2>&1;
+ then kubectl -n nuvolaris delete secret registry-pull-secret-int
+ fi
deploy:
silent: true
ignore_error: false
- desc: deploy the admin api
+ desc: deploy the admin api
cmds:
- test -e ${INGRESS_TYPE}-template.yaml || die "No avalable template for
ingress type ${INGRESS_TYPE}."
- test -n "$IMAGES_SYSTEMAPI" || die "IMAGES_SYSTEMAPI is not set. Please
set it to the desired image version."
- envsubst -i api-template.yaml -o _api.yaml > /dev/null 2>&1
- envsubst -i ${INGRESS_TYPE}-template.yaml -o _ingress.yaml > /dev/null
2>&1
- - $OPS debug kube ctl CMD="-n nuvolaris apply -f
$OPS_PWD/setup/nuvolaris/system-api/_api.yaml"
+ - kubectl -n nuvolaris apply -f
"$OPS_ROOT/setup/nuvolaris/system-api/_api.yaml"
#- cat _ingress.yaml
- - $OPS debug kube ctl CMD="-n nuvolaris apply -f
$OPS_PWD/setup/nuvolaris/system-api/_ingress.yaml"
+ - kubectl -n nuvolaris apply -f
"$OPS_ROOT/setup/nuvolaris/system-api/_ingress.yaml"
+ - task: install-toml
+ - task: install-secret
- |
echo "Admin API deployed with HOSTNAME: ${SYS_API_HOSTNAME}/system"
-
+
undeploy:
silent: true
desc: undeploy the admin api
- ignore_error: true
+ ignore_error: false
cmds:
- - $OPS debug kube ctl CMD="-n nuvolaris delete sts/nuvolaris-system-api
ing/nuvolaris-system-api-ingress svc/nuvolaris-system-api"
+ - task: remove-secret
+ - task: remove-toml
+ - kubectl -n nuvolaris delete sts/nuvolaris-system-api
ing/nuvolaris-system-api-ingress svc/nuvolaris-system-api
- |
echo "System Admin API undeployed"
-
+
update:
silent: true
desc: update the OpenServerless System Admin Api Stateful Set
cmds:
- task: deploy
- - $OPS debug kube ctl CMD="-n nuvolaris rollout restart statefulset
nuvolaris-system-api"
- preconditions:
+ - kubectl -n nuvolaris rollout restart statefulset nuvolaris-system-api
+ preconditions:
- sh: '[ $IMAGES_SYSTEMAPI != $CURRENT_API_VERSION ]'
msg: "Current OpenServerless System API stateful set it is already
updated to newest version. Request ignored."
env:
CURRENT_API_VERSION:
sh: |
- echo $($OPS debug kube ctl CMD="-n nuvolaris get
sts/nuvolaris-system-api
-ojsonpath='{.spec.template.spec.containers[0].image}'")
\ No newline at end of file
+ echo $(kubectl -n nuvolaris get sts/nuvolaris-system-api
-ojsonpath='{.spec.template.spec.containers[0].image}')
\ No newline at end of file
diff --git a/setup/opsfile.yml b/setup/opsfile.yml
index 44a1512..f4bd7f2 100644
--- a/setup/opsfile.yml
+++ b/setup/opsfile.yml
@@ -31,14 +31,14 @@ tasks:
vars:
PORTS: "{{ .PORTS | default \"\" }}"
cmds:
- - |
+ - |
{{if eq OS "windows"}}
$ports = "{{ .PORTS }}".Split(" ")
foreach ($entry in $ports) {
$parts = $entry -split "/"
$port = $parts[0]
$protocol = $parts[1].ToLower()
-
+
if ($protocol -eq "tcp" -and (Get-NetTCPConnection -LocalPort $port
-ErrorAction SilentlyContinue)) {
Write-Host "TCP Port $port is in use!" -ForegroundColor Red
exit 1
@@ -76,26 +76,39 @@ tasks:
done
{{end}}
- prereq:
- silent: true
- cmds:
- - exit 0
mini:
silent: true
desc: install miniops
+ vars:
+ APIHOST: '{{or ._apihost_ "http://miniops.me"}}'
cmds:
+ - echo '{{.APIHOST}}' | rg 'https?://(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]+/?'
>/dev/null || die "please spefify an accessibile http://host"
+ - task: _mini
+ vars:
+ APIHOST: '{{.APIHOST}}'
+ PROTO:
+ sh: echo '{{.APIHOST}}' | rg -o '(https?)://' -r '$1'
+ DOMAIN:
+ sh: echo '{{.APIHOST}}' | rg -o
'https?://((?:[a-zA-Z0-9-]+\.)+[a-zA-Z]+)/?' -r '$1'
+
+ _mini:
+ silent: true
+ cmds:
+ - echo APIHOST={{.APIHOST}}
+ - echo PROTO={{.PROTO}}
+ - echo DOMAIN={{.DOMAIN}}
- docker -v || die "Docker is not installed. Please install Docker
Desktop first."
- docker info 2>/dev/null >/dev/null || die "Docker is not running.
Please start Docker Desktop first."
- |
if test -z {{.__skip_check_cluster}}
- then
- if curl -sL http://miniops.me >/dev/null 2>/dev/null
+ then
+ if curl -sL {{.APIHOST}} >/dev/null 2>/dev/null
then
- if curl -sL http://miniops.me/api/info 2>/dev/null | jq -r
.description 2>/dev/null | rg OpenWhisk >/dev/null 2>/dev/null
+ if curl -sL {{.APIHOST}}/api/info 2>/dev/null | jq -r
.description 2>/dev/null | rg OpenWhisk >/dev/null 2>/dev/null
then
echo "*** Apache OpenServerless mini is already installed."
- echo "*** Login with: ops ide login devel http://miniops.me"
+ echo "*** Login with: ops ide login devel {{.APIHOST}}"
echo "*** You can find the password in .ops/devel.password in
your home directory"
echo "*** You can can uninstall and restart with: ops setup
docker delete"
exit 1
@@ -109,9 +122,10 @@ tasks:
fi
- ops setup docker check-space
- ops config slim
- - ops config apihost miniops.me --protocol=http
+ - ops config apihost '{{.DOMAIN}}' --protocol={{.PROTO}}
- ops setup devcluster
- ops setup nuvolaris streamer deploy
+ - ops setup nuvolaris system-api deploy
- ops setup nuvolaris add-user
devcluster:
@@ -126,18 +140,14 @@ tasks:
then {{.RUN}} ops setup docker delete
else
if test -z {{.__skip_check_ports}}
- then
+ then
task check-ports PORTS="{{ .PORTS }}"
fi
{{.RUN}} ops setup docker create
- if test -z {{.__skip_preload_images}}
- then
- {{.RUN}} ops setup docker preload
- fi
{{.RUN}} ops setup kubernetes create
{{.RUN}} ops setup nuvolaris login
config STATUS_LAST=devcluster
- fi
+ fi
cluster:
silent: true
@@ -150,8 +160,8 @@ tasks:
else
{{.RUN}} ops setup kubernetes create CONTEXT="{{._context_}}"
{{.RUN}} ops setup nuvolaris login
- config STATUS_LAST=cluster
- if test -n "{{._context_}}"
+ config STATUS_LAST=cluster
+ if test -n "{{._context_}}"
then config STATUS_CONTEXT="{{._context_}}"
fi
fi
@@ -171,32 +181,32 @@ tasks:
config STATUS_LAST=server STATUS_SERVER="{{._server_}}"
if test -n "{{._user_}}"
then config STATUS_USERNAME="{{._user_}}"
- fi
+ fi
fi
status:
silent: true
- cmds:
+ cmds:
- |
- case "$STATUS_LAST" in
+ case "$STATUS_LAST" in
(devcluster) {{.RUN}} ops setup devcluster --status ;;
(cluster) {{.RUN}} ops setup cluster "$STATUS_CONTEXT" --status ;;
- (server) {{.RUN}} ops setup server "$STATUS_SERVER"
"$STATUS_USERNAME" --status ;;
+ (server) {{.RUN}} ops setup server "$STATUS_SERVER"
"$STATUS_USERNAME" --status ;;
(*) echo nothing installed yet
esac
uninstall:
silent: true
- cmds:
+ cmds:
- |
- case "$STATUS_LAST" in
- (devcluster)
+ case "$STATUS_LAST" in
+ (devcluster)
{{.RUN}} ops setup devcluster --uninstall
config -r STATUS_LAST
;;
- (cluster)
- if test -n "$STATUS_CONTEXT"
- then
+ (cluster)
+ if test -n "$STATUS_CONTEXT"
+ then
{{.RUN}} ops setup cluster "$STATUS_CONTEXT" --uninstall
config -r STATUS_CONTEXT
else
@@ -204,16 +214,16 @@ tasks:
fi
config -r STATUS_LAST
;;
- (server)
+ (server)
if test -z "$STATUS_USERNAME"
- then
+ then
{{.RUN}} ops setup server "$STATUS_SERVER" --uninstall
else
{{.RUN}} ops setup server "$STATUS_SERVER" "$STATUS_USERNAME"
--uninstall
config -r STATUS_USERNAME
fi
- config -r STATUS_LAST STATUS_SERVER
- ;;
+ config -r STATUS_LAST STATUS_SERVER
+ ;;
(*) echo nothing installed yet
esac
diff --git a/update/opsfile.yml b/update/opsfile.yml
index 0488394..24d7165 100644
--- a/update/opsfile.yml
+++ b/update/opsfile.yml
@@ -33,7 +33,6 @@ env:
fi
tasks:
- hi: echo hi
cli:
desc: update the cli
@@ -61,6 +60,9 @@ tasks:
- config SECRET_POSTGRES_REPLICA="$(kubectl -n nuvolaris get
wsk/controller -o jsonpath='{.spec.postgres.admin.replica-password}')"
- config SECRET_POSTGRES_NUVOLARIS="$(kubectl -n nuvolaris get
wsk/controller -ojsonpath='{.spec.postgres.nuvolaris.password}')"
- config SECRET_NUVOLARIS_METADATA="$(kubectl -n nuvolaris get
wsk/controller -ojsonpath='{.spec.nuvolaris.password}')"
+ - config SECRET_MILVUS_ROOT="$(kubectl -n nuvolaris get wsk/controller
-ojsonpath='{.spec.milvus.password.root}')"
+ - config SECRET_MILVUS_S3="$(kubectl -n nuvolaris get wsk/controller
-ojsonpath='{.spec.milvus.password.s3}')"
+ - config REGISTRY_CONFIG_SECRET_PUSH_PULL="$(kubectl -n nuvolaris get
wsk/controller -ojsonpath='{.spec.registry.auth.password}')"
apply:
desc: apply updated config
@@ -68,7 +70,7 @@ tasks:
- $OPS update secrets
- $OPS setup kubernetes runtimes
- $OPS setup kubernetes instance
- - $OPS setup kubernetes services
+ - $OPS setup kubernetes wait-services
- $OPS setup nuvolaris login
operator:
diff --git a/util/docopts.md b/util/docopts.md
index 3173608..1ab1629 100644
--- a/util/docopts.md
+++ b/util/docopts.md
@@ -24,6 +24,7 @@ OpenServerless Utilities
```text
Usage:
+ util apihost
util system
util update-cli
util check-operator-version <version>
@@ -33,6 +34,7 @@ Usage:
util no-user-secrets <username>
util kubectl <args>...
util kubeconfig
+ util kubeget <object> <jsonpath>
util config <configjson> [--override] [--showhelp]
util clean
util upload [<folder>] [--batchsize=<batchsize>] [--verbose] [--clean]
@@ -42,21 +44,22 @@ Usage:
util ingress-type
util edit [<plugin>]
util link-plugin <plugin>
- util docker-proxy [<port>] [<host>] [--remove]
```
## Commands
```
+- apihost current apihost
- system system info (<os>-<arch> in Go format)
- update-cli update the cli downloading the binary
- check-operator-version check if you need to update the operator
-- secrets generate system secrets
+- secrets generate system secrets
- nosecrets remove system secrets
- user-secrets generate user secrets for the given user
- no-user-secrets remove user secrets for the given user
- kubectl execute kubectl on current kubeconfig
- kubeconfig export OVERWRITING current kubeconfig to
~/.kube/config
+- kubeget extract info from an object with a jsonpath
- config update configuration file interactively
- clean clean up the web bucket
- upload uploads a folder to the web bucket in
OpenServerless.
@@ -66,7 +69,6 @@ Usage:
- ingress-type return the ingress type
- edit edit (with vscode) the current tasks or a plugin
- link-plugin link the <plugin> in current directory to the
global list
-- docker-proxy launch (or remove) in docker a proxy listening in
public <port> (default 8080) to the <host> (default devel.miniops.me)
```
## Options
diff --git a/util/freeze/opsfile.yml b/util/freeze/opsfile.yml
new file mode 100644
index 0000000..5ebb6b4
--- /dev/null
+++ b/util/freeze/opsfile.yml
@@ -0,0 +1,176 @@
+version: 3
+
+vars:
+ CLUSTER: nuvolaris
+ KIND_CLUSTER: '{{.CLUSTER}}-control-plane'
+ BASE:
+ sh: echo ~/.ops
+ IMAGES:
+ sh: >
+ echo {{.BASE}}/{{OS}}-{{ARCH}}/images
+ KIND_IMAGE:
+ sh: >
+ awk '/image:/{print $2}' $OPS_ROOT/setup/docker/kind.yaml | tee
_docker.lst
+
+tasks:
+
+ docker-list:
+ silent: true
+ desc: list docker images
+ cmds:
+ - docker inspect {{.KIND_CLUSTER}} 2>/dev/null | jq -r '.[0].Config.Image'
+
+ kind-list:
+ silent: true
+ env:
+ CLU: "{{.KIND_CLUSTER}}"
+ desc: list images in kindes
+ cmds:
+ - awk '/image:/ {print $2}' $OPS_ROOT/setup/docker/ingress-deploy.yaml |
tee _kind.lst
+ - >
+ docker exec -it "$CLU" crictl images 2>/dev/null
+ | awk 'NR > 1 &&
!/^(registry.k8s.io\/(kube-|coredns|etc|pause|ingress-nginx)|docker.io\/kindest\/)/
{print $1 ":" $2 }'
+ | tee _kind.lst
+
+ docker-save:
+ silent: true
+ desc: save images in docker
+ cmds:
+ - docker inspect {{.KIND_CLUSTER}} | jq -r '.[0].Config.Image'
>_docker.lst
+ - mkdir -p {{.IMAGES}}/docker
+ - |
+ cat _docker.lst | while read img
+ do
+ file={{.IMAGES}}/docker/$(base64 -e "$img")
+ if test -e "$file"
+ then echo "already saved $img.{{ARCH}} "
+ else echo ">>> Saving: $img"
+ if docker pull --platform linux/{{ARCH}} "$img"
+ then echo "OK: save $file"
+ else echo "*** FAIL: pull $img"
+ fi
+ if docker save "$img" -o "$file"
+ then echo "OK: save $file"
+ else echo "*** FAIL: save $file"
+ fi
+ fi
+ done
+
+ kind-save:
+ silent: true
+ desc: list images in kindes
+ env:
+ CLU: "{{.KIND_CLUSTER}}"
+ cmds:
+ - awk '/image:/ {print $2}' $OPS_ROOT/setup/docker/ingress-deploy.yaml >
_kind.lst
+ - >
+ docker exec -it "$CLU" crictl images 2>/dev/null
+ | awk 'NR > 1 &&
!/^(registry.k8s.io\/(kube-|coredns|etc|pause|ingress-nginx)|docker.io\/kindest\/)/
{print $1 ":" $2 }'
+ >> _kind.lst
+ - mkdir -p {{.IMAGES}}/kind
+ - |
+ cat _kind.lst | while read img
+ do
+ file={{.IMAGES}}/kind/"$(base64 -e "$img")"
+ if test -e "$file"
+ then echo "already saved $img"
+ else echo ">>> Saving: {{ARCH}} $img"
+ if ! docker pull --platform linux/{{ARCH}} "$img"
+ then echo "*** FAIL pull $img" ; continue
+ fi
+ if ! docker save "$img" -o "$file"
+ then echo "*** FAIL save $file" ; continue
+ fi
+ echo "OK: save $file"
+ fi
+ done
+
+ image-save:
+ desc: save images
+ cmds:
+ - kind get clusters | grep {{.CLUSTER}} || die "please setup an ops
cluster first"
+ - task: docker-save
+ - task: kind-save
+
+ image-list:
+ silent: true
+ desc: list images
+ cmds:
+ - rm -f _images.lst
+ - |
+ for dir in docker kind
+ do for file in {{.IMAGES}}/$dir/*
+ do if test -e "$file"
+ then
+ b64=$(basename "$file")
+ img=$(base64 -d "${b64}")
+ echo $dir/$img
+ echo $img >>_images.lst
+ fi
+ done
+ done
+
+ image-clean:
+ prompt: "are you sure you wnat to remote images fron disk"
+ silent: true
+ desc: clean images
+ cmds:
+ - rm -f -v {{.IMAGES}}/docker/* {{.IMAGES}}/kind/*
+
+ docker-load:
+ silent: true
+ desc: load disk images in docker
+ cmds:
+ - |
+ for file in {{.IMAGES}}/docker/*
+ do
+ b64=$(basename "$file")
+ img=$(base64 -d "${b64#*-}")
+ echo Docker: loading "$img"
+ docker load -i "$file"
+ #docker tag $(awk '{print $4}' _image) $img
+ docker tag ${img#*@} ${img%@*}
+ done
+ status:
+ - test -z "$(ls {{.IMAGES}}/docker/* 2>/dev/null)"
+
+ kind-load:
+ silent: true
+ desc: load disk images in kind
+ cmds:
+ - |
+ for file in {{.IMAGES}}/kind/*
+ do
+ b64="$(basename "$file")"
+ img="$(base64 -d "${b64#*-}")"
+ echo "Kind: loading $img"
+ docker exec -i {{.CLUSTER}}-control-plane ctr --namespace=k8s.io
images import --snapshotter=overlayfs - < "$file"
+ done
+ echo 'Images loaded:'
+ - task: kind-list
+ status:
+ - test -z "$(ls {{.IMAGES}}/kind/* 2>/dev/null)"
+
+ test-clean:
+ ignore_errors: true
+ cmds:
+ - task: docker-clean
+ - kind delete cluster --name=test
+
+ test-compare:
+ - task: docker-list
+ - task: kind-list
+ - task: image-list
+ - cat _docker.lst _kind.lst | sort >_loaded.lst
+ - sort <_images.lst >_saved.lst
+ - echo "Comparing differences loaded and saved"
+ - diff _loaded.lst _saved.lst
+
+ test:
+ - task: test-clean
+ - task: docker-load
+ - kind create cluster --name=test --image={{.KIND_IMAGE}}
+ - task: kind-load
+ - task: test-compare
+ - task: test-clean
+
diff --git a/util/kube/opsfile.yml b/util/kube/opsfile.yml
index 129f03c..5d16367 100644
--- a/util/kube/opsfile.yml
+++ b/util/kube/opsfile.yml
@@ -33,7 +33,7 @@ env:
tasks:
waitfor:
- desc: wait for an object matching a condition
+ desc: wait for an object matching a condition
silent: true
cmds:
- test -n "{{.OBJ}}" || die "use OBJ=<pod/pod-name>"
@@ -42,14 +42,14 @@ tasks:
N=0
RES=false
while [[ $N -lt {{.RETRY}} ]]
- do
+ do
if kubectl -n nuvolaris wait --for="{{.FOR}}" "{{.OBJ}}"
--timeout="{{.TIMEOUT}}s"
- then RES=true; break
+ then RES=true; break
else echo "$((N++)) Waiting {{.OBJ}} for {{.FOR}}"
sleep "{{.SLEEP}}s"
fi
done
- $RES
+ $RES
wait:
desc: wait for a value matching the given jsonpath on the specific
resources under the namespace nuvolaris
@@ -61,17 +61,17 @@ tasks:
N=0
RES=false
while [[ $N -lt {{.RETRY}} ]]
- do
+ do
MATCHING_VALUE="$(kubectl -n nuvolaris get {{.OBJECT}} -o
jsonpath='{{.JSONPATH}}')"
if [[ -z "$MATCHING_VALUE" ]]
- then
+ then
echo "$((N++)) Waiting for {{.JSONPATH}} to be non empty value"
sleep 5
- else
+ else
RES=true; break
fi
done
- $RES
+ $RES
export:
desc: exporting NAMEd kubeconfig to specified FILE
@@ -80,7 +80,7 @@ tasks:
- test -e "$OPS_TMP/{{.NAME}}.kubeconfig" || die "no {{.NAME}} kubeconfig"
- |
FILE="$(realpath {{.FILE}})"
- cp "$OPS_TMP/kubeconfig" "$FILE"
+ cp "$OPS_TMP/kubeconfig" "$FILE"
import:
desc: importing FILE to the NAMEd kubeconfig
diff --git a/util/opsfile.yml b/util/opsfile.yml
index eacf8af..3d7e00e 100644
--- a/util/opsfile.yml
+++ b/util/opsfile.yml
@@ -36,7 +36,7 @@ tasks:
if {{.__showhelp}}
then FLAGS="$FLAGS --showhelp"
fi
- if {{.__override}}
+ if {{.__override}}
then FLAGS="$FLAGS --override"
fi
bun config/configurator.js $(opspath {{._configjson_}}) $FLAGS
@@ -47,6 +47,12 @@ tasks:
cmds:
- echo "{{OS}}-{{ARCH}}"
+ apihost:
+ desc: current apihost
+ silent: true
+ cmds:
+ - ops -wsk property get | awk '/whisk API host/{print $4}'
+
update-cli:
desc: update CLI
silent: true
@@ -70,7 +76,7 @@ tasks:
else echo "cannot auto update ops - update it manually"
echo "please run 'curl -sL bit.ly/get-ops | bash'"
fi
- else
+ else
echo "skipping rename $OPS_TMP/ops{{.EXE}} $OPS_CMD"
fi
@@ -92,6 +98,7 @@ tasks:
- config SECRET_POSTGRES_ADMIN="$(random --str 12)"
SECRET_POSTGRES_REPLICA="$(random --str 12)"
SECRET_POSTGRES_NUVOLARIS="$(random --str 12)"
- config SECRET_ETCD_ROOT="$(random --str 12)"
SECRET_MILVUS_ROOT="$(random --str 12)" SECRET_MILVUS_S3="$(random --str 12)"
SECRET_MILVUS_NUVOLARIS="$(random --str 12)"
- config SECRET_NUVOLARIS_METADATA="$(random --str 12)"
+ - config SECRET_SEAWEEDFS_NUVOLARIS="$(random --str 12)"
- echo "Generated $(config -d | rg SECRET_ | wc -l) secrets."
user-secrets:
@@ -144,7 +151,7 @@ tasks:
cmds:
- |
# no quote here - syntax array generated by docps
- args={{._args_}}
+ args={{._args_}}
# exanded and assigned to positional parameter
set -- ${args[@]}
# removing the '--' at the beginning required to pass extra flags
@@ -159,6 +166,21 @@ tasks:
else echo ~/.kube/config
fi
+ kubeget:
+ desc: extract informations from
+ silent: true
+ cmds:
+ - kubectl -n nuvolaris get "$OBJECT" -o jsonpath="{$JSONPATH}"
+ env:
+ JSONPATH: '{{._jsonpath_}}'
+ OBJECT: '{{._object_}}'
+ KUBECONFIG:
+ sh: |-
+ if test -e "$OPS_TMP/kubeconfig"
+ then echo "$OPS_TMP/kubeconfig"
+ else echo ~/.kube/config
+ fi
+
kubeconfig:
silent: true
prompt: Are you sure? I am overwriting your ~/.kube/config
@@ -166,7 +188,7 @@ tasks:
cmds:
- |
if test -e "$OPS_TMP/kubeconfig"
- then
+ then
if test -e ~/.kube/config
then BKP=~/.kube/config.$(datefmt -f ms)
mv ~/.kube/config $(realpath $BKP)
@@ -199,7 +221,7 @@ tasks:
env:
FOLDER_PATH:
sh: |
- if test -n "{{._folder_}}"
+ if test -n "{{._folder_}}"
then opspath "{{._folder_}}"
else opspath .
fi
@@ -257,30 +279,6 @@ tasks:
exit 1
fi
- docker-proxy:
- desc: create in docker a proxy to expose miniops.me (or others)
- silent: true
- vars:
- PORT: '{{or ._port_ "8080"}}'
- HOST: '{{or ._host_ "devel.miniops.me"}}'
- NGINX_CONF: >
- server {
- listen 80;
- location / {
- proxy_pass http://nuvolaris-control-plane:80;
- proxy_set_header Host {{.HOST}};
- }
- }
- cmds:
- - |
- if {{.__remove}}
- then docker rm docker-proxy-{{.PORT}} -f
- else
- if docker run -d --name docker-proxy-{{.PORT}} -p {{.PORT}}:80
--network kind nginx:alpine sh -c \
- "echo '{{.NGINX_CONF}}' > /etc/nginx/conf.d/default.conf && nginx
-g 'daemon off;'"
- then echo "docker-proxy started on port {{.PORT}} to http://{{.HOST}}"
- else echo "Cannot start docker-proxy-{{.PORT}} - either the port is
busy or another instance is running, remove it"
- fi
- fi
-
+ freeze:
+ desc: freeze util