dexter submitted this change.

View Change

Approvals: laforge: Looks good to me, but someone else must approve Jenkins Builder: Verified dexter: Looks good to me, approved jolly: Looks good to me, but someone else must approve
contrib: restructure REST API usage examples (tryme-scripts)

The so called tryme scripts are using a very clumsy method to set
the varying parameters (tryme.cfg). The files also mix with other
unrelated files in the contrib directory. There is also a lot of
distracting output displayed which complicates the usage of the
examples even further. This patch fixes those shortcomings.

- put everything related to the usage example into a dedicated
directory.
- renovate restop.py so that it produces more readable output.
- in the tryme_*.sh scripts, avoid output that is not needed.
- cleanup tryme.cfg so that it only contains one set of parameters,
add some helpful comments.
- add functionality to pass the the parameters either via
commandline options or via tryme.cfg, add a parameter to point
to an alternative .cfg file, so that users can use multiple
different configurations.
- update documentation
- cleanup other minor inconsistencies

Related: SYS#8100
Change-Id: I4e42ce85c84b47d3561011083da4a1e54958fd8e
---
A contrib/rest_api_usage_example/getopts.sh
A contrib/rest_api_usage_example/lookup.sh
A contrib/rest_api_usage_example/restop.py
A contrib/rest_api_usage_example/tryme.cfg
R contrib/rest_api_usage_example/tryme_addEim.sh
R contrib/rest_api_usage_example/tryme_configureImmediateEnable.sh
R contrib/rest_api_usage_example/tryme_delete.sh
R contrib/rest_api_usage_example/tryme_deleteEim.sh
R contrib/rest_api_usage_example/tryme_disable.sh
R contrib/rest_api_usage_example/tryme_download.sh
R contrib/rest_api_usage_example/tryme_enable.sh
R contrib/rest_api_usage_example/tryme_euiccDataRequest.sh
R contrib/rest_api_usage_example/tryme_euicc_get_state.sh
R contrib/rest_api_usage_example/tryme_euicc_set_state.sh
R contrib/rest_api_usage_example/tryme_getRAT.sh
R contrib/rest_api_usage_example/tryme_listEim.sh
R contrib/rest_api_usage_example/tryme_listProfileInfo.sh
R contrib/rest_api_usage_example/tryme_updateEim.sh
D contrib/restop.py
D contrib/tryme.cfg
D contrib/tryme_lookup.sh
M doc/examples.md
22 files changed, 252 insertions(+), 239 deletions(-)

diff --git a/contrib/rest_api_usage_example/getopts.sh b/contrib/rest_api_usage_example/getopts.sh
new file mode 100755
index 0000000..b97fb72
--- /dev/null
+++ b/contrib/rest_api_usage_example/getopts.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+EID=""
+AC="(none)"
+ICCID="(none)"
+CFG_FILE="tryme.cfg"
+
+while getopts "c:e:a:i:h" opt; do
+ case $opt in
+ c)
+ CFG_FILE=$OPTARG
+ ;;
+ e)
+ EID=$OPTARG
+ CFG_FILE=""
+ ;;
+ a)
+ AC=$OPTARG
+ CFG_FILE=""
+ ;;
+ i)
+ ICCID=$OPTARG
+ CFG_FILE=""
+ ;;
+ h)
+ echo "Usage: $0 -c path/to/my/tryme.cfg"
+ echo " $0 -e EID -a AC -i ICCID"
+ exit 0
+ ;;
+ \?)
+ echo "invalid option: -$OPTARG"
+ ;;
+ :)
+ echo "option -$OPTARG requires an argument."
+ ;;
+ esac
+done
+
+if [ -n "$CFG_FILE" ]; then
+ echo "sourcing parameters from config file: $CFG_FILE"
+ source $CFG_FILE
+fi
+
+if [ -z "$EID" ]; then
+ echo "error: no EID (mandatory) specified!"
+ exit 1
+fi
+
+echo "parameters:"
+echo "EID: $EID"
+echo "ICCID: $ICCID"
+echo "AC: $AC"
diff --git a/contrib/rest_api_usage_example/lookup.sh b/contrib/rest_api_usage_example/lookup.sh
new file mode 100755
index 0000000..988f5a3
--- /dev/null
+++ b/contrib/rest_api_usage_example/lookup.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+if [[ $# == 2 ]]; then
+ sleep 5
+ while true; do
+ ./restop.py -l -f $1 -r $2 > /dev/null
+ sleep 5
+ done
+else
+ echo "Usage: $0 facility resource-id"
+fi
+
+
+
diff --git a/contrib/rest_api_usage_example/restop.py b/contrib/rest_api_usage_example/restop.py
new file mode 100755
index 0000000..cf31e4d
--- /dev/null
+++ b/contrib/rest_api_usage_example/restop.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2025 Onomondo ApS & sysmocom - s.f.m.c. GmbH. All rights reserved.
+# SPDX-License-Identifier: AGPL-3.0-only
+# Author: Philipp Maier <pmaier@sysmocom.de> / sysmocom - s.f.m.c. GmbH
+
+import sys
+import argparse
+import json
+import requests
+import pprint
+import textwrap
+
+DOWNLOAD_DEFAULT='{ "eidValue" : "89882119900000000000000000000005", "order" : {"activationCode" : "1$testsmdpplus1.example.com$OPxLD-UVRuC-jysPI-YkOwT"}}'
+PSMO_DEFAULT='{ "eidValue" : "89882119900000000000000000000005", "order" : [{"psmo" : "enable", "iccid" : "98001032547698103285", "rollback" : false }]}'
+
+req_headers = {
+ 'Content-Type': 'application/json',
+ 'X-Admin-Protocol': 'onomondo/eim/v1.0.0',
+}
+
+def h2b(s) -> bytearray:
+ """convert from a string of hex nibbles to a sequence of bytes"""
+ return bytes.fromhex(s)
+
+def rest_create(host, facility, Json):
+ r = requests.post("http://" + str(host) + "/" + str(facility) + "/create", json=Json, headers=req_headers)
+ return str(r.url)
+
+def rest_lookup(host, facility, ResourceId):
+ r = requests.get("http://" + str(host) + "/" + str(facility) + "/lookup/" + str(ResourceId), headers=req_headers)
+ return r.json()
+
+def rest_delete(host, facility, ResourceId):
+ r = requests.get("http://" + str(host) + "/" + str(facility) + "/delete/" + str(ResourceId), headers=req_headers)
+ return r.json()
+
+def rest_list(host, facility):
+ r = requests.get("http://" + str(host) + "/" + str(facility) + "/list/", headers=req_headers)
+ return r.json()
+
+def main(argv):
+ parser = argparse.ArgumentParser(prog='restop', description='utility to operate on the REST API of onomondo_eim')
+ parser.add_argument("-s", "--host", default="127.0.0.1:8080")
+ parser.add_argument("-f", "--facility", help="REST API facility", default="download")
+ parser.add_argument("-c", "--create", help="creata a new REST resource", action='store_true')
+ parser.add_argument("-l", "--lookup", help="lookup an existing REST resource", action='store_true')
+ parser.add_argument("-d", "--delete", help="delete a no longer needed REST resource", action='store_true')
+ parser.add_argument("-t", "--list", help="list all currently existing REST resources", action='store_true')
+ parser.add_argument("-r", "--resource-id", help="REST resource identifier")
+ parser.add_argument("-j", "--json", help="JSON input")
+ parser.add_argument("-e", "--erlang-debuginfo", help="decode and display erlang debug information", action='store_true')
+
+ args = parser.parse_args()
+ pp = pprint.PrettyPrinter()
+
+ if args.create:
+ print("create on: " + str(args.host), file=sys.stderr)
+ print(" facility: " + str(args.facility), file=sys.stderr)
+ if args.json:
+ args_json = json.loads(str(args.json))
+ else:
+ if args.facility == "download":
+ args_json = json.loads(DOWNLOAD_DEFAULT)
+ elif args.facility == "psmo":
+ args_json = json.loads(PSMO_DEFAULT)
+ args_json_pretty = pp.pformat(args_json)
+ print(" json: " + textwrap.indent(args_json_pretty, " " * 7)[7:], file=sys.stderr)
+ resource_url = rest_create(args.host, args.facility, args_json)
+ print(" resourceId: " + resource_url.rsplit('/')[-1], file=sys.stderr)
+ print(resource_url)
+
+ elif args.lookup:
+ print("lookup on: " + str(args.host), file=sys.stderr)
+ print(" facility: " + str(args.facility), file=sys.stderr)
+ print(" resourceId: " + str(args.resource_id), file=sys.stderr)
+ result_json = rest_lookup(args.host, args.facility, args.resource_id)
+ result_json_pretty = pp.pformat(result_json)
+ print(" json: " + textwrap.indent(result_json_pretty, " " * 7)[7:], file=sys.stderr)
+ if args.erlang_debuginfo and 'debuginfo' in result_json:
+ import erlang
+ debuginfo_hexstr=result_json['debuginfo']
+ debuginfo_bytes=h2b(debuginfo_hexstr)
+ debuginfo_term=erlang.binary_to_term(debuginfo_bytes)
+ debuginfo_pretty = pp.pformat(debuginfo_term)
+ print(" debuginfo: " + textwrap.indent(debuginfo_pretty, " " * 12)[12:], file=sys.stderr)
+ print(json.dumps(result_json))
+
+ elif args.delete:
+ print("delete on: " + str(args.host), file=sys.stderr)
+ print(" facility: " + str(args.facility), file=sys.stderr)
+ print(" resourceId: " + str(args.resource_id), file=sys.stderr)
+ result_json = rest_delete(args.host, args.facility, args.resource_id)
+ result_json_pretty = pp.pformat(result_json)
+ print(" json: " + textwrap.indent(result_json_pretty, " " * 7)[7:], file=sys.stderr)
+ print(json.dumps(result_json))
+
+ elif args.list:
+ print("list on: " + str(args.host), file=sys.stderr)
+ print(" facility: " + str(args.facility), file=sys.stderr)
+ result_json = rest_list(args.host, args.facility)
+ result_json_pretty = pp.pformat(result_json)
+ print(" json: " + textwrap.indent(result_json_pretty, " " * 7)[7:], file=sys.stderr)
+ print(json.dumps(result_json))
+
+if __name__ == "__main__":
+ main(sys.argv[1:])
+
diff --git a/contrib/rest_api_usage_example/tryme.cfg b/contrib/rest_api_usage_example/tryme.cfg
new file mode 100644
index 0000000..0506a19
--- /dev/null
+++ b/contrib/rest_api_usage_example/tryme.cfg
@@ -0,0 +1,14 @@
+# Set this value to the EID of the eUICC you want to target. The EID is the
+# primary identifier on which the eIM identifies the requests from the IoT
+# device (IPAd).
+EID='89049044900000000000000000102452'
+
+# Change this value to the activation code (AC) of your profile download
+AC='1$smdpp.test.rsp.sysmocom.de$TS48V1-A-UNIQUE'
+
+# Set this value to the ICCID of your profile. The ICCID format used here is
+# the binary form as it can be found in EF.ICCID. (In case you do not know the
+# ICCID (yet), you may leave this field empty. The ICCID is returned by the eIM
+# (tryme_download.sh) when the profile download is complete. In case the profile
+# is already installed, you may request a list (tryme_listProfileInfo.sh).
+ICCID='989444999999990920F3' #8949449999999990023
diff --git a/contrib/tryme_addEim.sh b/contrib/rest_api_usage_example/tryme_addEim.sh
similarity index 90%
rename from contrib/tryme_addEim.sh
rename to contrib/rest_api_usage_example/tryme_addEim.sh
index a504010..70a246b 100755
--- a/contrib/tryme_addEim.sh
+++ b/contrib/rest_api_usage_example/tryme_addEim.sh
@@ -1,11 +1,10 @@
#!/bin/bash
-. ./tryme.cfg
+. ./getopts.sh

JSON='{ "eidValue" : "'$EID'", "order" : { "eco" : [ { "addEim" : { "eimConfigurationData" : "3079800465494D32810E3132372E302E302E313A383030308301018401FFA55BA059301306072A8648CE3D020106082A8648CE3D03010703420004FE584A6F450459574AECA195D0299737F74C89BA2D36DF9286EC25D973037A0FBA70D14DF3E1F7D0A305E57B95B731C4DE218D2D7F9F22113ED5D18C2E3DDF1C" } } ] } }'
RC=`./restop.py -c -f eco -j "$JSON"`
-echo $RC

echo "---------------------------------------8<---------------------------------------"
RESOURCE_ID=`echo $RC | cut -d '/' -f 6`
echo "ResourceId =" $RESOURCE_ID
-./tryme_lookup.sh eco $RESOURCE_ID
+./lookup.sh eco $RESOURCE_ID
diff --git a/contrib/tryme_configureImmediateEnable.sh b/contrib/rest_api_usage_example/tryme_configureImmediateEnable.sh
similarity index 86%
rename from contrib/tryme_configureImmediateEnable.sh
rename to contrib/rest_api_usage_example/tryme_configureImmediateEnable.sh
index 9cf4fde..9538beb 100755
--- a/contrib/tryme_configureImmediateEnable.sh
+++ b/contrib/rest_api_usage_example/tryme_configureImmediateEnable.sh
@@ -1,11 +1,10 @@
#!/bin/bash
-. ./tryme.cfg
+. ./getopts.sh

JSON='{ "eidValue" : "'$EID'", "order" : { "psmo": [ { "configureImmediateEnable" : { "immediateEnableFlag" : true, "defaultSmdpAddress" : "testsmdpplus1.example.com" } } ] } }'
RC=`./restop.py -c -f psmo -j "$JSON"`
-echo $RC

echo "---------------------------------------8<---------------------------------------"
RESOURCE_ID=`echo $RC | cut -d '/' -f 6`
echo "ResourceId =" $RESOURCE_ID
-./tryme_lookup.sh psmo $RESOURCE_ID
+./lookup.sh psmo $RESOURCE_ID
diff --git a/contrib/tryme_delete.sh b/contrib/rest_api_usage_example/tryme_delete.sh
similarity index 84%
rename from contrib/tryme_delete.sh
rename to contrib/rest_api_usage_example/tryme_delete.sh
index bf1a9b2..bedb3db 100755
--- a/contrib/tryme_delete.sh
+++ b/contrib/rest_api_usage_example/tryme_delete.sh
@@ -1,12 +1,11 @@
#!/bin/bash
-. ./tryme.cfg
+. ./getopts.sh

JSON='{ "eidValue" : "'$EID'", "order" : { "psmo" : [ { "delete" : { "iccid" : "'$ICCID'" } } ] } }'
RC=`./restop.py -c -f psmo -j "$JSON"`
-echo $RC

echo "---------------------------------------8<---------------------------------------"
RESOURCE_ID=`echo $RC | cut -d '/' -f 6`
echo "ResourceId =" $RESOURCE_ID
-./tryme_lookup.sh psmo $RESOURCE_ID
+./lookup.sh psmo $RESOURCE_ID

diff --git a/contrib/tryme_deleteEim.sh b/contrib/rest_api_usage_example/tryme_deleteEim.sh
similarity index 84%
rename from contrib/tryme_deleteEim.sh
rename to contrib/rest_api_usage_example/tryme_deleteEim.sh
index 8faf657..5177e6e 100755
--- a/contrib/tryme_deleteEim.sh
+++ b/contrib/rest_api_usage_example/tryme_deleteEim.sh
@@ -1,11 +1,11 @@
#!/bin/bash
-. ./tryme.cfg
+. ./getopts.sh
+
EIM_ID="eIM2"
JSON='{ "eidValue" : "'$EID'", "order" : { "eco" : [ { "deleteEim" : { "eimId" : "'$EIM_ID'" } } ] } }'
RC=`./restop.py -c -f eco -j "$JSON"`
-echo $RC

echo "---------------------------------------8<---------------------------------------"
RESOURCE_ID=`echo $RC | cut -d '/' -f 6`
echo "ResourceId =" $RESOURCE_ID
-./tryme_lookup.sh eco $RESOURCE_ID
+./lookup.sh eco $RESOURCE_ID
diff --git a/contrib/tryme_disable.sh b/contrib/rest_api_usage_example/tryme_disable.sh
similarity index 84%
rename from contrib/tryme_disable.sh
rename to contrib/rest_api_usage_example/tryme_disable.sh
index a45af94..cc55a41 100755
--- a/contrib/tryme_disable.sh
+++ b/contrib/rest_api_usage_example/tryme_disable.sh
@@ -1,11 +1,10 @@
#!/bin/bash
-. ./tryme.cfg
+. ./getopts.sh

JSON='{ "eidValue" : "'$EID'", "order" : { "psmo" : [ { "disable" : { "iccid" : "'$ICCID'" } } ] } }'
RC=`./restop.py -c -f psmo -j "$JSON"`
-echo $RC

echo "---------------------------------------8<---------------------------------------"
RESOURCE_ID=`echo $RC | cut -d '/' -f 6`
echo "ResourceId =" $RESOURCE_ID
-./tryme_lookup.sh psmo $RESOURCE_ID
+./lookup.sh psmo $RESOURCE_ID
diff --git a/contrib/tryme_download.sh b/contrib/rest_api_usage_example/tryme_download.sh
similarity index 82%
rename from contrib/tryme_download.sh
rename to contrib/rest_api_usage_example/tryme_download.sh
index 10725a2..56f9096 100755
--- a/contrib/tryme_download.sh
+++ b/contrib/rest_api_usage_example/tryme_download.sh
@@ -1,11 +1,10 @@
#!/bin/bash
-. ./tryme.cfg
+. ./getopts.sh

JSON='{ "eidValue" : "'$EID'", "order" : { "download" : {"activationCode" : "'$AC'" } } }'
RC=`./restop.py -c -f download -j "$JSON"`
-echo $RC

echo "---------------------------------------8<---------------------------------------"
RESOURCE_ID=`echo $RC | cut -d '/' -f 6`
echo "ResourceId =" $RESOURCE_ID
-./tryme_lookup.sh download $RESOURCE_ID
+./lookup.sh download $RESOURCE_ID
diff --git a/contrib/tryme_enable.sh b/contrib/rest_api_usage_example/tryme_enable.sh
similarity index 84%
rename from contrib/tryme_enable.sh
rename to contrib/rest_api_usage_example/tryme_enable.sh
index ac08706..93f52c6 100755
--- a/contrib/tryme_enable.sh
+++ b/contrib/rest_api_usage_example/tryme_enable.sh
@@ -1,11 +1,10 @@
#!/bin/bash
-. ./tryme.cfg
+. ./getopts.sh

JSON='{ "eidValue" : "'$EID'", "order" : { "psmo": [ { "enable" : { "iccid" : "'$ICCID'", "rollback" : false } } ] } }'
RC=`./restop.py -c -f psmo -j "$JSON"`
-echo $RC

echo "---------------------------------------8<---------------------------------------"
RESOURCE_ID=`echo $RC | cut -d '/' -f 6`
echo "ResourceId =" $RESOURCE_ID
-./tryme_lookup.sh psmo $RESOURCE_ID
+./lookup.sh psmo $RESOURCE_ID
diff --git a/contrib/tryme_euiccDataRequest.sh b/contrib/rest_api_usage_example/tryme_euiccDataRequest.sh
similarity index 74%
rename from contrib/tryme_euiccDataRequest.sh
rename to contrib/rest_api_usage_example/tryme_euiccDataRequest.sh
index ba70a69..28aa282 100755
--- a/contrib/tryme_euiccDataRequest.sh
+++ b/contrib/rest_api_usage_example/tryme_euiccDataRequest.sh
@@ -1,10 +1,10 @@
#!/bin/bash
-. ./tryme.cfg
-JSON='{ "eidValue" : "'$EID'", "order" : { "edr" : { "tagList" : "81BF20BF228384A5A6A8A9A0" } } }'
+. ./getopts.sh
+
+JSON='{ "eidValue" : "'$EID'", "order" : { "edr" : { "tagList" : "81BF20BF228384A5A6A8A9A0A2" } } }'
RC=`./restop.py -c -f edr -j "$JSON"`
-echo $RC

echo "---------------------------------------8<---------------------------------------"
RESOURCE_ID=`echo $RC | cut -d '/' -f 6`
echo "ResourceId =" $RESOURCE_ID
-./tryme_lookup.sh edr $RESOURCE_ID
+./lookup.sh edr $RESOURCE_ID
diff --git a/contrib/tryme_euicc_get_state.sh b/contrib/rest_api_usage_example/tryme_euicc_get_state.sh
similarity index 87%
rename from contrib/tryme_euicc_get_state.sh
rename to contrib/rest_api_usage_example/tryme_euicc_get_state.sh
index dc96cf0..f41ecc3 100755
--- a/contrib/tryme_euicc_get_state.sh
+++ b/contrib/rest_api_usage_example/tryme_euicc_get_state.sh
@@ -1,14 +1,13 @@
#!/bin/bash
-. ./tryme.cfg
+. ./getopts.sh

# States we want to retrieve with this request.
STATES='"counterValue", "consumerEuicc", "signAlgo", "signPubKey", "stateChangeCauseList"'

JSON='{ "eidValue" : "'$EID'", "order" : { "euicc" : { "get" : [ '$STATES' ] } } }'
RC=`./restop.py -c -f euicc -j "$JSON"`
-echo $RC

echo "---------------------------------------8<---------------------------------------"
RESOURCE_ID=`echo $RC | cut -d '/' -f 6`
echo "ResourceId =" $RESOURCE_ID
-./tryme_lookup.sh euicc $RESOURCE_ID
+./lookup.sh euicc $RESOURCE_ID
diff --git a/contrib/tryme_euicc_set_state.sh b/contrib/rest_api_usage_example/tryme_euicc_set_state.sh
similarity index 92%
rename from contrib/tryme_euicc_set_state.sh
rename to contrib/rest_api_usage_example/tryme_euicc_set_state.sh
index 04d8c51..5d30ea1 100755
--- a/contrib/tryme_euicc_set_state.sh
+++ b/contrib/rest_api_usage_example/tryme_euicc_set_state.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-. ./tryme.cfg
+. ./getopts.sh

# States we want to set with this request (list does not have to be complete, states not listest here are left
# unchanged.
@@ -11,9 +11,8 @@

JSON='{ "eidValue" : "'$EID'", "order" : { "euicc" : { "set" : '$STATES' } } }'
RC=`./restop.py -c -f euicc -j "$JSON"`
-echo $RC

echo "---------------------------------------8<---------------------------------------"
RESOURCE_ID=`echo $RC | cut -d '/' -f 6`
echo "ResourceId =" $RESOURCE_ID
-./tryme_lookup.sh euicc $RESOURCE_ID
+./lookup.sh euicc $RESOURCE_ID
diff --git a/contrib/tryme_getRAT.sh b/contrib/rest_api_usage_example/tryme_getRAT.sh
similarity index 83%
rename from contrib/tryme_getRAT.sh
rename to contrib/rest_api_usage_example/tryme_getRAT.sh
index fa61d51..4c3dcdf 100755
--- a/contrib/tryme_getRAT.sh
+++ b/contrib/rest_api_usage_example/tryme_getRAT.sh
@@ -1,11 +1,10 @@
#!/bin/bash
-. ./tryme.cfg
+. ./getopts.sh

JSON='{ "eidValue" : "'$EID'", "order" : { "psmo" : [ { "getRAT" : { } } ] } }'
RC=`./restop.py -c -f psmo -j "$JSON"`
-echo $RC

echo "---------------------------------------8<---------------------------------------"
RESOURCE_ID=`echo $RC | cut -d '/' -f 6`
echo "ResourceId =" $RESOURCE_ID
-./tryme_lookup.sh psmo $RESOURCE_ID
+./lookup.sh psmo $RESOURCE_ID
diff --git a/contrib/tryme_listEim.sh b/contrib/rest_api_usage_example/tryme_listEim.sh
similarity index 83%
rename from contrib/tryme_listEim.sh
rename to contrib/rest_api_usage_example/tryme_listEim.sh
index 0d86787..25ece68 100755
--- a/contrib/tryme_listEim.sh
+++ b/contrib/rest_api_usage_example/tryme_listEim.sh
@@ -1,11 +1,10 @@
#!/bin/bash
-. ./tryme.cfg
+. ./getopts.sh

JSON='{ "eidValue" : "'$EID'", "order" : { "eco" : [ { "listEim" : { } } ] } }'
RC=`./restop.py -c -f eco -j "$JSON"`
-echo $RC

echo "---------------------------------------8<---------------------------------------"
RESOURCE_ID=`echo $RC | cut -d '/' -f 6`
echo "ResourceId =" $RESOURCE_ID
-./tryme_lookup.sh eco $RESOURCE_ID
+./lookup.sh eco $RESOURCE_ID
diff --git a/contrib/tryme_listProfileInfo.sh b/contrib/rest_api_usage_example/tryme_listProfileInfo.sh
similarity index 83%
rename from contrib/tryme_listProfileInfo.sh
rename to contrib/rest_api_usage_example/tryme_listProfileInfo.sh
index 7d64b98..a555308 100755
--- a/contrib/tryme_listProfileInfo.sh
+++ b/contrib/rest_api_usage_example/tryme_listProfileInfo.sh
@@ -1,11 +1,10 @@
#!/bin/bash
-. ./tryme.cfg
+. ./getopts.sh

JSON='{ "eidValue" : "'$EID'", "order" : { "psmo" : [ { "listProfileInfo" : { } } ] } }'
RC=`./restop.py -c -f psmo -j "$JSON"`
-echo $RC

echo "---------------------------------------8<---------------------------------------"
RESOURCE_ID=`echo $RC | cut -d '/' -f 6`
echo "ResourceId =" $RESOURCE_ID
-./tryme_lookup.sh psmo $RESOURCE_ID
+./lookup.sh psmo $RESOURCE_ID
diff --git a/contrib/tryme_updateEim.sh b/contrib/rest_api_usage_example/tryme_updateEim.sh
similarity index 86%
rename from contrib/tryme_updateEim.sh
rename to contrib/rest_api_usage_example/tryme_updateEim.sh
index 5d08398..c228f1d 100755
--- a/contrib/tryme_updateEim.sh
+++ b/contrib/rest_api_usage_example/tryme_updateEim.sh
@@ -1,11 +1,10 @@
#!/bin/bash
-. ./tryme.cfg
+. ./getopts.sh

JSON='{ "eidValue" : "'$EID'", "order" : { "eco" : [ { "updateEim" : { "eimConfigurationData" : "3017800465494D32810F3132372E302E302E34323A39303030" } } ] } }'
RC=`./restop.py -c -f eco -j "$JSON"`
-echo $RC

echo "---------------------------------------8<---------------------------------------"
RESOURCE_ID=`echo $RC | cut -d '/' -f 6`
echo "ResourceId =" $RESOURCE_ID
-./tryme_lookup.sh eco $RESOURCE_ID
+./lookup.sh eco $RESOURCE_ID
diff --git a/contrib/restop.py b/contrib/restop.py
deleted file mode 100755
index a12ccd4..0000000
--- a/contrib/restop.py
+++ /dev/null
@@ -1,95 +0,0 @@
-#!/usr/bin/env python3
-#
-# Copyright (c) 2025 Onomondo ApS & sysmocom - s.f.m.c. GmbH. All rights reserved.
-# SPDX-License-Identifier: AGPL-3.0-only
-# Author: Philipp Maier <pmaier@sysmocom.de> / sysmocom - s.f.m.c. GmbH
-
-import sys
-import argparse
-import json
-import requests
-import erlang
-import pprint
-
-DOWNLOAD_DEFAULT='{ "eidValue" : "89882119900000000000000000000005", "order" : {"activationCode" : "1$testsmdpplus1.example.com$OPxLD-UVRuC-jysPI-YkOwT"}}'
-PSMO_DEFAULT='{ "eidValue" : "89882119900000000000000000000005", "order" : [{"psmo" : "enable", "iccid" : "98001032547698103285", "rollback" : false }]}'
-
-req_headers = {
- 'Content-Type': 'application/json',
- 'X-Admin-Protocol': 'onomondo/eim/v1.0.0',
-}
-
-def h2b(s) -> bytearray:
- """convert from a string of hex nibbles to a sequence of bytes"""
- return bytes.fromhex(s)
-
-def rest_create(host, facility, Json):
- r = requests.post("http://" + str(host) + "/" + str(facility) + "/create", json=Json, headers=req_headers)
- return str(r.url)
-
-def rest_lookup(host, facility, ResourceId):
- r = requests.get("http://" + str(host) + "/" + str(facility) + "/lookup/" + str(ResourceId), headers=req_headers)
- return r.json()
-
-def rest_delete(host, facility, ResourceId):
- r = requests.get("http://" + str(host) + "/" + str(facility) + "/delete/" + str(ResourceId), headers=req_headers)
- return r.json()
-
-def rest_list(host, facility):
- r = requests.get("http://" + str(host) + "/" + str(facility) + "/list/", headers=req_headers)
- return r.json()
-
-def main(argv):
- parser = argparse.ArgumentParser(prog='restop', description='utility to operate on the REST API of onomondo_eim')
- parser.add_argument("-s", "--host", default="127.0.0.1:8080")
- parser.add_argument("-f", "--facility", default="download")
- parser.add_argument("-c", "--create", action='store_true', default=False)
- parser.add_argument("-l", "--lookup", action='store_true', default=False)
- parser.add_argument("-d", "--delete", action='store_true', default=False)
- parser.add_argument("-t", "--list", action='store_true', default=False)
- parser.add_argument("-r", "--resource-id")
- parser.add_argument("-j", "--json")
-
- args = parser.parse_args()
-
- if args.create:
- print("create on: " + str(args.host), file=sys.stderr)
- print(" facility: " + str(args.facility), file=sys.stderr)
- if args.json:
- args_json = str(args.json)
- else:
- if args.facility == "download":
- args_json = DOWNLOAD_DEFAULT
- elif args.facility == "psmo":
- args_json = PSMO_DEFAULT
- print(" json: " + args_json, file=sys.stderr)
- print("result:", file=sys.stderr)
- print(rest_create(args.host, args.facility, json.loads(args_json)))
- elif args.lookup:
- print("lookup on: " + str(args.host), file=sys.stderr)
- print(" facility: " + str(args.facility), file=sys.stderr)
- print(" resourceId: " + str(args.resource_id), file=sys.stderr)
- result = rest_lookup(args.host, args.facility, args.resource_id)
- print(json.dumps(result))
- if 'debuginfo' in result:
- debuginfo_hexstr=result['debuginfo']
- debuginfo_bytes=h2b(debuginfo_hexstr)
- debuginfo_term=erlang.binary_to_term(debuginfo_bytes)
- pp = pprint.PrettyPrinter(depth=4)
- debuginfo_pretty = pp.pformat(debuginfo_term)
- print("decoded debuginfo: " + str(debuginfo_pretty), file=sys.stderr)
- elif args.delete:
- print("delete on: " + str(args.host), file=sys.stderr)
- print(" facility: " + str(args.facility), file=sys.stderr)
- print(" resourceId: " + str(args.resource_id), file=sys.stderr)
- print("result:", file=sys.stderr)
- print(json.dumps(rest_delete(args.host, args.facility, args.resource_id)))
- elif args.list:
- print("list on: " + str(args.host), file=sys.stderr)
- print(" facility: " + str(args.facility), file=sys.stderr)
- print("result:", file=sys.stderr)
- print(json.dumps(rest_list(args.host, args.facility)), file=sys.stderr)
-
-if __name__ == "__main__":
- main(sys.argv[1:])
-
diff --git a/contrib/tryme.cfg b/contrib/tryme.cfg
deleted file mode 100644
index 674da53..0000000
--- a/contrib/tryme.cfg
+++ /dev/null
@@ -1,63 +0,0 @@
-#EID='89882119900000000000000000000005' #NIST+BRP Test eUICC (Consumer)
-#EID='89044045118427484800000000011628' #NIST+BRP Test eUICC (IoT)
-#EID='89044045116727494800000004479172' #SLM17 ECu10.07 GSMA sample eUICC
-#EID='89086030202200000022000027485428' #eSIM me eUICC (Consumer)
-#EID='89049032123451234512345678901235' #Comprion Test eUICC (Consumer)
-EID='89034011022310000000000006803372' #Consumer eUICC for testing/demo
-
-case $1 in
- "A")
- #GSMA TS.48 V1 A
- AC='1$smdpp.test.rsp.sysmocom.de$TS48V1-A-UNIQUE'
- ICCID='989444999999990920F3' #8949449999999990023
- ;;
-
- "B")
- #GSMA TS.48 V1 B
- AC='1$smdpp.test.rsp.sysmocom.de$TS48V1-B-UNIQUE'
- ICCID='989444999999990930F1' #8949449999999990031
- ;;
- "C")
- #A test profile from a commercial operator (use GSMA eUICC)
- AC='1$rsp.truphone.com$QR-G-5C-1LS-1W1Z9P7'
- ICCID='984474680000230631F1' #changes after each download
- ;;
- "D")
- #TS48V1-B-UNIQUE-nojavacard-nocsim on self hosted SMDP+ instance
- #Osmo-smdpplus will verify the server address, you can put the SMPD+ hostname
- #(testsmdpplus1.example.com) into /etc/hosts: "127.0.0.1 testsmdpplus1.example.com"
- AC='1$testsmdpplus1.example.com$TS48V1-B-UNIQUE-nojavacard-nocsim'
- ICCID='989444999999990930F1' #8949449999999990031
- ;;
- "E")
- #A test profile that is installed on a test eUICC at some other location
- AC='1$rsp.example.com$UNKNOWN' #dummy value, unknown
- ICCID='98543700000012181938' #89457300000021819183
- ;;
- "X")
- #A way to sumbint any EID, ICCID and AC directly without putting it here.
- EID=$2
- ICCID=$3
- AC=$4
- ;;
- *)
- echo "EID=$EID"
- echo "Please select a profile:"
- echo "A: GSMA TS.48 V1 A"
- echo "B: GSMA TS.48 V1 B"
- echo "C: Truephone (commercial, GSMA)"
- echo "D: TS48V1-B-UNIQUE-nojavacard-nocsim (for debugging)"
- echo "E: Testprofile on another test eUICC (for testing/demo)"
- echo "X: Use any EID, ICCID or AC directly (tryme_*.sh EID [ICCID] [AC])"
- echo ""
- echo "A few examples:"
- echo "./tryme_download.sh X 89086030202200000022000027485428 NOT_NEEDED '1\$rsp.truphone.com\$QR-G-5C-1LS-1W1Z9P7'"
- echo "./tryme_enable.sh X 89086030202200000022000027485428 984474680000730600F7"
- echo "./tryme_listProfileInfo.sh X 89086030202200000022000027485428"
- echo "./tryme_download.sh E"
- echo "./tryme_enable.sh E"
- echo "./tryme_listProfileInfo.sh E"
- echo ""
- exit
- ;;
-esac
diff --git a/contrib/tryme_lookup.sh b/contrib/tryme_lookup.sh
deleted file mode 100755
index df8e129..0000000
--- a/contrib/tryme_lookup.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-
-if [[ $# == 2 ]]; then
- sleep 5
- while true; do
- ./restop.py -l -f $1 -r $2
- sleep 5
- done
-else
- echo "Usage: $0 facility resource-id"
-fi
-
-
-
diff --git a/doc/examples.md b/doc/examples.md
index 9f3726a..ab7f510 100644
--- a/doc/examples.md
+++ b/doc/examples.md
@@ -2,8 +2,8 @@
------------------

The REST API is complex interface that is difficult to operate out of the box without any prior familiarization. To
-give a system integrator a good starting point, the contrib directory contains "tryme-scripts" that serve as examples
-and an easy way try out the REST API.
+give a system integrator a good starting point, the contrib/rest_api_usage_example directory contains "tryme-scripts"
+that serve as examples and an easy way try out the REST API.

### Scripts

@@ -14,6 +14,17 @@
It should be noted that the tryme_*.sh scripts are really just simple examples that were created to simplify testing
during development.

+#### tryme.cfg
+
+This is just a simple shellscript that sets some initial variables. Some sample values are already present. It is
+recommended to edit tryme.cfg and to replace the sample values with some useful values. This is in particular the
+$EID variable at the top of the file.
+
+The file also defines a sample profiles along with a matching activation code (`$AC`) and ICCID (`$ICCID`). The ICCID
+is usually not known in advance. It becomes known after the eUICC has decrypted and installed the profile package. It
+should also be noted that the ICCID parameter is always issued in its raw format (digits swapped, padded with 'F' at
+the end).
+
#### restop.py

The python-script "restop.py" is called by the tryme "tryme_*.sh" scripts. This script can be used as a stand-alone
@@ -22,19 +33,19 @@
user must keep track of the REST resources he created, monitor them, check for errors, delete REST resources, resubmit
REST resources in case an `order` has failed, etc.

-#### tryme.cfg
+#### lookup.sh

-This is just a simple shellscript that sets some initial variables. Some sample values are already present. It is
-recommended to edit tryme.cfg and to replace the sample values with some useful values. This is in particular the
-$EID variable at the top of the file.
+This shellscript serves as a helper for the "tryme_*.sh" scripts. It is uses "restop.py" to query and display the
+status of the current REST resource in regular intervals.

-The file also defines some sample profiles along with their activation codes (`$AC`) and ICCIDs (`$ICCID`). The ICCID is
-usually not known in advance. It becomes known after the eUICC has decrypted and installed the profile package. It
-should also be noted that the ICCID parameter is always issued in its raw format (digits swapped, padded with 'F' at
-the end).
+#### getopts.sh

-In tryme.cfg one will also find a profile `X`, this profile is a placeholder in case the user decides not to edit
-tryme.cfg and to pass all parameters from the commandline instead.
+This shellscript is executed by the "tryme_*.sh" on each startup. It is not meant to be called directly by the user.
+The purpose of "getopts.sh" to either read the configurable parameters (EID, AC, ICCID) from "tryme.cfg" or to accept
+those parameters directly from the commandline. For a commandline help, the user may call any "tryme_*.sh" with the
+`-h` options. In case the "tryme_*.sh" scripts are called without parameters, the parameters are loaded from "tryme.cfg"
+In case a different config file shall be used, the user use the `-c` parameter to change the location of the config
+file.

### Downloading And Enabling A Profile

@@ -42,13 +53,11 @@
following example we will pass all parameters directly from the commandline. It is assumed that the REST API of
onomondo-eim is available at 127.0.0.1:8080.

-In the first step we will issue a download `order` using the `tryme_download.sh`. The parameter `X` tells tryme.cfg to
-use the placeholder profile. The second parameter is the EID (not to be confused with ICCID) of the eUICC. The
-third parameter serves as a placeholder for the ICCID, which we do not know or need yet. The last parameter is the
-`activationCode`.
+In the first step we will issue a download `order` using the `tryme_download.sh`. The parameter `-e` specifies the
+EID, The second parameter `-a` specifies the `activationCode` (AC).

```
-./tryme_download.sh X 12345678900000000000000000001234 NOT_NEEDED '1$rsp.example.com$EXAMPLE'
+./tryme_download.sh -e 12345678900000000000000000001234 -a '1$rsp.example.com$EXAMPLE'
```

When the script is executed, it will `create` the related REST resource and then `lookup` the REST `resource`
@@ -66,11 +75,11 @@
(to keep the rest table clean one should `delete` the rest resource now as described above)

However, the profile is not enabled yet. In order to use it, we must issue an `enable` PSMO first. To do that we may
-run `tryme_enable.sh`. The parameter `X` tells tryme.cfg to use the placeholder profile again. The second parameter is
-the EID and the third parameter is the ICCID that we have just taken from the JSON output above.
+run `tryme_enable.sh`. The parameter `-e` tells specifies the EID again. The second parameter `-i` specifies the
+the ICCID that we have just taken from the JSON output above.

```
-./tryme_enable.sh X 12345678900000000000000000001234 12324567899999911191
+./tryme_enable.sh -e 12345678900000000000000000001234 -i 12324567899999911191
```

We now must wait again until the IPAd fetches the related eIM package with the eUICC package that contains the `enable`
@@ -90,7 +99,7 @@

To send a `listProfileInfo` run:
```
-./tryme_listProfileInfo.sh X 12345678900000000000000000001234
+./tryme_listProfileInfo.sh -e 12345678900000000000000000001234
```

As soon as the IPAd has fetched and executed the related eUICC package, the JSON output should look like this:
@@ -111,7 +120,7 @@

To perform an eUICC data request, execute the following script like so:
```
-./tryme_euiccDataRequest.sh X 12345678900000000000000000001234
+./tryme_euiccDataRequest.sh -e 12345678900000000000000000001234
```

There should be response like this:
@@ -138,7 +147,7 @@

We would edit the order into tryme_set_euicc_param.sh and run the script:
```
-./tryme_euicc_set_state.sh X 12345678900000000000000000001234
+./tryme_euicc_set_state.sh -e 12345678900000000000000000001234
```

The order will execute as an internal process. This means that no IPAd interaction is involved. However, on the REST
@@ -165,7 +174,7 @@

We would edit the order into tryme_set_euicc_param.sh and run the script:
```
-./tryme_euicc_get_state.sh X 12345678900000000000000000001234
+./tryme_euicc_get_state.sh -e 12345678900000000000000000001234
```

The eIM will respond with a list of key value pairs of the requested eUICC states:

To view, visit change 43142. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-MessageType: merged
Gerrit-Project: onomondo-eim
Gerrit-Branch: master
Gerrit-Change-Id: I4e42ce85c84b47d3561011083da4a1e54958fd8e
Gerrit-Change-Number: 43142
Gerrit-PatchSet: 6
Gerrit-Owner: dexter <pmaier@sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: dexter <pmaier@sysmocom.de>
Gerrit-Reviewer: jolly <andreas@eversberg.eu>
Gerrit-Reviewer: laforge <laforge@osmocom.org>