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,155 @@
1
+ import datetime
2
+ import json
3
+ import os
4
+ import platform
5
+ import subprocess
6
+ import sys
7
+ import uuid
8
+ from collections import defaultdict
9
+ from functools import wraps
10
+
11
+ from . import telemetryuploader
12
+ from .telemetryconfig import TelemetryConfig
13
+ from .decorators import hash256_result, suppress_all_exceptions
14
+
15
+ PRODUCT_NAME = 'iotedgedev'
16
+
17
+
18
+ class TelemetrySession(object):
19
+ def __init__(self, correlation_id=None):
20
+ self.start_time = None
21
+ self.end_time = None
22
+ self.correlation_id = correlation_id or str(uuid.uuid4())
23
+ self.command = 'command_name'
24
+ self.parameters = []
25
+ self.result = 'None'
26
+ self.result_summary = None
27
+ self.exception = None
28
+ self.extra_props = {}
29
+ self.machineId = self._get_hash_mac_address()
30
+ self.events = defaultdict(list)
31
+
32
+ def generate_payload(self):
33
+ props = {
34
+ 'EventId': str(uuid.uuid4()),
35
+ 'CorrelationId': self.correlation_id,
36
+ 'MachineId': self.machineId,
37
+ 'ProductName': PRODUCT_NAME,
38
+ 'ProductVersion': _get_core_version(),
39
+ 'CommandName': self.command,
40
+ 'OS.Type': platform.system().lower(),
41
+ 'OS.Version': platform.version().lower(),
42
+ 'Result': self.result,
43
+ 'StartTime': str(self.start_time),
44
+ 'EndTime': str(self.end_time),
45
+ 'Parameters': ','.join(self.parameters)
46
+ }
47
+
48
+ if self.result_summary:
49
+ props['ResultSummary'] = self.result_summary
50
+
51
+ if self.exception:
52
+ props['Exception'] = self.exception
53
+
54
+ props.update(self.extra_props)
55
+
56
+ self.events[_get_AI_key()].append({
57
+ 'name': '{}/command'.format(PRODUCT_NAME),
58
+ 'properties': props
59
+ })
60
+
61
+ payload = json.dumps(self.events)
62
+ return _remove_symbols(payload)
63
+
64
+ @suppress_all_exceptions()
65
+ @hash256_result
66
+ def _get_hash_mac_address(self):
67
+ s = ''
68
+ for index, c in enumerate(hex(uuid.getnode())[2:].upper()):
69
+ s += c
70
+ if index % 2:
71
+ s += '-'
72
+
73
+ s = s.strip('-')
74
+ return s
75
+
76
+
77
+ _session = TelemetrySession()
78
+
79
+
80
+ def _user_agrees_to_telemetry(func):
81
+ @wraps(func)
82
+ def _wrapper(*args, **kwargs):
83
+ config = TelemetryConfig()
84
+ if not config.get_boolean(config.DEFAULT_DIRECT, config.TELEMETRY_SECTION):
85
+ return None
86
+ return func(*args, **kwargs)
87
+
88
+ return _wrapper
89
+
90
+
91
+ @suppress_all_exceptions()
92
+ def start(cmdname, params=[]):
93
+ _session.command = cmdname
94
+ _session.start_time = datetime.datetime.utcnow()
95
+ if params is not None:
96
+ _session.parameters.extend(params)
97
+
98
+
99
+ @suppress_all_exceptions()
100
+ def success():
101
+ _session.result = 'Success'
102
+
103
+
104
+ @suppress_all_exceptions()
105
+ def fail(exception, summary):
106
+ _session.exception = exception
107
+ _session.result = 'Fail'
108
+ _session.result_summary = summary
109
+
110
+
111
+ @suppress_all_exceptions()
112
+ def add_extra_props(props):
113
+ if props is not None:
114
+ _session.extra_props.update(props)
115
+
116
+
117
+ @_user_agrees_to_telemetry
118
+ @suppress_all_exceptions()
119
+ def flush():
120
+ # flush out current information
121
+ _session.end_time = datetime.datetime.utcnow()
122
+
123
+ payload = _session.generate_payload()
124
+ if payload:
125
+ _upload_telemetry_with_user_agreement(payload)
126
+
127
+ # reset session fields, retaining correlation id and application
128
+ _session.__init__(correlation_id=_session.correlation_id)
129
+
130
+
131
+ @suppress_all_exceptions(fallback_return=None)
132
+ def _get_core_version():
133
+ from iotedgedev import __version__ as core_version
134
+ return core_version
135
+
136
+
137
+ @suppress_all_exceptions()
138
+ def _get_AI_key():
139
+ from iotedgedev import __AIkey__ as key
140
+ return key
141
+
142
+
143
+ # This includes a final user-agreement-check; ALL methods sending telemetry MUST call this.
144
+ @_user_agrees_to_telemetry
145
+ @suppress_all_exceptions()
146
+ def _upload_telemetry_with_user_agreement(payload, **kwargs):
147
+ # Call telemetry uploader as a subprocess to prevent blocking iotedgedev process
148
+ subprocess.Popen([sys.executable, os.path.realpath(telemetryuploader.__file__), payload], **kwargs)
149
+
150
+
151
+ def _remove_symbols(s):
152
+ if isinstance(s, str):
153
+ for c in '$%^&|':
154
+ s = s.replace(c, '_')
155
+ return s
@@ -0,0 +1,85 @@
1
+ import os
2
+
3
+ import configparser
4
+
5
+ from .decorators import suppress_all_exceptions
6
+
7
+ PRIVACY_STATEMENT = """
8
+ Welcome to iotedgedev!
9
+ -------------------------
10
+ Telemetry
11
+ ---------
12
+ The iotedgedev collects usage data in order to improve your experience.
13
+ The data is anonymous and does not include commandline argument values.
14
+ The data is collected by Microsoft.
15
+
16
+ You can change your telemetry settings by updating '{0}' to 'no' in {1}
17
+ """
18
+
19
+
20
+ class TelemetryConfig(object):
21
+ DEFAULT_DIRECT = 'DEFAULT'
22
+ FIRSTTIME_SECTION = 'firsttime'
23
+ TELEMETRY_SECTION = 'collect_telemetry'
24
+
25
+ def __init__(self):
26
+ self.config_parser = configparser.ConfigParser({
27
+ self.FIRSTTIME_SECTION: 'yes'
28
+ })
29
+ self.setup()
30
+
31
+ @suppress_all_exceptions()
32
+ def setup(self):
33
+ config_path = self.get_config_path()
34
+ config_folder = os.path.dirname(config_path)
35
+ if not os.path.exists(config_folder):
36
+ os.makedirs(config_folder)
37
+ if not os.path.exists(config_path):
38
+ self.dump()
39
+ else:
40
+ self.load()
41
+ self.dump()
42
+
43
+ @suppress_all_exceptions()
44
+ def load(self):
45
+ with open(self.get_config_path(), 'r') as f:
46
+ if hasattr(self.config_parser, 'read_file'):
47
+ self.config_parser.read_file(f)
48
+
49
+ @suppress_all_exceptions()
50
+ def dump(self):
51
+ with open(self.get_config_path(), 'w') as f:
52
+ self.config_parser.write(f)
53
+
54
+ @suppress_all_exceptions()
55
+ def get(self, direct, section):
56
+ return self.config_parser.get(direct, section)
57
+
58
+ @suppress_all_exceptions()
59
+ def get_boolean(self, direct, section):
60
+ return self.config_parser.getboolean(direct, section)
61
+
62
+ @suppress_all_exceptions()
63
+ def set(self, direct, section, val):
64
+ if val is not None:
65
+ self.config_parser.set(direct, section, val)
66
+ self.dump()
67
+
68
+ @suppress_all_exceptions()
69
+ def check_firsttime(self):
70
+ if self.get(self.DEFAULT_DIRECT, self.FIRSTTIME_SECTION) != 'no':
71
+ self.set(self.DEFAULT_DIRECT, self.FIRSTTIME_SECTION, 'no')
72
+ print(PRIVACY_STATEMENT.format(self.TELEMETRY_SECTION, self.get_config_path()))
73
+ self.set(self.DEFAULT_DIRECT, self.TELEMETRY_SECTION, 'yes')
74
+ self.dump()
75
+
76
+ @suppress_all_exceptions()
77
+ def get_config_path(self):
78
+ config_folder = self.get_config_folder()
79
+ if config_folder:
80
+ return os.path.join(config_folder, 'setting.ini')
81
+ return None
82
+
83
+ @suppress_all_exceptions()
84
+ def get_config_folder(self):
85
+ return os.path.join(os.path.expanduser("~"), '.iotedgedev')
@@ -0,0 +1,53 @@
1
+ import json
2
+ import sys
3
+
4
+ from applicationinsights import TelemetryClient
5
+ from applicationinsights.channel import (SynchronousQueue, SynchronousSender,
6
+ TelemetryChannel)
7
+ from applicationinsights.exceptions import enable
8
+ from urllib.request import Request, urlopen
9
+
10
+ from iotedgedev.decorators import suppress_all_exceptions
11
+
12
+
13
+ class LimitedRetrySender(SynchronousSender):
14
+ def __init__(self):
15
+ super(LimitedRetrySender, self).__init__()
16
+
17
+ def send(self, data_to_send):
18
+ """ Override the default resend mechanism in SenderBase. Stop resend when it fails."""
19
+ request_payload = json.dumps([a.write() for a in data_to_send])
20
+
21
+ req = Request(self._service_endpoint_uri, bytearray(request_payload, 'utf-8'),
22
+ {'Accept': 'application/json', 'Content-Type': 'application/json; charset=utf-8'})
23
+ try:
24
+ urlopen(req, timeout=10)
25
+ except Exception:
26
+ pass
27
+
28
+
29
+ @suppress_all_exceptions()
30
+ def upload(data_to_save):
31
+ data_to_save = json.loads(data_to_save)
32
+
33
+ for instrumentation_key in data_to_save:
34
+ client = TelemetryClient(instrumentation_key=instrumentation_key,
35
+ telemetry_channel=TelemetryChannel(queue=SynchronousQueue(LimitedRetrySender())))
36
+ enable(instrumentation_key)
37
+ for record in data_to_save[instrumentation_key]:
38
+ name = record['name']
39
+ raw_properties = record['properties']
40
+ properties = {}
41
+ measurements = {}
42
+ for k, v in raw_properties.items():
43
+ if isinstance(v, str):
44
+ properties[k] = v
45
+ else:
46
+ measurements[k] = v
47
+ client.track_event(name, properties, measurements)
48
+ client.flush()
49
+
50
+
51
+ if __name__ == '__main__':
52
+ # If user doesn't agree to upload telemetry, this scripts won't be executed. The caller should control.
53
+ upload(sys.argv[1])
@@ -0,0 +1,87 @@
1
+ #
2
+ # CONNECTION STRINGS
3
+ #
4
+
5
+ IOTHUB_CONNECTION_STRING=""
6
+
7
+ DEVICE_CONNECTION_STRING=""
8
+
9
+ #
10
+ # CONTAINER REGISTRY
11
+ #
12
+ # Settings for your default container registry.
13
+ # - Local Registry: Set CONTAINER_REGISTRY_SERVER to "localhost:5000" - USERNAME/PASSWORD are not required.
14
+ # - Azure Container Registry: Set CONTAINER_REGISTRY_SERVER to "myregistry.azurecr.io". USERNAME/PASSWORD are required.
15
+ # - Docker Hub: Set CONTAINER_REGISTRY_SERVER and CONTAINER_REGISTRY_USERNAME to your Docker Hub username. Set CONTAINER_REGISTRY_PASSWORD to your Docker Hub password.
16
+
17
+ CONTAINER_REGISTRY_SERVER="localhost:5000"
18
+ CONTAINER_REGISTRY_USERNAME=""
19
+ CONTAINER_REGISTRY_PASSWORD=""
20
+
21
+ # To specify additional container registries ensure the prefix is CONTAINER_REGISTRY_SERVER_, CONTAINER_REGISTRY_USERNAME_, CONTAINER_REGISTRY_PASSWORD_
22
+ # And the token following the prefix uniquely associates the SERVER/USERNAME/PASSWORD
23
+ # Token can be any string of alphanumeric characters
24
+
25
+ # CONTAINER_REGISTRY_SERVER_2=""
26
+ # CONTAINER_REGISTRY_USERNAME_2=""
27
+ # CONTAINER_REGISTRY_PASSWORD_2=""
28
+
29
+ #
30
+ # HOST
31
+ #
32
+
33
+ EDGE_RUNTIME_VERSION="%EDGE_RUNTIME_VERSION%"
34
+ EDGEAGENT_SCHEMA_VERSION="%EDGEAGENT_SCHEMA_VERSION%"
35
+ EDGEHUB_SCHEMA_VERSION="%EDGEHUB_SCHEMA_VERSION%"
36
+
37
+ #
38
+ # MODULES
39
+ #
40
+
41
+ BYPASS_MODULES=""
42
+ # "" - to build all modules
43
+ # "*" - to bypass all modules
44
+ # "filtermodule, module1" - Comma delimited list of modules to bypass when building
45
+
46
+ CONTAINER_TAG=""
47
+
48
+ #
49
+ # SOLUTION SETTINGS
50
+ #
51
+
52
+ CONFIG_OUTPUT_DIR="config"
53
+ DEPLOYMENT_CONFIG_TEMPLATE_FILE="deployment.template.json"
54
+ DEPLOYMENT_CONFIG_DEBUG_TEMPLATE_FILE="deployment.debug.template.json"
55
+ DEFAULT_PLATFORM="amd64"
56
+ MODULES_PATH="modules"
57
+
58
+ LOGS_PATH="logs"
59
+
60
+ #
61
+ # DOCKER LOGS COMMAND
62
+ #
63
+ # Command used when calling iotedgedev docker --logs or --show-logs
64
+
65
+ LOGS_CMD="start /B start cmd.exe @cmd /k docker logs {0} -f"
66
+ # "start /B start cmd.exe @cmd /k docker logs {0} -f" - for CMD
67
+ # "docker logs {0} -f -new_console:sV" - for ConEmu
68
+
69
+ #
70
+ # AZURE SETTINGS
71
+ #
72
+ # These settings will override parameters to the `iotedgedev azure --setup` command.
73
+ # CREDENTIALS="username password"
74
+ # SERVICE_PRINCIPAL="username password tenant"
75
+ # RESOURCE_GROUP_LOCATION="australiaeast|australiasoutheast|brazilsouth|canadacentral|canadaeast|centralindia|centralus|eastasia|eastus|eastus2|japanwest|japaneast|northeurope|northcentralus|southindia|uksouth|ukwest|westus|westeurope|southcentralus|westcentralus|westus2"
76
+ # IOTHUB_SKU="F1|S1|S2|S3"
77
+ # UPDATE_DOTENV="True|False"
78
+
79
+ SUBSCRIPTION_ID=""
80
+ RESOURCE_GROUP_NAME=""
81
+ RESOURCE_GROUP_LOCATION=""
82
+ IOTHUB_NAME=""
83
+ IOTHUB_SKU=""
84
+ EDGE_DEVICE_ID=""
85
+ CREDENTIALS=""
86
+ SERVICE_PRINCIPAL=""
87
+ UPDATE_DOTENV=""
@@ -0,0 +1,10 @@
1
+ **/.vs
2
+ **/bin
3
+ **/obj
4
+ **/out
5
+ build
6
+ .env
7
+ venv
8
+ logs
9
+ .config
10
+ config
@@ -0,0 +1,79 @@
1
+ {
2
+ "$schema-template": "4.0.0",
3
+ "modulesContent": {
4
+ "$edgeAgent": {
5
+ "properties.desired": {
6
+ "schemaVersion": "${EDGEAGENT_SCHEMA_VERSION}",
7
+ "runtime": {
8
+ "type": "docker",
9
+ "settings": {
10
+ "minDockerVersion": "v1.25",
11
+ "loggingOptions": "",
12
+ "registryCredentials": {}
13
+ }
14
+ },
15
+ "systemModules": {
16
+ "edgeAgent": {
17
+ "type": "docker",
18
+ "settings": {
19
+ "image": "mcr.microsoft.com/azureiotedge-agent:${EDGE_RUNTIME_VERSION}",
20
+ "createOptions": {}
21
+ }
22
+ },
23
+ "edgeHub": {
24
+ "type": "docker",
25
+ "status": "running",
26
+ "restartPolicy": "always",
27
+ "settings": {
28
+ "image": "mcr.microsoft.com/azureiotedge-hub:${EDGE_RUNTIME_VERSION}",
29
+ "createOptions": {
30
+ "HostConfig": {
31
+ "PortBindings": {
32
+ "5671/tcp": [
33
+ {
34
+ "HostPort": "5671"
35
+ }
36
+ ],
37
+ "8883/tcp": [
38
+ {
39
+ "HostPort": "8883"
40
+ }
41
+ ],
42
+ "443/tcp": [
43
+ {
44
+ "HostPort": "443"
45
+ }
46
+ ]
47
+ }
48
+ }
49
+ }
50
+ }
51
+ }
52
+ },
53
+ "modules": {
54
+ "tempSensor": {
55
+ "version": "1.0",
56
+ "type": "docker",
57
+ "status": "running",
58
+ "restartPolicy": "always",
59
+ "settings": {
60
+ "image": "mcr.microsoft.com/azureiotedge-simulated-temperature-sensor:1.0",
61
+ "createOptions": {}
62
+ }
63
+ }
64
+ }
65
+ }
66
+ },
67
+ "$edgeHub": {
68
+ "properties.desired": {
69
+ "schemaVersion": "${EDGEHUB_SCHEMA_VERSION}",
70
+ "routes": {
71
+ "sensorTo%MODULE%": "FROM /messages/modules/tempSensor/outputs/temperatureOutput INTO BrokeredEndpoint(\"/modules/%MODULE%/inputs/input1\")"
72
+ },
73
+ "storeAndForwardConfiguration": {
74
+ "timeToLiveSecs": 7200
75
+ }
76
+ }
77
+ }
78
+ }
79
+ }
@@ -0,0 +1,50 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "name": "%MODULE% Remote Debug (C)",
6
+ "type": "cppdbg",
7
+ "request": "attach",
8
+ "program": "./main",
9
+ "processId": "${command:pickRemoteProcess}",
10
+ "pipeTransport": {
11
+ "pipeCwd": "${workspaceFolder}",
12
+ "pipeProgram": "docker",
13
+ "pipeArgs": [
14
+ "exec",
15
+ "-i",
16
+ "%MODULE%",
17
+ "sh",
18
+ "-c"
19
+ ],
20
+ "debuggerPath": "/usr/bin/gdb"
21
+ },
22
+ "sourceFileMap": {
23
+ "%APP_FOLDER%": "${workspaceFolder}/modules/%MODULE_FOLDER%"
24
+ },
25
+ "linux": {
26
+ "MIMode": "gdb",
27
+ "setupCommands": [
28
+ {
29
+ "description": "Enable pretty-printing for gdb",
30
+ "text": "-enable-pretty-printing",
31
+ "ignoreFailures": true
32
+ }
33
+ ]
34
+ },
35
+ "osx": {
36
+ "MIMode": "lldb"
37
+ },
38
+ "windows": {
39
+ "MIMode": "gdb",
40
+ "setupCommands": [
41
+ {
42
+ "description": "Enable pretty-printing for gdb",
43
+ "text": "-enable-pretty-printing",
44
+ "ignoreFailures": true
45
+ }
46
+ ]
47
+ }
48
+ }
49
+ ]
50
+ }
@@ -0,0 +1,43 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "name": "%MODULE% Remote Debug (.NET Core)",
6
+ "type": "coreclr",
7
+ "request": "attach",
8
+ "processId": "${command:pickRemoteProcess}",
9
+ "pipeTransport": {
10
+ "pipeProgram": "docker",
11
+ "pipeArgs": [
12
+ "exec",
13
+ "-i",
14
+ "%MODULE%",
15
+ "sh",
16
+ "-c"
17
+ ],
18
+ "debuggerPath": "~/vsdbg/vsdbg",
19
+ "pipeCwd": "${workspaceFolder}",
20
+ "quoteArgs": true
21
+ },
22
+ "sourceFileMap": {
23
+ "%APP_FOLDER%": "${workspaceFolder}/modules/%MODULE_FOLDER%"
24
+ },
25
+ "justMyCode": true
26
+ },
27
+ {
28
+ "name": "%MODULE% Local Debug (.NET Core)",
29
+ "type": "coreclr",
30
+ "request": "launch",
31
+ "program": "${workspaceRoot}/modules/%MODULE_FOLDER%/bin/Debug/netcoreapp2.1/%MODULE%.dll",
32
+ "args": [],
33
+ "cwd": "${workspaceRoot}/modules/%MODULE_FOLDER%",
34
+ "internalConsoleOptions": "openOnSessionStart",
35
+ "stopAtEntry": false,
36
+ "console": "internalConsole",
37
+ "env": {
38
+ "EdgeHubConnectionString": "${config:azure-iot-edge.EdgeHubConnectionString}",
39
+ "EdgeModuleCACertificateFile": "${config:azure-iot-edge.EdgeModuleCACertificateFile}"
40
+ }
41
+ }
42
+ ]
43
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "type": "java",
6
+ "name": "%MODULE% Local Debug (java)",
7
+ "request": "launch",
8
+ "cwd": "${workspaceRoot}/modules/%MODULE_FOLDER%",
9
+ "console": "internalConsole",
10
+ "stopOnEntry": false,
11
+ "mainClass": "%GROUP_ID%.App",
12
+ "args": "",
13
+ "projectName": "%MODULE%",
14
+ "env": {
15
+ "EdgeHubConnectionString": "${config:azure-iot-edge.EdgeHubConnectionString}",
16
+ "EdgeModuleCACertificateFile": "${config:azure-iot-edge.EdgeModuleCACertificateFile}"
17
+ }
18
+ },
19
+ {
20
+ "type": "java",
21
+ "name": "%MODULE% Remote Debug (java)",
22
+ "request": "attach",
23
+ "hostName": "localhost",
24
+ "port": 5005
25
+ }
26
+ ]
27
+ }
@@ -0,0 +1,36 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "name": "%MODULE% Remote Debug (Node.js)",
6
+ "type": "node",
7
+ "request": "attach",
8
+ "port": 9229,
9
+ "address": "localhost",
10
+ "localRoot": "${workspaceRoot}/modules/%MODULE_FOLDER%",
11
+ "remoteRoot": "/app",
12
+ "protocol": "inspector"
13
+ },
14
+ {
15
+ "name": "%MODULE% Remote Debug (Node.js in Windows Container)",
16
+ "type": "node",
17
+ "request": "attach",
18
+ "port": 9229,
19
+ "address": "localhost",
20
+ "localRoot": "${workspaceRoot}/modules/%MODULE_FOLDER%",
21
+ "remoteRoot": "C:\\app",
22
+ "protocol": "inspector"
23
+ },
24
+ {
25
+ "name": "%MODULE% Local Debug (Node.js)",
26
+ "type": "node",
27
+ "request": "launch",
28
+ "program": "${workspaceRoot}/modules/%MODULE_FOLDER%/app.js",
29
+ "console": "integratedTerminal",
30
+ "env": {
31
+ "EdgeHubConnectionString": "${config:azure-iot-edge.EdgeHubConnectionString}",
32
+ "EdgeModuleCACertificateFile": "${config:azure-iot-edge.EdgeModuleCACertificateFile}"
33
+ }
34
+ }
35
+ ]
36
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [{
4
+ "name": "%MODULE% Remote Debug (Python)",
5
+ "type": "python",
6
+ "request": "attach",
7
+ "port": 5678,
8
+ "host": "localhost",
9
+ "logToFile": true,
10
+ "redirectOutput": true,
11
+ "pathMappings": [{
12
+ "localRoot": "${workspaceFolder}/modules/%MODULE_FOLDER%",
13
+ "remoteRoot": "%APP_FOLDER%"
14
+ }],
15
+ "windows": {
16
+ "pathMappings": [{
17
+ "localRoot": "${workspaceFolder}\\modules\\%MODULE_FOLDER%",
18
+ "remoteRoot": "%APP_FOLDER%"
19
+ }]
20
+ }
21
+ }]
22
+ }