Combining Balena and Azure IoT Edge

Hello @banto-78 lets try to reproduce this step-by-step. The command that we are looking into takes the content of the $J_FILE variable and attempts to add some fields in there. According to the Dockerfile, this $J_FILE variable is set by reading the file at /usr/src/app/iot-edge/samples/simulated_device_cloud_upload/src/simulated_device_cloud_upload_lin.json.
First of all we need to make sure this is working as expected, as dt-rush mentioned above the path needs to be updated by adding v1. Once you figured out the correct path remember to update it in the line below.

J_FILE=$(cat /usr/src/app/iot-edge/samples/simulated_device_cloud_upload/src/simulated_device_cloud_upload_lin.json)

Once this is sorted out the file should never result as empty. Now if we have fields missing this probably means that one or more of the env vars $DEVICE1, $DEVICE2, $DEVICE1KEY or $DEVICE2KEY are missing.

Many thanks for your message. The missing path issue I think I’ve fixed already. All paths are (or looks to me) up to date including J_FILE:
J_FILE=$(cat /usr/src/app/iot-edge/v1/samples/simulated_device_cloud_upload/src/simulated_device_cloud_upload_lin.json)

I have defined the device env variables $DEVICE1, $DEVICE2, $DEVICE1KEY or $DEVICE2KEY too. The replace.json is produced but still empty.

Few additional notes though:

1
why the script has “sleep infinity” ? I have removed it since it will never let the script continue…

2
According to the JSON structure this code:

jq ‘.modules[1].args[0].deviceId="’$DEVICE1’"’ | \
jq ‘.modules[1].args[0].deviceKey="’$DEVICE1KEY’"’ | \
jq ‘.modules[1].args[1].deviceId="’$DEVICE2’"’ | \
jq ‘.modules[1].args[1].deviceKey="’$DEVICE2KEY’"’ \
> replaced.json

shouldn’t be rather:

jq ‘.modules[0].args[0].deviceId="’$DEVICE1’"’ | \
jq ‘.modules[0].args[0].deviceKey="’$DEVICE1KEY’"’ | \
jq ‘.modules[0].args[1].deviceId="’$DEVICE2’"’ | \
jq ‘.modules[0].args[1].deviceKey="’$DEVICE2KEY’"’ \
> replaced.json

??

thanks.

Are you sure the path is not iot-edge-v1/v1/...? Add an echo $J_FILE right after J_FILE=$(cat ...) to confirm that its being read. As far as the env vars I think that .modules[1] is correct. They are meant to replace the lines in https://github.com/Azure/iot-edge-v1/blob/master/v1/samples/simulated_device_cloud_upload/src/simulated_device_cloud_upload_lin.json#L26-L35 which is the second entry in the modules array.
I am not sure about the sleep inifinity, it might be needed at the end of the script but should probably not be in the middle :slight_smile:

Took a lot but i finally found the bug!

Write this in one line without backslash:

echo "$J_FILE" | \  
  jq '.modules[0].args.IoTHubName="<IoTHubName>"' | \
  jq '.modules[0].args.IoTHubSuffix="azure-devices.net"' | \
  jq '.modules[0].args.Transport="AMQP"' | \
  jq '.modules[1].args[0].deviceId="'$DEVICE1'"' | \
  jq '.modules[1].args[0].deviceKey="'$DEVICE1KEY'"' | \
  jq '.modules[1].args[1].deviceId="'$DEVICE2'"' | \
  jq '.modules[1].args[1].deviceKey="'$DEVICE2KEY'"' \
  > replaced.json

Hi @banto_78, glad it works for you now!

One note as well, though, you can do the same thing without the multiple jq calls, as in the same call you can do multiple replacements:

echo "$J_FILE" | \
  jq '.modules[0].args.IoTHubName="<IoTHubName>" | .modules[0].args.IoTHubSuffix="azure-devices.net" | .modules[0].args.Transport="AMQP" | .modules[1].args[0].deviceId="'$DEVICE1'" | .modules[1].args[0].deviceKey="'$DEVICE1KEY'" | .modules[1].args[1].deviceId="'$DEVICE2'" | .modules[1].args[1].deviceKey="'$DEVICE2KEY'"' \
  > replaced.json

though the downside is that I don’t think there can be a linebreak in those replacements, so that’s one looong line unfortunately.

Anyways, it seems like you are unblocked! We are always happy to hear how things are going for you!

Also checking it out @banto_78 , the issue might be in case the code is copy-paste from the blog. Even if in the blog source there are no trailing whitespaces, but in the paste there are trailing whitespace on the echo .... line, that I see also in your comment above (this one: Combining Balena and Azure IoT Edge )

The \ concatenation of lines only works if that character is the last one in the line (no trailing white spaces are allowed). If I copy paste from the blog, I run into an issue, if I trim the whitespace on that first line, it all works fine. So I guess the blame is on how our blog renders code, unfortunately…

Does it make sense? Or have I missed anything?

thanks, indeed. Removing trailing white spaces works too!

https://github.com/maxtheaviator/resin-azure-iotedge-multicontainer can be interesting indeed but I get error during the build, like:

Step 3/11 : RUN pip3 install --upgrade setuptools pip
[iotedge] —> Running in ef85c9745838
[iotedge] Traceback (most recent call last):
[iotedge] File “/usr/local/bin/pip3”, line 7, in
[iotedge] from pip._internal import main
[iotedge] File “/usr/lib/python3/dist-packages/pip/init.py”, line 72, in
[iotedge] from pip.log import logger
[iotedge] File “/usr/lib/python3/dist-packages/pip/log.py”, line 9, in
[iotedge] import colorama, pkg_resources
[iotedge] File “/usr/lib/python3/dist-packages/pkg_resources.py”, line 1520, in
[iotedge] register_loader_type(importlib_bootstrap.SourceFileLoader, DefaultProvider)
[iotedge] AttributeError: module ‘importlib._bootstrap’ has no attribute ‘SourceFileLoader’
[iotedge]
[iotedge] Removing intermediate container ef85c9745838
[Info] Uploading images
[iotedge] The command ‘/bin/sh -c pip3 install --upgrade setuptools pip’ returned a non-zero code: 1

I have also changed the base image to:
FROM balenalib/raspberrypi3-python:3.6-jessie-build

Hey @banto-78

That looks like an issue with Python or Pip when trying to upgrade setuptools or pip. I suggest you to ask in a Python specific forum, as they will be able to help much more than us (our Python knowledge is not extensive)!

I have fixed the error above. It was related to python and pip installation in Dockerfile.

Now when the container starts it gives this error:

02.07.19 17:47:19 (+0200) iotedge ERROR: Error during pull for image local/azure-iotedge-runtime-resin:latest
02.07.19 17:47:19 (+0200) iotedge 404 Client Error: Not Found (“pull access denied for local/azure-iotedge-runtime-resin, repository does not exist or may require ‘docker login’”)
02.07.19 17:47:19 (+0200) iotedge ERROR: Exiting with errors. Return code: 1

Hi @banto-78

Are you using a Docker base image that’s private? The Balena Cloud servers might not have access to pull it for you if so.

I am using this project:

I do not think there is anything private here.

It builds a Docker image as local/azure-iotedge-runtime-resin:latest. Maybe this becomes a inaccessible location ?!

hey @banto-78 what device type are you using? Also have you tried this line https://github.com/maxtheaviator/resin-azure-iotedge-multicontainer/blob/master/iotedge/app/startIotEdgeDevice.sh#L3 manually?

I am using RPi3 with image:

FROM balenalib/raspberrypi3-python:3.6-jessie-build

Where should I run that command? On the RPi3?

thanks

yeah, what I would do is put in a sleep infinity just above that line in the start script, then once that sleep is running, i would try run that line manually from the command line. My suspicion is that it is not finding a Dockerfile in the /azure-iotedge-runtime directory and so the container engine is trying to pull the image from dockerhub, but it doesn’t exist

Ok so if i attach to the container with shell and I go in “app” dir, the result of that line gives:

root@3827faf1ca3b:/app# docker build -t local/azure-iotedge-runtime-resin:latest /azure-iotedge-runtime
/usr/local/bin/docker: 2: exec: /usr/local/bin/balena: not found

any idea? Balena not installed?

okay, so from what i can see in that project, they install balena-engine in the container at this point: https://github.com/maxtheaviator/resin-azure-iotedge-multicontainer/blob/master/iotedge/Dockerfile#L12 and i guess that line is not working correctly when installing for arm. can you run curl -sfL https://balena.io/install.sh | sh from with in the container

ok, it pauses for 1 sec and then returns. But it does not print anything… Looks the link is wrong

and can you run balena version or access the binary that is missing? it sounds like its not installed correctly

well as i said above balena does not exist:

root@3827faf1ca3b:/# balena version
bash: balena: command not found

note that docker is just a file that aliases balena:

#!/bin/sh
exec /usr/local/bin/balena “$@”

So to me you’ve identified the problem. Balena is not installed. So how can we fix that curl line?