From fd24b27add5a29a1ff3b4877a3ae144740176bcd Mon Sep 17 00:00:00 2001 From: Daniel Hung Date: Thu, 6 Oct 2022 15:53:42 +0800 Subject: [PATCH] Update for V2_beta_1.2.3 - Add V2 shell scripts & files - Remove V1 tests & vsts_ci folders --- DEBIAN/control | 6 + EULA.md | 81 +++++ EULA.pdf | Bin 0 -> 68964 bytes MAKESELF/install.sh | 17 + NOTICE | 62 ++++ src/20.04/dmidecode_3.3-4.debian.tar.xz | Bin 0 -> 16652 bytes src/20.04/dmidecode_3.3-4_arm64.deb | Bin 0 -> 54380 bytes src/azure-iot-edge-installer.sh | 239 +++++++------- src/config/default-settings.json | 7 + src/config/hotfix-only.json | 5 + src/config/install-only.json | 5 + src/config/provision-only.json | 5 + src/install-container-management.sh | 4 +- src/install-edge-runtime.sh | 163 +++------- src/install-hotfix.sh | 32 ++ src/install-percept-packages.sh | 116 +++++++ src/provision-and-configure.sh | 298 ++++++++++++++++++ src/read-config-file.sh | 95 ++++++ src/show-help-menu.sh | 61 ++++ src/utils.sh | 109 +++++-- src/validate-post-install.sh | 101 ++++-- src/validate-tier1-os.sh | 34 +- tests/e2e-tests/test-devicestate.sh | 160 ---------- tests/e2e-tests/test-edge-deployment.json | 66 ---- tests/e2e-tests/test-ihedgecs.sh | 56 ---- tests/e2e-tests/test-uninstall.sh | 32 -- tests/perf_tests.sh | 26 -- tests/requirements.txt | 1 - tests/send_one_message_to_iot_hub_device.py | 25 -- tests/test_utils.sh | 77 ----- tests/track_duration.sh | 112 ------- tests/unit-tests/test-cmd-parser.sh | 67 ---- tests/unit-tests/test-logger.sh | 48 --- tests/unit-tests/test-telemetry-flag.sh | 24 -- .../unit-tests/test-validate-post-install.sh | 47 --- tests/unit-tests/test-validate-tier1-os.sh | 59 ---- vsts_ci/azure-pipelines-e2e.yml | 53 ---- vsts_ci/azure-pipelines-perf.yml | 52 --- vsts_ci/azure-pipelines.yml | 65 ---- vsts_ci/continuous-e2e-setup.yml | 20 -- vsts_ci/continuous-e2e-uninstalledge.yml | 16 - vsts_ci/continuous-e2e.yml | 18 -- vsts_ci/continuous-perf.yml | 28 -- vsts_ci/linux/continuous-linux.yml | 16 - vsts_ci/raspi/continuous-raspi.yml | 16 - 45 files changed, 1154 insertions(+), 1370 deletions(-) create mode 100644 DEBIAN/control create mode 100644 EULA.md create mode 100644 EULA.pdf create mode 100755 MAKESELF/install.sh create mode 100644 NOTICE create mode 100644 src/20.04/dmidecode_3.3-4.debian.tar.xz create mode 100644 src/20.04/dmidecode_3.3-4_arm64.deb mode change 100644 => 100755 src/azure-iot-edge-installer.sh create mode 100644 src/config/default-settings.json create mode 100644 src/config/hotfix-only.json create mode 100644 src/config/install-only.json create mode 100644 src/config/provision-only.json mode change 100644 => 100755 src/install-container-management.sh mode change 100644 => 100755 src/install-edge-runtime.sh create mode 100755 src/install-hotfix.sh create mode 100755 src/install-percept-packages.sh create mode 100755 src/provision-and-configure.sh create mode 100755 src/read-config-file.sh create mode 100755 src/show-help-menu.sh mode change 100644 => 100755 src/utils.sh mode change 100644 => 100755 src/validate-post-install.sh mode change 100644 => 100755 src/validate-tier1-os.sh delete mode 100644 tests/e2e-tests/test-devicestate.sh delete mode 100644 tests/e2e-tests/test-edge-deployment.json delete mode 100644 tests/e2e-tests/test-ihedgecs.sh delete mode 100644 tests/e2e-tests/test-uninstall.sh delete mode 100644 tests/perf_tests.sh delete mode 100644 tests/requirements.txt delete mode 100644 tests/send_one_message_to_iot_hub_device.py delete mode 100644 tests/test_utils.sh delete mode 100644 tests/track_duration.sh delete mode 100644 tests/unit-tests/test-cmd-parser.sh delete mode 100644 tests/unit-tests/test-logger.sh delete mode 100644 tests/unit-tests/test-telemetry-flag.sh delete mode 100644 tests/unit-tests/test-validate-post-install.sh delete mode 100644 tests/unit-tests/test-validate-tier1-os.sh delete mode 100644 vsts_ci/azure-pipelines-e2e.yml delete mode 100644 vsts_ci/azure-pipelines-perf.yml delete mode 100644 vsts_ci/azure-pipelines.yml delete mode 100644 vsts_ci/continuous-e2e-setup.yml delete mode 100644 vsts_ci/continuous-e2e-uninstalledge.yml delete mode 100644 vsts_ci/continuous-e2e.yml delete mode 100644 vsts_ci/continuous-perf.yml delete mode 100644 vsts_ci/linux/continuous-linux.yml delete mode 100644 vsts_ci/raspi/continuous-raspi.yml diff --git a/DEBIAN/control b/DEBIAN/control new file mode 100644 index 0000000..5761cfc --- /dev/null +++ b/DEBIAN/control @@ -0,0 +1,6 @@ +Package: eai-installer +Version: 1.2.3 +Architecture: arm64 +Maintainer: Azure Percept +Description: Microsoft Edge AI Installer + A set of Linux shell scripts to install Percept related Debian packages and also provision user configurations to make the device available to connect with Azure Percept resources. diff --git a/EULA.md b/EULA.md new file mode 100644 index 0000000..1fff422 --- /dev/null +++ b/EULA.md @@ -0,0 +1,81 @@ +## MICROSOFT SOFTWARE LICENSE TERMS +EDGE AI INSTALLER \* +
+ +These license terms are an agreement between you and Microsoft Corporation (or one of its affiliates). They apply to the software named above and any Microsoft services or software updates (except to the extent such services or updates are accompanied by new or additional terms, in which case those different terms apply prospectively and do not alter your or Microsoft’s rights relating to pre-updated software or services). IF YOU COMPLY WITH THESE LICENSE TERMS, YOU HAVE THE RIGHTS BELOW. BY USING THE SOFTWARE, YOU ACCEPT THESE TERMS. + +**1. INSTALLATION AND USE RIGHTS.** + + **a) General.** You may install and use any number of copies of the software on your devices. + + **b) Third Party Components.** The software may include third party components with separate legal notices or governed by other agreements, as may be described in the ThirdPartyNotices file(s) accompanying the software. + +**2. SCOPE OF LICENSE.** The software is licensed, not sold. Microsoft reserves all other rights. Unless applicable law gives you more rights despite this limitation, you will not (and have no right to): + + **a)** work around any technical limitations in the software that only allow you to use it in certain ways; + + **b)** reverse engineer, decompile or disassemble the software, or otherwise attempt to derive the source code for the software, except and to the extent required by third party licensing terms governing use of certain open source components that may be included in the software; + + **c)** remove, minimize, block, or modify any notices of Microsoft or its suppliers in the software; + + **d)** use the software in any way that is against the law or to create or propagate malware; or + + **e)** share, publish, distribute, or lease the software, provide the software as a stand-alone offering for others to use, or transfer the software or this agreement to any third party. + +**3. PRE-RELEASE SOFTWARE.** The software is a pre-release version. It may not operate correctly. It may be different from the commercially released version. + +**4. FEEDBACK.** If you give feedback about the software to Microsoft, you give to Microsoft, without charge, the right to use, share and commercialize your feedback in any way and for any purpose. You will not give feedback that is subject to a license that requires Microsoft to license its software or documentation to third parties because Microsoft includes your feedback in them. These rights survive this agreement. + +**5. DATA.** + + **a) Data Collection.** The software may collect information about you and your use of the software, and send that to Microsoft. Microsoft may use this information to provide services and improve our products and services. You may opt-out of many of these scenarios, but not all, as described in the product documentation. There are also some features in the software that may enable you to collect data from users of your applications. If you use these features to enable data collection in your applications, you must comply with applicable law, including providing appropriate notices to users of your applications. You can learn more about data collection and use in the help documentation and the privacy statement at [https://aka.ms/privacy](https://aka.ms/privacy). Your use of the software operates as your consent to these practices. + + **b) Processing of Personal Data.** To the extent Microsoft is a processor or subprocessor of personal data in connection with the software, Microsoft makes the commitments in the European Union General Data Protection Regulation Terms of the Online Services Terms to all customers effective May 25, 2018, at [https://docs.microsoft.com/en-us/legal/gdpr](https://docs.microsoft.com/en-us/legal/gdpr). + +**6. EXPORT RESTRICTIONS.** You must comply with all domestic and international export laws and regulations that apply to the software, which include restrictions on destinations, end users, and end use. For further information on export restrictions, visit [https://aka.ms/exporting](https://aka.ms/exporting). + +**7. SUPPORT SERVICES.** Microsoft is not obligated under this agreement to provide any support services for the software. Any support provided is “as is”, “with all faults”, and without warranty of any kind. + +**8. ENTIRE AGREEMENT.** This agreement, and any other terms Microsoft may provide for supplements, updates, or third-party applications, is the entire agreement for the software. + +**9. APPLICABLE LAW AND PLACE TO RESOLVE DISPUTES.** If you acquired the software in the United States or Canada, the laws of the state or province where you live (or, if a business, where your principal place of business is located) govern the interpretation of this agreement, claims for its breach, and all other claims (including consumer protection, unfair competition, and tort claims), regardless of conflict of laws principles. If you acquired the software in any other country, its laws apply. If U.S. federal jurisdiction exists, you and Microsoft consent to exclusive jurisdiction and venue in the federal court in King County, Washington for all disputes heard in court. If not, you and Microsoft consent to exclusive jurisdiction and venue in the Superior Court of King County, Washington for all disputes heard in court. + +**10. CONSUMER RIGHTS; REGIONAL VARIATIONS.** This agreement describes certain legal rights. You may have other rights, including consumer rights, under the laws of your state, province, or country. Separate and apart from your relationship with Microsoft, you may also have rights with respect to the party from which you acquired the software. This agreement does not change those other rights if the laws of your state, province, or country do not permit it to do so. For example, if you acquired the software in one of the below regions, or mandatory country law applies, then the following provisions apply to you: + + **a) Australia.** You have statutory guarantees under the Australian Consumer Law and nothing in this agreement is intended to affect those rights. + + **b) Canada.** If you acquired this software in Canada, you may stop receiving updates by turning off the automatic update feature, disconnecting your device from the Internet (if and when you re-connect to the Internet, however, the software will resume checking for and installing updates), or uninstalling the software. The product documentation, if any, may also specify how to turn off updates for your specific device or software. + + **c) Germany and Austria.** + +  **i. Warranty.** The properly licensed software will perform substantially as described in any Microsoft materials that accompany the software. However, Microsoft gives no contractual guarantee in relation to the licensed software. + +  **ii. Limitation of Liability.** In case of intentional conduct, gross negligence, claims based on the Product Liability Act, as well as, in case of death or personal or physical injury, Microsoft is liable according to the statutory law. + +  Subject to the foregoing clause ii., Microsoft will only be liable for slight negligence if Microsoft is in breach of such material contractual obligations, the fulfillment of which facilitate the due performance of this agreement, the breach of which would endanger the purpose of this agreement and the compliance with which a party may constantly trust in (so-called "cardinal obligations"). In other cases of slight negligence, Microsoft will not be liable for slight negligence. + +**11. DISCLAIMER OF WARRANTY. THE SOFTWARE IS LICENSED “AS IS.” YOU BEAR THE RISK OF USING IT. MICROSOFT GIVES NO EXPRESS WARRANTIES, GUARANTEES, OR CONDITIONS. TO THE EXTENT PERMITTED UNDER APPLICABLE LAWS, MICROSOFT EXCLUDES ALL IMPLIED WARRANTIES, INCLUDING MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.** + +**12. LIMITATION ON AND EXCLUSION OF DAMAGES. IF YOU HAVE ANY BASIS FOR RECOVERING DAMAGES DESPITE THE PRECEDING DISCLAIMER OF WARRANTY, YOU CAN RECOVER FROM MICROSOFT AND ITS SUPPLIERS ONLY DIRECT DAMAGES UP TO U.S. $5.00. YOU CANNOT RECOVER ANY OTHER DAMAGES, INCLUDING CONSEQUENTIAL, LOST PROFITS, SPECIAL, INDIRECT OR INCIDENTAL DAMAGES.** + +**This limitation applies to (a) anything related to the software, services, content (including code) on third party Internet sites, or third party applications; and (b) claims for breach of contract, warranty, guarantee, or condition; strict liability, negligence, or other tort; or any other claim; in each case to the extent permitted by applicable law.** + +**It also applies even if Microsoft knew or should have known about the possibility of the damages. The above limitation or exclusion may not apply to you because your state, province, or country may not allow the exclusion or limitation of incidental, consequential, or other damages.** + +**13. CONFIDENTIAL INFORMATION.** The software, including its user interface, features and documentation, is confidential and proprietary to Microsoft and its suppliers. + + **a) Use.** For five years after installation of the software or its commercial release, whichever is first, you may not disclose confidential information to third parties. You may disclose confidential information only to your employees and consultants who need to know the information. You must have written agreements with them that protect the confidential information at least as much as this agreement. + + **b) Survival.** Your duty to protect confidential information survives this agreement. + + **c) Exclusions.** You may disclose confidential information in response to a judicial or governmental order. You must first give written notice to Microsoft to allow it to seek a protective order or otherwise protect the information. Confidential information does not include information that: + +  **i.** becomes publicly known through no wrongful act; + +  **ii.** you received from a third party who did not breach confidentiality obligations to Microsoft or its suppliers; or + +  **iii.** you developed independently. + +
+ +\* Edge AI installer is the placeholder product name and will be updated with the official product name once approved. diff --git a/EULA.pdf b/EULA.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e1a61c3d1634ec7ba2dcb08204d661018e2a7c2d GIT binary patch literal 68964 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 z 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

Hs!{qis(Aa$P#D8mc&#Od93~gTE2tLIq(|8u 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 O^R4FQ;)ea+>i+^5So5X; literal 0 HcmV?d00001 diff --git a/MAKESELF/install.sh b/MAKESELF/install.sh new file mode 100755 index 0000000..619610c --- /dev/null +++ b/MAKESELF/install.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +sudo dpkg -i eai-installer_*.deb + +if [ "$?" != "0" ]; +then + echo "************************************************************************" + echo " The installation failed. Please try again..." + echo "************************************************************************" +else + echo "************************************************************************" + echo " Edge AI Installer is installed successfully!" + echo " You can get more details from the help menu:" + echo " $ cd /usr/local/microsoft/eai-installer" + echo " $ sudo ./azure-iot-edge-installer.sh --help" + echo "************************************************************************" +fi diff --git a/NOTICE b/NOTICE new file mode 100644 index 0000000..3925ada --- /dev/null +++ b/NOTICE @@ -0,0 +1,62 @@ +NOTICES AND INFORMATION +Do Not Translate or Localize + +Edge AI Installer +Copyright 2022 Microsoft + +This software incorporates material from +Azure IoT Edge configuration tool (https://github.com/Azure/iot-edge-config) + +The Initial Developer of the 20.04/dmidecode_3.3-4.debian.tar.xz +is Ubuntu Core Developers (ubuntu-devel-discuss@lists.ubuntu.com) +Copyright: 2003-2007 Petter Reinholdtsen + 2011-2012 Daniel Baumann + 2014-2019 Jörg Frings-Fürst + +--------------------------------------------------------- + +Binary: 20.04/dmidecode_3.3-4_arm64.deb +Source: 20.04/dmidecode_3.3-4.debian.tar.xz +The remainder of source can be downloaded from +Ubuntu Package server (https://packages.ubuntu.com/impish/dmidecode) + +License: GPL-2+ + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + . + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + . + You should have received a copy of the GNU General Public License + along with this program. If not, see . + . + The complete text of the GNU General Public License + can be found in /usr/share/common-licenses/GPL-2 file. + +--------------------------------------------------------- + +MIT License + + Copyright (c) Microsoft Corporation. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE diff --git a/src/20.04/dmidecode_3.3-4.debian.tar.xz b/src/20.04/dmidecode_3.3-4.debian.tar.xz new file mode 100644 index 0000000000000000000000000000000000000000..68e39f3579688e0de8a30bcf5b79528a4f4880e5 GIT binary patch literal 16652 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 literal 0 HcmV?d00001 diff --git a/src/20.04/dmidecode_3.3-4_arm64.deb b/src/20.04/dmidecode_3.3-4_arm64.deb new file mode 100644 index 0000000000000000000000000000000000000000..65a54e25357dc4d34b153ae6e53a7769352d096c GIT binary patch literal 54380 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

E`C1V_zK3QN>VV@ySded9F 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�y(dQ;-8Z~I%`n2>tq^S;PQpE`^=c##VV4XD?2#l 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\tThe Azure IoT Edge Device Connection String" - echo -e "${MAGENTA}\tThe default provisioning method. For example," - echo -e "\t$ sudo ./azure-iot-edge-installer.sh -c \"\"" - echo -e "${DEFAULT}" - echo "${BOLD}DPS Provisioning:${DEFAULT}" - echo -e "\t-s, --scope-id \t\t\tThe Azure DPS ID Scope" - echo -e "\t-r, --registration-id \t\tThe Azure IoT DPS enrollment Registration ID" - echo -e "\t-k, --symmetric-key \t\tThe Symmetric Key for the individual enrollment" - echo -e "${MAGENTA}\tThree arguments above are all neccessary for DPS provisioning. For example," - echo -e "\t$ sudo ./azure-iot-edge-installer.sh -s -r -k " - echo "${DEFAULT}" - echo "${BOLD}Telemetry:${DEFAULT}" - echo -e "\t-nt, --telemetry-opt-out\t\t\tDisable usage telemetry feature" - echo -e "\t-cv, --correlation-vector\t\t\tCorrelation vector specific to the run\n" -} - # add flag:variable_name dictionary entries add_option_args "TELEMETRY_OPT_OUT" -nt --telemetry-opt-out add_option_args "VERBOSE_LOGGING" -v --verbose @@ -131,8 +57,15 @@ add_option_args "SCOPE_ID" -s --scope-id add_option_args "REGISTRATION_ID" -r --registration-id add_option_args "SYMMETRIC_KEY" -k --symmetric-key add_option_args "CORRELATION_VECTOR" -cv --correlation-vector +add_option_args "FORCE_RUN" -f --force add_option_args "SHOW_HELP" -h --help add_option_args "CONNECTION_STRING" -c --connection-string +add_option_args "HOSTNAME" -hn --hostname +add_option_args "UPGRADE" -u --upgrade +add_option_args "INPUT_FILE" -i --input-file + +# load help menu +source show-help-menu.sh # parse command line inputs and fetch output from parser declare -A parsed_cmds="$(cmd_parser $@)" @@ -141,7 +74,29 @@ declare -A parsed_cmds="$(cmd_parser $@)" if [[ ${#@} == 0 || "${parsed_cmds["SHOW_HELP"]}" != "" ]]; then show_help - exit ${EXIT_CODES[1]} + exit ${EXIT_CODES[0]} +fi + +# show special characters limitation for connection string +if [[ "$@" == *"-c"* || "$@" == *"--connection-string"* ]]; +then + conn_string="${parsed_cmds["CONNECTION_STRING"]}" + device_tmp=${conn_string#*;DeviceId=} + device_id=${device_tmp%;SharedAccessKey=*} + + if [[ ${#@} > 0 && ${#parsed_cmds[*]} == 0 ]] || + [[ "${device_id}" == *"="* || "${device_id}" == *"%"* || "${device_id}" == *"!"* || "${device_id}" == *"$"* ]]; + then + echo "CONNECTION_STRING = \"${conn_string}\"" + echo "" + echo "${YELLOW}Please notice the installer does not support the following special characters for DeviceId in the connection string!" + echo " - equal sign ( = )" + echo " - percent sign ( % )" + echo " - exclamation mark ( ! )" + echo " - dollar sign ( $ )${DEFAULT}" + show_help + exit ${EXIT_CODES[1]} + fi fi # validate that all arguments are acceptable / known @@ -153,26 +108,36 @@ then exit ${EXIT_CODES[1]} fi -# is a connection string given for provisioning? +# upgrade packages +if [[ "${parsed_cmds["UPGRADE"]}" != "" ]]; +then + only_upgrade + exit ${EXIT_CODES[0]} +fi + +# parse input config file +if [[ "${parsed_cmds["INPUT_FILE"]}" != "" ]]; +then + source read-config-file.sh + prepare_json + file_parser ${parsed_cmds["INPUT_FILE"]} +fi + +# check arguments for provisioning +if [[ "${parsed_cmds["INPUT_FILE"]}" == "" ]] || + [[ "${parsed_cmds["INPUT_FILE"]}" != "" && "${parsed_cfgs[{action}{do_provisioning}]}" == "true" ]]; +then if [[ "${parsed_cmds["CONNECTION_STRING"]}" == "" ]]; then - # validate that all DPS parameters have been provided - if [[ "${parsed_cmds["SCOPE_ID"]}" == "" || "${parsed_cmds["REGISTRATION_ID"]}" == "" || "${parsed_cmds["SYMMETRIC_KEY"]}" == "" ]]; - then - echo Missing argument - echo defined: "'"${!parsed_cmds[@]}"'" - echo given: "'"${parsed_cmds[@]}"'" - show_help - exit ${EXIT_CODES[2]} - fi -else - if [[ "${parsed_cmds["CONNECTION_STRING"]}" == "true" ]]; - then - echo Missing argument - echo The IoTEdge device connection string must be provided with the '-c / --connection-string' option - show_help - exit ${EXIT_CODES[2]} - fi +if [[ "${parsed_cmds["SCOPE_ID"]}" == "" || "${parsed_cmds["REGISTRATION_ID"]}" == "" || "${parsed_cmds["SYMMETRIC_KEY"]}" == "" ]]; +then + echo Missing provisioning argument + echo defined: "'"${!parsed_cmds[@]}"'" + echo given: "'"${parsed_cmds[@]}"'" + show_help + exit ${EXIT_CODES[2]} +fi +fi fi set_opt_out_selection ${parsed_cmds["TELEMETRY_OPT_OUT"]} ${parsed_cmds["CORRELATION_VECTOR"]} ${parsed_cmds["SCOPE_ID"]} ${parsed_cmds["REGISTRATION_ID"]} @@ -186,6 +151,11 @@ then exit ${EXIT_CODES[3]} fi +### Installation ### +if [[ "${parsed_cmds["INPUT_FILE"]}" == "" ]] || + [[ "${parsed_cmds["INPUT_FILE"]}" != "" && "${parsed_cfgs[{action}{do_install}]}" == "true" ]]; +then + # run scripts in order, can take parsed input from above platform=$(get_platform) prepare_apt $platform @@ -194,14 +164,57 @@ source install-container-management.sh install_container_management source install-edge-runtime.sh +install_edge_runtime + +source install-percept-packages.sh +install_osconfig +install_defender + +configure_percept_services + +fi + +### Hotfix ### +if [[ "${parsed_cmds["INPUT_FILE"]}" == "" ]] || + [[ "${parsed_cmds["INPUT_FILE"]}" != "" && "${parsed_cfgs[{action}{do_hotfix}]}" == "true" ]]; +then + +source install-hotfix.sh +is_aarch64 +if [ "$?" == "0" ]; +then + # arm64 + install_defender_hotfix +else + # amd64 + log_info "No hotfix is required!" +fi + +fi + +### Provisioning & Configuration ### +source provision-and-configure.sh +if [[ "${parsed_cmds["INPUT_FILE"]}" == "" ]] || + [[ "${parsed_cmds["INPUT_FILE"]}" != "" && "${parsed_cfgs[{action}{do_provisioning}]}" == "true" ]]; +then + +setup_product_info +stop_iotedge_service if [[ "${parsed_cmds["CONNECTION_STRING"]}" == "" ]]; then - install_edge_runtime_dps ${parsed_cmds["SCOPE_ID"]} ${parsed_cmds["REGISTRATION_ID"]} ${parsed_cmds["SYMMETRIC_KEY"]} + setup_hostname ${parsed_cmds["HOSTNAME"]} ${parsed_cmds["REGISTRATION_ID"]} + dps_provisioning ${parsed_cmds["SCOPE_ID"]} ${parsed_cmds["REGISTRATION_ID"]} ${parsed_cmds["SYMMETRIC_KEY"]} else - install_edge_runtime_cs ${parsed_cmds["CONNECTION_STRING"]} + setup_hostname ${parsed_cmds["HOSTNAME"]} ${parsed_cmds["CONNECTION_STRING"]} + cs_provisioning ${parsed_cmds["CONNECTION_STRING"]} +fi + fi +reset_percept_services +### Validation ### source validate-post-install.sh validate_post_install +show_package_version exit ${EXIT_CODES[0]} diff --git a/src/config/default-settings.json b/src/config/default-settings.json new file mode 100644 index 0000000..ccfaa60 --- /dev/null +++ b/src/config/default-settings.json @@ -0,0 +1,7 @@ +{ + "action" : { + "do_install" : true, + "do_hotfix" : true, + "do_provisioning" : true + } +} diff --git a/src/config/hotfix-only.json b/src/config/hotfix-only.json new file mode 100644 index 0000000..5633cb1 --- /dev/null +++ b/src/config/hotfix-only.json @@ -0,0 +1,5 @@ +{ + "action" : { + "do_hotfix" : true + } +} diff --git a/src/config/install-only.json b/src/config/install-only.json new file mode 100644 index 0000000..508b040 --- /dev/null +++ b/src/config/install-only.json @@ -0,0 +1,5 @@ +{ + "action" : { + "do_install" : true + } +} diff --git a/src/config/provision-only.json b/src/config/provision-only.json new file mode 100644 index 0000000..1c6b7ad --- /dev/null +++ b/src/config/provision-only.json @@ -0,0 +1,5 @@ +{ + "action" : { + "do_provisioning" : true + } +} diff --git a/src/install-container-management.sh b/src/install-container-management.sh old mode 100644 new mode 100755 index f45efcb..ccbacbd --- a/src/install-container-management.sh +++ b/src/install-container-management.sh @@ -16,13 +16,13 @@ ###################################### install_container_management() { - if [ -x "$(command -v docker)" ]; + if [ "x$(command -v docker)" != "x" ]; then log_info "docker command is already available." else log_info "Installing moby-engine container management" - apt-get install moby-engine -y 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT & + apt-get install -o Dpkg::Options::="--force-confdef" moby-engine=20.10.17+azure-ubuntu20.04u3 -y 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT & long_running_command $! exit_code=$? if [[ $exit_code != 0 ]]; diff --git a/src/install-edge-runtime.sh b/src/install-edge-runtime.sh old mode 100644 new mode 100755 index 170a7f1..af73ca9 --- a/src/install-edge-runtime.sh +++ b/src/install-edge-runtime.sh @@ -6,160 +6,77 @@ #script to install edge runtime 1.2 ###################################### -# apply_config_changes +# remove_packages # -# - apply changes and restart +# - Remove the installed packages including of +# * IoTEdge +# * OSConfig +# * Defender for IoT # # ARGUMENTS: +# None # OUTPUTS: # Write output to stdout # RETURN: +# updates the global variable OK_TO_CONTINUE in case of success to true. ###################################### -function apply_config_changes() { - log_info "Apply settings - this will restart Azure IoTEdge" - iotedge config apply 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT - exit_code=$? - if [[ $exit_code == 0 ]]; - then - log_info "IoTEdge has been configured successfully" - fi -} +function remove_packages() { + log_info "Removing installed packages..." -###################################### -# install_common -# -# - install the runtime -# -# ARGUMENTS: -# OUTPUTS: -# Write output to stdout -# RETURN: -###################################### - -function install_common() { - log_info "Installing edge runtime..." - - apt-get install aziot-edge -y 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT & + apt-get remove --purge ${percept_packages[@]} -y 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT & long_running_command $! exit_code=$? if [[ $exit_code != 0 ]]; then - log_info "aziot-edged installation failed with exit code: %d" $exit_code + log_info "apt remove failed with exit code: %d" $exit_code exit ${EXIT_CODES[10]} fi - log_info "Installed edge runtime..." + log_info "Removed all packages" } ###################################### -# install_edge_runtime_dps -# -# - installs Azure IoT Edge Runtime 1.2, DPS provisioning -# - generates the edge's configuration file from template and -# fills in the DPS provisioning section from provided parameters -# -# ARGUMENTS: -# SCOPE_ID -# REGISTRATION_ID -# SYMMETRIC_KEY -# OUTPUTS: -# Write output to stdout -# RETURN: -# updates the global variable OK_TO_CONTINUE in case of success to true. -###################################### - -function install_edge_runtime_dps() { - if [[ $# != 3 || "$1" == "" || "$2" == "" || "$3" == "" ]]; - then - log_error "Scope ID, Registration ID, and the Symmetric Key are required" - exit ${EXIT_CODES[2]} - fi - - if [ -x "$(command -v iotedge)" ]; - then - log_error "Edge runtime is already available." - exit ${EXIT_CODES[9]} - fi - - install_common - - # create config.toml - log_info "Create instance configuration 'config.toml'." - - local SCOPE_ID=$1 - local REGISTRATION_ID=$2 - local SYMMETRIC_KEY=$3 - - log_info "Set DPS provisioning parameters." - - local FILE_NAME="/etc/aziot/config.toml" - - # create a config.toml - will replace existing - echo 'hostname = "'`hostname`'"' > $FILE_NAME - echo '' >> $FILE_NAME - echo '## DPS provisioning with symmetric key' >> $FILE_NAME - echo '[provisioning]' >> $FILE_NAME - echo 'source = "dps"' >> $FILE_NAME - echo 'global_endpoint = "https://global.azure-devices-provisioning.net"' >> $FILE_NAME - echo 'id_scope = "'$SCOPE_ID'"' >> $FILE_NAME - echo '' >> $FILE_NAME - echo '[provisioning.attestation]' >> $FILE_NAME - echo 'method = "symmetric_key"' >> $FILE_NAME - echo 'registration_id = "'$REGISTRATION_ID'"' >> $FILE_NAME - echo '' >> $FILE_NAME - echo 'symmetric_key = { value = "'$SYMMETRIC_KEY'" }' >> $FILE_NAME - echo '' >> $FILE_NAME - - apply_config_changes -} - -###################################### -# install_edge_runtime_cs +# install_edge_runtime # # - installs Azure IoT Edge Runtime 1.2 -# - generates the edge's configuration file from template and -# fills in the manual provisioning section from provided parameters # # ARGUMENTS: -# CONNECTION_STRING +# None # OUTPUTS: # Write output to stdout # RETURN: # updates the global variable OK_TO_CONTINUE in case of success to true. ###################################### -function install_edge_runtime_cs() { - if [[ $# != 1 || "$1" == "" ]]; +function install_edge_runtime() { + if [ "x$(command -v iotedge)" != "x" ]; then - log_error "IoTEdge Device Connection string is required" - exit ${EXIT_CODES[2]} + log_warn "Edge runtime is already available." + + if [[ "${parsed_cmds["FORCE_RUN"]}" == "" ]]; + then + read -p "Do you want to install again? [Y/n] " ans + if [ ${ans^} == 'Y' ]; + then + remove_packages + else + exit ${EXIT_CODES[9]} + fi + else + log_info "Force to run the installation!" + remove_packages + fi fi - if [ -x "$(command -v iotedge)" ]; + log_info "Installing edge runtime..." + + apt-get install -o Dpkg::Options::="--force-confdef" aziot-identity-service="${package_versions[0]}" aziot-edge="${package_versions[1]}" -y 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT & + long_running_command $! + exit_code=$? + if [[ $exit_code != 0 ]]; then - log_error "Edge runtime is already available." - exit ${EXIT_CODES[9]} + log_info "aziot-edged installation failed with exit code: %d" $exit_code + exit ${EXIT_CODES[10]} fi - - install_common - - # create config.toml - log_info "Create instance configuration 'config.toml'." - - local CONNECTION_STRING=$1 - - log_info "Set manual provisioning parameters." - - local FILE_NAME="/etc/aziot/config.toml" - - # create a config.toml - will replace existing - echo 'hostname = "'`hostname`'"' > $FILE_NAME - echo '' >> $FILE_NAME - echo '## Manual provisioning configuration' >> $FILE_NAME - echo '[provisioning]' >> $FILE_NAME - echo 'source = "manual"' >> $FILE_NAME - echo 'connection_string = "'$CONNECTION_STRING'"' >> $FILE_NAME - echo '' >> $FILE_NAME - - apply_config_changes + log_info "Installed edge runtime..." } diff --git a/src/install-hotfix.sh b/src/install-hotfix.sh new file mode 100755 index 0000000..1d81ced --- /dev/null +++ b/src/install-hotfix.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash + +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +#script to install hotfix for percept related functions + +###################################### +# install_defender_hotfix +# +# - Fix the system hang issue caused by Defender for IoT (defender-iot-micro-agent-edge) +# +# ARGUMENTS: +# None +# OUTPUTS: +# Write output to stdout +# RETURN: +# +###################################### + +function install_defender_hotfix() { + log_info "Installing defender hotfix ..." + dpkg -i ${VERSION_ID}/dmidecode_3.3-4_arm64.deb 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT & + long_running_command $! + exit_code=$? + if [[ $exit_code != 0 ]]; + then + log_info "dmidecode_3.3-4: installation failed with exit code: %d" $exit_code + exit ${EXIT_CODES[10]} + fi + log_info "Installed defender hotfix" +} diff --git a/src/install-percept-packages.sh b/src/install-percept-packages.sh new file mode 100755 index 0000000..9e79115 --- /dev/null +++ b/src/install-percept-packages.sh @@ -0,0 +1,116 @@ +#!/usr/bin/env bash + +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +#script to install percept related packages + +###################################### +# install_osconfig +# +# - Install OSConfig +# +# ARGUMENTS: +# None +# OUTPUTS: +# Write output to stdout +# RETURN: +# +###################################### + +function install_osconfig() { + # OSConfig + log_info "Installing osconfig..." + apt-get install -o Dpkg::Options::="--force-confdef" osconfig="${package_versions[2]}" -y 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT & + long_running_command $! + exit_code=$? + if [[ $exit_code != 0 ]]; + then + log_info "osconfig installation failed with exit code: %d" $exit_code + exit ${EXIT_CODES[10]} + fi + log_info "Installed osconfig" +} + +###################################### +# install_defender +# +# - Install Defender for IoT (defender-iot-micro-agent-edge) +# +# ARGUMENTS: +# None +# OUTPUTS: +# Write output to stdout +# RETURN: +# +###################################### + +function install_defender() { + # Defender for IoT + log_info "Installing defender..." + apt-get install -o Dpkg::Options::="--force-confdef" defender-iot-micro-agent-edge="${package_versions[3]}" -y 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT & + long_running_command $! + exit_code=$? + if [[ $exit_code != 0 ]]; + then + log_info "defender installation failed with exit code: %d" $exit_code + exit ${EXIT_CODES[10]} + fi + log_info "Installed defender" +} + +###################################### +# configure_percept_services +# +# - Fix the warning and error messages from 'iotedge check' command +# +# ARGUMENTS: +# None +# OUTPUTS: +# Write output to stdout +# RETURN: +# updates the global variable OK_TO_CONTINUE in case of success to true. +###################################### + +function configure_percept_services() { + log_info "Set Docker default parameters" + local FILE_NAME="/etc/docker/daemon.json" + local existing_item="" + + if [ ! -f $FILE_NAME ]; + then + log_info "Create $FILE_NAME" + # create a docker daemon.json + echo '{' > $FILE_NAME + echo ' "dns": ["1.1.1.1", "8.8.8.8"],' >> $FILE_NAME + echo ' "log-driver": "json-file",' >> $FILE_NAME + echo ' "log-opts": {' >> $FILE_NAME + echo ' "max-size": "10m",' >> $FILE_NAME + echo ' "max-file": "3"' >> $FILE_NAME + echo ' }' >> $FILE_NAME + echo '}' >> $FILE_NAME + chmod 644 $FILE_NAME + else + # Log Driver & Options + existing_item="$(grep log-driver $FILE_NAME)" + if [ "x$existing_item" == "x" ]; + then + log_info "Add Log driver & options to $FILE_NAME" + sed -i '1 a\ + "log-driver": "json-file",\ + "log-opts": {\ + "max-size": "10m",\ + "max-file": "3"\ + },' $FILE_NAME + fi + + # DNS + existing_item="$(grep dns $FILE_NAME)" + if [ "x$existing_item" == "x" ]; + then + log_info "Add DNS to $FILE_NAME" + sed -i '1 a\ + "dns": ["1.1.1.1", "8.8.8.8"],' $FILE_NAME + fi + fi +} diff --git a/src/provision-and-configure.sh b/src/provision-and-configure.sh new file mode 100755 index 0000000..8fd31e9 --- /dev/null +++ b/src/provision-and-configure.sh @@ -0,0 +1,298 @@ +#!/usr/bin/env bash + +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +#script to provision & configure + +###################################### +# setup_product_info +# +# - Write OS Variant, Manufacturer & Product Name into /etc/product-info.toml +# - If the file exists AND the key name os_variant exists, do nothing +# - Add additional_info into /etc/aziot/config.toml.edge.template +# +# ARGUMENTS: +# +# OUTPUTS: +# Write output to stdout +# RETURN: +# +###################################### + +function setup_product_info() { + local PRODUCT_INFO_FILE="/etc/product-info.toml" + local os_varient="operating_system_variant" + local varient_mark="eai_installer" + local existing_item="" + + if [ ! -f $PRODUCT_INFO_FILE ]; + then + log_info "Create $PRODUCT_INFO_FILE" + touch $PRODUCT_INFO_FILE + chmod 644 $PRODUCT_INFO_FILE + + echo "${os_varient}=\"${varient_mark}\"" > $PRODUCT_INFO_FILE + echo "product_name=\"$(get_product_name)\"" >> $PRODUCT_INFO_FILE + echo "system_vendor=\"$(get_manufacturer)\"" >> $PRODUCT_INFO_FILE + else + # OS Varient + existing_item="$(grep $os_varient $PRODUCT_INFO_FILE)" + if [ "x$existing_item" == "x" ]; + then + log_info "Write ${os_varient} to $PRODUCT_INFO_FILE" + echo "${os_varient}=\"${varient_mark}\"" >> $PRODUCT_INFO_FILE + fi + # Product Name + existing_item="$(grep product_name $PRODUCT_INFO_FILE)" + if [ "x$existing_item" == "x" ]; + then + log_info "Write product_name to $PRODUCT_INFO_FILE" + echo "product_name=\"$(get_product_name)\"" >> $PRODUCT_INFO_FILE + fi + # Manufacturer + existing_item="$(grep system_vendor $PRODUCT_INFO_FILE)" + if [ "x$existing_item" == "x" ]; + then + log_info "Write system_vendor to $PRODUCT_INFO_FILE" + echo "system_vendor=\"$(get_manufacturer)\"" >> $PRODUCT_INFO_FILE + fi + fi + + local TEMPLATE_TOML_FILE="/etc/aziot/config.toml.edge.template" + if [ -f $TEMPLATE_TOML_FILE ]; + then + existing_item="$(grep additional_info $TEMPLATE_TOML_FILE)" + if [ "x$existing_item" == "x" ]; + then + log_info "Update $TEMPLATE_TOML_FILE" + sed -i '/parent_hostname/ a\ +\n\ +# ==============================================================================\ +# Additional information\ +# ==============================================================================\ +#\ +# Uncomment the next line to override the system information from /etc/os-release\ +#\ +additional_info = "file:///etc/product-info.toml"' $TEMPLATE_TOML_FILE + fi + fi +} + +###################################### +# stop_iotedge_service +# +# - Stop iotedge services before we do provisioning +# +# ARGUMENTS: +# +# OUTPUTS: +# Write output to stdout +# RETURN: +# +###################################### + +function stop_iotedge_service() +{ + local status=$(sudo iotedge system status | grep -i running) + + if [ "$status" != "" ]; then + log_info "Stop iotedge services ..." + iotedge system stop 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT & + long_running_command $! + fi +} + +###################################### +# setup_hostname +# +# - Get hostname from either given value, connnection string or DPS registration id. +# - Update device hostname +# - Remove existing containers with old hostname +# +# ARGUMENTS: +# HOSTNAME +# CONNECTION_STRING or REGISTRATION_ID +# OUTPUTS: +# Write output to stdout +# RETURN: +# updates the global variable OK_TO_CONTINUE in case of success to true. +###################################### + +function setup_hostname() { + if [[ $# == 2 && "$1" != "" && "$2" != "" ]]; + then + local NEW_HOSTNAME=$1 + # get hostname from connection string or DPS registration id + if [[ "$1" == "true" ]]; + then + NEW_HOSTNAME=$2 + if [[ "$2" != *"DeviceId="* ]]; + then + log_info "Assign DPS registration id (${NEW_HOSTNAME}) as hostname" + else + local DEVICE_ID=${NEW_HOSTNAME#*;DeviceId=} + NEW_HOSTNAME=${DEVICE_ID%;SharedAccessKey=*} + log_info "Assign Device ID (${NEW_HOSTNAME}) as hostname" + fi + else + log_info "New hostname: ${NEW_HOSTNAME}" + fi + + # update device's hostname + log_info "Update device hostname..." + local OLD_HOSTNAME=`hostname` + hostnamectl set-hostname $NEW_HOSTNAME 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT + sed -i "s/${OLD_HOSTNAME}/${NEW_HOSTNAME}/g" /etc/hosts 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT + sudo systemctl restart avahi-daemon.service 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT + + log_info "Device hostname is set completely" + + # remove the containers with old hostname + if [[ "x$(docker ps -aq -f name=edgeHub -f name=edgeAgent)" != "x" ]]; + then + log_info "Remove existing containers: edgeHub, edgeAgent" + docker rm -f $(docker ps -aq -f name=edgeHub -f name=edgeAgent) 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT + fi + fi +} + +###################################### +# dps_provisioning +# +# - generates the edge's configuration file from template and +# fills in the DPS provisioning section from provided parameters +# +# ARGUMENTS: +# SCOPE_ID +# REGISTRATION_ID +# SYMMETRIC_KEY +# OUTPUTS: +# Write output to stdout +# RETURN: +# updates the global variable OK_TO_CONTINUE in case of success to true. +###################################### + +function dps_provisioning() { + if [[ $# != 3 || "$1" == "" || "$2" == "" || "$3" == "" ]]; + then + log_error "Scope ID, Registration ID, and the Symmetric Key are required" + exit ${EXIT_CODES[2]} + fi + + # create config.toml + log_info "Create instance configuration 'config.toml'." + + local SCOPE_ID=$1 + local REGISTRATION_ID=$2 + local SYMMETRIC_KEY=$3 + + log_info "Set DPS provisioning parameters." + + local FILE_NAME="/etc/aziot/config.toml" + + # create a config.toml - will replace existing + echo 'hostname = "'`hostname`'"' > $FILE_NAME + echo 'additional_info = "file:///etc/product-info.toml"' >> $FILE_NAME + echo '' >> $FILE_NAME + echo '## DPS provisioning with symmetric key' >> $FILE_NAME + echo '[provisioning]' >> $FILE_NAME + echo 'source = "dps"' >> $FILE_NAME + echo '' >> $FILE_NAME + echo 'global_endpoint = "https://global.azure-devices-provisioning.net"' >> $FILE_NAME + echo 'id_scope = "'$SCOPE_ID'"' >> $FILE_NAME + echo '' >> $FILE_NAME + echo '[provisioning.attestation]' >> $FILE_NAME + echo 'method = "symmetric_key"' >> $FILE_NAME + echo 'registration_id = "'$REGISTRATION_ID'"' >> $FILE_NAME + echo '' >> $FILE_NAME + echo 'symmetric_key = { value = "'$SYMMETRIC_KEY'" }' >> $FILE_NAME + echo '' >> $FILE_NAME + + log_info "Apply settings - this will restart the edge" + iotedge config apply 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT + exit_code=$? + if [[ $exit_code == 0 ]]; + then + log_info "IotEdge has been configured successfully" + else + log_error "Cannot apply config! Please check ${BOLD}$STDERR_REDIRECT${DEFAULT} for details" + exit ${EXIT_CODES[2]} + fi +} + +###################################### +# cs_provisioning +# +# - get the connection string from provided parameters and +# run 'iotedge config' commands to apply the connection string +# +# ARGUMENTS: +# CONNECTION_STRING +# OUTPUTS: +# Write output to stdout +# RETURN: +# updates the global variable OK_TO_CONTINUE in case of success to true. +###################################### + +function cs_provisioning() { + if [[ $# != 1 || "$1" == "" ]]; + then + log_error "Connection string is required" + exit ${EXIT_CODES[2]} + fi + + if [[ "$1" != *"HostName"* || "$1" != *"DeviceId"* || "$1" != *"SharedAccessKey"* ]]; + then + log_error "Connection string is invalid! Make sure the connection string includes 'HostName', 'DeviceId' & 'SharedAccessKey' keywords or check if double quotes (\"\") are used as parameters!" + exit ${EXIT_CODES[2]} + fi + + log_info "Assign connection string to the config file" + iotedge config mp --force --connection-string $1 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT + + log_info "Write configurations to config.toml" + local FILE_NAME="/etc/aziot/config.toml" + sed -i "1 a hostname = \"`hostname`\"" $FILE_NAME + sed -i "2 a additional_info = \"file:///etc/product-info.toml\"" $FILE_NAME + + log_info "Apply settings - this will restart the edge" + iotedge config apply 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT + exit_code=$? + if [[ $exit_code == 0 ]]; + then + log_info "IotEdge has been configured successfully" + else + log_error "Cannot apply config! Please check ${BOLD}$STDERR_REDIRECT${DEFAULT} for details" + exit ${EXIT_CODES[2]} + fi +} + +###################################### +# reset_percept_services +# +# - restart docker and percept specific services +# +# ARGUMENTS: +# None +# OUTPUTS: +# Write output to stdout +# RETURN: +# +###################################### + +function reset_percept_services() { + log_info "Restart docker service ..." + sudo systemctl restart docker 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT + exit_code=$? + if [[ $exit_code == 0 ]]; + then + log_info "Docker has been configured successfully" + fi + + log_info "Restart osconfig service" + sudo systemctl restart osconfig.service + + log_info "Restart defender service" + sudo systemctl restart defender-iot-micro-agent.service +} diff --git a/src/read-config-file.sh b/src/read-config-file.sh new file mode 100755 index 0000000..9d3faab --- /dev/null +++ b/src/read-config-file.sh @@ -0,0 +1,95 @@ +#!/usr/bin/env bash + +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +#script to read JSON format input file + +###################################### +# prepare_json +# +# - Check perl package for json query feature +# +# ARGUMENTS: +# +# OUTPUTS: +# Write output to stdout +# RETURN: +# +###################################### +function prepare_json() { + if [ "x$(command -v json_pp)" != "x" ]; + then + log_info "Perl JSON::PP module is available" + else + log_error "Please install 'perl' package for --input-file option by running '${YELLOW}sudo apt-get install perl -y${DEFAULT}'." + exit ${EXIT_CODES[6]} + fi +} + +###################################### +# file_parser +# +# - Parse configurations from the input json file +# +# ARGUMENTS: +# JSON file path +# OUTPUTS: +# Write output to stdout +# RETURN: +# +###################################### +declare -A parsed_cfgs +declare -a cfg_options=("{action}{do_install}" + "{action}{do_provisioning}" + "{action}{do_hotfix}") + +function file_parser() { + local perl_cmd='local $/;my $json=JSON::PP->new;print $json->encode( $json->decode()->' + local is_found=false + + if [ $# != 1 ]; + then + exit ${EXIT_CODES[2]} + else + input_file=$1 + if [ -f $input_file ]; + then + log_info "Read configurations from %s ..." $input_file + for key in ${!cfg_options[*]}; + do + cat $input_file | perl -MJSON::PP -e "${perl_cmd}${cfg_options[$key]} )" 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT + exit_code=$? + if [[ $exit_code == 0 ]]; + then + is_found=true + fi + + parsed_cfgs[${cfg_options[$key]}]=$(cat $input_file | perl -MJSON::PP -e "${perl_cmd}${cfg_options[$key]} )" 2>>$STDERR_REDIRECT) + log_info "\t${YELLOW}${cfg_options[$key]} = ${parsed_cfgs[${cfg_options[$key]}]}${DEFAULT}" + done + if [[ $is_found == false ]]; + then + log_error "Cannot find valid item! Please check the input file." + exit ${EXIT_CODES[2]} + fi + + # prompt to users for action + if [[ "${parsed_cmds["FORCE_RUN"]}" == "" ]]; + then + read -p "Is the configuration correct? [Y/n] " ans + if [ ${ans^} == 'Y' ]; + then + log_info "Processing the configuration ..." + else + exit ${EXIT_CODES[2]} + fi + else + log_info "Force to process the configuration ..." + fi + else + log_error "The config file '%s' does not exist!" $input_file + exit ${EXIT_CODES[2]} + fi + fi +} diff --git a/src/show-help-menu.sh b/src/show-help-menu.sh new file mode 100755 index 0000000..e82d822 --- /dev/null +++ b/src/show-help-menu.sh @@ -0,0 +1,61 @@ +#!/usr/bin/env bash + +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +#script to show help menu + +###################################### +# show_help +# +# - Display HELP menu for options +# +# ARGUMENTS: +# None +# OUTPUTS: +# Write output to stdout +# RETURN: +# +###################################### + +function show_help() { + echo "" + echo "${BOLD}Usage: sudo ./azure-iot-edge-installer.sh [OPTION]...${DEFAULT}" + echo "" + echo "${BOLD}Basic:${DEFAULT}" + echo -e "\t-h, --help\t\t\t\t\tPrint this help" + echo -e "\t-f, --force\t\t\t\t\tRun installation immediately without prompt" + echo -e "\t-u, --upgrade\t\t\t\t\tInstall upgrades for the installed packages only and ignore new package installation" + echo "" + echo "${BOLD}Connection String Provisioning:${DEFAULT}" + echo -e "\t-c, --connection-string \tThe Azure IoT Edge Device Connection String" + echo -e "${MAGENTA}\tThe default provisioning method. For example," + echo -e "\t$ sudo ./azure-iot-edge-installer.sh -c \"\"" + echo -e "${DEFAULT}" + echo "${BOLD}DPS Provisioning:${DEFAULT}" + echo -e "\t-s, --scope-id \t\t\tThe Azure DPS ID Scope" + echo -e "\t-r, --registration-id \t\tThe Azure DPS enrollment Registration ID" + echo -e "\t-k, --symmetric-key \t\tThe Symmetric Key for the individual enrollment" + echo -e "${MAGENTA}\tThree arguments above are all neccessary for DPS provisioning. For example," + echo -e "\t$ sudo ./azure-iot-edge-installer.sh -s -r -k " + echo "${DEFAULT}" + echo "${BOLD}Advanced:${DEFAULT}" + echo -e "\t-hn, --hostname [HOSTNAME]\t\t\tSet hostname for both device & IoT Edge" + echo -e "${MAGENTA}\tIf no value is given, the hostname is automatically extracted from the connection string (DeviceID field)" + echo -e "\tor set as the DPS registration id. Otherwise, the given value would overwrite the automatic naming options.\n" + echo -e "\tPlease also notice that the hostname should comply with RFC 1035." + echo -e "\t - Hostname must be between 1 and 255 octets inclusive." + echo -e "\t - Each label in the hostname (component separated by \".\") must be between 1 and 63 octets inclusive." + echo -e "\t - Each label must start with an ASCII alphabet character (a-z, A-Z), end with an ASCII alphanumeric character (a-z, A-Z, 0-9), and must contain only ASCII alphanumeric character or hypens (a-z, A-Z, 0-9, \"-\")" + echo "${DEFAULT}" + echo -e "\t-i, --input-file \t\t\tRead the configurations from a JSON format input file" + echo -e "${MAGENTA}\tIt supports the 'action' field. Please refer to .json files in the 'config' folder." + echo -e "\tFor example, you can do provisioning only by this way: (make sure 'aziot-edge' is installed before running this)" + echo -e "\t$ sudo ./azure-iot-edge-installer.sh -i config/provision-only.json -c \"\"" + echo -e "\t- OR -" + echo -e "\t$ sudo ./azure-iot-edge-installer.sh -i config/provision-only.json -s -r -k " + echo "${DEFAULT}" + echo "${BOLD}Telemetry:${DEFAULT}" + echo -e "\t-nt, --telemetry-opt-out\t\t\tDisable usage telemetry feature" + echo -e "\t-cv, --correlation-vector\t\t\tCorrelation vector specific to the run\n" +} diff --git a/src/utils.sh b/src/utils.sh old mode 100644 new mode 100755 index 00b9d91..7d51a58 --- a/src/utils.sh +++ b/src/utils.sh @@ -160,7 +160,7 @@ function cmd_parser() { parsed_cmd[${flag_to_variable_dict[$key]}]="" done - local arg_pos=0 + local count=1 while [ $# -ne 0 ]; do if [[ $1 == -* ]]; @@ -174,12 +174,17 @@ function cmd_parser() { valid_argument=true if [[ $# == 1 || $2 == -* ]]; then - arg_pos=$(($arg_pos+1)) parsed_cmd[${flag_to_variable_dict[$key]}]=true else - arg_pos=$(($arg_pos+2)) - parsed_cmd[${flag_to_variable_dict[$key]}]=\${$arg_pos} + if [[ "$1" == "-c" || "$1" == "--connection-string" ]]; + then + count=$(($count+1)) + parsed_cmd[${flag_to_variable_dict[$key]}]=\${$count} + else + parsed_cmd[${flag_to_variable_dict[$key]}]=$2 + fi shift + count=$(($count+1)) fi break fi @@ -197,6 +202,7 @@ function cmd_parser() { fi shift + count=$(($count+1)) done # view content of entire dictionary @@ -361,8 +367,8 @@ function prepare_apt() { if [[ $? == 0 ]]; then log_info "apt function testing ... remove apt-utils" - apt-get remove apt-utils -y 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT & - long_running_command $! + echo "If no response for a while, press CTRL + C to exit and run '${YELLOW}sudo apt remove apt-utils${DEFAULT}' for details." + apt remove apt-utils -y 1>>$STDOUT_REDIRECT exit_code=$? if [[ $exit_code != 0 ]]; then @@ -372,8 +378,8 @@ function prepare_apt() { fi log_info "apt function testing ... install apt-utils" - apt-get install apt-utils -y 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT & - long_running_command $! + echo "If no response for a while, press CTRL + C to exit and run '${YELLOW}sudo apt-get install apt-utils${DEFAULT}' for details." + apt-get install apt-utils -y 1>>$STDOUT_REDIRECT exit_code=$? if [[ $exit_code != 0 ]]; then @@ -386,6 +392,78 @@ function prepare_apt() { fi } +###################################### +# get_manufacturer +# +# - Retrieved the Manufacturer info from SMBIOS +# +# ARGUMENTS: +# OUTPUTS: +# Write output to stdout +# RETURN: +# +###################################### + +function get_manufacturer() { + local manufacturer="" + manufacturer="$(sudo dmidecode -t system | grep Manufacturer | cut -d ':' -f 2)" + echo ${manufacturer:1} +} + +###################################### +# get_product_name +# +# - Retrieved the Product Name info from SMBIOS +# +# ARGUMENTS: +# OUTPUTS: +# Write output to stdout +# RETURN: +# +###################################### + +function get_product_name() { + local product_name="" + product_name="$(sudo dmidecode -t system | grep "Product Name" | cut -d ':' -f 2)" + echo ${product_name:1} +} + +export -f get_manufacturer get_product_name + +###################################### +# only_upgrade +# +# - Install upgrades for the installed packages only and skip installing new packages +# +# ARGUMENTS: +# OUTPUTS: +# Write output to stdout +# RETURN: +# +###################################### + +function only_upgrade() { + # update list + log_info "apt-get update ..." + apt-get update 2>>$STDERR_REDIRECT 1>>$STDOUT_REDIRECT & + long_running_command $! + exit_code=$? + if [[ $exit_code != 0 ]]; + then + log_error "apt-get update failed!" $exit_code + fi + + # only upgrade + log_info "apt-get --only-upgrade install for percept specific packages ..." + apt-get --only-upgrade install -y ${percept_packages[@]} + exit_code=$? + if [[ $exit_code != 0 ]]; + then + log_error "apt-get --only-upgrade install failed!" $exit_code + exit ${EXIT_CODES[6]} + fi +} + BG_PROCESS_ACTIVE=false BG_PROCESS_ID=-1 ###################################### @@ -411,7 +489,7 @@ function long_running_command() { do for next_symbol in '-' '\\' '|' '/'; do - echo -en "$next_symbol ${GREEN}Running ${DEFAULT}...\b\b\b\b\b\b\b\b\b\b\b\b\b\b" + echo -en "$next_symbol\b" sleep 0.15 local MYPS=$(ps -a | awk '/'$BG_PROCESS_ID'/ {print $1}') if [ "$MYPS" == "" ]; @@ -421,7 +499,7 @@ function long_running_command() { fi done done - echo -en " \b\b\b\b\b\b\b\b\b\b\b\b\b\b" + echo -en " \b" wait $BG_PROCESS_ID BG_PROCESS_ID=-1 fi @@ -497,26 +575,15 @@ function handle_exit() { if [[ "$LOCAL_E2E" == "1" ]]; then - iotedge check if [[ $e_code != 0 ]]; then echo errors-file ----------------------------- - echo '' cat $STDERR_REDIRECT - echo '' echo errors-file ----------------------------- fi echo stdout-file ----------------------------- - echo '' cat $STDOUT_REDIRECT - echo '' echo stdout-file ----------------------------- - - echo config-file ----------------------------- - echo '' - cat /etc/aziot/config.toml - echo '' - echo config-file ----------------------------- fi announce_my_log_file "All logs were appended to" $OUTPUT_FILE diff --git a/src/validate-post-install.sh b/src/validate-post-install.sh old mode 100644 new mode 100755 index 1f5f7ed..906a3e8 --- a/src/validate-post-install.sh +++ b/src/validate-post-install.sh @@ -3,30 +3,48 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. -###################################### -# validate-post-install.sh -# -# Utility function to check if the IoT Edgre Runtime local services are running -# ARGUMENTS: -# Service name -# "sudo iotedge system status" output -# OUTPUTS: -# Write output to stdout -# RETURN: -# 0 if service is running, 1 otherwise -###################################### - function is_service_running() { + local retry_max=5 local service_name=${1,,} - local iotedge_status=${2,,} + + for retry in $(seq 1 $retry_max) + do + + local status=$(sudo iotedge system status) + local iotedge_status=${status,,} service_status=$(awk '/'$service_name'/ {print $2}' <<< $iotedge_status) if [ "$service_status" != "running" ] && [ "$service_status" != "ready" ]; + then + if [ $retry == $retry_max ]; + then + log_error "'%s' is not running." $service_name + log_error "Run these commands to gather additional logs:" + log_error "sudo iotedge system logs" + log_error "sudo iotedge check" + return 1 + else + # Wait 3 seconds and retry + sleep 3 + fi + else + log_info "'%s' is running." $service_name + return 0 + fi + + done +} + +function is_percept_service_running() { + local service_name=${1,,} + + sudo systemctl is-active --quiet $service_name + exit_code=$? + if [[ $exit_code != 0 ]]; then log_error "'%s' is not running." $service_name log_error "Run these commands to gather additional logs:" - log_error "sudo iotedge system logs" - log_error "sudo iotedge check" + log_error "sudo systemctl status %s" $service_name return 1 fi @@ -34,10 +52,22 @@ function is_service_running() { return 0 } +###################################### +# validate-post-install +# +# Utility function to check if the IoT Edgre Runtime local services are running +# ARGUMENTS: +# Service name +# "sudo iotedge system status" output +# OUTPUTS: +# Write output to stdout +# RETURN: +# 0 if service is running, 1 otherwise +###################################### + function validate_post_install() { log_info "Post install validation starting." - local status=$(iotedge system status) - + declare -a iotedge_services=("aziot-edged" "aziot-identityd" "aziot-keyd" @@ -46,10 +76,41 @@ function validate_post_install() { for service_name in "${iotedge_services[@]}" do - is_service_running $service_name "$status" + is_service_running $service_name + done + + declare -a percept_services=("osconfig" + "defender-iot-micro-agent") + + for service_name in "${percept_services[@]}" + do + is_percept_service_running $service_name done log_info "Post install validation completed." } -export -f validate_post_install +###################################### +# show_package_version +# +# - Print the version of all installed packages +# +# ARGUMENTS: +# None +# OUTPUTS: +# Write output to stdout +# RETURN: +# updates the global variable OK_TO_CONTINUE in case of success to true. +###################################### + +function show_package_version() { + log_info "Installed package version:" + + for package_name in "${percept_packages[@]}" + do + package_version=$(apt-cache policy $package_name | grep Installed | cut -d ' ' -f 4) + log_info " %s: %s" $package_name $package_version + done +} + +export -f validate_post_install show_package_version diff --git a/src/validate-tier1-os.sh b/src/validate-tier1-os.sh old mode 100644 new mode 100755 index 25a6f62..2d78853 --- a/src/validate-tier1-os.sh +++ b/src/validate-tier1-os.sh @@ -30,7 +30,7 @@ function is_os_tier1() { ;; raspbian) - if [ "$VERSION_CODENAME" == "bullseye" ] || [ "$VERSION_CODENAME" == "stretch" ] || [ "$VERSION_ID" == "9" ] || [ "$VERSION_ID" == "11" ]; + if [ "$VERSION_CODENAME" == "stretch" ] || [ "$VERSION_ID" == "9" ]; then return 0 fi @@ -74,12 +74,7 @@ function get_platform() { ;; raspbian) - if [ "$VERSION_CODENAME" == "bullseye" ] || [ "$VERSION_ID" == "11" ]; - then - os_platform="$ID_LIKE/11" - else - os_platform="$ID_LIKE/stretch/multiarch" - fi + os_platform="$ID_LIKE/stretch/multiarch" ;; esac @@ -88,3 +83,28 @@ function get_platform() { export -f is_os_tier1 get_platform +###################################### +# is_aarch64 +# +# - Check if the platform architecture is aarch64 +# +# ARGUMENTS: +# +# OUTPUTS: +# Write output to stdout +# RETURN: +# 0 if the architecture is aarch64, 1 otherwise (x86_64) +###################################### + +function is_aarch64() { + local os_arch=$(uname -p) + + if [[ $os_arch == "aarch64" ]]; + then + return 0 + else + return 1 + fi +} + +export -f is_aarch64 diff --git a/tests/e2e-tests/test-devicestate.sh b/tests/e2e-tests/test-devicestate.sh deleted file mode 100644 index a657326..0000000 --- a/tests/e2e-tests/test-devicestate.sh +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -###################################### -# test-devicestate -# -# End to end test to validate that the azure-iot-edge-installer.sh -# succesfully gets the Central device to provisioned state -# ARGUMENTS: -# subscription - The Azure subscription where the Central app is created -# OUTPUTS: -# Write output to stdout -# RETURN: -# 0 if test succeeds, 1 otherwise -###################################### - -###################################### -# Clean up test resources -# ARGUMENTS: -# armToken - Azure Resource Manager token for itneracting with the Azure subscription -# apiToken - the API token used for interaction with Central app -# device_id - the ID of the newly created device -# token_id - the API token ID used for interaction with Central app -# rg - resource group name for central app -# centralapp_name - central app name -# OUTPUTS: -# Write output to stdout -# RETURN: -# Void -###################################### -function cleanup() { - echo Starting cleanup - - local armToken=$1 - local apiToken=$2 - local device_id=$3 - local token_id=$4 - local rg=$5 - local centralapp_name=$6 - - # Clean up device if it exists - local out=$(curl -X GET -H "Authorization:$apiToken" https://${centralapp_name}.azureiotcentral.com/api/preview/devices/${device_id}) - echo $out - local device_exists=$(jq -r '.id' <<< "$out") - if [ "$device_exists" == "$device_id" ]; - then - echo Device ${device_id} exists - echo Delete device ${device_id} - curl -X DELETE -H "Authorization:Bearer $armToken" https://${centralapp_name}.azureiotcentral.com/api/preview/devices/${device_id} - else - echo Device ${device_id} does not exist - fi; - - # Clean up API token if it exists - local out=$(curl -X GET -H "Authorization:$apiToken" https://${centralapp_name}.azureiotcentral.com/api/preview/apiTokens/${token_id}) - echo $out - local apiToken_exists=$(jq -r '.id' <<< "$out") - if [ "$apiToken_exists" == "$token_id" ]; - then - echo API token ${token_id} exists - echo Delete API token ${token_id} - curl -X DELETE -H "Authorization:Bearer $armToken" https://${centralapp_name}.azureiotcentral.com/api/preview/apiTokens/${token_id} - else - echo API token ${token_id} does not exist - fi; - - # Clean up central app - echo Clean up central app - az iot central app delete -g ${rg} -n ${centralapp_name} -y - - echo Completed cleanup -} - -# Azure IoT DDE team subscription -subscription=$1 - -# Create a random number to make sure create new resources per each run -let num=$RANDOM*$RANDOM -prefix=e2e -token_id="${prefix}testtoken${num}" -device_id="${prefix}testdevice${num}" -device_displayName=$device_id -device_template=dtmi:p7xmntslpen:vzbw2mcng -test_result=1 # fail by default -rg=PipelineResources-IoTEdgeConfig -centralapp_name=${prefix}test-iotc-inventory-app${num} - -# The Central app is stored in PipelineResources-IoTEdgeConfig resource group -echo Get access token to subscription "Azure IoT Edge Dev Tools - Test" -out=$(az account get-access-token --resource https://apps.azureiotcentral.com -s ${subscription}) -echo $out -armToken=$(jq -r '.accessToken' <<< "$out") - -# Create a central app -echo Create a central app -az iot central app create -g ${rg} -n ${centralapp_name} -s ${centralapp_name} --template iotc-inventory - -# Create API token -echo Create API token to interact with Central app -out=$(curl -X PUT -d '{"roles":[{"role":"ca310b8d-2f4a-44e0-a36e-957c202cd8d4"}]}' -H "Content-Type:application/json" -H "Authorization:Bearer $armToken" https://${centralapp_name}.azureiotcentral.com/api/preview/apiTokens/${token_id}); -echo $out -apiToken=$(jq -r '.token' <<< "$out") - -if [ "$apiToken" == "null" ]; -then - echo Failed to create API token. Exit. - exit $test_result; -fi; - -echo Create a new device -out=$(curl -X PUT -d '{"displayName":"'$device_displayName'","instanceOf":"'$device_template'","simulated":false,"approved":true}' -H "Content-Type: application/json" -H "Authorization:$apiToken" https://${centralapp_name}.azureiotcentral.com/api/preview/devices/${device_id}) -echo $out -devicestate_before=$(jq -r '.provisioned' <<< "$out") -echo New device state is provisioned=$devicestate_before - -if [ "$devicestate_before" != "false" ]; -then - echo "Error: New device must not be provisioned. Cleanup and exit." - cleanup "$armToken" "$apiToken" "$device_id" "$token_id" "$rg" "$centralapp_name" - exit $test_result -else - echo "Device is not provisioned as expected. Continue."; -fi; - -echo Get device credentials -creds=$(curl -X GET -H "Authorization:$apiToken" https://${centralapp_name}.azureiotcentral.com/api/preview/devices/${device_id}/credentials) -echo $creds -scope_id=$(jq -r '.idScope' <<< "$creds") -primary_key=$(jq -r '.symmetricKey.primaryKey' <<< "$creds") - -echo Run the Azure IoT Edge Installer -#wget -O azure-iot-edge-installer.sh https://github.com/Azure/iot-edge-config/releases/latest/download/azure-iot-edge-installer.sh \ -cd ./../../src -chmod u+x azure-iot-edge-installer.sh -sudo LOCAL_E2E=1 ./azure-iot-edge-installer.sh --telemetry-opt-out --scope-id "$scope_id" --registration-id "$device_id" --symmetric-key "$primary_key" -chmod u-x azure-iot-edge-installer.sh - -# give 2 mins for changes to propagate to central app -sleep 120 - -# device state should be provisioned after running the script -out=$(curl -X GET -H "Authorization:$apiToken" https://${centralapp_name}.azureiotcentral.com/api/preview/devices/${device_id}) -echo $out -devicestate_after=$(jq -r '.provisioned' <<< "$out") -echo After running azure-iot-edge-installer.sh, new device state is provisioned=$devicestate_after - -if [ "$devicestate_after" != "true" ]; -then - echo "Error: Device must be provisioned. Exit."; -else - echo "Device is provisioned as expected. Success."; - test_result=0 # success -fi; - -# Clean up -cleanup "$armToken" "$apiToken" "$device_id" "$token_id" "$rg" "$centralapp_name" - -exit $test_result diff --git a/tests/e2e-tests/test-edge-deployment.json b/tests/e2e-tests/test-edge-deployment.json deleted file mode 100644 index 2ab6246..0000000 --- a/tests/e2e-tests/test-edge-deployment.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "content": { - "modulesContent": { - "$edgeAgent": { - "properties.desired": { - "schemaVersion": "1.1", - "runtime": { - "type": "docker", - "settings": { - "minDockerVersion": "v1.25", - "loggingOptions": "", - "registryCredentials": {} - } - }, - "systemModules": { - "edgeAgent": { - "type": "docker", - "settings": { - "image": "mcr.microsoft.com/azureiotedge-agent:1.2", - "createOptions": "{}" - } - }, - "edgeHub": { - "type": "docker", - "status": "running", - "restartPolicy": "always", - "settings": { - "image": "mcr.microsoft.com/azureiotedge-hub:1.2", - "createOptions": "{\"HostConfig\":{\"PortBindings\":{\"5671/tcp\":[{\"HostPort\":\"5671\"}],\"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}" - } - } - }, - "modules": { - "SimulatedTemperatureSensor": { - "version": "1.0", - "type": "docker", - "status": "running", - "restartPolicy": "always", - "settings": { - "image": "mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.0", - "createOptions": "{}" - } - } - } - } - }, - "$edgeHub": { - "properties.desired": { - "schemaVersion": "1.1", - "routes": { - "upstream": "FROM /messages/* INTO $upstream" - }, - "storeAndForwardConfiguration": { - "timeToLiveSecs": 7200 - } - } - }, - "SimulatedTemperatureSensor": { - "properties.desired": { - "SendData": true, - "SendInterval": 5 - } - } - } - } -} \ No newline at end of file diff --git a/tests/e2e-tests/test-ihedgecs.sh b/tests/e2e-tests/test-ihedgecs.sh deleted file mode 100644 index ff15509..0000000 --- a/tests/e2e-tests/test-ihedgecs.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -###################################### -# test-ihedgecs -# -# End to end test to validate that the azure-iot-edge-installer.sh -# succesfully gets the Central device to provisioned state -# ARGUMENTS: -# subscription - The Azure subscription where the Central app is created -# OUTPUTS: -# Write output to stdout -# RETURN: -# 0 if test succeeds, 1 otherwise -###################################### - -# Azure IoT DDE team subscription -subscription=$1 - -# Create a random number to make sure create new resources per each run -let num=$RANDOM*$RANDOM -prefix=e2e -iothub_id="${prefix}-ih-${num}" -edge_device_id="${prefix}-testdevice-${num}" -device_displayName=$edge_device_id -rg_name=PipelineResources-IoTEdgeConfig - -az account set -s ${subscription} - -echo Create the test IoT Hub '${iothub_id}' for the run -az iot hub create --resource-group ${rg_name} --location westus2 --name ${iothub_id} --sku S2 - -echo Create the edge device '${edge_device_id}' for the run, edge enabled -az iot hub device-identity create -n ${iothub_id} -d ${edge_device_id} --ee - -echo Retrieve the connection string -out=$(az iot hub device-identity connection-string show -n ${iothub_id} -d ${edge_device_id}) -device_connection_string=$(jq -r '.connectionString' <<< "$out") - -echo Configure the edge device with a test deployment manifest -az iot edge set-modules --hub-name ${iothub_id} --device-id ${edge_device_id} --content ./test-edge-deployment.json - -echo Run the Azure IoT Edge Installer -#wget -O azure-iot-edge-installer.sh https://github.com/Azure/iot-edge-config/releases/latest/download/azure-iot-edge-installer.sh \ -cd ./../../src -chmod u+x azure-iot-edge-installer.sh -sudo LOCAL_E2E=1 ./azure-iot-edge-installer.sh --telemetry-opt-out --connection-string "${device_connection_string}" -chmod u-x azure-iot-edge-installer.sh - -# Give 2 mins for changes to propagate to central app -sleep 120 - -# Clean up - az iot hub delete --resource-group ${rg_name} --name ${iothub_id} \ No newline at end of file diff --git a/tests/e2e-tests/test-uninstall.sh b/tests/e2e-tests/test-uninstall.sh deleted file mode 100644 index a32d566..0000000 --- a/tests/e2e-tests/test-uninstall.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -###################################### -# test-uninstall -# -# clean up between e2-e runs -# ARGUMENTS: -# OUTPUTS: -# Write output to stdout -# RETURN: -# 0 -###################################### - -#Question - is 'sudo' really needed here? -#Answer - it doesn't hurt! -echo Uninstall Azure IoTEdge and its subs -sudo apt-get remove --purge --auto-remove aziot-edge -y - -echo Remove any dangling docker containers -sudo docker rm $(sudo docker ps -a -q) > /dev/null 2>&1 - -echo Remove all docker images -sudo docker rmi -f $(sudo docker images -aq) > /dev/null 2>&1 - -echo Remove moby-engine and its subs -sudo apt-get remove --purge --auto-remove moby-engine -y - -echo Remove log, output and error files -sudo rm -f /tmp/azure-iot-edge-installer*.* > /dev/null 2>&1 diff --git a/tests/perf_tests.sh b/tests/perf_tests.sh deleted file mode 100644 index 96d881c..0000000 --- a/tests/perf_tests.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -###################################### -# perf_tests -# -# runs performance tests -# ARGUMENTS: -# an integer - number of times to run each test -# OUTPUTS: -# RETURN: -# 0 on success, -1 otherwise -###################################### - - -subscription=$(az account show | awk '/"id/ { print substr($2,2,36) }') - -# for each test ... -echo ./track_duration.sh -c $1 -t ./e2e-tests/test-devicestate.sh $subscription -cd e2e-tests -../track_duration.sh -v -c $1 -t ./test-devicestate.sh $subscription -cd .. - -exit 0 \ No newline at end of file diff --git a/tests/requirements.txt b/tests/requirements.txt deleted file mode 100644 index 736000d..0000000 --- a/tests/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -azure.iot.device diff --git a/tests/send_one_message_to_iot_hub_device.py b/tests/send_one_message_to_iot_hub_device.py deleted file mode 100644 index 94305b2..0000000 --- a/tests/send_one_message_to_iot_hub_device.py +++ /dev/null @@ -1,25 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -import argparse -import sys - - -from azure.iot.device import IoTHubDeviceClient - - -# prepare the command line arguments parser -parser = argparse.ArgumentParser() -parser.add_argument("connection_string") -parser.add_argument("message") - -# parse the arguments -arguments = parser.parse_args() - -client = IoTHubDeviceClient.create_from_connection_string(arguments.connection_string) -client.send_message(arguments.message) -print(arguments.message) - -client.shutdown() diff --git a/tests/test_utils.sh b/tests/test_utils.sh deleted file mode 100644 index 5685ee5..0000000 --- a/tests/test_utils.sh +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -# -error_output() { - printf "%b\n" "${RED:-}Error: $1${DEFAULT:-}" >&2 -} - -output() { - printf "%b\n" "${BOLD:-}${DEFAULT:-} $1" >&2 -} - -verbose_output() { - if [ "$verbose" = true ]; - then - output "$1" - fi -} - -export -f output error_output verbose_output - -NR_PASSING=0 -NR_FAILING=0 -NR_TOTALS=0 -assert_eq() { - local expected=$1; shift - local actual=$1; shift - - NR_TOTALS=$(bc <<< $NR_TOTALS+1) - if [ "$expected" == "$actual" ]; - then - NR_PASSING=$(bc <<< $NR_PASSING+1) - else - NR_FAILING=$(bc <<< $NR_FAILING+1) - error_output "expected: $expected; actual: $actual" - fi -} - -assert_not_eq() { - local expected=$1; shift - local actual=$1; shift - - NR_TOTALS=$(bc <<< $NR_TOTALS+1) - if [ "$expected" != "$actual" ]; - then - NR_PASSING=$(bc <<< $NR_PASSING+1) - else - NR_FAILING=$(bc <<< $NR_FAILING+1) - error_output "expected: $expected; actual: $actual" - fi -} - -assert_file() { - local file_name=$1; shift - - NR_TOTALS=$(bc <<< $NR_TOTALS+1) - if [[ -f $file_name ]]; - then - NR_PASSING=$(bc <<< $NR_PASSING+1) - else - NR_FAILING=$(bc <<< $NR_FAILING+1) - error_output "please call log_init prior to running the tests." - exit -1 - fi -} - -show_test_totals() { - local BN=`basename $0` - - printf "\n" - printf "$BN: total tests %d; %d passing; %d failing" "$NR_TOTALS" $NR_PASSING $NR_FAILING - printf "\n\n" -} - -export -f assert_eq assert_not_eq assert_file show_test_totals \ No newline at end of file diff --git a/tests/track_duration.sh b/tests/track_duration.sh deleted file mode 100644 index 284d7c1..0000000 --- a/tests/track_duration.sh +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -###################################### -# track_duration -# -# compute duration of runs for a given command and report them as messages -# to a predefined device associated with a specific azure iot hub -# ARGUMENTS: -# v/verbose if set, generates verbose logs -# c/count specify the number of runs -# t/test sepcify which command to run. Must be the last parameter -# all arguments will be passed as is to the specified command -# OUTPUTS: -# sends duration reports to the cloud -# RETURN: -# 0 on success, -1 otherwise -###################################### - -# Stop script on NZEC -set -e - -# Exposing stream 3 as a pipe to standard output of the script itself -exec 3>&1 - -# bring in the library -MY_LOCATION=$(dirname $0) -source ${MY_LOCATION}/test_utils.sh - -# -verbose=false -count=1 -test_command="" -script_name="$(basename "$0")" -declare -a runs -while [ $# -ne 0 ] -do - name="$1" - case "$name" in - -v|--verbose|-[Vv]erbose) - verbose=true - ;; - -c|--count|-[Cc]ount) - shift - count=$1 - ;; - -t|--test|-[Tt]est) - shift - test_command="$@" - test_name="$1" - shift $(bc <<< $#-1) - ;; - -?|--?|-h|--help|-[Hh]elp) - echo "Usage: $script_name [OPTIONS] -t|--test TestToRun [TEST_OPTIONS]" - echo " $script_name -h|-?|--help" - echo "" - echo "$script_name is a simple command line interface for collecting test runs duration averages." - echo " --test option specifies which test to run, with arguments, and must appear as the last option." - echo "" - echo "Options:" - echo " --verbose,-Verbose Display diagnostics information." - echo " --count,-Count Specify number of runs." - echo " -?,--?,-h,--help,-Help Shows this help message" - echo "" - exit 0 - ;; - *) - error_output "Unknown argument \`$name\`" - exit 1 - esac - - shift -done - -if [ $count -lt 0 ]; -then - exit -1 -fi - -if [ "$test_command" == "" ]; -then - exit -2 -fi - -# -IH_CONN_STR=$(az iot hub device-identity connection-string show -n e2etest-iotc-hub -d e2etest_iotc_d | awk '/connection/ { print $2 }' | sed -e 's;";;g') - -time_stamp=`date '+%Y-%m-%d %H:%M:%S'` -os_name="`uname`" -os_kernel="`uname -r`" - -total=0.0 -verbose_output "" -for ((curr = 1; curr <= $count; curr++)) -do - start=`date +%s.%N` - command $test_command - end=`date +%s.%N` - - runs[$curr-1]=$(bc <<< $end-$start) - total=$(bc <<< $total+${runs[$curr-1]}) - verbose_output "run $curr took $(bc <<< $end-$start) seconds" - python3 ${MY_LOCATION}/send_one_message_to_iot_hub_device.py "$IH_CONN_STR" "{\"OSName\": \"$os_name\", \"Kernel\": \"$os_kernel\", \"TestName\": \"$test_name\", \"TimeStamp\": \"$time_stamp\", \"Duration\": ${runs[$iter]}}" -done - -verbose_output "" -verbose_output "average run time for '$test_command' is: $(echo "scale = 3; $total/$count" | bc) seconds" -verbose_output "----------------------------------------------------------------------------------------------\n" - -exit 0 \ No newline at end of file diff --git a/tests/unit-tests/test-cmd-parser.sh b/tests/unit-tests/test-cmd-parser.sh deleted file mode 100644 index c62a525..0000000 --- a/tests/unit-tests/test-cmd-parser.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -# import utils.sh -source ../../src/utils.sh - -# add flag:variable_name dictionary entries -add_option_args "VERBOSE_LOGGING" -v --verbose -add_option_args "SCOPE_ID" -s --scope-id -add_option_args "REGISTRATION_ID" -r --registration-id -add_option_args "SYMMETRIC_KEY" -k --symmetric-key -add_option_args "DEVICE_PROVISIONING" -dp -add_option_args "AZURE_CLOUD_ID" -ap -add_option_args "CONNECTION_STRING" -c --connection-string - -# unit test to test all illegal flags, output should be empty -test_illegal_flags() { - # parse sample input to parser - declare -A parsed_cmds="$(cmd_parser -illegal val -t anotherillegalval -z yetanotherillegalval)" - - # compare output, should be empty - if [ "${parsed_cmds[*]}" != "" ]; - then - echo "Failed to pass unit test 'test_illegal_flags' in test-cmd-parser.sh. Non-empty result: ${parsed_cmds[*]}" - fi -} - -test_all_legal_flags_cn() { - # parse sample input to parser - declare -A parsed_cmds="$(cmd_parser $@)" - - # compare output, should be 'x;y;z', true - if [[ "${parsed_cmds['CONNECTION_STRING']}" != "x;y;z" || "${parsed_cmds['VERBOSE_LOGGING']}" != true ]]; - then - echo "Failed to pass unit test 'test_all_legal_flags_cn' in test-cmd-parser.sh. Non-empty result: ${parsed_cmds[*]}" - fi -} - -test_all_legal_flags_dps() { - # parse sample input to parser - declare -A parsed_cmds="$(cmd_parser $@)" - - # compare output, should be 123456 - if [[ "${parsed_cmds['DEVICE_PROVISIONING']}" != "1" || "${parsed_cmds['AZURE_CLOUD_ID']}" != "5" || "${parsed_cmds['SCOPE_ID']}" != "2" || "${parsed_cmds['REGISTRATION_ID']}" != "4" || "${parsed_cmds['SYMMETRIC_KEY']}" != "3" || "${parsed_cmds['VERBOSE_LOGGING']}" != "6" ]]; - then - echo "Failed to pass unit test 'test_all_legal_flags_dps' in test-cmd-parser.sh. Non-empty result: ${parsed_cmds[*]}" - fi -} - -test_extra_arguments() { - # parse sample input to parser - declare -A parsed_cmds="$(cmd_parser illegalinput 0 -ap 4 -s 1 -r 3 more -extra -k 2)" - - # compare output, should be 1 2 3 4 - if [ "${parsed_cmds[*]}" != "" ]; - then - echo "Failed to pass unit test 'test_extra_arguments' in test-cmd-parser.sh" - fi -} - -# run all tests -test_illegal_flags -test_all_legal_flags_cn -c 'x;y;z' -v -test_all_legal_flags_dps -dp 1 -ap 5 -s 2 -r 4 -k 3 -v 6 -test_extra_arguments diff --git a/tests/unit-tests/test-logger.sh b/tests/unit-tests/test-logger.sh deleted file mode 100644 index 7eb92ff..0000000 --- a/tests/unit-tests/test-logger.sh +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -exec 3>&1 - -# bring in the utils library -source ../../src/utils.sh -source ../test_utils.sh - -log_init -assert_file $OUTPUT_FILE - -WC_L=`wc -l "$OUTPUT_FILE"` -WC=${WC_L% *} -assert_eq 0 $WC - -log_error "%s %d %.3f" one 2 12.3042 -log_error "two three" -WC_L=`wc -l "$OUTPUT_FILE"` -WC=${WC_L% *} -assert_eq 2 $WC - -log_warn "%s %d %.3f" one 2 12.3042 -log_warn "two three" -WC_L=`wc -l "$OUTPUT_FILE"` -WC=${WC_L% *} -assert_eq 4 $WC - -log_info "%s %d %.3f" one 2 12.3042 -log_info "two three" -WC_L=`wc -l "$OUTPUT_FILE"` -WC=${WC_L% *} -assert_eq 6 $WC - -STRVAL1="One" -INTVAL1=45 -FLOATVAL1=2453.56890 -log_info "---------------------------------------------" -log_info "'%s' ;" "$STRVAL1" -log_info "%.2f" $FLOATVAL1 -WC_L=`wc -l "$OUTPUT_FILE"` -WC=${WC_L% *} -assert_eq 9 $WC - -show_test_totals -rm $OUTPUT_FILE \ No newline at end of file diff --git a/tests/unit-tests/test-telemetry-flag.sh b/tests/unit-tests/test-telemetry-flag.sh deleted file mode 100644 index bd83eac..0000000 --- a/tests/unit-tests/test-telemetry-flag.sh +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -exec 3>&1 - -# bring in the utils library -source ../../src/utils.sh -source ../test_utils.sh - -function test_flag_on() { - set_opt_out_selection true - assert_eq $(get_opt_in_selection) false -} - -function test_flag_off() { - set_opt_out_selection false - assert_eq $(get_opt_in_selection) true -} - -test_flag_on -test_flag_off -show_test_totals diff --git a/tests/unit-tests/test-validate-post-install.sh b/tests/unit-tests/test-validate-post-install.sh deleted file mode 100644 index fcfd151..0000000 --- a/tests/unit-tests/test-validate-post-install.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -source ../../src/utils.sh -source ../../src/validate-post-install.sh -source ../test_utils.sh - -test_service_running() { - is_service_running "servicenameA" "servicenameA Running" - assert_eq 0 $? -} - -test_service_ready() { - is_service_running "servicenameA" "servicenameA Ready" - assert_eq 0 $? -} - -test_service_not_running() { - is_service_running "servicenameA" "servicenameA Failed" - assert_eq 1 $? -} - -test_service_missing() { - is_service_running "servicenameA" "servicenameB Running" - assert_eq 1 $? -} - -test_service_casesensitive() { - is_service_running "servicenameA" "servicenameA ruNNing" - assert_eq 0 $? -} - -test_service_casesensitive() { - is_service_running "servicenameA" "servicenameA ruNNing" - assert_eq 0 $? -} - -# run tests -test_service_running -test_service_ready -test_service_not_running -test_service_missing -test_service_casesensitive - -show_test_totals diff --git a/tests/unit-tests/test-validate-tier1-os.sh b/tests/unit-tests/test-validate-tier1-os.sh deleted file mode 100644 index ca9ef77..0000000 --- a/tests/unit-tests/test-validate-tier1-os.sh +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env bash - -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -source ../../src/utils.sh -source ../../src/validate-tier1-os.sh -source ../test_utils.sh - -test_ubuntu1804() { - ID="ubuntu" - VERSION_ID="18.04" - is_os_tier1 "$ID" "$VERSION_ID" - assert_eq 0 $? -} - -test_ubuntu2004() { - ID="ubuntu" - VERSION_ID="20.04" - is_os_tier1 "$ID" "$VERSION_ID" - assert_eq 0 $? -} - -test_raspbian() { - ID="raspbian" - VERSION_ID="9" - is_os_tier1 "$ID" "$VERSION_ID" - assert_eq 0 $? -} - -test_raspbian11() { - ID="raspbian" - VERSION_ID="11" - is_os_tier1 "$ID" "$VERSION_ID" - assert_eq 0 $? -} - -test_tier2() { - ID="debian" - VERSION_ID="9" - is_os_tier1 "$ID" "$VERSION_ID" - assert_eq 1 $? -} -test_tier2_11() { - ID="debian" - VERSION_ID="11" - is_os_tier1 "$ID" "$VERSION_ID" - assert_eq 1 $? -} - -# run tests -test_ubuntu1804 -test_ubuntu2004 -test_raspbian -test_raspbian11 -test_tier2 -test_tier2_11 - -show_test_totals diff --git a/vsts_ci/azure-pipelines-e2e.yml b/vsts_ci/azure-pipelines-e2e.yml deleted file mode 100644 index b181497..0000000 --- a/vsts_ci/azure-pipelines-e2e.yml +++ /dev/null @@ -1,53 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -# Starter pipeline -# Start with a minimal pipeline that you can customize to build and deploy your code. -# Add steps that build, run tests, deploy, and more: -# https://aka.ms/yaml - -trigger: -- main - -stages: -- stage: E2ETest - displayName: E2E Tests - jobs: - - job: LinuxE2ETests - pool: - name: IoT-Devices-E2E - steps: - - template: continuous-e2e-setup.yml - - template: continuous-e2e-uninstalledge.yml - - template: continuous-e2e.yml - dependsOn: [] - condition: succeeded() - - - job: RaspberryPiE2ETests - pool: - name: Raspberry-Pi - steps: - - template: continuous-e2e-setup.yml - - template: continuous-e2e-uninstalledge.yml - - template: continuous-e2e.yml - dependsOn: [] - condition: succeeded() - - - job: Ubuntu1804E2ETests - pool: - vmImage: ubuntu-18.04 - steps: - - template: continuous-e2e-setup.yml - - template: continuous-e2e.yml - dependsOn: [] - condition: succeeded() - - - job: Ubuntu2004E2ETests - pool: - vmImage: ubuntu-20.04 - steps: - - template: continuous-e2e-setup.yml - - template: continuous-e2e.yml - dependsOn: [] - condition: succeeded() - diff --git a/vsts_ci/azure-pipelines-perf.yml b/vsts_ci/azure-pipelines-perf.yml deleted file mode 100644 index 9f9f8c6..0000000 --- a/vsts_ci/azure-pipelines-perf.yml +++ /dev/null @@ -1,52 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -# Starter pipeline -# Start with a minimal pipeline that you can customize to build and deploy your code. -# Add steps that build, run tests, deploy, and more: -# https://aka.ms/yaml - -trigger: -- main - -stages: -- stage: PERFTests - displayName: Performance Tests - jobs: - - job: LinuxE2ETests - pool: - name: IoT-Devices-E2E - steps: - - template: continuous-e2e-setup.yml - - template: continuous-e2e-uninstalledge.yml - - template: continuous-perf.yml - dependsOn: [] - condition: succeeded() - - - job: RaspberryPiPerfTests - pool: - name: Raspberry-Pi - steps: - - template: continuous-e2e-setup.yml - - template: continuous-e2e-uninstalledge.yml - - template: continuous-perf.yml - dependsOn: [] - condition: succeeded() - - - job: Ubuntu1804PerfTests - pool: - vmImage: ubuntu-18.04 - steps: - - template: continuous-e2e-setup.yml - - template: continuous-perf.yml - dependsOn: [] - condition: succeeded() - - - job: Ubuntu2004PerfTests - pool: - vmImage: ubuntu-20.04 - steps: - - template: continuous-e2e-setup.yml - - template: continuous-perf.yml - dependsOn: [] - condition: succeeded() \ No newline at end of file diff --git a/vsts_ci/azure-pipelines.yml b/vsts_ci/azure-pipelines.yml deleted file mode 100644 index 7dd30cf..0000000 --- a/vsts_ci/azure-pipelines.yml +++ /dev/null @@ -1,65 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -# Starter pipeline -# Start with a minimal pipeline that you can customize to build and deploy your code. -# Add steps that build, run tests, deploy, and more: -# https://aka.ms/yaml - -trigger: -- main - -stages: -- stage: UnitTest - displayName: Unit Tests - jobs: - - job: Linux1804UnitTests - pool: - vmImage: ubuntu-18.04 - steps: - - template: linux/continuous-linux.yml - - - job: Linux2004UnitTests - pool: - vmImage: ubuntu-20.04 - steps: - - template: linux/continuous-linux.yml - - - job: RaspberryPiUnitTests - pool: - vmImage: ubuntu-latest - steps: - - template: raspi/continuous-raspi.yml - - - job: GithubRelease - pool: - vmImage: ubuntu-18.04 - dependsOn: - - Linux1804UnitTests - - Linux2004UnitTests - - RaspberryPiUnitTests - condition: and(succeeded('Linux1804UnitTests'), succeeded('Linux2004UnitTests'), succeeded('RaspberryPiUnitTests')) - steps: - - script: | - mkdir dest - cp src/*.sh dest/ - displayName: Create dest/ directory - - task: GitHubRelease@1 - displayName: 'GitHub release (create) RC' - inputs: - gitHubConnection: 'github.com_cindydeng1998' - tagPattern: '^v?[0-9]+\.[0-9]+\.[0-9]+-rc[0-9]+$' - assets: 'dest/*.sh' - isDraft: true - - task: GitHubRelease@1 - displayName: 'GitHub release (create)' - inputs: - gitHubConnection: 'github.com_cindydeng1998' - tagPattern: '^v?[0-9]+\.[0-9]+\.[0-9]+$' - assets: 'dest/*.sh' - isDraft: true - - task: ComponentGovernanceComponentDetection@0 - inputs: - scanType: 'Register' - verbosity: 'Verbose' - alertWarningLevel: 'High' \ No newline at end of file diff --git a/vsts_ci/continuous-e2e-setup.yml b/vsts_ci/continuous-e2e-setup.yml deleted file mode 100644 index f43b53d..0000000 --- a/vsts_ci/continuous-e2e-setup.yml +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -steps: -- script: | - apt-get update -y - sudo apt-get install jq - displayName: 'Install jq' -- task: AzureCLI@2 - inputs: - azureSubscription: 'Azure IoT Edge Dev Tools - Test' - scriptType: 'bash' - scriptLocation: 'inlineScript' - inlineScript: | - az config set extension.use_dynamic_install=yes_without_prompt - az upgrade - az extension add --name azure-iot - az --version - az account set -s $(AzureSubscriptionId) - displayName: 'Set Azure resources' \ No newline at end of file diff --git a/vsts_ci/continuous-e2e-uninstalledge.yml b/vsts_ci/continuous-e2e-uninstalledge.yml deleted file mode 100644 index d870c62..0000000 --- a/vsts_ci/continuous-e2e-uninstalledge.yml +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -steps: -- task: AzureCLI@2 - inputs: - azureSubscription: 'Azure IoT Edge Dev Tools - Test' - scriptType: 'bash' - scriptLocation: 'inlineScript' - inlineScript: | - sudo apt-get remove --purge --auto-remove aziot-edge -y - sudo docker rm $(sudo docker ps -a -q) > /dev/null 2>&1 - sudo docker rmi -f $(sudo docker images -aq) > /dev/null 2>&1 - sudo apt-get remove --purge --auto-remove moby-engine -y - sudo rm -f /tmp/azure-iot-edge-installer*.* > /dev/null 2>&1 - displayName: 'Uninstall iotedge package from previous run' diff --git a/vsts_ci/continuous-e2e.yml b/vsts_ci/continuous-e2e.yml deleted file mode 100644 index 7befbfd..0000000 --- a/vsts_ci/continuous-e2e.yml +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -steps: -- task: AzureCLI@2 - inputs: - azureSubscription: 'Azure IoT Edge Dev Tools - Test' - scriptType: 'bash' - scriptLocation: 'inlineScript' - inlineScript: | - cd tests/e2e-tests - chmod u+x test-devicestate.sh - ./test-devicestate.sh $(AzureSubscriptionId) - chmod u+x test-uninstall.sh - ./test-uninstall.sh - chmod u+x test-ihedgecs.sh - ./test-ihedgecs.sh $(AzureSubscriptionId) - displayName: 'Run All E2E Tests' diff --git a/vsts_ci/continuous-perf.yml b/vsts_ci/continuous-perf.yml deleted file mode 100644 index b9e5454..0000000 --- a/vsts_ci/continuous-perf.yml +++ /dev/null @@ -1,28 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -steps: -- task: UsePythonVersion@0 - displayName: "Use Python 3.8" - inputs: - versionSpec: 3.8 - -- task: AzureCLI@2 - displayName: 'Run All Performance Tests' - inputs: - azureSubscription: 'Azure IoT Edge Dev Tools - Test' - scriptType: 'bash' - scriptLocation: 'inlineScript' - inlineScript: | - cd tests - python3 --version - pip3 --version - pip3 install -r requirements.txt - chmod +x ./track_duration.sh - chmod +x ./perf_tests.sh - chmod +x ./e2e-tests/test-devicestate.sh - az config set extension.use_dynamic_install=yes_without_prompt - az extension add --name azure-iot - az --version - az account set -s $(AzureSubscriptionId) - ./perf_tests.sh $(NumberOfRuns) \ No newline at end of file diff --git a/vsts_ci/linux/continuous-linux.yml b/vsts_ci/linux/continuous-linux.yml deleted file mode 100644 index f3c0997..0000000 --- a/vsts_ci/linux/continuous-linux.yml +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -steps: -- script: echo Hello Linux! - displayName: 'Echo Hello Linux' - -- script: | - cd tests/unit-tests - chmod +x ./*.sh - ./test-validate-post-install.sh - ./test-validate-tier1-os.sh - ./test-cmd-parser.sh - ./test-logger.sh - ./test-telemetry-flag.sh - displayName: 'Run All Linux Unit Tests' diff --git a/vsts_ci/raspi/continuous-raspi.yml b/vsts_ci/raspi/continuous-raspi.yml deleted file mode 100644 index 501c44a..0000000 --- a/vsts_ci/raspi/continuous-raspi.yml +++ /dev/null @@ -1,16 +0,0 @@ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. - -steps: -- script: echo Hello Raspi! - displayName: 'Echo Hello Raspi!' - -- script: | - cd tests/unit-tests - chmod +x ./*.sh - ./test-validate-post-install.sh - ./test-validate-tier1-os.sh - ./test-cmd-parser.sh - ./test-logger.sh - ./test-telemetry-flag.sh - displayName: 'Run All Raspberry Pi Unit Tests'