Example configuration of Vagrantfile:
:Vagrantfile
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/xenial64"
# config.vm.box_check_update = false
config.vm.network "forwarded_port", guest: 80, host: 8080
config.vm.network "forwarded_port", guest: 8888, host: 18888
config.vm.network "private_network", ip: "192.168.33.10"
config.vm.provider "virtualbox" do |vb|
# # Display the VirtualBox GUI when booting the machine
# vb.gui = true
#
# # Customize the amount of memory on the VM:
vb.memory = "8192"
end
end
Download devstack.
sudo add-apt-repository ppa:masterminds/glide && sudo apt-get update
sudo apt install glide
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
# To build 'dep'
# (workaround the toml issue)
sudo tar -C /usr/local -xzf go1.7.linux-amd64.tar.gz
mkdir -p ~/go/bin
go get -u github.com/golang/dep/...
cd $GOPATH/src/github.com/golang/dep
git checkout 8cdbc074c229c0e225a1a37a88fbadef5d988595
go get github.com/golang/dep/...
rm -rf /usr/local/go
unet GOPATH
cd ~
git clone https://git.openstack.org/openstack-dev/devstack.git $DEVSTACK_DIR
cd devstack
cp samples/local.conf ./
As a next step, edit local.conf as follows.
Note: You have to enable aodh and ceilometer to confirm alarm notification.
GIT_BASE=https://git.openstack.org
HOST_IP=192.168.33.10
enable_plugin aodh https://git.openstack.org/openstack/aodh
enable_plugin picasso https://github.com/openstack/picasso.git
CEILOMETER_BACKEND=mongodb
enable_plugin ceilometer https://git.openstack.org/openstack/ceilometer
# Picasso configuration
PICASSO_REPO=${PICASSO_REPO:-https://github.com/openstack/picasso.git}
PICASSO_BRANCH=${PICASSO_BRANCH:-master}
PICASSO_DIR=${PICASSO_DIR:-${DEST}/picasso}
PICASSO_PORT=${PICASSO_PORT:-10001}
PICASSO_LOG_LEVEL=${PICASSO_LOG_LEVEL:-DEBUG}
PICASSO_LOG_FILE=${PICASSO_LOG_FILE:-/var/log/picasso-api.log}
# Picasso client configuration
PICASSO_CLIENT_REPO=${PICASSO_CLIENT_REPO:-https://github.com/openstack/python-picassoclient.git}
PICASSO_CLIENT_DIR=${PICASSO_CLIENT_DIR:-${DEST}/python-picassoclient}
PICASSO_CLIENT_BRANCH=${PICASSO_CLIENT_BRANCH:-master}
# Functions parameters
FUNCTIONS_REPO=${FUNCTIONS_REPO:-https://github.com/iron-io/functions.git}
FUNCTIONS_BRANCH=${FUNCTIONS_BRANCH:-master}
FUNCTIONS_PORT=${FUNCTIONS_PORT:-10501}
FUNCTIONS_DB=${FUNCTIONS_DBPATH:-bolt://$FUNCTIONS_DIR/devstack.functions.storage.db?bucket=funcs}
FUNCTIONS_MQ=${FUNCTIONS_DBPATH:-bolt://$FUNCTIONS_DIR/devstack.functions.queue.db}
FUNCTIONS_LOG_LEVEL=${FUNCTIONS_LOG_LEVEL:-DEBUG}
DOCKER_OPTS=${DOCKER_OPTS:---dns 8.8.8.8 --storage-driver=overlay2 -H fd://}
Then, invoke stack.sh
# For small disk instances:
sudo apt install mongodb-server
sudo vi /etc/mongodb.conf
----
#journal = true
nojournal = true
----
./stack.sh
vi /opt/stack/picasso/Dockerfile
RUN pip3 install aiohttp==1.3.0
Revert to March/2017 version of 'functions'.
vi /opt/stack/picasso/devstack/plugin.sh
function install_functions {
echo_summary "Pulling Functions sources"
git_clone $FUNCTIONS_REPO $GOPATH/src/github.com/iron-io/functions $FUNCTIONS_BRANCH
(cd $GOPATH/src/github.com/iron-io/functions && git checkout 90f93706f229c90d6465be743e23b40492462831)
pushd $FUNCTIONS_DIR && GOPATH=${GOPATH} make all; popd
}
source ~/devstack/openrc admin
WARNING: setting legacy OS_TENANT_NAME to support cli tools.
openstack fn apps list
openstack fn apps create alarm-notifier-app
func_name=`openstack fn apps list | grep alarm-notifier-app | awk '{print $2}'`
echo $func_name
+-------------+--------------------------------------------------+ | Field | Value | +-------------+--------------------------------------------------+ | name | alarm-notifier-app-89acd99a48a | | created_at | 2017-04-19 02:13:11.814701 | | updated_at | 2017-04-19 02:13:11.814715 | | project_id | 89acd99a48a0452b898b3e4f690a5b80 | | config | None | | id | 26c3911622a84e729e8df793126443da | | description | App for project 89acd99a48a0452b898b3e4f690a5b80 | +-------------+--------------------------------------------------+ alarm-notifier-app-89acd99a48a
openstack fn routes create $func_name /hello async iron/hello --is-public
+-----------------+------------+ | Field | Value | +-----------------+------------+ | image | iron/hello | | memory | 128 | | is_public | True | | timeout | 30 | | path | /hello | | max_concurrency | 1 | | type | async | +-----------------+------------+
nova boot --image $(glance image-list | awk '/cirros-0.3.5-x86_64-disk / {print $2}') --flavor 42 test_alarms
/usr/local/lib/python2.7/dist-packages/novaclient/client.py:278: UserWarning: The 'tenant_id' argument is deprecated in Ocata and its use may result in errors in future releases. As 'project_id' is provided, the 'tenant_id' argument will be ignored. warnings.warn(msg) +--------------------------------------+-----------------------------------------------------------------+ | Property | Value | +--------------------------------------+-----------------------------------------------------------------+ | OS-DCF:diskConfig | MANUAL | | OS-EXT-AZ:availability_zone | | | OS-EXT-SRV-ATTR:host | - | | OS-EXT-SRV-ATTR:hostname | test-alarms | | OS-EXT-SRV-ATTR:hypervisor_hostname | - | | OS-EXT-SRV-ATTR:instance_name | | | OS-EXT-SRV-ATTR:kernel_id | | | OS-EXT-SRV-ATTR:launch_index | 0 | | OS-EXT-SRV-ATTR:ramdisk_id | | | OS-EXT-SRV-ATTR:reservation_id | r-mx9oafnh | | OS-EXT-SRV-ATTR:root_device_name | - | | OS-EXT-SRV-ATTR:user_data | - | | OS-EXT-STS:power_state | 0 | | OS-EXT-STS:task_state | scheduling | | OS-EXT-STS:vm_state | building | | OS-SRV-USG:launched_at | - | | OS-SRV-USG:terminated_at | - | | accessIPv4 | | | accessIPv6 | | | adminPass | JQUoefbd2g8S | | config_drive | | | created | 2017-04-19T02:13:34Z | | description | - | | flavor | m1.nano (42) | | hostId | | | host_status | | | id | 49f6c81a-12ad-49bf-9199-6c9ed190cc91 | | image | cirros-0.3.5-x86_64-disk (3628bb95-0c01-44f7-ba1c-2b13199eeb62) | | key_name | - | | locked | False | | metadata | {} | | name | test_alarms | | os-extended-volumes:volumes_attached | [] | | progress | 0 | | security_groups | default | | status | BUILD | | tags | [] | | tenant_id | 89acd99a48a0452b898b3e4f690a5b80 | | updated | 2017-04-19T02:13:34Z | | user_id | 6f7eae51aaaa4a868c23e2fb736c87a4 | +--------------------------------------+-----------------------------------------------------------------+
aodh alarm create \
--type threshold \
--name cpu_high \
--description 'instance running hot' \
--meter-name cpu_util \
--threshold 20.0 \
--comparison-operator gt \
--statistic max \
--period 600 \
--evaluation-periods 1 \
--alarm-action $(openstack fn routes expose-url $func_name /hello) \
--query resource_id=$(nova list | grep test_alarms | awk '{print $2}')
/usr/local/lib/python2.7/dist-packages/novaclient/client.py:278: UserWarning: The 'tenant_id' argument is deprecated in Ocata and its use may result in errors in future releases. As 'project_id' is provided, the 'tenant_id' argument will be ignored. warnings.warn(msg) +---------------------------+--------------------------------------------------+ | Field | Value | +---------------------------+--------------------------------------------------+ | alarm_actions | [u'http://192.168.33.10:10001/r/alarm-notifier- | | | app-89acd99a48a/hello'] | | alarm_id | 268618b5-4b6f-4141-8124-0b4a8c726b6d | | comparison_operator | gt | | description | instance running hot | | enabled | True | | evaluation_periods | 1 | | exclude_outliers | False | | insufficient_data_actions | [] | | meter_name | cpu_util | | name | cpu_high | | ok_actions | [] | | period | 600 | | project_id | 89acd99a48a0452b898b3e4f690a5b80 | | query | resource_id = 49f6c81a-12ad- | | | 49bf-9199-6c9ed190cc91 | | repeat_actions | False | | severity | low | | state | insufficient data | | state_timestamp | 2017-04-19T02:15:12.240495 | | statistic | max | | threshold | 20.0 | | time_constraints | [] | | timestamp | 2017-04-19T02:15:12.240495 | | type | threshold | | user_id | 6f7eae51aaaa4a868c23e2fb736c87a4 | +---------------------------+--------------------------------------------------+
As a first step, log in to the instance.
Then, invoke dd command so that aodh alarm is going to be fired.
openstack security group rule create default --protocol icmp --remote-ip 0.0.0.0/0
openstack security group rule create default --protocol tcp --dst-port 22:22 --remote-ip 0.0.0.0/0
ns_rq=`ip netns show | grep qrouter`
sudo ip netns exec $ns_rq bash
ssh cirros@10.0.0.6
dd if=/dev/zero of=/dev/null
aodh alarm-history search
+-------------------+-------------------+------------------+-------------------+ | alarm_id | timestamp | type | detail | +-------------------+-------------------+------------------+-------------------+ | 268618b5-4b6f-414 | 2017-04-19T02:30: | state transition | {"transition_reas | | 1-8124-0b4a8c726b | 16.202627 | | on": "Transition | | 6d | | | to alarm due to 1 | | | | | samples outside | | | | | threshold, most | | | | | recent: | | | | | 38.3480281761", | | | | | "state": "alarm"} | | 268618b5-4b6f-414 | 2017-04-19T02:15: | creation | {"alarm_actions": | | 1-8124-0b4a8c726b | 12.240495 | | ["http://192.168. | | 6d | | | 33.10:10001/r | | | | | /alarm-notifier- | | | | | app-89acd99a48a/h | | | | | ello"], | | | | | "user_id": "6f7ea | | | | | e51aaaa4a868c23e2 | | | | | fb736c87a4", | | | | | "name": | | | | | "cpu_high", | | | | | "state": | | | | | "insufficient | | | | | data", | | | | | "timestamp": "201 | | | | | 7-04-19T02:15:12. | | | | | 240495", | | | | | "description": | | | | | "instance running | | | | | hot", "enabled": | | | | | true, "state_time | | | | | stamp": "2017-04- | | | | | 19T02:15:12.24049 | | | | | 5", "rule": | | | | | {"meter_name": | | | | | "cpu_util", "eval | | | | | uation_periods": | | | | | 1, "period": 600, | | | | | "statistic": | | | | | "max", | | | | | "threshold": | | | | | 20.0, "query": | | | | | [{"field": | | | | | "resource_id", | | | | | "type": "", | | | | | "value": | | | | | "49f6c81a-12ad-49 | | | | | bf-9199-6c9ed190c | | | | | c91", "op": | | | | | "eq"}], "comparis | | | | | on_operator": | | | | | "gt", "exclude_ou | | | | | tliers": false}, | | | | | "alarm_id": "2686 | | | | | 18b5-4b6f-4141-81 | | | | | 24-0b4a8c726b6d", | | | | | "time_constraints | | | | | ": [], "insuffici | | | | | ent_data_actions" | | | | | : [], | | | | | "repeat_actions": | | | | | false, | | | | | "ok_actions": [], | | | | | "project_id": "89 | | | | | acd99a48a0452b898 | | | | | b3e4f690a5b80", | | | | | "type": | | | | | "threshold", | | | | | "severity": | | | | | "low"} | +-------------------+-------------------+------------------+-------------------+
It seems that Iron.io does not support convenient way to check execution history so far. You can track history on syslog.
grep "Apr 19 02:30" /var/log/syslog | grep functions
Apr 19 02:30:16 ubuntu-xenial functions[23573]: time="2017-04-19T02:30:16Z" level=debug msg="Finding route on datastore" action="server.handleRunnerRequest)-fm" app=alarm-notifier-app-89acd99a48a call_id=07713835-50e5-5c9a-bd7f-ee661d0fd5c5 path="/hello" route="/hello" Apr 19 02:30:16 ubuntu-xenial functions[23573]: time="2017-04-19T02:30:16Z" level=debug msg="Got routes from datastore" action="server.handleRunnerRequest)-fm" app=alarm-notifier-app-89acd99a48a call_id=07713835-50e5-5c9a-bd7f-ee661d0fd5c5 route="/hello" routes=1 Apr 19 02:30:16 ubuntu-xenial functions[23573]: time="2017-04-19T02:30:16Z" level=info msg="Pushed to MQ" call_id=07713835-50e5-5c9a-bd7f-ee661d0fd5c5 Apr 19 02:30:16 ubuntu-xenial functions[23573]: time="2017-04-19T02:30:16Z" level=info msg="Added new task to queue" action="server.handleRunnerRequest)-fm" app=alarm-notifier-app-89acd99a48a call_id=07713835-50e5-5c9a-bd7f-ee661d0fd5c5 image="iron/hello" route="/hello" Apr 19 02:30:16 ubuntu-xenial functions[23573]: time="2017-04-19T02:30:16Z" level=info msg=Reserved call_id=07713835-50e5-5c9a-bd7f-ee661d0fd5c5 Apr 19 02:30:16 ubuntu-xenial functions[23573]: time="2017-04-19T02:30:16Z" level=debug msg="Running task:07713835-50e5-5c9a-bd7f-ee661d0fd5c5" call_id=07713835-50e5-5c9a-bd7f-ee661d0fd5c5 runner=async Apr 19 02:30:16 ubuntu-xenial functions[23573]: time="2017-04-19T02:30:16Z" level=debug msg="Processed task" call_id=07713835-50e5-5c9a-bd7f-ee661d0fd5c5 runner=async Apr 19 02:30:16 ubuntu-xenial functions[23573]: time="2017-04-19T02:30:16Z" level=info call_id=07713835-50e5-5c9a-bd7f-ee661d0fd5c5 name=run.alarm-notifier-app-89acd99a48a.requests runner=async type=count value=1 Apr 19 02:30:16 ubuntu-xenial functions[23573]: time="2017-04-19T02:30:16Z" level=info call_id=07713835-50e5-5c9a-bd7f-ee661d0fd5c5 name=run.alarm-notifier-app-89acd99a48a.waittime runner=async type=time value=0s Apr 19 02:30:16 ubuntu-xenial functions[23573]: time="2017-04-19T02:30:16Z" level=info msg=Deleted call_id=07713835-50e5-5c9a-bd7f-ee661d0fd5c5 Apr 19 02:30:16 ubuntu-xenial functions[23573]: time="2017-04-19T02:30:16Z" level=info msg="Task complete" call_id=07713835-50e5-5c9a-bd7f-ee661d0fd5c5 runner=async Apr 19 02:30:17 ubuntu-xenial functions[23573]: time="2017-04-19T02:30:17Z" level=debug msg="Starting container execution" call_id=07713835-50e5-5c9a-bd7f-ee661d0fd5c5 container=task-1492569016991038844-07713835-50e5-5c9a-bd7f-ee661d0fd5c5 runner=async Apr 19 02:30:17 ubuntu-xenial functions[23573]: time="2017-04-19T02:30:17Z" level=info msg="Hello World!" app_name=alarm-notifier-app-89acd99a48a call_id=07713835-50e5-5c9a-bd7f-ee661d0fd5c5 image="iron/hello" path= runner=async user_log=true Apr 19 02:30:17 ubuntu-xenial functions[23573]: time="2017-04-19T02:30:17Z" level=info msg="container status" call_id=07713835-50e5-5c9a-bd7f-ee661d0fd5c5 container_error= container_finished=2017-04-19 02:30:17.340404294 +0000 UTC container_running=false container_status=exited exit_code=0 runner=async Apr 19 02:30:17 ubuntu-xenial functions[23573]: time="2017-04-19T02:30:17Z" level=info call_id=07713835-50e5-5c9a-bd7f-ee661d0fd5c5 name=run.alarm-notifier-app-89acd99a48a.succeeded runner=async type=count value=1 Apr 19 02:30:17 ubuntu-xenial functions[23573]: time="2017-04-19T02:30:17Z" level=info call_id=07713835-50e5-5c9a-bd7f-ee661d0fd5c5 name=run.alarm-notifier-app-89acd99a48a.time runner=async type=time value=440.736062ms Apr 19 02:30:17 ubuntu-xenial functions[23573]: time="2017-04-19T02:30:17Z" level=info call_id=07713835-50e5-5c9a-bd7f-ee661d0fd5c5 name="run.exec_time" runner=async type=time value=440.736062ms
openstack fn routes list $func_name
+-------+--------+----------+--------+---------+-----------------+-----------+--------+ | type | path | image | memory | timeout | max_concurrency | is_public | config | +-------+--------+----------+--------+---------+-----------------+-----------+--------+ | async | /hello | iron/hel | 128 | 30 | 1 | True | | | | | lo | | | | | | +-------+--------+----------+--------+---------+-----------------+-----------+--------+
openstack fn routes show $func_name /hello
+-----------------+------------+ | Field | Value | +-----------------+------------+ | image | iron/hello | | memory | 128 | | is_public | True | | timeout | 30 | | path | /hello | | max_concurrency | 1 | | type | async | +-----------------+------------+
Operators can also be accessd to iron.io via native API or fn-CLI directly.
To install 'fn' command, invoke following url.
curl -LSs https://goo.gl/VZrL8t | sh
export API_URL=http://localhost:10501
fn apps list
alarm-notifier-app-89acd99a48a
fn routes list $func_name
path image endpoint /hello iron/hello
fn routes call $func_name /hello
{"call_id":"71c8630b-f2fb-5bce-b022-62e635247df8"}
grep 71c8630b-f2fb-5bce-b022-62e635247df8 /var/log/syslog
Apr 19 02:35:07 ubuntu-xenial functions[23573]: time="2017-04-19T02:35:07Z" level=debug msg="Finding route on datastore" action="server.handleRunnerRequest)-fm" app=alarm-notifier-app-89acd99a48a call_id=71c8630b-f2fb-5bce-b022-62e635247df8 path="/hello" route="/hello" Apr 19 02:35:07 ubuntu-xenial functions[23573]: time="2017-04-19T02:35:07Z" level=debug msg="Got routes from datastore" action="server.handleRunnerRequest)-fm" app=alarm-notifier-app-89acd99a48a call_id=71c8630b-f2fb-5bce-b022-62e635247df8 route="/hello" routes=1 Apr 19 02:35:07 ubuntu-xenial functions[23573]: time="2017-04-19T02:35:07Z" level=info msg="Pushed to MQ" call_id=71c8630b-f2fb-5bce-b022-62e635247df8 Apr 19 02:35:07 ubuntu-xenial functions[23573]: time="2017-04-19T02:35:07Z" level=info msg="Added new task to queue" action="server.handleRunnerRequest)-fm" app=alarm-notifier-app-89acd99a48a call_id=71c8630b-f2fb-5bce-b022-62e635247df8 image="iron/hello" route="/hello" Apr 19 02:35:08 ubuntu-xenial functions[23573]: time="2017-04-19T02:35:08Z" level=info msg=Reserved call_id=71c8630b-f2fb-5bce-b022-62e635247df8 Apr 19 02:35:08 ubuntu-xenial functions[23573]: time="2017-04-19T02:35:08Z" level=debug msg="Running task:71c8630b-f2fb-5bce-b022-62e635247df8" call_id=71c8630b-f2fb-5bce-b022-62e635247df8 runner=async Apr 19 02:35:08 ubuntu-xenial functions[23573]: time="2017-04-19T02:35:08Z" level=debug msg="Processed task" call_id=71c8630b-f2fb-5bce-b022-62e635247df8 runner=async Apr 19 02:35:08 ubuntu-xenial functions[23573]: time="2017-04-19T02:35:08Z" level=info call_id=71c8630b-f2fb-5bce-b022-62e635247df8 name=run.alarm-notifier-app-89acd99a48a.requests runner=async type=count value=1 Apr 19 02:35:08 ubuntu-xenial functions[23573]: time="2017-04-19T02:35:08Z" level=info call_id=71c8630b-f2fb-5bce-b022-62e635247df8 name=run.alarm-notifier-app-89acd99a48a.waittime runner=async type=time value=0s Apr 19 02:35:08 ubuntu-xenial functions[23573]: time="2017-04-19T02:35:08Z" level=info msg=Deleted call_id=71c8630b-f2fb-5bce-b022-62e635247df8 Apr 19 02:35:08 ubuntu-xenial functions[23573]: time="2017-04-19T02:35:08Z" level=info msg="Task complete" call_id=71c8630b-f2fb-5bce-b022-62e635247df8 runner=async Apr 19 02:35:08 ubuntu-xenial functions[23573]: time="2017-04-19T02:35:08Z" level=debug msg="Starting container execution" call_id=71c8630b-f2fb-5bce-b022-62e635247df8 container=task-1492569308306242597-71c8630b-f2fb-5bce-b022-62e635247df8 runner=async Apr 19 02:35:08 ubuntu-xenial functions[23573]: time="2017-04-19T02:35:08Z" level=info msg="Hello World!" app_name=alarm-notifier-app-89acd99a48a call_id=71c8630b-f2fb-5bce-b022-62e635247df8 image="iron/hello" path= runner=async user_log=true Apr 19 02:35:08 ubuntu-xenial functions[23573]: time="2017-04-19T02:35:08Z" level=info msg="container status" call_id=71c8630b-f2fb-5bce-b022-62e635247df8 container_error= container_finished=2017-04-19 02:35:08.556707421 +0000 UTC container_running=false container_status=exited exit_code=0 runner=async Apr 19 02:35:08 ubuntu-xenial functions[23573]: time="2017-04-19T02:35:08Z" level=info call_id=71c8630b-f2fb-5bce-b022-62e635247df8 name=run.alarm-notifier-app-89acd99a48a.succeeded runner=async type=count value=1 Apr 19 02:35:08 ubuntu-xenial functions[23573]: time="2017-04-19T02:35:08Z" level=info call_id=71c8630b-f2fb-5bce-b022-62e635247df8 name=run.alarm-notifier-app-89acd99a48a.time runner=async type=time value=334.906475ms Apr 19 02:35:08 ubuntu-xenial functions[23573]: time="2017-04-19T02:35:08Z" level=info call_id=71c8630b-f2fb-5bce-b022-62e635247df8 name="run.exec_time" runner=async type=time value=334.906475ms
export DOCKER_HOST=tcp://localhost:2375
mkdir ~/picasso-func ; cd ~/picasso-func
vi func.go
func.go:
package main
import (
"encoding/json"
"fmt"
"os"
)
type Person struct {
Name string
}
func main() {
p := &Person{Name: "World"}
json.NewDecoder(os.Stdin).Decode(p)
fmt.Printf("Hello %v!", p.Name)
}
fn init testuser/hello
fn build
fn run
fn build && fn push
fn apps create myapp
fn routes create myapp /hello
export DOCKER_HOST=tcp://localhost:2375
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE testuser/hello 0.0.1 d2a63df5a52d 5 minutes ago 12.6 MB picasso-api latest f8aa15239468 2 hours ago 791 MB <none> <none> 60be38a5d6e7 20 hours ago 791 MB <none> <none> dbf4f0595bb5 24 hours ago 791 MB <none> <none> 42a97c056272 26 hours ago 791 MB <none> <none> d719aa45609a 26 hours ago 791 MB python 3.5 4e5ed9f6613e 8 days ago 687 MB iron/go dev 3d25645a73f8 2 weeks ago 857 MB iron/hello latest f4dd2a73dac8 4 months ago 12.1 MB iron/go latest c05f82fa066a 12 months ago 10.5 MB
curl $API_URL/r/myapp/hello
Hello World!
fn apps list
alarm-notifier-app-5811d3471a5 alarm-notifier-app-db507b128d5 myapp
fn routes list myapp
path image endpoint /hello testuser/hello:0.0.1