Register & Update Device at Once

Learn how to register a device and deploy an update at the same time.

Registration and Update deployment is a common use-case that might be useful for several scenarios, for such cases we created a script by using our REST API to register the device and deploy an update at the same time.

For example, If you would like to make sure that all devices registered to your fleet are automatically updated with the latest software, or, some kind of configuration that initiates after a successful factory reset.

Instead of registering the device via the installation command or a pre-made image, we will use a Python script on the device that will register and deploy an update to itself.

Prerequisites:

  • REST API enabled

  • Be familiar with our API and tokens - Overview

  • An Update Flow is created and ready to deploy

  • Python3 is installed on the device.

  • requests library installed on the device

The script performs the following:

  1. Registers the Device to Connect, according to the selected project

  2. Deploying an update flow that was previously configured in the platform.

  3. Even if the device is already registered, the update will still be deployed.

Instructions:

Take the code below and edit with the following configuration at the top:

  • USER_TOKEN - Your user token, can be taken from Settings > Account > Show User Token.

  • PROJECT_NAME - The name of the desired project that the device will be connected to.

  • UPDATE_FLOW_ID - ID of the desired flow to be deployed on the device, the flow must be a part of the project above.

import requests
import subprocess
import os
import json
import time

# ----------------------------#


# Needed to be edit per user before running
USER_TOKEN = ""
PROJECT_NAME = ""
UPDATE_FLOW_ID = ""
# ----------------------------#


# Don't touch - will be added automatically by the script
DEVICE_TOKEN = ""
DEVICE_UUID = ""
# Don't touch - static paths and URLs
INSTALLATION_URL = """su -c 'wget -O - https://connect.jfrog.io/v2/install_connect | sh -s {} {}'"""
CONNECT_AGENT_PATH = "/etc/connect/service/ConnectAgent"
AGENT_FLAG_TO_GET_DEVICE_TOKEN = "--print-token"
DEPLOY_UPDATE_API_URL = "https://api.connect.jfrog.io/v2/deploy_update"
GET_DEVICE_DETAILS_API_URL = "https://api.connect.jfrog.io/v1/devices_details"


def is_connect_agent_exist_on_device():
    return os.path.exists(CONNECT_AGENT_PATH)


def install_connect_agent(user_token, project_name):
    final_installation_url = INSTALLATION_URL.format(user_token, project_name)

    subprocess.check_output(final_installation_url, shell=True)

    print("waiting 2 minutes before continuing the process...")

    time.sleep(120)


def get_device_token():
    device_token = subprocess.check_output(CONNECT_AGENT_PATH + " " + AGENT_FLAG_TO_GET_DEVICE_TOKEN, shell=True)

    return device_token.decode('ascii')


def get_device_uuid(user_token, project_name, device_token):
    json_content = {'project_name': project_name,

                    'group_name': 'Production',

                    'user_token': user_token,

                    'device_token': device_token}

    call_request = requests.get(GET_DEVICE_DETAILS_API_URL, json=json_content)

    call_response = json.loads(call_request.text)

    return call_response["message"][0]["device_uuid"]


def deploy_update_flow(update_flow_id, user_token, project_name, device_uuid):
    print("deploying update flow {} on device {} ....".format(update_flow_id, device_uuid))

    json_content = {'user_token': user_token,

                    'metadata': {'comment': 'deploy app v1',

                                 'app': {'name': 'app', 'version': 'v1'}},
                                 
                    'deployment_configuration': {
                                 'flow_id': update_flow_id}

                    'devices_filter': {'project': {'name': project_name},

                                       'groups': [{'name': 'production'}],

                                       'filters': [{'type': 'specific_device',

                                                    'operand': 'is',

                                                    'value': device_uuid}]}

                    }

    call_request = requests.post(DEPLOY_UPDATE_API_URL, json=json_content)

    call_response = json.loads(call_request.text)

    if call_request.status_code == 200:

        print("process finished successfully")

    else:

        if call_request.status_code == 429:

            error = "API limit reached"

        else:

            error = call_response["error_message"]

        print(error)


if __name__ == '__main__':

    if not is_connect_agent_exist_on_device():

        if USER_TOKEN and PROJECT_NAME and UPDATE_FLOW_ID:

            install_connect_agent(USER_TOKEN, PROJECT_NAME)

        else:

            print(
                "one or all of the required parameters - user token, project name and update flow id were not provided, make sure to edit the script before running again")

            exit(1)

    else:

        print("JFrog Connect is already installed on device")

    if not DEVICE_TOKEN:
        DEVICE_TOKEN = get_device_token()

    if not DEVICE_UUID:
        DEVICE_UUID = get_device_uuid(USER_TOKEN, PROJECT_NAME, DEVICE_TOKEN)

    deploy_update_flow(UPDATE_FLOW_ID, USER_TOKEN, PROJECT_NAME, DEVICE_UUID)

2. Copy the script to the device

3. Choose when the script would run, some prefer having it running after the next power-on, while others initiate it with their on-device application.

Last updated