iotedgedev 3.3.4__zip

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (356) hide show
  1. s/.devcontainer/Dockerfile +75 -0
  2. s/.devcontainer/devcontainer.json +40 -0
  3. s/.devcontainer/library-scripts/docker-in-docker-debian.sh +236 -0
  4. s/.env.tmp +108 -0
  5. s/.git/FETCH_HEAD +61 -0
  6. s/.git/HEAD +1 -0
  7. s/.git/config +12 -0
  8. s/.git/description +1 -0
  9. s/.git/hooks/applypatch-msg.sample +15 -0
  10. s/.git/hooks/commit-msg.sample +24 -0
  11. s/.git/hooks/fsmonitor-watchman.sample +173 -0
  12. s/.git/hooks/post-update.sample +8 -0
  13. s/.git/hooks/pre-applypatch.sample +14 -0
  14. s/.git/hooks/pre-commit.sample +49 -0
  15. s/.git/hooks/pre-merge-commit.sample +13 -0
  16. s/.git/hooks/pre-push.sample +53 -0
  17. s/.git/hooks/pre-rebase.sample +169 -0
  18. s/.git/hooks/pre-receive.sample +24 -0
  19. s/.git/hooks/prepare-commit-msg.sample +42 -0
  20. s/.git/hooks/push-to-checkout.sample +78 -0
  21. s/.git/hooks/update.sample +128 -0
  22. s/.git/index +0 -0
  23. s/.git/info/exclude +6 -0
  24. s/.git/logs/HEAD +1 -0
  25. s/.git/logs/refs/remotes/origin/EO +1 -0
  26. s/.git/logs/refs/remotes/origin/avagraw/security_fix +1 -0
  27. s/.git/logs/refs/remotes/origin/cherry-pick-rename +1 -0
  28. s/.git/logs/refs/remotes/origin/chyuan/fix-validation-not-fail-test +1 -0
  29. s/.git/logs/refs/remotes/origin/chyuan/update-linux-agent +1 -0
  30. s/.git/logs/refs/remotes/origin/dependabot/pip/pyyaml-5.4 +1 -0
  31. s/.git/logs/refs/remotes/origin/eliises/add-device-tagging-docs +1 -0
  32. s/.git/logs/refs/remotes/origin/main +1 -0
  33. s/.git/logs/refs/remotes/origin/ray-deps +1 -0
  34. s/.git/logs/refs/remotes/origin/ray-dev-setup +1 -0
  35. s/.git/logs/refs/remotes/origin/ray-tox +1 -0
  36. s/.git/logs/refs/remotes/origin/release-pipeline-automation +1 -0
  37. s/.git/logs/refs/remotes/origin/spmcdono/fix-pipeline-test-install +1 -0
  38. s/.git/logs/refs/remotes/origin/spmcdono/layered-deployments +1 -0
  39. s/.git/logs/refs/remotes/origin/spmcdono/pypi-package-test-pipeline +1 -0
  40. s/.git/logs/refs/remotes/origin/spmcdono/remove-py2 +1 -0
  41. s/.git/logs/refs/remotes/origin/spmcdono/remove-py2-dev +1 -0
  42. s/.git/logs/refs/remotes/origin/spmcdono/test-native-runtime-install +1 -0
  43. s/.git/logs/refs/remotes/origin/spmcdono/update-pipeline +1 -0
  44. s/.git/logs/refs/remotes/origin/user/marine/EliiseS/devcontainer +1 -0
  45. s/.git/logs/refs/remotes/origin/user/marine/fixsimver +1 -0
  46. s/.git/logs/refs/remotes/origin/user/marine/layereddeploymentsbuildtest +1 -0
  47. s/.git/logs/refs/remotes/origin/user/marine/master-to-main +1 -0
  48. s/.git/logs/refs/remotes/origin/user/marine/pipeline +1 -0
  49. s/.git/logs/refs/remotes/origin/user/vikas +1 -0
  50. s/.git/logs/refs/remotes/origin/user/vikas0212/verify-tests +1 -0
  51. s/.git/logs/refs/remotes/origin/user/vikas2 +1 -0
  52. s/.git/logs/refs/remotes/origin/user/vikas_pypi +1 -0
  53. s/.git/logs/refs/remotes/origin/user/vikas_pypi-1 +1 -0
  54. s/.git/logs/refs/remotes/origin/user/vikas_testing +1 -0
  55. s/.git/logs/refs/remotes/origin/user/xinzed/dps_conn_str +1 -0
  56. s/.git/logs/refs/remotes/origin/user/xinzed/update-python-docker +1 -0
  57. s/.git/logs/refs/remotes/origin/vikas/azure +1 -0
  58. s/.git/logs/refs/remotes/origin/vikas/dependebot +1 -0
  59. s/.git/logs/refs/remotes/origin/xinzed/3_1_0rc1 +1 -0
  60. s/.git/logs/refs/remotes/origin/xinzed/update-runtime +1 -0
  61. s/.git/objects/pack/pack-a8179feb7da51d11a42c37c5b3c8593cffe17075.idx +0 -0
  62. s/.git/objects/pack/pack-a8179feb7da51d11a42c37c5b3c8593cffe17075.pack +0 -0
  63. s/.git/refs/remotes/origin/EO +1 -0
  64. s/.git/refs/remotes/origin/avagraw/security_fix +1 -0
  65. s/.git/refs/remotes/origin/cherry-pick-rename +1 -0
  66. s/.git/refs/remotes/origin/chyuan/fix-validation-not-fail-test +1 -0
  67. s/.git/refs/remotes/origin/chyuan/update-linux-agent +1 -0
  68. s/.git/refs/remotes/origin/dependabot/pip/pyyaml-5.4 +1 -0
  69. s/.git/refs/remotes/origin/eliises/add-device-tagging-docs +1 -0
  70. s/.git/refs/remotes/origin/main +1 -0
  71. s/.git/refs/remotes/origin/ray-deps +1 -0
  72. s/.git/refs/remotes/origin/ray-dev-setup +1 -0
  73. s/.git/refs/remotes/origin/ray-tox +1 -0
  74. s/.git/refs/remotes/origin/release-pipeline-automation +1 -0
  75. s/.git/refs/remotes/origin/spmcdono/fix-pipeline-test-install +1 -0
  76. s/.git/refs/remotes/origin/spmcdono/layered-deployments +1 -0
  77. s/.git/refs/remotes/origin/spmcdono/pypi-package-test-pipeline +1 -0
  78. s/.git/refs/remotes/origin/spmcdono/remove-py2 +1 -0
  79. s/.git/refs/remotes/origin/spmcdono/remove-py2-dev +1 -0
  80. s/.git/refs/remotes/origin/spmcdono/test-native-runtime-install +1 -0
  81. s/.git/refs/remotes/origin/spmcdono/update-pipeline +1 -0
  82. s/.git/refs/remotes/origin/user/marine/EliiseS/devcontainer +1 -0
  83. s/.git/refs/remotes/origin/user/marine/fixsimver +1 -0
  84. s/.git/refs/remotes/origin/user/marine/layereddeploymentsbuildtest +1 -0
  85. s/.git/refs/remotes/origin/user/marine/master-to-main +1 -0
  86. s/.git/refs/remotes/origin/user/marine/pipeline +1 -0
  87. s/.git/refs/remotes/origin/user/vikas +1 -0
  88. s/.git/refs/remotes/origin/user/vikas0212/verify-tests +1 -0
  89. s/.git/refs/remotes/origin/user/vikas2 +1 -0
  90. s/.git/refs/remotes/origin/user/vikas_pypi +1 -0
  91. s/.git/refs/remotes/origin/user/vikas_pypi-1 +1 -0
  92. s/.git/refs/remotes/origin/user/vikas_testing +1 -0
  93. s/.git/refs/remotes/origin/user/xinzed/dps_conn_str +1 -0
  94. s/.git/refs/remotes/origin/user/xinzed/update-python-docker +1 -0
  95. s/.git/refs/remotes/origin/vikas/azure +1 -0
  96. s/.git/refs/remotes/origin/vikas/dependebot +1 -0
  97. s/.git/refs/remotes/origin/xinzed/3_1_0rc1 +1 -0
  98. s/.git/refs/remotes/origin/xinzed/update-runtime +1 -0
  99. s/.git/refs/tags/v0.49.0 +1 -0
  100. s/.git/refs/tags/v0.50.0 +1 -0
  101. s/.git/refs/tags/v0.51.0 +1 -0
  102. s/.git/refs/tags/v0.52.0 +1 -0
  103. s/.git/refs/tags/v0.53.0 +1 -0
  104. s/.git/refs/tags/v0.54.0 +1 -0
  105. s/.git/refs/tags/v0.55.0 +1 -0
  106. s/.git/refs/tags/v0.56.0 +1 -0
  107. s/.git/refs/tags/v0.57.0 +1 -0
  108. s/.git/refs/tags/v0.58.0 +1 -0
  109. s/.git/refs/tags/v0.59.0 +1 -0
  110. s/.git/refs/tags/v0.60.0 +1 -0
  111. s/.git/refs/tags/v0.61.0 +1 -0
  112. s/.git/refs/tags/v0.62.0 +1 -0
  113. s/.git/refs/tags/v0.63.0 +1 -0
  114. s/.git/refs/tags/v0.64.0 +1 -0
  115. s/.git/refs/tags/v0.65.0 +1 -0
  116. s/.git/refs/tags/v0.66.0 +1 -0
  117. s/.git/refs/tags/v0.67.0 +1 -0
  118. s/.git/refs/tags/v0.68.0 +1 -0
  119. s/.git/refs/tags/v0.69.0 +1 -0
  120. s/.git/refs/tags/v0.70.0 +1 -0
  121. s/.git/refs/tags/v0.71.0 +1 -0
  122. s/.git/refs/tags/v0.72.0 +1 -0
  123. s/.git/refs/tags/v0.73.0 +1 -0
  124. s/.git/refs/tags/v0.74.0 +1 -0
  125. s/.git/refs/tags/v0.75.0 +1 -0
  126. s/.git/refs/tags/v0.76.0 +1 -0
  127. s/.git/refs/tags/v0.77.0 +1 -0
  128. s/.git/refs/tags/v0.78.0 +1 -0
  129. s/.git/refs/tags/v0.79.0 +1 -0
  130. s/.git/refs/tags/v0.82.0 +1 -0
  131. s/.git/refs/tags/v0.82.0-container +1 -0
  132. s/.git/refs/tags/v1.0.0 +1 -0
  133. s/.git/refs/tags/v1.1.0 +1 -0
  134. s/.git/refs/tags/v1.2.0 +1 -0
  135. s/.git/refs/tags/v1.3.0 +1 -0
  136. s/.git/refs/tags/v2.0.0 +1 -0
  137. s/.git/refs/tags/v2.0.1 +1 -0
  138. s/.git/refs/tags/v2.0.2 +1 -0
  139. s/.git/refs/tags/v2.1.0 +1 -0
  140. s/.git/refs/tags/v2.1.1 +1 -0
  141. s/.git/refs/tags/v2.1.2 +1 -0
  142. s/.git/refs/tags/v2.1.3 +1 -0
  143. s/.git/refs/tags/v2.1.4 +1 -0
  144. s/.git/refs/tags/v2.1.6 +1 -0
  145. s/.git/refs/tags/v2.2.0 +1 -0
  146. s/.git/refs/tags/v3.0.0 +1 -0
  147. s/.git/refs/tags/v3.0.0-rc +1 -0
  148. s/.git/refs/tags/v3.1.0 +1 -0
  149. s/.git/refs/tags/v3.1.1 +1 -0
  150. s/.git/refs/tags/v3.1.2 +1 -0
  151. s/.git/refs/tags/v3.2.0 +1 -0
  152. s/.git/refs/tags/v3.2.0rc0 +1 -0
  153. s/.git/refs/tags/v3.3.0 +1 -0
  154. s/.git/refs/tags/v3.3.1 +1 -0
  155. s/.git/refs/tags/v3.3.2 +1 -0
  156. s/.git/refs/tags/v3.3.3 +1 -0
  157. s/.git/refs/tags/v3.3.3-rc0 +1 -0
  158. s/.git/refs/tags/v3.3.4 +1 -0
  159. s/.github/ISSUE_TEMPLATE/bug_report.md +16 -0
  160. s/.github/ISSUE_TEMPLATE/feature_request.md +7 -0
  161. s/.github/workflows/wiki.yml +54 -0
  162. s/.gitignore +103 -0
  163. s/.vscode/launch.json +26 -0
  164. s/.vscode/settings.json +30 -0
  165. s/CHANGELOG.md +156 -0
  166. s/CODE_OF_CONDUCT.md +1 -0
  167. s/CONTRIBUTING.md +122 -0
  168. s/LICENSE +14 -0
  169. s/MANIFEST.in +7 -0
  170. s/Makefile +87 -0
  171. s/README.md +204 -0
  172. s/assets/armdeployment.png +0 -0
  173. s/assets/armoutputs.png +0 -0
  174. s/assets/deploy/ARMDeployment/ARMDeployment.deployproj +36 -0
  175. s/assets/deploy/ARMDeployment/Deploy-AzureResourceGroup.ps1 +118 -0
  176. s/assets/deploy/ARMDeployment/azuredeploy.json +145 -0
  177. s/assets/deploy/ARMDeployment/azuredeploy.parameters.json +6 -0
  178. s/assets/deploy/ARMDeployment.sln +25 -0
  179. s/assets/edgedevtool2mins.png +0 -0
  180. s/assets/edgedevtoolintro.png +0 -0
  181. s/assets/edgedevtoolquickstartlarge.png +0 -0
  182. s/assets/edgedevtoolquickstartsmall.png +0 -0
  183. s/assets/edgedevtoolwsl.png +0 -0
  184. s/azure-pipelines.yml +144 -0
  185. s/build/lib/iotedgedev/__init__.py +6 -0
  186. s/build/lib/iotedgedev/args.py +18 -0
  187. s/build/lib/iotedgedev/azurecli.py +542 -0
  188. s/build/lib/iotedgedev/buildoptionsparser.py +151 -0
  189. s/build/lib/iotedgedev/buildprofile.py +5 -0
  190. s/build/lib/iotedgedev/cli.py +830 -0
  191. s/build/lib/iotedgedev/connectionstring.py +58 -0
  192. s/build/lib/iotedgedev/constants.py +12 -0
  193. s/build/lib/iotedgedev/containerregistry.py +5 -0
  194. s/build/lib/iotedgedev/decorators.py +116 -0
  195. s/build/lib/iotedgedev/deploymentmanifest.py +313 -0
  196. s/build/lib/iotedgedev/dockercls.py +255 -0
  197. s/build/lib/iotedgedev/dotnet.py +31 -0
  198. s/build/lib/iotedgedev/edge.py +33 -0
  199. s/build/lib/iotedgedev/envvars.py +240 -0
  200. s/build/lib/iotedgedev/iothub.py +65 -0
  201. s/build/lib/iotedgedev/module.py +62 -0
  202. s/build/lib/iotedgedev/modules.py +332 -0
  203. s/build/lib/iotedgedev/organizedgroup.py +48 -0
  204. s/build/lib/iotedgedev/output.py +57 -0
  205. s/build/lib/iotedgedev/simulator.py +58 -0
  206. s/build/lib/iotedgedev/solution.py +48 -0
  207. s/build/lib/iotedgedev/telemetry.py +155 -0
  208. s/build/lib/iotedgedev/telemetryconfig.py +85 -0
  209. s/build/lib/iotedgedev/telemetryuploader.py +53 -0
  210. s/build/lib/iotedgedev/template/.env.tmp +87 -0
  211. s/build/lib/iotedgedev/template/.gitignore +10 -0
  212. s/build/lib/iotedgedev/template/deployment.template.json +79 -0
  213. s/build/lib/iotedgedev/template/launch_c.json +50 -0
  214. s/build/lib/iotedgedev/template/launch_csharp.json +43 -0
  215. s/build/lib/iotedgedev/template/launch_java.json +27 -0
  216. s/build/lib/iotedgedev/template/launch_node.json +36 -0
  217. s/build/lib/iotedgedev/template/launch_python.json +22 -0
  218. s/build/lib/iotedgedev/utility.py +179 -0
  219. s/build/lib/iotedgedev/version.py +4 -0
  220. s/build.sh +150 -0
  221. s/cleanup.sh +7 -0
  222. s/dist/iotedgedev-3.3.4-py3-none-any.whl +0 -0
  223. s/docker/tool/build-docker.sh +168 -0
  224. s/docker/tool/deps.txt +7 -0
  225. s/docker/tool/linux/Dockerfile +7 -0
  226. s/docker/tool/linux/Dockerfile.base +61 -0
  227. s/docker/tool/linux/install-dev.sh +8 -0
  228. s/docker/tool/linux/run.ps1 +5 -0
  229. s/docker/tool/linux/run.sh +5 -0
  230. s/docker/tool/push-docker.sh +35 -0
  231. s/docker/tool/windows/Dockerfile +4 -0
  232. s/docker/tool/windows/Dockerfile.base +63 -0
  233. s/docker/tool/windows/install-dev.bat +4 -0
  234. s/docker/tool/windows/run.ps1 +30 -0
  235. s/docs/Azure-Setup.md +102 -0
  236. s/docs/Command-List.md +564 -0
  237. s/docs/Command-Tips.md +51 -0
  238. s/docs/Edge-Device-Setup.md +23 -0
  239. s/docs/Home.md +10 -0
  240. s/docs/Manual-Dev-Machine-Setup.md +77 -0
  241. s/docs/Migration-Guides.md +131 -0
  242. s/docs/Overview.md +66 -0
  243. s/docs/Python-Virtual-Environment-Setup.md +35 -0
  244. s/docs/Quickstart-with-IoT-Edge-Dev-Container.md +145 -0
  245. s/docs/Test-Coverage.md +7 -0
  246. s/docs/Troubleshooting.md +21 -0
  247. s/docs/Usage.md +123 -0
  248. s/docs/_Sidebar.md +13 -0
  249. s/iotedgedev/__init__.py +6 -0
  250. s/iotedgedev/args.py +18 -0
  251. s/iotedgedev/azurecli.py +542 -0
  252. s/iotedgedev/buildoptionsparser.py +151 -0
  253. s/iotedgedev/buildprofile.py +5 -0
  254. s/iotedgedev/cli.py +830 -0
  255. s/iotedgedev/connectionstring.py +58 -0
  256. s/iotedgedev/constants.py +12 -0
  257. s/iotedgedev/containerregistry.py +5 -0
  258. s/iotedgedev/decorators.py +116 -0
  259. s/iotedgedev/deploymentmanifest.py +313 -0
  260. s/iotedgedev/dockercls.py +255 -0
  261. s/iotedgedev/dotnet.py +31 -0
  262. s/iotedgedev/edge.py +33 -0
  263. s/iotedgedev/envvars.py +240 -0
  264. s/iotedgedev/iothub.py +65 -0
  265. s/iotedgedev/module.py +62 -0
  266. s/iotedgedev/modules.py +332 -0
  267. s/iotedgedev/organizedgroup.py +48 -0
  268. s/iotedgedev/output.py +57 -0
  269. s/iotedgedev/simulator.py +58 -0
  270. s/iotedgedev/solution.py +48 -0
  271. s/iotedgedev/telemetry.py +155 -0
  272. s/iotedgedev/telemetryconfig.py +85 -0
  273. s/iotedgedev/telemetryuploader.py +53 -0
  274. s/iotedgedev/template/.env.tmp +87 -0
  275. s/iotedgedev/template/.gitignore +10 -0
  276. s/iotedgedev/template/deployment.template.json +79 -0
  277. s/iotedgedev/template/launch_c.json +50 -0
  278. s/iotedgedev/template/launch_csharp.json +43 -0
  279. s/iotedgedev/template/launch_java.json +27 -0
  280. s/iotedgedev/template/launch_node.json +36 -0
  281. s/iotedgedev/template/launch_python.json +22 -0
  282. s/iotedgedev/utility.py +179 -0
  283. s/iotedgedev/version.py +4 -0
  284. s/iotedgedev.egg-info/PKG-INFO +21 -0
  285. s/iotedgedev.egg-info/SOURCES.txt +100 -0
  286. s/iotedgedev.egg-info/dependency_links.txt +1 -0
  287. s/iotedgedev.egg-info/entry_points.txt +3 -0
  288. s/iotedgedev.egg-info/not-zip-safe +1 -0
  289. s/iotedgedev.egg-info/requires.txt +18 -0
  290. s/iotedgedev.egg-info/top_level.txt +1 -0
  291. s/pull_request_template.md +9 -0
  292. s/pytest.ini +4 -0
  293. s/requirements.txt +12 -0
  294. s/requirements_dev.txt +17 -0
  295. s/scripts/gen-help-markdown.bat +177 -0
  296. s/scripts/install-pip.sh +1 -0
  297. s/scripts/setup-wsl.sh +7 -0
  298. s/setup.cfg +18 -0
  299. s/setup.py +66 -0
  300. s/tests/__init__.py +5 -0
  301. s/tests/assets/deployment.manifest_invalid.json +106 -0
  302. s/tests/assets/deployment.manifest_invalid_createoptions.json +102 -0
  303. s/tests/assets/deployment.manifest_invalid_schema.json +69 -0
  304. s/tests/assets/deployment.template.non_str_placeholder.json +79 -0
  305. s/tests/assets/deployment.template_1.json +163 -0
  306. s/tests/assets/deployment.template_2.json +163 -0
  307. s/tests/assets/deployment.template_3.json +174 -0
  308. s/tests/assets/deployment.template_4.json +79 -0
  309. s/tests/assets/deployment.template_invalidresult.json +183 -0
  310. s/tests/assets/deployment.template_without_schema_template.json +99 -0
  311. s/tests/assets/launch.json +225 -0
  312. s/tests/assets/launch_without_nodejs.json +194 -0
  313. s/tests/assets/test_solution_shared_lib/.gitignore +2 -0
  314. s/tests/assets/test_solution_shared_lib/.vscode/launch.json +43 -0
  315. s/tests/assets/test_solution_shared_lib/deployment.debug.template.json +100 -0
  316. s/tests/assets/test_solution_shared_lib/deployment.escapedpath.template.json +90 -0
  317. s/tests/assets/test_solution_shared_lib/deployment.template.json +106 -0
  318. s/tests/assets/test_solution_shared_lib/layered_deployment.flattened_props.template.json +21 -0
  319. s/tests/assets/test_solution_shared_lib/layered_deployment.no_modules.template.json +12 -0
  320. s/tests/assets/test_solution_shared_lib/libs/sharedlib/Class1.cs +12 -0
  321. s/tests/assets/test_solution_shared_lib/libs/sharedlib/sharedlib.csproj +7 -0
  322. s/tests/assets/test_solution_shared_lib/modules/non_module_project/placeholder.txt +0 -0
  323. s/tests/assets/test_solution_shared_lib/modules/sample_module/.gitignore +34 -0
  324. s/tests/assets/test_solution_shared_lib/modules/sample_module/Dockerfile.amd64 +18 -0
  325. s/tests/assets/test_solution_shared_lib/modules/sample_module/Dockerfile.amd64.debug +25 -0
  326. s/tests/assets/test_solution_shared_lib/modules/sample_module/Dockerfile.windows-amd64 +15 -0
  327. s/tests/assets/test_solution_shared_lib/modules/sample_module/Program.cs +91 -0
  328. s/tests/assets/test_solution_shared_lib/modules/sample_module/module.json +18 -0
  329. s/tests/assets/test_solution_shared_lib/modules/sample_module/sample_module.csproj +26 -0
  330. s/tests/assets/test_solution_shared_lib/sample_module_2/.gitignore +34 -0
  331. s/tests/assets/test_solution_shared_lib/sample_module_2/Dockerfile.amd64 +18 -0
  332. s/tests/assets/test_solution_shared_lib/sample_module_2/Dockerfile.amd64.debug +25 -0
  333. s/tests/assets/test_solution_shared_lib/sample_module_2/Dockerfile.windows-amd64 +15 -0
  334. s/tests/assets/test_solution_shared_lib/sample_module_2/Program.cs +91 -0
  335. s/tests/assets/test_solution_shared_lib/sample_module_2/module.json +18 -0
  336. s/tests/assets/test_solution_shared_lib/sample_module_2/sample_module_2.csproj +26 -0
  337. s/tests/test_azurecli.py +33 -0
  338. s/tests/test_buildoptionsparser.py +155 -0
  339. s/tests/test_cli.py +55 -0
  340. s/tests/test_config.py +28 -0
  341. s/tests/test_connectionstring.py +87 -0
  342. s/tests/test_decorators.py +44 -0
  343. s/tests/test_deploymentmanifest.py +106 -0
  344. s/tests/test_envvars.py +169 -0
  345. s/tests/test_iotedgedev_iothub_deploy.py +199 -0
  346. s/tests/test_iotedgedev_simulator.py +133 -0
  347. s/tests/test_iotedgedev_solution.py +457 -0
  348. s/tests/test_iotedgedev_solution_build.py +246 -0
  349. s/tests/test_iotedgedev_solution_tag.py +99 -0
  350. s/tests/test_utility.py +132 -0
  351. s/tests/utility.py +132 -0
  352. s/tox.ini +29 -0
  353. s/vsts_ci/.vsts-ci.yml +93 -0
  354. s/vsts_ci/darwin/continuous-build-darwin.yml +54 -0
  355. s/vsts_ci/linux/continuous-build-linux.yml +28 -0
  356. s/vsts_ci/win32/continuous-build-win32.yml +26 -0
@@ -0,0 +1,457 @@
1
+ import json
2
+ import os
3
+ import platform
4
+ import shutil
5
+ import time
6
+ from unittest import mock
7
+
8
+ import pytest
9
+ from iotedgedev.connectionstring import (DeviceConnectionString,
10
+ IoTHubConnectionString)
11
+ from iotedgedev.envvars import EnvVars
12
+ from iotedgedev.output import Output
13
+ from iotedgedev.version import PY35
14
+
15
+ from .utility import (assert_json_file_equal, get_all_docker_containers,
16
+ get_all_docker_images, get_docker_os_type,
17
+ get_platform_type, remove_docker_container,
18
+ remove_docker_image, runner_invoke)
19
+
20
+ pytestmark = pytest.mark.e2e
21
+
22
+ output = Output()
23
+ envvars = EnvVars(output)
24
+
25
+ root_dir = os.getcwd()
26
+ tests_dir = os.path.join(root_dir, "tests")
27
+ tests_assets_dir = os.path.join(tests_dir, "assets")
28
+
29
+ env_file_name = envvars.get_dotenv_file()
30
+ env_file_path = envvars.get_dotenv_path(env_file_name)
31
+
32
+ launch_json_file = os.path.join(tests_dir, "assets", "launch.json")
33
+ launch_json_file_without_nodejs = os.path.join(tests_dir, "assets", "launch_without_nodejs.json")
34
+
35
+ test_solution = "test_solution"
36
+ test_solution_dir = os.path.join(tests_dir, test_solution)
37
+
38
+ test_solution_shared_lib = "test_solution_shared_lib"
39
+ test_solution_shared_lib_dir = os.path.join(tests_dir, "assets", test_solution_shared_lib)
40
+
41
+ templates = ["c", "csharp", "java", "nodejs", "python", "csharpfunction"]
42
+
43
+
44
+ def create_solution(template, custom_module_name=None):
45
+ if custom_module_name is None:
46
+ module_name = template + "module"
47
+ else:
48
+ module_name = custom_module_name
49
+ result = runner_invoke(['new', test_solution, '-m', module_name, '-t', template])
50
+
51
+ return result
52
+
53
+
54
+ def clean_folder(folder_path):
55
+ os.chdir(tests_dir)
56
+ time.sleep(5)
57
+ shutil.rmtree(folder_path, ignore_errors=True)
58
+
59
+
60
+ @pytest.fixture
61
+ def prepare_solution_with_env():
62
+ os.chdir(tests_dir)
63
+
64
+ template = "csharp"
65
+ module_name = "filtermodule"
66
+ result = create_solution(template, module_name)
67
+ if 'AZURE IOT EDGE SOLUTION CREATED' not in result.output:
68
+ raise Exception(result.stdout)
69
+
70
+ shutil.copyfile(env_file_path, os.path.join(test_solution_dir, env_file_name))
71
+
72
+ os.chdir(test_solution_dir)
73
+
74
+ yield prepare_solution_with_env
75
+ clean_folder(test_solution_dir)
76
+
77
+ return
78
+
79
+
80
+ def test_solution_create_in_non_empty_current_path(prepare_solution_with_env):
81
+ result = runner_invoke(['solution', 'new', '.'], True)
82
+
83
+ assert "Directory is not empty" in result.output
84
+
85
+
86
+ def test_solution_create_in_empty_current_path(prepare_solution_with_env):
87
+ dirname = "emptydir_current"
88
+ os.makedirs(dirname)
89
+ os.chdir(os.path.join(test_solution_dir, dirname))
90
+
91
+ result = runner_invoke(['solution', 'new', '.'])
92
+
93
+ assert 'AZURE IOT EDGE SOLUTION CREATED' in result.output
94
+
95
+
96
+ def test_solution_create_in_non_empty_dir(prepare_solution_with_env):
97
+ os.chdir(tests_dir)
98
+
99
+ result = runner_invoke(['solution', 'new', test_solution], True)
100
+
101
+ assert "Directory is not empty" in result.output
102
+
103
+
104
+ def test_solution_create_in_empty_child_dir(prepare_solution_with_env):
105
+ dirname = "emptydir"
106
+ os.makedirs(dirname)
107
+
108
+ result = runner_invoke(['solution', 'new', dirname])
109
+
110
+ assert 'AZURE IOT EDGE SOLUTION CREATED' in result.output
111
+
112
+
113
+ def test_solution_create_valid_runtime_tag():
114
+ dirname = "empty_dir"
115
+ os.makedirs(dirname)
116
+
117
+ result = runner_invoke(['solution', 'new', dirname, '-er', '1.1'])
118
+
119
+ assert 'AZURE IOT EDGE SOLUTION CREATED' in result.output
120
+ shutil.rmtree(dirname, ignore_errors=True)
121
+
122
+
123
+ def test_solution_create_invalid_runtime_tag():
124
+ result = runner_invoke(['solution', 'new', "empty_invalid_dir", '-er', '6'])
125
+
126
+ assert '-edge-runtime-version `6` is not valid' in result.output
127
+
128
+
129
+ def test_module_add(prepare_solution_with_env):
130
+ launch_file = launch_json_file
131
+ for template in templates:
132
+ # Node.js modules is skipped on non-Windows for below known issue.
133
+ # https://github.com/Azure/iotedgedev/issues/312
134
+ # https://github.com/Azure/iotedgedev/issues/346
135
+ if (template == "nodejs") and (platform.system().lower() != 'windows'):
136
+ launch_file = launch_json_file_without_nodejs
137
+ else:
138
+ module_name = template + "module"
139
+ result = runner_invoke(["solution", "add", module_name, '--template', template])
140
+ assert 'ADD COMPLETE' in result.output
141
+ assert os.path.exists(os.path.join(os.environ["MODULES_PATH"], module_name))
142
+ assert_module_folder_structure(template)
143
+
144
+ assert_json_file_equal(os.path.join(test_solution_dir, ".vscode", "launch.json"), launch_file)
145
+
146
+
147
+ def assert_solution_folder_structure(template):
148
+ module_name = template + "module"
149
+
150
+ expected_files = [".env", "deployment.template.json", "deployment.debug.template.json",
151
+ os.path.join(".vscode", "launch.json"),
152
+ os.path.join("modules", module_name, "Dockerfile.amd64"),
153
+ os.path.join("modules", module_name, "Dockerfile.amd64.debug"),
154
+ os.path.join("modules", module_name, "Dockerfile.arm32v7"),
155
+ os.path.join("modules", module_name, "module.json")]
156
+ for expected_file in expected_files:
157
+ assert os.path.exists(os.path.join(test_solution_dir, expected_file))
158
+
159
+ expected_template_files = [os.environ["DEPLOYMENT_CONFIG_TEMPLATE_FILE"], os.environ["DEPLOYMENT_CONFIG_DEBUG_TEMPLATE_FILE"]]
160
+
161
+ for expected_template_file in expected_template_files:
162
+ with open(os.path.join(test_solution_dir, expected_template_file)) as f:
163
+ content = json.load(f)
164
+
165
+ assert module_name in content["modulesContent"]["$edgeAgent"]["properties.desired"]["modules"]
166
+ assert module_name in content["modulesContent"]["$edgeAgent"]["properties.desired"]["modules"][module_name]["settings"]["image"]
167
+ assert module_name in content["modulesContent"]["$edgeHub"]["properties.desired"]["routes"]["sensorTo" + module_name]
168
+ assert module_name in content["modulesContent"]["$edgeHub"]["properties.desired"]["routes"][module_name + "ToIoTHub"]
169
+
170
+
171
+ def assert_module_folder_structure(template):
172
+ module_name = template + "module"
173
+ expected_template_files = [os.environ["DEPLOYMENT_CONFIG_TEMPLATE_FILE"], os.environ["DEPLOYMENT_CONFIG_DEBUG_TEMPLATE_FILE"]]
174
+
175
+ for expected_template_file in expected_template_files:
176
+ with open(expected_template_file) as f:
177
+ content = json.load(f)
178
+
179
+ assert module_name in content["modulesContent"]["$edgeAgent"]["properties.desired"]["modules"]
180
+ assert module_name in content["modulesContent"]["$edgeAgent"]["properties.desired"]["modules"][module_name]["settings"]["image"]
181
+ assert module_name in content["modulesContent"]["$edgeHub"]["properties.desired"]["routes"][module_name + "ToIoTHub"]
182
+
183
+ if expected_template_file == os.environ["DEPLOYMENT_CONFIG_DEBUG_TEMPLATE_FILE"]:
184
+ if module_name in ["cmodule", "pythonmodule", "nodejsmodule", "javamodule"]:
185
+ assert "HostConfig" in content["modulesContent"]["$edgeAgent"]["properties.desired"]["modules"][module_name]["settings"]["createOptions"]
186
+
187
+
188
+ def test_module_add_invalid_name(prepare_solution_with_env):
189
+ """Test the addmodule command with invalid module name"""
190
+
191
+ result = runner_invoke(["solution", "add", "_csharpmodule", "--template", "csharp"], True)
192
+ assert "Module name cannot start or end with the symbol _" in result.output
193
+
194
+ result = runner_invoke(["solution", "add", "csharpmodule_", "--template", "csharp"], True)
195
+ assert "Module name cannot start or end with the symbol _" in result.output
196
+
197
+ result = runner_invoke(["solution", "add", "csharp-module", "--template", "csharp"], True)
198
+ assert "Module name can only contain alphanumeric characters and the symbol _" in result.output
199
+
200
+ result = runner_invoke(["solution", "add", "filtermodule", "--template", "csharp"], True)
201
+ assert "already exists under" in result.output
202
+
203
+
204
+ @pytest.fixture
205
+ def test_push_modules():
206
+ result = runner_invoke(['push', '-P', get_platform_type()])
207
+
208
+ assert 'BUILD COMPLETE' in result.output
209
+ assert 'PUSH COMPLETE' in result.output
210
+ assert 'ERROR' not in result.output
211
+
212
+
213
+ @pytest.fixture
214
+ def test_deploy_modules():
215
+ if get_docker_os_type() == "windows":
216
+ result = runner_invoke(['deploy', '-f', os.path.join('config', 'deployment.' + get_platform_type() + '.json')])
217
+ else:
218
+ result = runner_invoke(['deploy'])
219
+
220
+ assert 'DEPLOYMENT COMPLETE' in result.output
221
+ assert 'ERROR' not in result.output.replace('ERROR: Error while checking for extension', '')
222
+
223
+
224
+ @pytest.fixture
225
+ def test_monitor(capfd):
226
+ runner_invoke(['monitor', '--timeout', '5'])
227
+
228
+ out, err = capfd.readouterr()
229
+ if not PY35:
230
+ assert 'Monitoring events from device' in out
231
+ else:
232
+ assert not err
233
+
234
+
235
+ def test_e2e(prepare_solution_with_env, test_push_modules, test_deploy_modules, test_monitor):
236
+ print("Testing e2e with env file")
237
+
238
+
239
+ def test_valid_env_iothub_connectionstring():
240
+ """Test for loading data of env file"""
241
+
242
+ env_iothub_connectionstring = os.getenv("IOTHUB_CONNECTION_STRING")
243
+ connectionstring = IoTHubConnectionString(env_iothub_connectionstring)
244
+
245
+ assert connectionstring.iothub_host.name
246
+ assert connectionstring.iothub_host.hub_name
247
+ assert connectionstring.shared_access_key
248
+ assert connectionstring.shared_access_key_name
249
+
250
+
251
+ def test_valid_env_device_connectionstring():
252
+ """Test for loading data of env file"""
253
+
254
+ env_device_connectionstring = os.getenv("DEVICE_CONNECTION_STRING")
255
+ connectionstring = DeviceConnectionString(env_device_connectionstring)
256
+
257
+ assert connectionstring.iothub_host.name
258
+ assert connectionstring.iothub_host.hub_name
259
+ assert connectionstring.shared_access_key
260
+ assert connectionstring.device_id
261
+
262
+
263
+ def test_create_new_solution():
264
+ os.chdir(tests_dir)
265
+ clean_folder(test_solution_dir)
266
+
267
+ for template in templates:
268
+ # Node.js modules is skipped on non-Windows for below known issue.
269
+ # https://github.com/Azure/iotedgedev/issues/312
270
+ # https://github.com/Azure/iotedgedev/issues/346
271
+ if (template == "nodejs") and (platform.system().lower() != 'windows'):
272
+ continue
273
+ else:
274
+ result = create_solution(template)
275
+ assert_solution_folder_structure(template)
276
+ assert 'AZURE IOT EDGE SOLUTION CREATED' in result.output
277
+ clean_folder(test_solution_dir)
278
+
279
+
280
+ def test_solution_push_with_default_platform(prepare_solution_with_env):
281
+ result = runner_invoke(['push'])
282
+
283
+ module_name = "filtermodule"
284
+ test_solution_config_dir = os.path.join('config', 'deployment.' + get_platform_type() + '.json')
285
+ env_container_registry_server = os.getenv("CONTAINER_REGISTRY_SERVER")
286
+ with open(test_solution_config_dir) as f:
287
+ content = json.load(f)
288
+
289
+ assert 'BUILD COMPLETE' in result.output
290
+ assert 'PUSH COMPLETE' in result.output
291
+ assert 'ERROR' not in result.output
292
+ assert env_container_registry_server + "/" + module_name + ":0.0.1-" + get_platform_type() in content[
293
+ "modulesContent"]["$edgeAgent"]["properties.desired"]["modules"][module_name]["settings"]["image"]
294
+ assert module_name in get_all_docker_images()
295
+
296
+
297
+ def test_generate_deployment_manifest():
298
+ try:
299
+ os.chdir(test_solution_shared_lib_dir)
300
+ shutil.copyfile(env_file_path, os.path.join(test_solution_shared_lib_dir, env_file_name))
301
+
302
+ new_config_deployment_name = 'deployment.' + get_platform_type() + '.json'
303
+ new_config_deployment_path = os.path.join(test_solution_shared_lib_dir, 'config', new_config_deployment_name)
304
+
305
+ if get_docker_os_type() == "windows":
306
+ result = runner_invoke(['genconfig', '-P', get_platform_type()])
307
+ else:
308
+ result = runner_invoke(['genconfig'])
309
+
310
+ assert 'ERROR' not in result.output
311
+
312
+ with open(new_config_deployment_path, "r") as f:
313
+ content = json.load(f)
314
+
315
+ module_image_name = content["modulesContent"]["$edgeAgent"]["properties.desired"]["modules"][
316
+ "sample_module"]["settings"]["image"]
317
+ module_2_image_name = content["modulesContent"]["$edgeAgent"]["properties.desired"]["modules"][
318
+ "sample_module_2"]["settings"]["image"]
319
+ env_container_registry_server = os.getenv("CONTAINER_REGISTRY_SERVER")
320
+ assert env_container_registry_server + "/sample_module:0.0.1-RC-" + get_platform_type() == module_image_name
321
+ assert env_container_registry_server + "/sample_module_2:0.0.1-RC-" + get_platform_type() == module_2_image_name
322
+
323
+ finally:
324
+ os.remove(os.path.join(test_solution_shared_lib_dir, env_file_name))
325
+
326
+
327
+ def test_validate_deployment_template_and_manifest_failed():
328
+ try:
329
+ deployment_file_name = "deployment.template_invalidresult.json"
330
+ os.chdir(tests_assets_dir)
331
+ shutil.copyfile(env_file_path, os.path.join(tests_assets_dir, env_file_name))
332
+
333
+ if get_docker_os_type() == "windows":
334
+ result = runner_invoke(['genconfig', '-P', get_platform_type(), '-f', deployment_file_name])
335
+ else:
336
+ result = runner_invoke(['genconfig', '-f', deployment_file_name])
337
+
338
+ assert "ERROR" not in result.output
339
+ # File name should be printed
340
+ assert "Validating generated deployment manifest %s" % os.path.join("config", deployment_file_name) in result.output
341
+ # All schema errors should be detected, not only the first error
342
+ assert "Warning: Deployment manifest schema error: 'address' is a required property. "
343
+ "Property path:modulesContent->$edgeAgent->properties.desired->runtime->settings->registryCredentials->test" in result.output
344
+ assert "Warning: Deployment manifest schema error: 1 is not of type 'string'. "
345
+ "Property path:modulesContent->$edgeAgent->properties.desired->runtime->settings->registryCredentials->test->username" in result.output
346
+ # Schema errors resulted by expanding environment variables should be detected
347
+ assert "Warning: Deployment manifest schema error: '' does not match '^[^\\s]+$'. "
348
+ "Property path:modulesContent->$edgeAgent->properties.desired->runtime->settings->registryCredentials->test2->address" in result.output
349
+ assert "Warning: Deployment manifest schema validation failed" in result.output
350
+ assert "Deployment manifest schema validation passed" not in result.output
351
+ assert "Validating createOptions for module csharpmodule" in result.output
352
+ assert "createOptions of module csharpmodule validation passed" in result.output
353
+ assert "Warning: createOptions of module edgeAgent should be an object" in result.output
354
+ assert "Warning: Errors found during createOptions validation" in result.output
355
+ assert "Validation for all createOptions passed" not in result.output
356
+
357
+ finally:
358
+ os.remove(os.path.join(tests_assets_dir, env_file_name))
359
+
360
+
361
+ @mock.patch.dict(os.environ, {"CONTAINER_REGISTRY_PASSWORD": "nonempty"})
362
+ def test_validate_deployment_template_and_manifest_success():
363
+ try:
364
+ deployment_file_name = "deployment.template.json"
365
+ os.chdir(test_solution_shared_lib_dir)
366
+ shutil.copyfile(env_file_path, os.path.join(test_solution_shared_lib_dir, env_file_name))
367
+
368
+ if get_docker_os_type() == "windows":
369
+ result = runner_invoke(['genconfig', '-P', get_platform_type(), '-f', deployment_file_name])
370
+ else:
371
+ result = runner_invoke(['genconfig', '-f', deployment_file_name])
372
+
373
+ assert "ERROR" not in result.output
374
+ assert "Deployment manifest schema validation passed" in result.output
375
+ assert "Warning: Deployment manifest schema validation failed" not in result.output
376
+ assert "Validation for all createOptions passed" in result.output
377
+ assert "Warning: Errors found during createOptions validation" not in result.output
378
+
379
+ finally:
380
+ os.remove(os.path.join(test_solution_shared_lib_dir, env_file_name))
381
+
382
+
383
+ def test_validate_create_options_failed():
384
+ os.chdir(tests_assets_dir)
385
+ deployment_file_name = "deployment.manifest_invalid.json"
386
+
387
+ if get_docker_os_type() == "windows":
388
+ result = runner_invoke(['genconfig', '-P', get_platform_type(), '-f', deployment_file_name])
389
+ else:
390
+ result = runner_invoke(['genconfig', '-f', deployment_file_name])
391
+
392
+ assert "ERROR" not in result.output
393
+ assert "Warning: Length of createOptions01 in module tempSensor exceeds 512" in result.output
394
+ assert "Warning: Length of createOptions02 in module tempSensor exceeds 512" in result.output
395
+ assert "Warning: createOptions of module csharpmodule is not a valid JSON string" in result.output
396
+ assert "Warning: createOptions of module csharpfunction should be an object" in result.output
397
+ assert "Warning: createOptions of module csharpfunction2 is not a valid JSON string" in result.output
398
+ assert "No settings or createOptions property found in module edgeAgent. Skip createOptions validation." in result.output
399
+ assert "createOptions of module edgeHub validation passed" in result.output
400
+ assert "Warning: Errors found during createOptions validation" in result.output
401
+
402
+
403
+ @pytest.mark.parametrize(
404
+ "deployment_file_name",
405
+ ["deployment.manifest_invalid.json", "deployment.manifest_invalid_schema.json", "deployment.manifest_invalid_createoptions.json"]
406
+ )
407
+ def test_fail_gen_config_on_validation_error(deployment_file_name):
408
+ os.chdir(tests_assets_dir)
409
+
410
+ with pytest.raises(Exception) as context:
411
+ if get_docker_os_type() == "windows":
412
+ result = runner_invoke(['genconfig', '-P', get_platform_type(), '-f', deployment_file_name, '--fail-on-validation-error'])
413
+ else:
414
+ result = runner_invoke(['genconfig', '-f', deployment_file_name, '--fail-on-validation-error'])
415
+
416
+ if get_docker_os_type() == "windows":
417
+ result = runner_invoke(['genconfig', '-P', get_platform_type(), '-f', deployment_file_name])
418
+ else:
419
+ result = runner_invoke(['genconfig', '-f', deployment_file_name])
420
+
421
+ assert "ERROR: Deployment manifest validation failed. Please see previous logs for more details." in str(context.value)
422
+ assert "ERROR" not in result.output
423
+
424
+
425
+ @mock.patch.dict(os.environ, {"TTL": "7200"})
426
+ def test_gen_config_with_non_string_placeholder():
427
+ os.chdir(tests_assets_dir)
428
+ deployment_file_name = "deployment.template.non_str_placeholder.json"
429
+ if get_docker_os_type() == "windows":
430
+ result = runner_invoke(['genconfig', '-P', get_platform_type(), '-f', deployment_file_name, '--fail-on-validation-error'])
431
+ else:
432
+ result = runner_invoke(['genconfig', '-f', deployment_file_name, '--fail-on-validation-error'])
433
+
434
+ assert "ERROR" not in result.output
435
+
436
+
437
+ @mock.patch.dict(os.environ, {"CONTAINER_REGISTRY_SERVER": "localhost:5000"})
438
+ @pytest.mark.skipif(get_docker_os_type() == 'windows', reason='windows container does not support local registry image')
439
+ def test_push_modules_to_local_registry(prepare_solution_with_env):
440
+ try:
441
+ module_name = "filtermodule"
442
+
443
+ if module_name in get_all_docker_images():
444
+ remove_docker_image(module_name)
445
+
446
+ result = runner_invoke(['push', '-P', get_platform_type()])
447
+
448
+ assert 'ERROR' not in result.output
449
+ assert result.exit_code == 0
450
+ assert 'BUILD COMPLETE' in result.output
451
+ assert 'PUSH COMPLETE' in result.output
452
+ assert f"localhost:5000/{module_name in get_all_docker_images()}"
453
+ finally:
454
+ if "registry" in get_all_docker_containers():
455
+ remove_docker_container("registry")
456
+ if "registry" in get_all_docker_images():
457
+ remove_docker_image("registry:2")