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 1cbae59 sync to main
1cbae59 is described below
commit 1cbae59d6c6e5f235801d742fa3456cf9dfcc8ec
Author: Michele Sciabarra <“[email protected]”>
AuthorDate: Thu Mar 26 09:42:55 2026 +0000
sync to main
---
ide/deploy/bun.lockb | Bin
ide/deploy/deploy.js | 5 +-
ide/docopts.md | 3 +-
ide/opsfile.yml | 29 +++++--
opsroot.json | 39 ++++++---
setup/devcontainer/deployment.yaml | 110 ++++++++++++++++++++++++
setup/devcontainer/opsfile.yml | 167 +++++++++++++++++++++++++++++++++++++
setup/docker/kind.yaml | 10 ++-
setup/docker/opsfile.yml | 25 ++++--
setup/kubernetes/DEBUG.txt | 25 ++++++
setup/kubernetes/operator.yaml | 5 +-
setup/kubernetes/opsfile.yml | 41 +++++----
setup/opsfile.yml | 2 +-
util/docopts.md | 5 +-
util/freeze/findimages.js | 50 +++++++++++
util/freeze/opsfile.yml | 42 +++++++---
util/opsfile.yml | 7 ++
util/stdtext.js | 23 +++++
18 files changed, 530 insertions(+), 58 deletions(-)
diff --git a/ide/deploy/bun.lockb b/ide/deploy/bun.lockb
old mode 100755
new mode 100644
diff --git a/ide/deploy/deploy.js b/ide/deploy/deploy.js
index 28f16bc..628814a 100644
--- a/ide/deploy/deploy.js
+++ b/ide/deploy/deploy.js
@@ -41,7 +41,10 @@ async function exec(cmd) {
cwd: process.env.OPS_PWD,
stdio: ["inherit", "inherit", "inherit"],
});
- await proc.exited;
+ const code = await proc.exited;
+ if (code !== 0) {
+ throw new Error(`command failed (${code}): ${cmd}`);
+ }
}
async function extractArgs(files) {
diff --git a/ide/docopts.md b/ide/docopts.md
index 8b35feb..1c157ef 100644
--- a/ide/docopts.md
+++ b/ide/docopts.md
@@ -24,7 +24,7 @@ OpenServerless Ide Development Utilities.
```text
Usage:
- ide login [<username>] [<apihost>] [--pin]
+ ide login [<username>] [<apihost>] [--pin] [--mode=<mode>]
ide devel [--fast] [--dry-run]
ide deploy [<action>|--packages|--web] [--dry-run]
ide undeploy [<action>] [--dry-run]
@@ -65,4 +65,5 @@ Usage:
--web Only deploy web folder, skip packages
--fast Skip the initial deployment step and go in incremental update
mode
--pin Pin the current auth in the .env to check you are not
deploying on the wrong user
+--mode this will load from .env.<mode> after .env
```
diff --git a/ide/opsfile.yml b/ide/opsfile.yml
index 75d28e8..2d6e65c 100644
--- a/ide/opsfile.yml
+++ b/ide/opsfile.yml
@@ -43,7 +43,7 @@ tasks:
silent: true
vars:
MSG: |
- This command must be run inside a devcontainer.
+ This command on windows requires a devcontainr
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'.
@@ -137,7 +137,7 @@ tasks:
login:
- silent: false
+ silent: true
desc: login in you OpenServerless host
cmds:
- |
@@ -145,6 +145,11 @@ tasks:
if test -e "$OPS_PWD/.env"
then source "$OPS_PWD/.env"
fi
+ if [ -n "{{.__mode}}" ] && [ -e "$OPS_PWD/.env.{{.__mode}}" ]
+ then
+ echo "Loading .env.{{.__mode}}"
+ source "$OPS_PWD/.env.{{.__mode}}"
+ fi
if test -n "$OPS_USERNAME"
then echo "Please use OPS_USER, OPS_USERNAME is deprecated"
fi
@@ -164,10 +169,8 @@ tasks:
fi
else
export OPSDEV_USERNAME="{{._username_}}"
- if test -e "$OPS_PWD/.env.{{._username_}}"
- then source "$OPS_PWD/.env.{{._username_}}"
- fi
fi
+
if test -z "{{._apihost_}}"
then
if test -z "$OPS_APIHOST"
@@ -188,21 +191,29 @@ tasks:
then
OPSDEV_HOST_PROT="$(echo "$OPSDEV_APIHOST" | awk -F '://' '{print
$1}')"
OPSDEV_HOST_URL="$(echo "$OPSDEV_APIHOST" | awk -F '://' '{print
$2}')"
+ OPSDEV_STREAM="${OPSDEV_APIHOST/\/\////stream.}"
+ OPSDEV_S3="${OPSDEV_APIHOST/\/\////s3.}"
+ OPSDEV_HOST="$OPSDEV_HOST_PROT://$OPSDEV_USERNAME.$OPSDEV_HOST_URL"
config OPSDEV_APIHOST="$OPSDEV_APIHOST"
config OPSDEV_USERNAME="$OPSDEV_USERNAME"
- config
OPSDEV_HOST="$OPSDEV_HOST_PROT://$OPSDEV_USERNAME.$OPSDEV_HOST_URL"
+ config OPSDEV_HOST="$OPSDEV_HOST"
+ config OPSDEV_S3="$OPSDEV_S3"
+ config OPSDEV_STREAM="$OPSDEV_STREAM"
+ config VITE_OPSDEV_STREAM="$OPSDEV_STREAM"
+ config VITE_OPSDEV_S3="$OPSDEV_S3"
+ config VITE_OPSDEV_HOST="$OPSDEV_HOST"
+ config VITE_OPSDEV_APIHOST="$OPSDEV_APIHOST"
source ~/.wskprops
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
+ rg -v "AUTH_CHECK=" >$OPS_PWD/.env $OPS_PWD/.env.$$
echo "AUTH_CHECK=$AUTH" >>$OPS_PWD/.env
+ rm $OPS_PWD/.env.$$
fi
-
-
poll:
silent: true
desc: poll activation logs
diff --git a/opsroot.json b/opsroot.json
index 677fac3..1c8a1d9 100644
--- a/opsroot.json
+++ b/opsroot.json
@@ -1,15 +1,30 @@
{
- "version": "0.1.0-2409121919.dev",
- "config": {
- "ops": {
- "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.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.2512101357"
- }
+ "version": "0.1.0-2409121919.dev",
+ "config": {
+ "ops": {
+ "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": {
+ "standalone":
"ghcr.io/nuvolaris/openwhisk-controller:3.1.0-mastrogpt.2402101445",
+ "operator":
"registry.hub.docker.com/apache/openserverless-operator:0.1.0-incubating.2603190945",
+ "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.2512101357",
+ "devcontainer":
"apache/openserverless-devcontainer:0.1.0-incubating.2603111653",
+ "ingress": "registry.k8s.io/ingress-nginx/controller:v1.7.0",
+ "couchdb": "docker.io/apache/couchdb:2.3",
+ "etcd": "docker.io/bitnamilegacy/etcd:3.5.17-debian-12-r0",
+ "redis": "docker.io/bitnamilegacy/redis:8.2.1",
+ "seaweedfs": "docker.io/chrislusf/seaweedfs:3.97",
+ "busybox":"docker.io/library/busybox:1.36.0",
+ "registry": "docker.io/library/registry:3.0.0",
+ "milvus": "docker.io/milvusdb/milvus:v2.5.2",
+ "nginx": "docker.io/nginxinc/nginx-unprivileged:1.24",
+ "pgvector": "docker.io/pgvector/pgvector:pg16",
+ "kubegres": "docker.io/reactivetechio/kubegres:1.18",
+ "ferretdb": "ghcr.io/nuvolaris/ferretdb:1.6.0",
+ "rbacproxy": "registry.k8s.io/kubebuilder/kube-rbac-proxy:v0.14.1"
}
+ }
}
diff --git a/setup/devcontainer/deployment.yaml
b/setup/devcontainer/deployment.yaml
new file mode 100644
index 0000000..c231209
--- /dev/null
+++ b/setup/devcontainer/deployment.yaml
@@ -0,0 +1,110 @@
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+ name: ssh-devcontainer
+ namespace: nuvolaris
+ labels:
+ app: ssh-devcontainer
+spec:
+ serviceName: ssh-devcontainer
+ replicas: 1
+ selector:
+ matchLabels:
+ app: ssh-devcontainer
+ template:
+ metadata:
+ labels:
+ app: ssh-devcontainer
+ spec:
+ hostname: ssh-devcontainer
+ volumes:
+ - name: workspace
+ hostPath:
+ path: /workspace
+ - name: nginx-config
+ configMap:
+ name: nginx-proxy-config
+ containers:
+ - name: devcontainer
+ image: $IMAGE
+ ports:
+ - containerPort: 2222
+ name: ssh
+ protocol: TCP
+ securityContext:
+ runAsUser: $USERID
+ runAsGroup: $USERID
+ volumeMounts:
+ - name: workspace
+ mountPath: /home/workspace
+ env:
+ - name: OPS_USER
+ value: $OPS_USER
+ - name: OPS_PASSWORD
+ value: $OPS_PASSWORD
+ - name: OPS_APIHOST
+ value: $OPS_APIHOST
+ - name: DEBIAN_FRONTEND
+ value: noninteractive
+ - name: SSHKEY
+ valueFrom:
+ secretKeyRef:
+ name: ssh-secret
+ key: authorized_keys
+ - name: reverse-proxy
+ image: nginx:alpine
+ ports:
+ - containerPort: 80
+ name: http
+ protocol: TCP
+ command: ["nginx", "-g", "daemon off;"]
+ volumeMounts:
+ - name: nginx-config
+ mountPath: /etc/nginx/nginx.conf
+ subPath: nginx.conf
+ readOnly: true
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+ name: nginx-proxy-config
+ namespace: nuvolaris
+data:
+ nginx.conf: |
+ events {
+ worker_connections 1024;
+ }
+ http {
+ client_max_body_size 1g;
+
+ server {
+ listen 80;
+ server_name miniops.me *.miniops.me;
+
+ location / {
+ proxy_pass
http://ingress-nginx-controller.ingress-nginx.svc.cluster.local;
+ proxy_set_header Host $$host;
+ proxy_set_header X-Real-IP $$remote_addr;
+ proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for;
+ proxy_set_header X-Forwarded-Proto http;
+ }
+ }
+ }
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: ssh-devcontainer
+ namespace: nuvolaris
+ labels:
+ app: ssh-devcontainer
+spec:
+ type: NodePort
+ selector:
+ app: ssh-devcontainer
+ ports:
+ - port: 2222
+ targetPort: 2222
+ nodePort: 30222
+ protocol: TCP
+ name: ssh
diff --git a/setup/devcontainer/opsfile.yml b/setup/devcontainer/opsfile.yml
new file mode 100644
index 0000000..0c862ea
--- /dev/null
+++ b/setup/devcontainer/opsfile.yml
@@ -0,0 +1,167 @@
+version: "3"
+
+vars:
+ UID:
+ sh: 'echo {{ if eq OS "windows" }}1000{{ else }}$(id -u){{ end }}'
+ GID:
+ sh: 'echo {{ if eq OS "windows" }}1000{{ else }}$(id -g){{ end }}'
+ SSHDIR:
+ sh: echo ~/.ssh | replace -s \\ -r / --stdin
+ SSHKEY:
+ sh: echo {{.SSHDIR}}/id_miniops
+ DRY: ""
+ EXTRA: ""
+
+
+env:
+ KUBECONFIG:
+ sh: |-
+ if test -e "$OPS_TMP/kubeconfig"
+ then echo "$OPS_TMP/kubeconfig"
+ else echo ~/.kube/config
+ fi
+
+tasks:
+
+ vars:
+
+ gen-key:
+ silent: true
+ desc: generating an internal ssh key
+ cmds:
+ - |
+ if ! test -e "{{.SSHKEY}}"
+ then mkdir -p "{{.SSHDIR}}"
+ echo Generating key {{.SSHKEY}}
+ ssh-keygen -q -a 100 -t ed25519 -a 100 -N '' -f "{{.SSHKEY}}" -C
"miniops key"
+ else
+ echo Using {{.SSHKEY}}
+ fi
+ - |
+ touch "{{.SSHDIR}}/config"
+ if ! rg "Host miniops" ~/.ssh/config >/dev/null
+ then echo Adding miniops entry in ssh config
+ echo -e "\nHost miniops\n Hostname localhost\n Port 2222\n User
devel\n StrictHostKeyChecking no\n UserKnownHostsFile=/dev/null\n
IdentityFile ~/.ssh/id_miniops\n" >> ~/.ssh/config
+ else
+ echo Found miniops entry in ssh config
+ fi
+ - |
+ if rg "miniops key" "{{.SSHDIR}}/authorized_keys" 2>/dev/null >/dev/null
+ then
+ echo Access already added
+ else
+ cat "{{.SSHKEY}}.pub" >>"{{.SSHDIR}}/authorized_keys"
+ echo Added key for external Access
+ {{if ne OS "windows"}}
+ chmod 0700 "{{.SSHDIR}}"
+ chmod 0600 "{{.SSHDIR}}/authorized_keys"
+ {{end}}
+ fi
+
+ deploy:
+ silent: true
+ desc: deploy the devcontainer in kubernetes
+ env:
+ OPS_APIHOST: http://miniops.me
+ OPS_USER: devel
+ OPS_PASSWORD:
+ sh: cat ~/.ops/devel.password
+ cmds:
+ - ops util apihost | rg miniops.me || die "devcontainer requires
miniops.me"
+ - task: gen-key
+ - >
+ kubectl -n nuvolaris create secret generic ssh-secret
+ --from-literal=authorized_keys="$(cat {{.SSHKEY}}.pub)" 2>/dev/null
|| die "devcontainer already exists"
+ - |
+ export IMAGE="{{.IMAGES_DEVCONTAINER}}"
+ envsubst < deployment.yaml >_deployment.yaml
+ kubectl apply -f _deployment.yaml
+ - ops setup kubernetes wait-pod SELECTOR="-l app=ssh-devcontainer"
COND=false FILE=_devcontainer
+ - >
+ retry -t 100 -m 600 ssh miniops exit 2>&1
+ | awk '{s=""; for(i=1;i<=NR;i++) s=s"#"; printf "\rwaiting for ssh:
[%s]", s; fflush()}'
+ - echo -e "\nyou can now connect to the devcontainer with 'ssh miniops'"
+
+ undeploy:
+ silent: true
+ desc: undeploy the devcontainer in kubernetes
+ cmds:
+ - kubectl -n nuvolaris delete sts/ssh-devcontainer secret/ssh-secret
+ - echo Please remove the Host miniops entry from your ~/.ssh/config file
if present
+
+ kind-load:
+ silent: true
+ desc: load the devcontainer image from docker to kind to avoid pulling
from outside
+ cmds:
+ - kind load docker-image {{.IMAGES_DEVCONTAINER}} --name nuvolaris
+
+ docker-run:
+ desc: run the ssh-devcontainer in docker with W=<workspace absolute path>
+ silent: true
+ requires: { vars: [W]}
+ vars:
+ EXTRA: #"--entrypoint=/bin/bash -ti"
+ cmds:
+ - test -e "$OPS_PWD/workspace/package.json" || die "mising workdpace
folder with starter"
+ - test -e ~/.ssh/id_rsa.pub || die "please generate an ssh key with
'ssk-keygen -t rsa'"
+ - echo "{{.W}}" | rg '^/' || die "W=<absolute path> required"
+ - docker rm -f ssh-devcontainer 2>/dev/null
+ - >
+ {{.DRY}} docker run
+ --hostname ssh-devcontainer
+ --name ssh-devcontainer --rm
+ -e SSHKEY="$(cat "{{.SSHKEY}}")"
+ -e USERID={{.UID}}
+ --mount "type=bind,src={{.W}},dst=/home/workspace"
+ -p 2223:2222
+ {{.EXTRA}}
+ {{.IMAGES_DEVCONTAINER}}
+
+ connect:
+ silent: true
+ desc: specify U=<user> and H=<host> to connect a remote devcontainer
+ requires:
+ vars: [H,U]
+ cmds:
+ - echo Connecting to {{.U}}@{{.H}}
+ - |
+ if ! test -e "{{.SSHKEY}}.pub"
+ then scp "{{.U}}@{{.H}}:.ssh/id_miniops" "{{.SSHKEY}}" && ssh-keygen -f
"{{.SSHKEY}}" -y >"{{.SSHKEY}}.pub"
+ fi
+ if test -e "{{.SSHKEY}}.pub"
+ then echo Found "{{.SSHKEY}}"
+ else echo "Remote user has not a miniops configured" ; exit 1
+ fi
+ - |
+ if ! rg '^Host miniops$' "{{.SSHDIR}}/config" >/dev/null
+ then cat <<EOF >>"{{.SSHDIR}}/config"
+
+ Host miniops
+ ProxyJump remote-miniops
+ HostName localhost
+ Port 2222
+ User devel
+ IdentityFile ~/.ssh/id_miniops
+ StrictHostKeyChecking no
+ UserKnownHostsFile /dev/null
+ EOF
+ else
+ echo Found ssh config miniops
+ fi
+ - |
+ if ! rg '^Host remote-miniops$' "{{.SSHDIR}}/config" >/dev/null
+ then cat <<EOF >>"{{.SSHDIR}}/config"
+
+ Host remote-miniops
+ Hostname {{.H}}
+ User {{.U}}
+ IdentityFile ~/.ssh/id_miniops
+ EOF
+ echo Added ssh config remote-miniops
+ else
+ echo Found ssh config remote-miniops
+ fi
+
+ - echo "You can now reach devcontainer with ssh miniops"
+
+
diff --git a/setup/docker/kind.yaml b/setup/docker/kind.yaml
index 696eaa6..ae7c085 100644
--- a/setup/docker/kind.yaml
+++ b/setup/docker/kind.yaml
@@ -31,6 +31,14 @@ nodes:
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true,nuvolaris.io/kube=kind"
+ - |
+ kind: ClusterConfiguration
+ controlPlaneEndpoint: "nuvolaris-control-plane:6443"
+ apiServer:
+ certSANs:
+ - "nuvolaris-control-plane"
+ - "localhost"
+ - "127.0.0.1"
extraPortMappings:
- containerPort: 80
hostPort: 80
@@ -62,5 +70,5 @@ nodes:
containerPath: /zookeeper/log
- hostPath: "$DATADIR/kafka"
containerPath: /kafka
- - hostPath: "$OPS_HOME/workspace"
+ - hostPath: "$WORKSPACE"
containerPath: /workspace
diff --git a/setup/docker/opsfile.yml b/setup/docker/opsfile.yml
index e43b194..595220f 100644
--- a/setup/docker/opsfile.yml
+++ b/setup/docker/opsfile.yml
@@ -19,12 +19,14 @@ version: '3'
vars:
CLUSTER: nuvolaris
INGRESS:
"https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml"
+ HOMEDIR:
+ sh: echo ~ | replace --stdin -s \\ -r /
env:
DATADIR:
- sh: echo "$OPS_TMP/kind"
+ sh: echo "$OPS_TMP/kind" | replace --stdin -s \\ -r /
WORKSPACE:
- sh: echo "$OPS_HOME/workspace"
+ sh: echo "{{.HOMEDIR}}/.ops-workspace"
KUBECONFIG:
sh: |-
if test -e "$OPS_TMP/kubeconfig"
@@ -62,7 +64,7 @@ tasks:
cluster:
silent: true
cmds:
- - mkdir -p "$DATADIR" "$OPS_HOME/workspace"
+ - mkdir -p "$DATADIR" "$WORKSPACE"
- envsubst -i kind.yaml -o _kind.yaml
- >
kind create cluster
@@ -79,9 +81,19 @@ tasks:
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
+ - task: wait-kube
+
+ wait-kube:
+ silent: true
+ desc: wait kubeconfig
+ cmds:
+ - |
+ while ! test -e $OPS_TMP/kubeconfig
+ do echo waiting kubeconfig
+ sleep 1
+ done
+ - retry kubectl --kubeconfig $OPS_TMP/kubeconfig cluster-info
+
ingress:
silent: true
@@ -117,6 +129,7 @@ tasks:
then kind export kubeconfig --name {{.CLUSTER}} --kubeconfig
"$OPS_TMP/kubeconfig"
else
ops util freeze docker-load
+ ops util freeze kind-preload
ops setup docker cluster
ops util freeze kind-load
ops setup docker ingress
diff --git a/setup/kubernetes/DEBUG.txt b/setup/kubernetes/DEBUG.txt
new file mode 100644
index 0000000..c49b2ce
--- /dev/null
+++ b/setup/kubernetes/DEBUG.txt
@@ -0,0 +1,25 @@
+# check pod status
+ops debug kube pod
+
+# delete a kuberenetes cluster
+ops setup kubernetes delete
+
+
+# create the entire cluster in the default kubernetes
+# kubeconfig shold be in ~/.ops/tmp/kubeconfig or in ~/.kube/config
+ops setup kubernetes create
+
+# watch what is happening in another terminal
+ops debug watch
+
+# step by step operator launch with standby
+ops setup kubernetes permission
+ops setup kubernetes pre-deploy
+ops setup kubernetes operator COMMAND="tail -f /dev/null"
+
+ops debug kube pod
+
+# enter
+ops util kubeconfig
+kubectl exec -ti -n nuvolaris nuvolaris-operator-0 -- bash
+
diff --git a/setup/kubernetes/operator.yaml b/setup/kubernetes/operator.yaml
index 121296b..74526e3 100644
--- a/setup/kubernetes/operator.yaml
+++ b/setup/kubernetes/operator.yaml
@@ -78,8 +78,11 @@ spec:
containers:
- name: nuvolaris-operator
image: ${IMAGES_OPERATOR}
+ command:
+ - bash
+ - -c
+ - ${COMMAND}
imagePullPolicy: IfNotPresent
- command: ["./run.sh"]
args: ["--verbose"]
securityContext:
capabilities:
diff --git a/setup/kubernetes/opsfile.yml b/setup/kubernetes/opsfile.yml
index 733eb8c..a09d817 100644
--- a/setup/kubernetes/opsfile.yml
+++ b/setup/kubernetes/opsfile.yml
@@ -21,6 +21,7 @@ vars:
RETRY: 100
TIMEOUT: 10s
CONTEXT: ""
+ COMMAND: "./run.sh"
env:
KUBECONFIG:
@@ -90,9 +91,6 @@ env:
tasks:
- streamer:
- desc: deploy streamer
-
status:
desc: show nuvolaris cluster status
silent: true
@@ -114,14 +112,13 @@ tasks:
kubectl version
crd:
- #desc get crd
+ desc: get crd
silent: true
cmds:
- kubectl get wsk/controller -n nuvolaris -o yaml
-
wait:
- #desc: wait for an object to reach a condition
+ desc: wait for an object to reach a condition
silent: true
status:
- test "{{.COND}}" != "true"
@@ -156,7 +153,7 @@ tasks:
$RES
wait-pod:
- #desc: wait for a pod to be available - leave the result in FILE
+ desc: wait for a pod to be available - leave the result in FILE
silent: true
status:
- test "{{.COND}}" != "true"
@@ -221,7 +218,7 @@ tasks:
fi
prepare:
- #desc: prepare the environment
+ desc: prepare the environment
ignore_error: true
silent: true
cmds:
@@ -237,8 +234,9 @@ tasks:
cmds:
- echo "export OPERATOR_VOLUME_STORAGE_CLASS={{.OP_VOL_STORAGE_CLASS}}"
+
operator:
- #desc: deploy operator
+ desc: deploy operator (use COMMAND=your-start-command to change default
./run.sh)
silent: true
status:
- config SKIP_OPERATOR_LAUNCH
@@ -246,6 +244,7 @@ tasks:
- |
eval $(task storageclass-env)
echo "Operator storage class is $OPERATOR_VOLUME_STORAGE_CLASS"
+ export COMMAND="{{.COMMAND}}"
envsubst -i operator-pvc.yaml -o _operator-pvc.yaml
envsubst -i operator.yaml -o _operator.yaml
- "kubectl apply -f _operator-pvc.yaml -f _operator.yaml"
@@ -274,7 +273,7 @@ tasks:
wait-openwhisk:
silent: true
- #desc: wait for openwhisk start
+ desc: wait for openwhisk start
status:
- config SKIP_OPERATOR_LAUNCH
cmds:
@@ -291,7 +290,7 @@ tasks:
wait-services:
silent: true
- #desc: wait for active services
+ desc: wait for active services
status:
- config SKIP_OPERATOR_LAUNCH
cmds:
@@ -370,18 +369,30 @@ tasks:
- task: create
- config -r SKIP_OPERATOR_LAUNCH
- deploy:
+
+ pre-deploy:
silent: true
- desc: deploy in namespace (use namespace admin)
+ desc: prepare deploy
cmds:
- task: context
- task: secrets
- task: runtimes
- - task: operator
- - task: instance
+
+ post-deploy:
+ desc: wait results
+ cmds:
- task: wait-openwhisk
- task: wait-services
+ deploy:
+ silent: true
+ desc: deploy in namespace (use namespace admin)
+ cmds:
+ - task: pre-deploy
+ - task: operator
+ - task: instance
+ - task: post-deploy
+
delete:
silent: true
ignore_error: true
diff --git a/setup/opsfile.yml b/setup/opsfile.yml
index f4bd7f2..df0bab0 100644
--- a/setup/opsfile.yml
+++ b/setup/opsfile.yml
@@ -124,9 +124,9 @@ tasks:
- ops config slim
- ops config apihost '{{.DOMAIN}}' --protocol={{.PROTO}}
- ops setup devcluster
+ - ops setup nuvolaris add-user
- ops setup nuvolaris streamer deploy
- ops setup nuvolaris system-api deploy
- - ops setup nuvolaris add-user
devcluster:
vars:
diff --git a/util/docopts.md b/util/docopts.md
index 1ab1629..86aec9f 100644
--- a/util/docopts.md
+++ b/util/docopts.md
@@ -44,6 +44,7 @@ Usage:
util ingress-type
util edit [<plugin>]
util link-plugin <plugin>
+ util stdtext <text>
```
## Commands
@@ -69,14 +70,16 @@ 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
+- stdtext standardize the text to the text convetions of the
underlying platform (windows/unix)
```
## Options
```
- --showhelp Show configuration tool help.
+ --showhelp Show configuration tool help.
--override Override the current configuration.
--verbose Provide more details.
--clean Remove all files from the web bucket before upload.
--batchsize=<batchsize> Number of concurrent web uploads
+ --dry Dry Run
```
\ No newline at end of file
diff --git a/util/freeze/findimages.js b/util/freeze/findimages.js
new file mode 100644
index 0000000..4d4ecbd
--- /dev/null
+++ b/util/freeze/findimages.js
@@ -0,0 +1,50 @@
+/*
+write a simple bun script with no deps that will list images to be preloaded
+assume IMAGE_DIR are available in process.env
+
+read all the component images from the section config.images
+in $OPS_ROOT/opsroot.json skip controller and invoker
+
+search the runtime images looking in $OPS_ROOT/runtimes.json
+pick only entries with default true, skipping those with tag nightly or latest
+
+assemble image from the image sction using docker.io/<prefix>/<name>:tag
+
+for each image found:
+- if the file $IMAGE_DIR/<base64 of image> exists, skip the preloading
+- print the image to be preloaded
+
+*/
+const opsRoot = process.env.OPS_ROOT
+const imageDir = process.env.IMAGE_DIR
+
+const images = []
+
+// Component images from opsroot.json, skip controller and invoker
+const skipKeys = new Set(["controller", "invoker"])
+const opsroot = await Bun.file(`${opsRoot}/opsroot.json`).json()
+for (const [key, img] of Object.entries(opsroot.config.images)) {
+ if (skipKeys.has(key)) continue
+ images.push(img)
+}
+
+// Runtime images from runtimes.json, only defaults, skip nightly/latest tags
+const skipTags = new Set(["latest", "nightly"])
+const runtimes = await Bun.file(`${opsRoot}/runtimes.json`).json()
+for (const family of Object.values(runtimes.runtimes)) {
+ for (const runtime of family) {
+ if (!runtime.default || !runtime.image) continue
+ const { prefix, name, tag } = runtime.image
+ if (!tag || skipTags.has(tag)) continue
+ images.push(`docker.io/${prefix}/${name}:${tag}`)
+ }
+}
+
+// Print only images that need preloading
+for (const img of images) {
+ const marker = `${imageDir}/${btoa(img)}`
+ const found = await Bun.file(marker).exists()
+ if (!found) {
+ console.log(img)
+ }
+}
diff --git a/util/freeze/opsfile.yml b/util/freeze/opsfile.yml
index 5ebb6b4..541dd43 100644
--- a/util/freeze/opsfile.yml
+++ b/util/freeze/opsfile.yml
@@ -4,7 +4,7 @@ vars:
CLUSTER: nuvolaris
KIND_CLUSTER: '{{.CLUSTER}}-control-plane'
BASE:
- sh: echo ~/.ops
+ sh: echo ~/.ops | replace -s \\ -r / --stdin
IMAGES:
sh: >
echo {{.BASE}}/{{OS}}-{{ARCH}}/images
@@ -44,15 +44,15 @@ tasks:
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
+ 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
@@ -67,6 +67,20 @@ tasks:
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
+ - task: _kind-get-images
+
+ kind-preload:
+ desc: preload docker images from config
+ silent: true
+ env:
+ IMAGE_DIR: "{{.IMAGES}}/kind"
+ cmds:
+ - bun findimages.js >_kind.lst
+ - task: _kind-get-images
+
+ _kind-get-images:
+ silent: true
+ cmds:
- mkdir -p {{.IMAGES}}/kind
- |
cat _kind.lst | while read img
@@ -85,6 +99,14 @@ tasks:
fi
done
+ kind-preload-one:
+ silent: true
+ desc: preload one specified image
+ cmds:
+ - test -n "{{.CLI_ARGS}}" || die "specify the image to preload"
+ - echo "{{.CLI_ARGS}}" >_kind.lst
+ - task: _kind-get-images
+
image-save:
desc: save images
cmds:
diff --git a/util/opsfile.yml b/util/opsfile.yml
index 3d7e00e..3738ffa 100644
--- a/util/opsfile.yml
+++ b/util/opsfile.yml
@@ -264,6 +264,7 @@ tasks:
fi
code "$DIR"
+
link-plugin:
desc: link a plugin
silent: true
@@ -282,3 +283,9 @@ tasks:
freeze:
desc: freeze util
+ stdtext:
+ desc: standardize text to the convetion of the platfom
+ silent: true
+ cmds:
+ - bun stdtext.js {{OS}} "{{._text_}}"
+
diff --git a/util/stdtext.js b/util/stdtext.js
new file mode 100644
index 0000000..700a0ab
--- /dev/null
+++ b/util/stdtext.js
@@ -0,0 +1,23 @@
+/*
+accept two args: "os" and "file"
+
+read the file, accepting either lf or crlf terminators
+
+and rewrite it with the platform's convention
+
+if the first arg is "windows" use crlf, otherwise use lf
+*/
+const fs = require("fs");
+
+const os = process.argv[2];
+const file = process.argv[3];
+
+if (!os || !file) {
+ console.error("Usage: stdtext.js <os> <file>");
+ process.exit(1);
+}
+
+const content = fs.readFileSync(file, "utf8");
+const lines = content.split(/\r?\n/);
+const eol = os === "windows" ? "\r\n" : "\n";
+fs.writeFileSync(file, lines.join(eol));
\ No newline at end of file