Application Type - Generic¶
Generic type means that you can run any process in operating system you want. You just need to provide command that can be executed. Additionally it is required to provide commands to stop and terminate the process. It can be a script, command or any other option in operating system. It is possible also to add aditional commands that you can execute over API remotly.
Example configuration¶
app:
name: 'python-app'
version: '1.0.0'
appType: 'standard'
procType: 'native'
processProvider:
name: 'GenericOsProcessProviderImpl'
version: '1.0.0'
executable:
start:
command: 'python3 ${application-instance-path}/bin/main.py --port ${application-instance-port-1} --log_dir ${application-instance-logs-path}'
cpus: null
memory: null
successLine: 'Application started.'
before: []
after: []
path: null
getPid: null
pidFilePath: null
readStreamsWaitTimeInMillis: 90000
stop:
command: "pkill -SIGTERM -F ${application-instance-logs-path}/ONTEON_PID"
terminate:
command: "pkill -SIGKILL -F ${application-instance-logs-path}/ONTEON_PID"
custom_command_name:
command: "./run_my_custom_command"
placeHolder:
name: 'PlaceHolderManagerImpl'
version: '1.0.0'
filesToReplace: []
variables: {}
serviceRepository:
healthCheckUrl: 'http://${address}:${application-instance-port-1}'
entities:
- entity:
priority: 1
port: ${application-instance-port-1}
protocol:
type: 'HTTP'
version: '1.1'
isExternal: true
isInternal: true
Configuration keys¶
app.name¶
Name of application.
app.version¶
Version of application.
app.type¶
Application type. It should be set to standard.
Possible values:
- standard - Standard application.
- embedded - Application used for internal purposes, such as edge balancer.
- unknown - Unknown application.
app.procType¶
Process type. It should be set to native.
Possible values:
- native - Native application.
- docker - Docker application.
- unknown - Unknown application.
app.processProvider.name¶
Name of process provider. It should be set to GenericOsProcessProviderImpl.
Possible values:
- GenericOsProcessProviderImpl - for native processes.
- JVMOsProcessProviderImpl - for native JVM processes.
- DockerOsProcessProviderImpl - for docker processes.
app.processProvider.version¶
Version of process provider. It should be set to 1.0.0.
app.processProvider.executable.(action).command¶
Command that executes specific action.
app:
processProvider:
executable:
start:
command: '${application-instance-path}/bin/bin/start.sh --port ${application-instance-port-1}'
app.processProvider.executable.start.successLine¶
Log line that will determine that the application has started. If you do not specify success line, Onteon node will wait 90 seconds. Wait time can be changed here.
app.processProvider.executable.start.cpus¶
CPUs limit for process.
app.processProvider.executable.start.memory¶
Memory limit for process.
app.processProvider.executable.start.before¶
List of actions (defined on executable list) to run before running start command.
app.processProvider.executable.start.after¶
List of actions (defined on executable list) to run after running start command.
app.processProvider.executable.start.path¶
Path to directory with executable.
app.processProvider.executable.start.getPid¶
Command to retrieve application's process ID.
app.processProvider.executable.start.pidFilePath¶
Path to file that contains application's process ID.
app.processProvider.executable.start.readStreamsWaitTimeInMillis¶
Time in milliseconds that Onteon Node Manager will wait for the application's success line to occur. If success line it not defined, then it is a time in milliseconds, after which Onteon Node Manager will assume that the application is started and check if it's running using application's PID.
app.placeHolder.name¶
Placeholder name.
app.placeHolder.version¶
Placeholder version.
app.placeHolder.filesToReplace¶
List of files that will have placeholder replaced.
app.placeHolder.variables¶
Placeholders variables in key-value format.
app.serviceRepository.healthCheckUrl¶
Url that will determine if application is alive.
app.serviceRepository.entities¶
List of service repository entities.
app:
serviceRepository:
entities:
- entity:
priority: 1
port: ${application-instance-port-1} # entity port
protocol:
type: 'HTTP' # entity protocol
version: '1.1' # entity protocol version
isExternal: true # if true, application will be available in edge balancer
isInternal: true # if true, application will be available in inner balancer
Additional embedded application configuration keys¶
Besides base configuration keys listed above, applications with appType: 'embedded'
have additional keys.
app:
name: 'python-app'
version: '1.0.0'
appType: 'embedded'
procType: 'native'
itShouldBeStartedOnNodeManagerStartup: true
startupIndex: 1
isItRequiredForSystemConsistency: true
processProvider:
name: 'GenericOsProcessProviderImpl'
version: '1.0.0'
executable:
start:
command: 'python3 ${application-instance-path}/bin/main.py --port ${application-instance-port-1} --log_dir ${application-instance-logs-path}'
cpus: null
memory: null
successLine: 'Application started.'
before: []
after: []
path: null
getPid: null
pidFilePath: null
readStreamsWaitTimeInMillis: 90000
stop:
command: "pkill -SIGTERM -F ${application-instance-logs-path}/ONTEON_PID"
terminate:
command: "pkill -SIGKILL -F ${application-instance-logs-path}/ONTEON_PID"
custom_command_name:
command: "./run_my_custom_command"
placeHolder:
name: 'PlaceHolderManagerImpl'
version: '1.0.0'
filesToReplace: []
variables: {}
serviceRepository:
healthCheckUrl: 'http://${address}:${application-instance-port-1}'
entities:
- entity:
priority: 1
port: ${application-instance-port-1}
protocol:
type: 'HTTP'
version: '1.1'
isExternal: true
isInternal: true
app.itShouldBeStartedOnNodeManagerStartup¶
Defines if application should be started on Node Manager startup.
Possible values:
- true
- false
app.startupIndex¶
Specifies the order in which the application should start during startup sequence.
app.isItRequiredForSystemConsistency¶
Defines if node manager requires this application to start (if the application start fails, then node manager does not start) to work properly.
Possible values:
- true
- false
Docker containers under the Generic app type¶
PID detection under Docker¶
When the docker run or docker start command is used, then that dockerized
application PID will not be the same as the docker command that was executed.
In such case automatically detected PID will disappear and that will in
turn cause the application instance to be considered as stopped.
Because of this, when the Generic app type
is used to run Docker containers,
then there is a need to create a custom getPid script.
Such getPid script should reach out to Docker engine and provide
the application PID as it is visible to the operating system
(outside of a given container).
To extract the Docker container instance PID as it is visible to the operating system use the following command:
Example getPid script for Docker apps¶
Example getPid script for Docker apps is as follows
(be sure to replace APP-NAME):
Be sure to also point start.getPid value the the correct script path. For example:
app:
processProvider:
executable:
start:
getPid: "bash ${application-instance-path}/bin/bash-scripts/getPid.sh"
Instance ID and Docker¶
In case there needs to be more than one instance of a dockerized app running,
then setup is a bit more complicated.
Because each container must have a unique name, scripts have to use a special
instance id variable called ${application-instance-id}.
Place this variable inside a env.bash file and source it inside start,
getPid and stop scripts.
Example usage of application-instance-id¶
Conf (conf/conf.yml):
app:
placeHolder:
name: "PlaceHolderManagerImpl"
version: "1.0.0"
filesToReplace:
- "${application-instance-path}/bin/environment/env.bash"
Env (bin/environment/env.bash):
Start (bin/bash-scripts/start.bash):
#!/usr/bin/env bash
trap "exit 128" INT
set -eu
SOURCE="${BASH_SOURCE[0]}"
while [[ -h "${SOURCE}" ]] ; do
DIR="$(cd -P "$(dirname "${SOURCE}")" >/dev/null 2>&1 && pwd)"
SOURCE="$(readlink "${SOURCE}")"
[[ "${SOURCE}" != /* ]] && SOURCE="${DIR}/${SOURCE}"
done
SCRIPT_DIR="$(cd -P "$(dirname "${SOURCE}")" >/dev/null 2>&1 && pwd)"
cd "${SCRIPT_DIR}"
source ../environment/env.bash
docker run --detach --restart="no" --name="APP-NAME-${INSTANCE}" \
CONTAINER-NAME
echo "Successfully started"
Stop (bin/bash-scripts/stop.bash):
#!/usr/bin/env bash
trap "exit 128" INT
set -eu
SOURCE="${BASH_SOURCE[0]}"
while [[ -h "${SOURCE}" ]] ; do
DIR="$(cd -P "$(dirname "${SOURCE}")" >/dev/null 2>&1 && pwd)"
SOURCE="$(readlink "${SOURCE}")"
[[ "${SOURCE}" != /* ]] && SOURCE="${DIR}/${SOURCE}"
done
SCRIPT_DIR="$(cd -P "$(dirname "${SOURCE}")" >/dev/null 2>&1 && pwd)"
cd "${SCRIPT_DIR}"
source ../environment/env.bash
docker stop "APP-NAME-${INSTANCE}"
Port bind under Docker¶
Similarly to instance names, ports will also clash.
Thus application-instance-port-n has to be used just like it was done with
${application-instance-id}.
application-instance-port-n name is generated and n is substituted with
generated port indexes.
We will use one port and so the variable name will be
${application-instance-port-1}.
Example usage of application-instance-port-1¶
Conf (conf/conf.yml):
app:
placeHolder:
name: "PlaceHolderManagerImpl"
version: "1.0.0"
filesToReplace:
- "${application-instance-path}/bin/environment/env.bash"
serviceRepository:
entities:
- entity:
priority: 1
port: ${application-instance-port-1}
protocol:
type: "HTTP"
version: "1.1"
isExternal: true
isInternal: true
Env (bin/environment/env.bash):
Start (bin/bash-scripts/start.bash):
#!/usr/bin/env bash
trap "exit 128" INT
set -eu
SOURCE="${BASH_SOURCE[0]}"
while [[ -h "${SOURCE}" ]] ; do
DIR="$(cd -P "$(dirname "${SOURCE}")" >/dev/null 2>&1 && pwd)"
SOURCE="$(readlink "${SOURCE}")"
[[ "${SOURCE}" != /* ]] && SOURCE="${DIR}/${SOURCE}"
done
SCRIPT_DIR="$(cd -P "$(dirname "${SOURCE}")" >/dev/null 2>&1 && pwd)"
cd "${SCRIPT_DIR}"
source ../environment/env.bash
docker run --detach --restart="no" --name="APP-NAME-${INSTANCE}" \
-p "${PORT_1}:APP-PORT" CONTAINER-NAME
echo "Successfully started"
Putting it all together for dockerized applications¶
Lets take a look at using Docker inside Onteon for a nginx container.
Conf (conf/conf.yml):
---
app:
name: "nginx"
version: "1.26.3"
appType: "standard"
procType: "native"
processProvider:
name: "GenericOsProcessProviderImpl"
version: "1.0.0"
executable:
start:
command: "bash ${application-instance-path}/bin/bash-scripts/start.bash"
successLine: "Successfully started"
getPid: "bash ${application-instance-path}/bin/bash-scripts/getPid.bash"
stop:
command: "bash ${application-instance-path}/bin/bash-scripts/stop.bash"
terminate:
command: "bash ${application-instance-path}/bin/bash-scripts/terminate.bash"
placeHolder:
name: "PlaceHolderManagerImpl"
version: "1.0.0"
filesToReplace:
- "${application-instance-path}/bin/environment/env.bash"
serviceRepository:
entities:
- entity:
priority: 1
port: ${application-instance-port-1}
protocol:
type: "HTTP"
version: "1.1"
isExternal: true
isInternal: true
Env (bin/environment/env.bash):
#!/usr/bin/env bash
INSTANCE="${application-instance-id}"
PORT_1="${application-instance-port-1}"
APP="nginx"
VERSION="1.26.3"
CONTAINER_PORT_1="80"
Start will run Nginx using special Onteon-generated port and instance name.
Start (bin/bash-scripts/start.bash):
#!/usr/bin/env bash
trap "exit 128" INT
set -eu
SOURCE="${BASH_SOURCE[0]}"
while [[ -h "${SOURCE}" ]] ; do
DIR="$(cd -P "$(dirname "${SOURCE}")" >/dev/null 2>&1 && pwd)"
SOURCE="$(readlink "${SOURCE}")"
[[ "${SOURCE}" != /* ]] && SOURCE="${DIR}/${SOURCE}"
done
SCRIPT_DIR="$(cd -P "$(dirname "${SOURCE}")" >/dev/null 2>&1 && pwd)"
cd "${SCRIPT_DIR}"
source ../environment/env.bash
docker run --detach --restart="no" --name="${APP}-${INSTANCE}" \
-p "${PORT_1}:${CONTAINER_PORT_1}" "${APP}:${VERSION}"
echo "Successfully started"
GetPid extracts real container PID as discussed above.
getPid (bin/bash-scripts/getPid.bash):
#!/usr/bin/env bash
trap "exit 128" INT
set -eu
SOURCE="${BASH_SOURCE[0]}"
while [[ -h "${SOURCE}" ]] ; do
DIR="$(cd -P "$(dirname "${SOURCE}")" >/dev/null 2>&1 && pwd)"
SOURCE="$(readlink "${SOURCE}")"
[[ "${SOURCE}" != /* ]] && SOURCE="${DIR}/${SOURCE}"
done
SCRIPT_DIR="$(cd -P "$(dirname "${SOURCE}")" >/dev/null 2>&1 && pwd)"
cd "${SCRIPT_DIR}"
source ../environment/env.bash
exec docker inspect -f '{{.State.Pid}}' "${APP}-${INSTANCE}"
Stop will stop Nginx Docker container with docker stop.
Stop (bin/bash-scripts/stop.bash):
#!/usr/bin/env bash
trap "exit 128" INT
set -eu
SOURCE="${BASH_SOURCE[0]}"
while [[ -h "${SOURCE}" ]] ; do
DIR="$(cd -P "$(dirname "${SOURCE}")" >/dev/null 2>&1 && pwd)"
SOURCE="$(readlink "${SOURCE}")"
[[ "${SOURCE}" != /* ]] && SOURCE="${DIR}/${SOURCE}"
done
SCRIPT_DIR="$(cd -P "$(dirname "${SOURCE}")" >/dev/null 2>&1 && pwd)"
cd "${SCRIPT_DIR}"
source ../environment/env.bash
docker stop "${APP}-${INSTANCE}"
Terminate will kill Nginx Docker container with docker kill.
Terminate (bin/bash-scripts/terminate.bash):
#!/usr/bin/env bash
trap "exit 128" INT
set -eu
SOURCE="${BASH_SOURCE[0]}"
while [[ -h "${SOURCE}" ]] ; do
DIR="$(cd -P "$(dirname "${SOURCE}")" >/dev/null 2>&1 && pwd)"
SOURCE="$(readlink "${SOURCE}")"
[[ "${SOURCE}" != /* ]] && SOURCE="${DIR}/${SOURCE}"
done
SCRIPT_DIR="$(cd -P "$(dirname "${SOURCE}")" >/dev/null 2>&1 && pwd)"
cd "${SCRIPT_DIR}"
source ../environment/env.bash
docker kill "${APP}-${INSTANCE}"
If everything works correctly, then in the docker ps -a command output
there should be an app instance that has a random hash at the end of
its name and also it should be possible to send requests to the
dockerized nginx app on both internal and external load balancer,
for example: