mirror of
https://github.com/coderofsalvation/podi.git
synced 2026-05-18 05:04:56 +02:00
work in progress [might break]
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
FROM alpine:3.1
|
||||
|
||||
RUN apk update \
|
||||
&& apk add openssh git \
|
||||
&& apk add openssh git socat\
|
||||
&& addgroup -S git && adduser -D -S git -G git -s /bin/sh \
|
||||
&& mkdir -p /home/git/.ssh \
|
||||
&& chmod 0700 /home/git/.ssh \
|
||||
|
||||
@@ -4,11 +4,11 @@ test -d app && rm -rf app
|
||||
mkdir app
|
||||
cd app
|
||||
cp ../podi .
|
||||
./podi init_localhost
|
||||
cp ../recipe/app/simple .pod/.
|
||||
cp ../recipe/start/envfile .pod/.
|
||||
export RECIPE_REPOS=http://localhost:8081/recipe/index.txt
|
||||
./podi recipe run/baremetal
|
||||
./podi init_runtime
|
||||
./podi init git@localhost:/home/git/app5 master 2222
|
||||
./podi envset git@localhost app5 PORT=9000
|
||||
./podi envset git@localhost app5 PORT=9999
|
||||
git add .pod app .env
|
||||
git commit -m "recipe app/simple"
|
||||
git push app5 master
|
||||
|
||||
15
.test/tests/86_recipe_simple_app_webcli
Executable file
15
.test/tests/86_recipe_simple_app_webcli
Executable file
@@ -0,0 +1,15 @@
|
||||
.test/test describe $0
|
||||
|
||||
test -d app && rm -rf app
|
||||
mkdir app
|
||||
cd app
|
||||
cp ../podi .
|
||||
export RECIPE_REPOS=http://localhost:8081/recipe/index.txt
|
||||
set -x
|
||||
./podi recipe run/baremetal_webcli
|
||||
./podi init_runtime
|
||||
./podi init git@localhost:/home/git/app5 master 2222
|
||||
./podi envset git@localhost app5 PORT=9999
|
||||
git add .pod app .env
|
||||
git commit -m "recipe app/simple"
|
||||
git push app5 master
|
||||
@@ -1,17 +1,18 @@
|
||||
.test/test describe $0
|
||||
|
||||
HOST=git@server.app.isvery.ninja
|
||||
GITPATH=/home/git/test
|
||||
PORT=222
|
||||
ssh -p $PORT $HOST rm -rf /home/git/test
|
||||
test -d app && rm -rf app
|
||||
mkdir app
|
||||
cd app
|
||||
cp ../podi .
|
||||
./podi init_localhost
|
||||
echo
|
||||
cp ../recipe/app/container .pod/.
|
||||
cp ../recipe/start/envfile .pod/.
|
||||
set -x
|
||||
./podi init git@localhost:/home/git/app5 master 2222
|
||||
echo
|
||||
export RECIPE_REPOS=http://localhost:8081/recipe/index.txt
|
||||
./podi recipe run/container
|
||||
./podi init_runtime
|
||||
./podi init $HOST:$GITPATH master $PORT
|
||||
./podi envset $HOST test PORT=9999
|
||||
git add .pod app .env
|
||||
git commit -m "recipe app/simple" &>/dev/null
|
||||
git push app5 master
|
||||
./podi envset git@localhost app5 PORT=9999
|
||||
git commit -m "recipe app/simple"
|
||||
git push test master
|
||||
|
||||
18
.test/tests/87_recipe_simple_app_container_webcli
Executable file
18
.test/tests/87_recipe_simple_app_container_webcli
Executable file
@@ -0,0 +1,18 @@
|
||||
.test/test describe $0
|
||||
|
||||
HOST=git@server.app.isvery.ninja
|
||||
GITPATH=/home/git/test
|
||||
PORT=222
|
||||
ssh -p $PORT $HOST rm -rf /home/git/test
|
||||
test -d app && rm -rf app
|
||||
mkdir app
|
||||
cd app
|
||||
cp ../podi .
|
||||
export RECIPE_REPOS=http://localhost:8081/recipe/index.txt
|
||||
./podi recipe run/container_webcli
|
||||
./podi init_runtime
|
||||
./podi init $HOST:$GITPATH master $PORT
|
||||
./podi envset $HOST test PORT=9999
|
||||
git add .pod app .env
|
||||
git commit -m "recipe app/simple"
|
||||
git push test master
|
||||
14
.test/tests/88_recipe_simple_app_autosuspend
Executable file
14
.test/tests/88_recipe_simple_app_autosuspend
Executable file
@@ -0,0 +1,14 @@
|
||||
.test/test describe $0
|
||||
|
||||
test -d app && rm -rf app
|
||||
mkdir app
|
||||
cd app
|
||||
cp ../podi .
|
||||
export RECIPE_REPOS=http://localhost:8081/recipe/index.txt
|
||||
./podi recipe run/baremetal_autosuspend
|
||||
./podi init_runtime
|
||||
./podi init git@localhost:/home/git/app5 master 2222
|
||||
./podi envset git@localhost app5 PORT=9999
|
||||
git add .pod app .env
|
||||
git commit -m "recipe app/simple"
|
||||
git push -f app5 master
|
||||
19
.test/tests/89_recipe_simple_app_container_autosuspend
Executable file
19
.test/tests/89_recipe_simple_app_container_autosuspend
Executable file
@@ -0,0 +1,19 @@
|
||||
.test/test describe $0
|
||||
|
||||
HOST=git@server.app.isvery.ninja
|
||||
GITPATH=/home/git/test
|
||||
PORT=222
|
||||
set -x
|
||||
ssh -p $PORT $HOST rm -rf /home/git/test
|
||||
test -d app && rm -rf app
|
||||
mkdir app
|
||||
cd app
|
||||
cp ../podi .
|
||||
export RECIPE_REPOS=http://localhost:8081/recipe/index.txt
|
||||
./podi recipe run/container_autosuspend
|
||||
./podi init_runtime
|
||||
./podi init $HOST:$GITPATH master $PORT
|
||||
./podi envset $HOST test PORT=9998
|
||||
git add .pod app .env
|
||||
git commit -m "recipe app/simple"
|
||||
git push test master
|
||||
@@ -8,8 +8,6 @@
|
||||
$ cd myapp
|
||||
$ wget "https://raw.githubusercontent.com/coderofsalvation/podi/master/podi"
|
||||
$ chmod 755 podi
|
||||
$ ./podi recipe app/container # a template container recipe
|
||||
$ ./podi recipe start/envfile # cli-cmd to set remote env-vars
|
||||
```
|
||||
|
||||
> PROFIT! now init your (ssh)server to enable a heroku-ish workflow:
|
||||
@@ -19,11 +17,10 @@ $ ./podi recipe start/envfile # cli-cmd to set remote env-vars
|
||||
## Features
|
||||
|
||||
* fully hackable PaaS & Gitops-designer (embedded in your repo)
|
||||
* per-branch and per-sshuser deployments
|
||||
* multitenant: multi-branch and multi-sshuser deployments
|
||||
* `podi ls`: gitops templates for containerizing, autosuspending services on baremetal etc
|
||||
* hookable (`on build callmyfunction arg1`)
|
||||
* app templates
|
||||
* autosuspending app templates
|
||||
* podi weighs 5k, just needs ssh+git installed
|
||||
* podi weighs ~7k, just needs ssh+git installed
|
||||
* works on raspberry pi zero but also on kubernetes
|
||||
|
||||
## Create recipes
|
||||
|
||||
13
app/app
13
app/app
@@ -1,13 +0,0 @@
|
||||
#!/bin/sh
|
||||
d=-d
|
||||
test -z $PODI_GITPUSH && { PODI_APP=$(basename $(pwd)); f="-f"; d=""; }
|
||||
|
||||
IMAGE=docker.io/coderofsalvation/redbean:1.5
|
||||
CMD="/redbean.com -D . -p 80 -vv"
|
||||
POD=$(which podman || which docker)
|
||||
|
||||
test -f Dockerfile && IMAGE=$PODI_APP
|
||||
set -x
|
||||
$POD run $d --rm --volume $(pwd):/home/app -w /home/app -e PORT -p $PORT:80 --name $PODI_APP $IMAGE $CMD
|
||||
set +x;
|
||||
$POD logs $f $PODI_APP 2>&1 | awk "{print \"[app.log] \"\$0 }"
|
||||
67
podi
67
podi
@@ -1,8 +1,8 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
required="awk ssh git hostname basename"
|
||||
test -z $HOST && host=$USER@$(hostname) || host=$HOST
|
||||
RECIPE_REPOS="https://raw.githubusercontent.com/coderofsalvation/podi/master/recipe/.index.txt"
|
||||
test -z $HOST && host=$USER@$(hostname) || host=$HOST
|
||||
test -z "$RECIPE_REPOS" && RECIPE_REPOS="https://raw.githubusercontent.com/coderofsalvation/podi/master/recipe/index.txt"
|
||||
#trap "trigger cleanup" 0 1 2 3 6
|
||||
C_GREY="\\033[1;30m"
|
||||
C_BOLD="\\033[1;37;40m"
|
||||
@@ -12,12 +12,14 @@ C_PURPLE="\\033[38;5;207m"
|
||||
C_RED="\\033[0;31m"
|
||||
|
||||
# some hipster wrappers to make things readable and sexy later on
|
||||
extract() { awk '/^# '$1':/ { gsub("^# '$1': ","",$0); print $0 }' $0; }
|
||||
try() { set +e; "$@"; set -e; return 0; }
|
||||
silent() { "$@" 1>/dev/null 2>/dev/null; }
|
||||
silent() { "$@" 1>/dev/null 2>/dev/null; return $?; }
|
||||
installed() { which $1 2>/dev/null 1>/dev/null; }
|
||||
verbose() { printf " $C_BOLD\$$C_NORMAL $*\n"; "$@"; }
|
||||
prompt() { printf " [?] $C_CYAN$1$C_NORMAL"; printf "\n$2\n $3> "; read answer; }
|
||||
error() { printf " [$C_RED"e"$C_NORMAL] %s\n" "$*"; exit 1; }
|
||||
print() { printf " $C_PURPLE│ $C_NORMAL %s\n" "$*"; }
|
||||
print() { printf " $C_PURPLE│ $C_NORMAL %s\n" "$*"; return 0; }
|
||||
soften() { cat | while read line; do printf " $C_PURPLE| $C_GREY%s$C_NORMAL\n" "$line"; done; }
|
||||
header() { h=$1; shift; printf " $C_PURPLE├─ $C_CYAN""%s""$C_PURPLE $C_NORMAL%s\n" "$h" "$*"; }
|
||||
evalfunc() { type $1 | awk 'NR>2 && /^[^{][^}]/ { print $0 }'; }
|
||||
foreach() { local err=0; local args="$1";
|
||||
@@ -25,36 +27,30 @@ foreach() { local err=0; local args="$1";
|
||||
for j in $args; do "$@" "$j" || err=1; done
|
||||
test $err = 1 && return 1 || return 0
|
||||
}
|
||||
trigger() { printf "$C_BOLD%-25s $C_NORMAL[$C_CYAN✓$C_NORMAL] ($C_GREY%s)$C_NORMAL\n" "$(test $host = $USER@$(hostname) && printf $1 || printf " | $1")" $host 1>&2
|
||||
run_yaml() { awk '
|
||||
BEGIN{ file=""; buffer="" }
|
||||
/^[a-zA-Z0-9_]+: |-/ { gsub(":","",$1); file=$1 ; buffer = "" }
|
||||
/ .*/ { gsub(" ","",$0); buffer=buffer$0"\n" }
|
||||
/^$/ { print "writing "file; print buffer > file }
|
||||
' $1
|
||||
}
|
||||
trigger() { printf "$C_NORMAL [$C_CYAN✓$C_NORMAL] $C_BOLD%s$C_NORMAL\n" "$1"
|
||||
local cmd=$1; shift
|
||||
local actions="$(eval echo \$on_$cmd)"
|
||||
if test -n "$actions"; then
|
||||
silent try type $cmd && { $cmd "$@"; }
|
||||
for it in $actions; do trigger $it "$@"; done
|
||||
else
|
||||
set +e
|
||||
silent type $cmd || return 0;
|
||||
silent type $cmd && $cmd "$@";
|
||||
set -e
|
||||
fi
|
||||
return $?
|
||||
}
|
||||
on() { export on_$1="$2 $(eval echo \$on_$1)"; }
|
||||
|
||||
# pipeline: deploy(){
|
||||
# pipeline: trigger hello
|
||||
# pipeline: trigger backup
|
||||
# pipeline: trigger checkout
|
||||
# pipeline: trigger build
|
||||
# pipeline: trigger runtests
|
||||
# pipeline: trigger start
|
||||
# pipeline: }
|
||||
# pipeline:
|
||||
# pipeline: checkout(){
|
||||
# pipeline: git --work-tree=$(pwd) --git-dir=$(pwd)/.git checkout -f
|
||||
# pipeline: }
|
||||
|
||||
init_post_receive(){
|
||||
echo "#!/bin/sh
|
||||
export PODI_GITPUSH=1
|
||||
export PODI_REMOTE=$2
|
||||
export PODI_USER=$3
|
||||
export PODI_PORT=$4
|
||||
@@ -100,10 +96,17 @@ init(){ # init git@server:/dir/to/deploy [branch] [port] [name] : initializes a
|
||||
}
|
||||
|
||||
init_localhost(){
|
||||
test -d ~/.pod || { mkdir -p ~/.pod && extract config > ~/.pod/config; }
|
||||
test -d .pod || {
|
||||
mkdir -p .pod && extract pipeline > .pod/pipeline;
|
||||
test -d .pod && for i in .pod/* ; do . $i; done
|
||||
test -d .git || git init
|
||||
test -f .pod/pipeline || {
|
||||
test -d .pod || mkdir -p .pod
|
||||
test -d .pod/run || {
|
||||
prompt "how to run this app?" "$(recipe | grep '^run/' | cat -n)"
|
||||
runtime=$(recipe | grep '^run/' | awk "NR == $answer { print \$0 }")
|
||||
silent recipe $runtime && . .pod/$runtime
|
||||
init_runtime
|
||||
}
|
||||
test -f .pod/pipeline || recipe pipeline
|
||||
test -d .pod && for i in .pod/* ; do . $i; done
|
||||
test -f podi || cp $0 .
|
||||
}
|
||||
}
|
||||
@@ -126,7 +129,7 @@ init_server(){
|
||||
echo "export appname='$appname' " >> $config
|
||||
echo "export branch='$branch' " >> $config
|
||||
. $config
|
||||
ssh -p $port $user@$server HOST=$user@$server mkdir $gitpath
|
||||
try silent ssh -p $port $user@$server HOST=$user@$server mkdir $gitpath
|
||||
scp -r -P $port $0 .pod $user@$server:$gitpath/. 1>/dev/null
|
||||
try ssh -p $port $user@$server "cd $gitpath; ./podi init_gitops $gitpath $server $user $port"
|
||||
set +e
|
||||
@@ -146,7 +149,7 @@ init_gitops(){
|
||||
test -d $1/.git || {
|
||||
silent git init --bare "$1/.git" || error could not create $1/.git
|
||||
}
|
||||
trigger init_post_receive $1 $2 $3 $4 > $1/.git/hooks/post-receive
|
||||
init_post_receive $1 $2 $3 $4 > $1/.git/hooks/post-receive
|
||||
chmod +x $1/.git/hooks/post-receive
|
||||
}
|
||||
|
||||
@@ -154,21 +157,21 @@ recipe(){ # recipe <name_or_url> : installs a recipe from podi repo or url
|
||||
list(){
|
||||
for repo in $RECIPE_REPOS; do
|
||||
print $(dirname $repo)
|
||||
curl $repo
|
||||
curl -s $repo
|
||||
done
|
||||
}
|
||||
install(){
|
||||
for repo in $RECIPE_REPOS; do
|
||||
curl -s $repo | grep -E "^$1$" && {
|
||||
curl -s $repo | silent grep -E "^$1$" && {
|
||||
test -d .git || git init
|
||||
test -d .pod || mkdir .pod
|
||||
print "installing $(dirname $repo)/$1"
|
||||
print "writing .pod/$1"
|
||||
dir=$(dirname $1)
|
||||
test -d .pod/$dir || mkdir -p .pod/$dir
|
||||
curl -s $(dirname $repo)/$1 > .pod/$dir/$(basename $1)
|
||||
}
|
||||
done
|
||||
}
|
||||
init_localhost
|
||||
test -z $1 && list
|
||||
test -z $1 || install $1
|
||||
}
|
||||
@@ -191,7 +194,7 @@ usage(){
|
||||
gsub(".*{ # ","",$0)
|
||||
gsub(" :.*","",$0)
|
||||
printf(" %-55s %s\n",$0,info)
|
||||
}' $0 .pod/* 2>/dev/null
|
||||
}' $0 $(find .pod -type f | awk '{ printf "%s ",$0 }') 2>/dev/null
|
||||
echo
|
||||
init_remotes
|
||||
printf "deploy targets:\n"
|
||||
|
||||
@@ -8,4 +8,7 @@ init/gitops/jail
|
||||
start/envfile
|
||||
run/baremetal_autosuspend
|
||||
run/container
|
||||
run/container_autosuspend
|
||||
run/baremetal_webcli
|
||||
run/baremetal
|
||||
run/container_webcli
|
||||
|
||||
@@ -14,17 +14,23 @@ start(){
|
||||
test -f .pid && { print "stopping $PODI_APP"; silent try kill -15 $(cat .pid); }
|
||||
nohup ./podi daemonize $PODI_APP:$PORT &> app.log &
|
||||
echo $! > .pid
|
||||
print "started $PODI_APP [PID $(cat .pid)]"
|
||||
print "started $PODI_APP [PID $(cat .pid)] on $PODI_REMOTE:$PORT"
|
||||
}
|
||||
|
||||
ensure_file_app(){
|
||||
init_runtime(){
|
||||
test -f app || {
|
||||
print "'app' startfile not found, please create + commit it. For example:"
|
||||
echo " $ echo 'node app.js' > app && chmod 755 app" | soften
|
||||
exit 0
|
||||
generate(){
|
||||
echo '#!/bin/sh'
|
||||
echo 'echo PID=$(cat .pid) => $(date) PORT=$PORT'
|
||||
echo 'while sleep 1; do printf .; done '
|
||||
}
|
||||
prompt "generate + commit 'app' startfile?" "$(generate | soften)" "[y/n] "
|
||||
test $answer = "y" || error aborting
|
||||
generate > app
|
||||
chmod 755 app
|
||||
git add app && git commit -m "podi: adding app file"
|
||||
}
|
||||
test -f .pod/extract/rollback_simple || recipe extract/rollback_simple
|
||||
test -f .pod/start/envfile || recipe start/envfile
|
||||
test -f .pod/init/server/sshkey || recipe init/server/sshkey
|
||||
}
|
||||
|
||||
on init_localhost ensure_file_app
|
||||
|
||||
@@ -3,15 +3,16 @@
|
||||
# example usage: ./podman rollback git@server 3fe2f615
|
||||
|
||||
daemonize(){
|
||||
while sleep 1s; do
|
||||
while sleep 0.2s; do
|
||||
set +e
|
||||
echo "starting TTL=$TTL BOOTTIME=$BOOTTIME"
|
||||
echo "starting $PODI_APP TTL=$TTL BOOTTIME=$BOOTTIME"
|
||||
TTLARG=$TTL
|
||||
nc 2>&1 | silent grep BusyBox || NCARG="-N"
|
||||
timeout 2>&1 | silent grep BusyBox && TTLARG="-t $TTL"
|
||||
timeout -s 15 ${TTLARG} ./app
|
||||
echo "$(tail -n200 app.log)" > app.log
|
||||
echo sleeping on port $PORT
|
||||
echo "HTTP/1.1 302 OK\nrefresh:$BOOTTIME;url=/\n\n" | nc -lp $PORT | awk '{ printf "\r",$0 }'
|
||||
echo "HTTP/1.1 302 OK\nrefresh:$BOOTTIME;url=/\n\n" | nc $NCARG -lp $PORT | awk '{ printf "\r",$0 }'
|
||||
done
|
||||
}
|
||||
|
||||
@@ -19,20 +20,27 @@ start(){
|
||||
test -f .pid && { print "stopping $PODI_APP"; silent try kill -15 $(cat .pid); }
|
||||
nohup ./podi daemonize $PODI_APP:$PORT &> app.log &
|
||||
echo $! > .pid
|
||||
print "started $PODI_APP [PID $(cat .pid)]"
|
||||
print "started $PODI_APP [PID $(cat .pid)] on $PODI_REMOTE:$PORT"
|
||||
print "autosleeping after $TTL seconds (.env)"
|
||||
print "waking up after network request on port $PORT"
|
||||
}
|
||||
|
||||
ensure_file_app(){
|
||||
init_runtime(){
|
||||
test -f app || {
|
||||
print "'app' startfile not found, please create + commit it. For example:"
|
||||
echo " $ echo 'node app.js' > app && chmod 755 app" | soften
|
||||
exit 0
|
||||
generate(){
|
||||
echo '#!/bin/sh'
|
||||
echo 'echo PID=$(cat .pid) => $(date) PORT=$PORT'
|
||||
echo 'while sleep 1; do printf .; done '
|
||||
}
|
||||
prompt "generate + commit 'app' startfile?" "$(generate | soften)" "[y/n] "
|
||||
test $answer = "y" || error aborting
|
||||
generate > app
|
||||
chmod 755 app
|
||||
git add app && git commit -m "podi: adding app file"
|
||||
}
|
||||
test -f .pod/extract/rollback_simple || recipe extract/rollback_simple
|
||||
test -f .pod/start/envfile || recipe start/envfile
|
||||
test -f .pod/init/server/sshkey || recipe init/server/sshkey
|
||||
echo "export TTL=5 # suspend after 5 seconds of activity (update me!)" >> .env
|
||||
echo "export BOOTTIME=1 # give app 1 second to wakeup (update me!)" >> .env
|
||||
}
|
||||
|
||||
on init_localhost ensure_file_app
|
||||
on init_localhost create_app
|
||||
|
||||
37
recipe/run/baremetal_webcli
Normal file
37
recipe/run/baremetal_webcli
Normal file
@@ -0,0 +1,37 @@
|
||||
# info: simple app template
|
||||
# installation: run 'podi recipe app/simple' or put this file into .pod folder
|
||||
# example usage: ./podman rollback git@server 3fe2f615
|
||||
|
||||
daemonize(){
|
||||
while sleep 1s; do
|
||||
set +e
|
||||
./app
|
||||
echo "$(tail -n200 app.log)" > app.log
|
||||
done
|
||||
}
|
||||
|
||||
start(){
|
||||
test -f .pid && { print "stopping $PODI_APP"; silent try kill -15 $(cat .pid); }
|
||||
{ nohup ./podi daemonize $PODI_APP:$PORT 1> app.log 2> app.log; } &
|
||||
echo $! > .pid
|
||||
print "started $PODI_APP [PID $(cat .pid)] on $PODI_REMOTE:$PORT"
|
||||
print "just try 'curl $PODI_REMOTE:$PORT' or use your browser"
|
||||
}
|
||||
|
||||
init_runtime(){
|
||||
test -f app || {
|
||||
generate(){
|
||||
echo '#!/bin/sh'
|
||||
echo 'export JOB="cat hello.txt ; ls -la"'
|
||||
echo 'which socat &>/dev/null || { echo "please install socat as root"; exit 1; }'
|
||||
echo 'socat -t2 TCP4-LISTEN:$PORT,fork,max-children=3,forever,reuseaddr SYSTEM:"$JOB",pty,echo=0;'
|
||||
}
|
||||
generate > app
|
||||
chmod 755 app
|
||||
echo "HTTP/1.1 200\n\n H E L L O " > hello.txt
|
||||
git add app hello.txt && git commit -m "podi: adding app file"
|
||||
}
|
||||
test -f .pod/extract/rollback_simple || recipe extract/rollback_simple
|
||||
test -f .pod/start/envfile || recipe start/envfile
|
||||
test -f .pod/init/server/sshkey || recipe init/server/sshkey
|
||||
}
|
||||
@@ -1,5 +1,3 @@
|
||||
container=$(which podman || which docker || echo "")
|
||||
test -z $PODI_APP && PODI_APP=$(basename $(pwd))
|
||||
|
||||
hint_systemd(){
|
||||
service=/etc/systemd/system/$PODI_APP.service
|
||||
@@ -14,47 +12,50 @@ hint_systemd(){
|
||||
|
||||
build(){
|
||||
header .pod/app/container
|
||||
test -f Dockerfile || { print "'Dockerfile' not found..skipping build"; }
|
||||
test -f Dockerfile && {
|
||||
silent which $container || print '[!] please install podman (or docker)'
|
||||
silent which $container && verbose $container build -t $PODI_APP .
|
||||
silent which $POD || print '[!] please install podman (or docker)'
|
||||
silent which $POD && verbose $POD build -t $PODI_APP .
|
||||
} | soften
|
||||
return 0
|
||||
}
|
||||
|
||||
start(){
|
||||
header .pod/app/container
|
||||
silent which $container && {
|
||||
silent $container kill $PODI_APP
|
||||
silent $container rm -f $PODI_APP
|
||||
POD=$(which podman || which docker || echo "")
|
||||
silent which $POD || error "please install podman (or docker)"
|
||||
test -z $POD || {
|
||||
silent try $POD kill $PODI_APP
|
||||
silent try $POD rm -f $PODI_APP
|
||||
export PODI_APP=$PODI_APP
|
||||
eval "$(cat .env)"
|
||||
cat app
|
||||
verbose ./app
|
||||
hint_systemd
|
||||
print ""
|
||||
print "your container is running at $PODI_REMOTE:$PORT"
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
ensure_file_app(){
|
||||
init_runtime(){
|
||||
test -f app || {
|
||||
generate(){
|
||||
echo '#!/bin/sh' > app
|
||||
echo 'c=$(which podman || which docker)'
|
||||
echo 'follow=-f'
|
||||
echo 'bg=-d'
|
||||
echo 'test -z $PODI_APP && { bg=""; PODI_APP=$(basename $(pwd)); follow=""; }'
|
||||
echo 'set -x'
|
||||
echo '$c run $bg --rm --volume $(pwd):/home/app -w /home/app -e PORT -p $PORT:80 --name $PODI_APP docker.io/coderofsalvation/redbean /redbean.com -D . -p 80 -vv'
|
||||
echo 'set +x'
|
||||
echo '$c logs $follow $PODI_APP'
|
||||
echo '#!/bin/sh'
|
||||
echo 'POD=$(which podman || which docker)'
|
||||
echo 'test -z $PODI_APP && export PODI_APP=$(basename $(dir))'
|
||||
echo
|
||||
echo '$POD run -d --rm --volume $(pwd):/home/app -w /home/app -e PORT -p $PORT:80 --name $PODI_APP $PODI_APP'
|
||||
echo '$POD logs $PODI_APP'
|
||||
}
|
||||
prompt "'app' file not found:"
|
||||
generate | soften
|
||||
prompt "generate + commit it?"
|
||||
prompt "generate + commit 'app' startfile?" "$(generate | soften)" "[y/n] "
|
||||
test $answer = "y" || error aborting
|
||||
echo "FROM docker.io/coderofsalvation/redbean:1.5" > Dockerfile
|
||||
generate > app
|
||||
chmod 755 app
|
||||
git add app && git commit -m "podi: adding app file"
|
||||
git add app Dockerfile && git commit -m "podi: adding app file"
|
||||
}
|
||||
test -f .pod/extract/rollback_simple || recipe extract/rollback_simple
|
||||
test -f .pod/start/envfile || recipe start/envfile
|
||||
test -f .pod/init/server/sshkey || recipe init/server/sshkey
|
||||
}
|
||||
|
||||
83
recipe/run/container_autosuspend
Normal file
83
recipe/run/container_autosuspend
Normal file
@@ -0,0 +1,83 @@
|
||||
|
||||
hint_systemd(){
|
||||
service=/etc/systemd/system/$PODI_APP.service
|
||||
silent which podman || return 0
|
||||
test -f $service && return 0
|
||||
silent podman inspect $PODI_APP || return 0
|
||||
podman generate systemd $PODI_APP > $PODI_APP.service
|
||||
print "to survive server-reboots please run as root:"
|
||||
echo "cp $(pwd)/$PODI_APP.service /etc/systemd/system/." | soften
|
||||
echo "systemctl enable $PODI_APP.service" | soften
|
||||
}
|
||||
|
||||
build(){
|
||||
header .pod/app/container
|
||||
test -f Dockerfile || { print "'Dockerfile' not found..skipping build"; }
|
||||
test -f Dockerfile && {
|
||||
silent which $container || print '[!] please install podman (or docker)'
|
||||
silent which $container && verbose $container build -t $PODI_APP .
|
||||
} | soften
|
||||
return 0
|
||||
}
|
||||
|
||||
daemonize(){
|
||||
while sleep 0.2s; do
|
||||
set +e
|
||||
POD=$(which podman || which docker)
|
||||
nc 2>&1 | silent grep BusyBox || NCARG="-N"
|
||||
echo "starting $PODI_APP TTL=$TTL BOOTTIME=$BOOTTIME"
|
||||
test -z $($POD ps -a --filter=name=$PODI_APP| head -n-1) && ./app
|
||||
$POD start $PODI_APP
|
||||
sleep $TTL
|
||||
$POD stop $PODI_APP
|
||||
echo sleeping on port $PORT
|
||||
echo "HTTP/1.1 302 OK\nrefresh:$BOOTTIME;url=/\n\n" | nc $NCARG -lp $PORT | awk '{ printf "\r",$0 }'
|
||||
done
|
||||
}
|
||||
|
||||
start(){
|
||||
header .pod/app/container
|
||||
POD=$(which podman || which docker || echo "")
|
||||
silent which $POD || error "please install podman (or docker)"
|
||||
test -f .pid && { print "stopping $PODI_APP"; silent try kill -15 $(cat .pid); }
|
||||
test -z $POD || {
|
||||
silent try $POD kill $PODI_APP
|
||||
silent try $POD rm -f $PODI_APP
|
||||
export PODI_APP=$PODI_APP
|
||||
export PODI_GITPUSH=$PODI_GITPUSH
|
||||
eval "$(cat .env)"
|
||||
{ nohup ./podi daemonize $PODI_APP:$PORT 1> app.log 2> app.log; } &
|
||||
echo $! > .pid
|
||||
hint_systemd
|
||||
print ""
|
||||
print "started container $PODI_APP [PID $(cat .pid)] on $PODI_REMOTE:$PORT"
|
||||
print "autosleeping after $TTL seconds (.env)"
|
||||
print "waking up after network request on port $PORT"
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
init_runtime(){
|
||||
test -f app || {
|
||||
generate(){
|
||||
echo '#!/bin/sh'
|
||||
echo 'test -z $PODI_APP && PODI_APP=$(basename $(pwd))'
|
||||
echo 'test -f Dockerfile && IMAGE=$PODI_APP || IMAGE=docker.io/coderofsalvation/redbean:1.5'
|
||||
echo 'CMD="/redbean.com -D . -p 80 -vv"'
|
||||
echo 'POD=$(which podman || which docker)'
|
||||
echo
|
||||
echo '$POD run -d --rm --volume $(pwd):/home/app -w /home/app -e PORT -p $PORT:80 --name $PODI_APP $IMAGE $CMD'
|
||||
echo '$POD logs $PODI_APP 2>&1 | awk "{print \"[app.log] \"\$0 }"'
|
||||
}
|
||||
prompt "generate + commit 'app' startfile?" "$(generate | soften)" "[y/n] "
|
||||
test $answer = "y" || error aborting
|
||||
generate > app
|
||||
chmod 755 app
|
||||
git add app && git commit -m "podi: adding app file"
|
||||
}
|
||||
test -f .pod/extract/rollback_simple || recipe extract/rollback_simple
|
||||
test -f .pod/start/envfile || recipe start/envfile
|
||||
test -f .pod/init/server/sshkey || recipe init/server/sshkey
|
||||
echo "export TTL=5 # suspend after 5 seconds of activity (update me!)" >> .env
|
||||
echo "export BOOTTIME=2 # give app 2 second to wakeup (update me!)" >> .env
|
||||
}
|
||||
62
recipe/run/container_webcli
Normal file
62
recipe/run/container_webcli
Normal file
@@ -0,0 +1,62 @@
|
||||
POD=$(which podman || which docker || echo "")
|
||||
|
||||
hint_systemd(){
|
||||
service=/etc/systemd/system/$PODI_APP.service
|
||||
silent which podman || return 0
|
||||
test -f $service && return 0
|
||||
silent podman inspect $PODI_APP || return 0
|
||||
silent podman generate systemd $PODI_APP 1> $PODI_APP.service 2>/dev/null
|
||||
print "to survive server-reboots please run as root:"
|
||||
echo "cp $(pwd)/$PODI_APP.service /etc/systemd/system/." | soften
|
||||
echo "systemctl enable $PODI_APP.service" | soften
|
||||
}
|
||||
|
||||
build(){
|
||||
header .pod/app/container
|
||||
test -f Dockerfile || { print "'Dockerfile' not found..skipping build"; }
|
||||
test -f Dockerfile && {
|
||||
silent which $POD || print '[!] please install podman (or docker)'
|
||||
silent which $POD && verbose $POD build -t $PODI_APP .
|
||||
} | soften
|
||||
return 0
|
||||
}
|
||||
|
||||
start(){
|
||||
header .pod/app/container
|
||||
test -z $PODI_APP && PODI_APP=$(basename $(pwd))
|
||||
silent test -z $POD && error "please install podman (or docker)"
|
||||
test -z $POD || {
|
||||
export PODI_APP=$PODI_APP
|
||||
silent try $POD kill $PODI_APP
|
||||
silent try $POD rm -f $PODI_APP
|
||||
eval "$(cat .env)"
|
||||
POD=$(which podman || which docker)
|
||||
verbose $POD run -d --volume $(pwd):/home/app -w /home/app -e PORT -p $PORT:$PORT --name $PODI_APP --entrypoint=sh $PODI_APP -c ./app
|
||||
verbose $POD logs $PODI_APP 2>&1 | awk "{print \"[app.log] \"\$0 }"
|
||||
hint_systemd
|
||||
print ""
|
||||
print "your container is running at $PODI_REMOTE:$PORT"
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
init_runtime(){
|
||||
test -f app || {
|
||||
generate(){
|
||||
echo '#!/bin/sh'
|
||||
echo 'export JOB="cat hello.txt ; ls -la"'
|
||||
echo 'which socat &>/dev/null || { echo "please install socat as root"; exit 1; }'
|
||||
echo 'socat -t2 TCP4-LISTEN:$PORT,fork,max-children=3,forever,reuseaddr SYSTEM:"$JOB",pty,echo=0;'
|
||||
}
|
||||
prompt "generate + commit 'app' startfile?" "$(generate | soften)" "[y/n] "
|
||||
test $answer = "y" || error aborting
|
||||
generate > app
|
||||
chmod 755 app
|
||||
echo "HTTP/1.1 200\n\n H E L L O " > hello.txt
|
||||
echo "FROM docker.io/alpine/socat" > Dockerfile
|
||||
git add app Dockerfile hello.txt && git commit -m "podi: adding app file"
|
||||
}
|
||||
test -f .pod/extract/rollback_simple || recipe extract/rollback_simple
|
||||
test -f .pod/start/envfile || recipe start/envfile
|
||||
test -f .pod/init/server/sshkey || recipe init/server/sshkey
|
||||
}
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
envfile(){
|
||||
header .pod/envfile
|
||||
test -f .env && { print "reading '.env'" ; . .env; }
|
||||
test -f .env.live && { print "reading '.env.live'"; . .env.live; }
|
||||
test -f .env && { print "reading '.env'" ; eval "$(cat .env)"; }
|
||||
test -f .env.live && { print "reading '.env.live'"; eval "$(cat .env.live)"; }
|
||||
}
|
||||
|
||||
envset(){ # envset [git@server] [app] [FOO=bar] : shows or sets [remote] environment variables
|
||||
@@ -27,11 +27,9 @@ envset(){ # envset [git@server] [app] [FOO=bar] : shows or sets [remote] environ
|
||||
}
|
||||
|
||||
ensure_file_env(){
|
||||
test -f app || {
|
||||
test -f .env || {
|
||||
generate(){ echo "export PORT=$(awk 'BEGIN{ srand(); print int(rand()*1000)+8000 }')"; }
|
||||
prompt "'.env' file not found:"
|
||||
generate | soften
|
||||
prompt "generate + commit it?"
|
||||
prompt "generate + commit '.env' startfile?" "$(generate | soften)" "[y/n] "
|
||||
test $answer = "y" || error aborting
|
||||
generate > .env
|
||||
git add .env && git commit -m "podi: adding .env file"
|
||||
|
||||
Reference in New Issue
Block a user